From 9a307d7c52ef6dc1ce66f5f8cd63e12537484c60 Mon Sep 17 00:00:00 2001 From: tmat Date: Fri, 29 Apr 2022 15:22:30 -0700 Subject: [PATCH 001/176] Explicitly pass formatting options to Roslyn APIs (via External Access) --- .../Formatting/CSharpFormatter.cs | 11 ++++---- .../Formatting/CSharpOnTypeFormattingPass.cs | 15 +++++------ .../Formatting/FormattingOptionsExtensions.cs | 17 +++++++++++++ .../FormattingLanguageServerClient.cs | 25 ++++++++----------- .../Formatting/FormattingTestBase.cs | 8 ++++-- 5 files changed, 45 insertions(+), 31 deletions(-) create mode 100644 src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Formatting/FormattingOptionsExtensions.cs diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Formatting/CSharpFormatter.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Formatting/CSharpFormatter.cs index 33d7cbe4521..8a6140a8815 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Formatting/CSharpFormatter.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Formatting/CSharpFormatter.cs @@ -13,6 +13,7 @@ using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.ExternalAccess.Razor; using Microsoft.CodeAnalysis.Razor.Workspaces.Extensions; using Microsoft.CodeAnalysis.Text; using OmniSharp.Extensions.LanguageServer.Protocol.Models; @@ -135,15 +136,14 @@ private static async Task FormatOnServerAsync( Range projectedRange, CancellationToken cancellationToken) { + var csharpDocument = context.CSharpWorkspaceDocument; var csharpSourceText = context.CodeDocument.GetCSharpSourceText(); var spanToFormat = projectedRange.AsTextSpan(csharpSourceText); var root = await context.CSharpWorkspaceDocument.GetSyntaxRootAsync(cancellationToken); Assumes.NotNull(root); - var workspace = context.CSharpWorkspace; - - // Formatting options will already be set in the workspace. - var changes = CodeAnalysis.Formatting.Formatter.GetFormattedTextChanges(root, spanToFormat, workspace, cancellationToken: cancellationToken); + var services = csharpDocument.Project.Solution.Workspace.Services; + var changes = RazorCSharpFormattingInteractionService.GetFormattedTextChanges(services, root, spanToFormat, context.Options.GetIndentationOptions(), cancellationToken); var edits = changes.Select(c => c.AsTextEdit(csharpSourceText)).ToArray(); return edits; @@ -165,7 +165,8 @@ private static async Task> GetCSharpIndentationCoreAsync(Fo // At this point, we have added all the necessary markers and attached annotations. // Let's invoke the C# formatter and hope for the best. - var formattedRoot = CodeAnalysis.Formatting.Formatter.Format(root, context.CSharpWorkspace, cancellationToken: cancellationToken); + var services = context.CSharpWorkspaceDocument.Project.Solution.Workspace.Services; + var formattedRoot = RazorCSharpFormattingInteractionService.Format(services, root, context.Options.GetIndentationOptions(), cancellationToken); var formattedText = formattedRoot.GetText(); var desiredIndentationMap = new Dictionary(); diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Formatting/CSharpOnTypeFormattingPass.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Formatting/CSharpOnTypeFormattingPass.cs index a194a00b571..30e8f4c14b8 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Formatting/CSharpOnTypeFormattingPass.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Formatting/CSharpOnTypeFormattingPass.cs @@ -27,11 +27,13 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer.Formatting internal class CSharpOnTypeFormattingPass : CSharpFormattingPassBase { private readonly ILogger _logger; + private readonly RazorGlobalOptions _globalOptions; public CSharpOnTypeFormattingPass( RazorDocumentMappingService documentMappingService, FilePathNormalizer filePathNormalizer, ClientNotifierServiceBase server, + RazorGlobalOptions globalOptions, ILoggerFactory loggerFactory) : base(documentMappingService, filePathNormalizer, server) { @@ -41,6 +43,7 @@ public CSharpOnTypeFormattingPass( } _logger = loggerFactory.CreateLogger(); + _globalOptions = globalOptions; } public async override Task ExecuteAsync(FormattingContext context, FormattingResult result, CancellationToken cancellationToken) @@ -65,19 +68,13 @@ public async override Task ExecuteAsync(FormattingContext cont } // Ask C# for formatting changes. - var indentationOptions = new RazorIndentationOptions( - UseTabs: !context.Options.InsertSpaces, - TabSize: context.Options.TabSize, - IndentationSize: context.Options.TabSize); - var autoFormattingOptions = new RazorAutoFormattingOptions( - formatOnReturn: true, formatOnTyping: true, formatOnSemicolon: true, formatOnCloseBrace: true); - + var formattingChanges = await RazorCSharpFormattingInteractionService.GetFormattingChangesAsync( context.CSharpWorkspaceDocument, typedChar: context.TriggerCharacter, projectedIndex, - indentationOptions, - autoFormattingOptions, + context.Options.GetIndentationOptions(), + _globalOptions.GetAutoFormattingOptions(), indentStyle: CodeAnalysis.Formatting.FormattingOptions.IndentStyle.Smart, cancellationToken).ConfigureAwait(false); diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Formatting/FormattingOptionsExtensions.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Formatting/FormattingOptionsExtensions.cs new file mode 100644 index 00000000000..4c05cebc667 --- /dev/null +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Formatting/FormattingOptionsExtensions.cs @@ -0,0 +1,17 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT license. See License.txt in the project root for license information. + +using Microsoft.CodeAnalysis.ExternalAccess.Razor; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; + +namespace Microsoft.AspNetCore.Razor.LanguageServer.Formatting +{ + internal static class FormattingOptionsExtensions + { + public static RazorIndentationOptions GetIndentationOptions(this FormattingOptions options) + => new( + UseTabs: !options.InsertSpaces, + TabSize: options.TabSize, + IndentationSize: options.TabSize); + } +} diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Formatting/FormattingLanguageServerClient.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Formatting/FormattingLanguageServerClient.cs index 66149ac3404..3a8fba26d17 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Formatting/FormattingLanguageServerClient.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Formatting/FormattingLanguageServerClient.cs @@ -17,7 +17,7 @@ using Microsoft.AspNetCore.Razor.LanguageServer.Protocol; using Microsoft.AspNetCore.Razor.LanguageServer.Test.Common; using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.Formatting; +using Microsoft.CodeAnalysis.ExternalAccess.Razor; using Microsoft.CodeAnalysis.Razor.Workspaces.Extensions; using Microsoft.CodeAnalysis.Text; using Microsoft.VisualStudio.Text; @@ -36,7 +36,6 @@ using OmniSharp.Extensions.LanguageServer.Protocol.Server; using OmniSharp.Extensions.LanguageServer.Protocol.Server.WorkDone; using Xunit; -using FormattingOptions = OmniSharp.Extensions.LanguageServer.Protocol.Models.FormattingOptions; namespace Microsoft.AspNetCore.Razor.LanguageServer.Formatting { @@ -71,7 +70,7 @@ public void AddCodeDocument(RazorCodeDocument codeDocument) _documents.TryAdd("/" + path, codeDocument); } - private RazorDocumentFormattingResponse Format(DocumentOnTypeFormattingParams @params) + private RazorDocumentFormattingResponse Format() { var response = new RazorDocumentFormattingResponse(); @@ -150,14 +149,13 @@ private RazorDocumentFormattingResponse Format(RazorDocumentRangeFormattingParam throw new InvalidOperationException("We shouldn't be asked to format Razor language kind."); } - var options = @params.Options; var response = new RazorDocumentFormattingResponse(); if (@params.Kind == RazorLanguageKind.CSharp) { var codeDocument = _documents[@params.HostDocumentFilePath]; var csharpSourceText = codeDocument.GetCSharpSourceText(); - var csharpDocument = GetCSharpDocument(codeDocument, @params.Options); + var csharpDocument = GetCSharpDocument(codeDocument); if (!csharpDocument.TryGetSyntaxRoot(out var root)) { throw new InvalidOperationException("Couldn't get syntax root."); @@ -165,7 +163,10 @@ private RazorDocumentFormattingResponse Format(RazorDocumentRangeFormattingParam var spanToFormat = @params.ProjectedRange.AsTextSpan(csharpSourceText); - var changes = Formatter.GetFormattedTextChanges(root, spanToFormat, csharpDocument.Project.Solution.Workspace); + var services = csharpDocument.Project.Solution.Workspace.Services; + var options = @params.Options.GetIndentationOptions(); + var changes = RazorCSharpFormattingInteractionService.GetFormattedTextChanges( + services, root, spanToFormat, options, CancellationToken.None); response.Edits = changes.Select(c => c.AsTextEdit(csharpSourceText)).ToArray(); } @@ -204,15 +205,9 @@ public TextEdit AsTextEdit(SourceText sourceText) } } - private static Document GetCSharpDocument(RazorCodeDocument codeDocument, FormattingOptions options) + private static Document GetCSharpDocument(RazorCodeDocument codeDocument) { var adhocWorkspace = new AdhocWorkspace(); - var csharpOptions = adhocWorkspace.Options - .WithChangedOption(CodeAnalysis.Formatting.FormattingOptions.TabSize, LanguageNames.CSharp, (int)options.TabSize) - .WithChangedOption(CodeAnalysis.Formatting.FormattingOptions.IndentationSize, LanguageNames.CSharp, (int)options.TabSize) - .WithChangedOption(CodeAnalysis.Formatting.FormattingOptions.UseTabs, LanguageNames.CSharp, !options.InsertSpaces); - adhocWorkspace.TryApplyChanges(adhocWorkspace.CurrentSolution.WithOptions(csharpOptions)); - var project = adhocWorkspace.AddProject("TestProject", LanguageNames.CSharp); var csharpSourceText = codeDocument.GetCSharpSourceText(); var csharpDocument = adhocWorkspace.AddDocument(project.Id, "TestDocument", csharpSourceText); @@ -265,10 +260,10 @@ public override Task SendRequestAsync(string method, return Task.FromResult(Convert(response)); } - else if (@params is DocumentOnTypeFormattingParams onTypeFormattingParams && + else if (@params is DocumentOnTypeFormattingParams && string.Equals(method, "textDocument/onTypeFormatting", StringComparison.Ordinal)) { - var response = Format(onTypeFormattingParams); + var response = Format(); return Task.FromResult(Convert(response)); } diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Formatting/FormattingTestBase.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Formatting/FormattingTestBase.cs index 0df397d1dcf..55a534cf84a 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Formatting/FormattingTestBase.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Formatting/FormattingTestBase.cs @@ -17,6 +17,7 @@ using Microsoft.AspNetCore.Razor.LanguageServer.Test; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Razor; +using Microsoft.CodeAnalysis.ExternalAccess.Razor; using Microsoft.CodeAnalysis.Razor.ProjectSystem; using Microsoft.CodeAnalysis.Razor.Serialization; using Microsoft.CodeAnalysis.Razor.Workspaces.Extensions; @@ -221,19 +222,22 @@ private RazorFormattingService CreateFormattingService(RazorCodeDocument codeDoc var dispatcher = new LSPProjectSnapshotManagerDispatcher(LoggerFactory); var versionCache = new DefaultDocumentVersionCache(dispatcher); + var workspaceFactory = TestAdhocWorkspaceFactory.Instance; + var globalOptions = RazorGlobalOptions.GetGlobalOptions(workspaceFactory.Create()); + var client = new FormattingLanguageServerClient(); client.AddCodeDocument(codeDocument); var passes = new List() { new HtmlFormattingPass(mappingService, FilePathNormalizer, client, versionCache, LoggerFactory), new CSharpFormattingPass(mappingService, FilePathNormalizer, client, LoggerFactory), - new CSharpOnTypeFormattingPass(mappingService, FilePathNormalizer, client, LoggerFactory), + new CSharpOnTypeFormattingPass(mappingService, FilePathNormalizer, client, globalOptions, LoggerFactory), new RazorFormattingPass(mappingService, FilePathNormalizer, client, LoggerFactory), new FormattingDiagnosticValidationPass(mappingService, FilePathNormalizer, client, LoggerFactory), new FormattingContentValidationPass(mappingService, FilePathNormalizer, client, LoggerFactory), }; - return new DefaultRazorFormattingService(passes, LoggerFactory, TestAdhocWorkspaceFactory.Instance); + return new DefaultRazorFormattingService(passes, LoggerFactory, workspaceFactory); } private static SourceText ApplyEdits(SourceText source, TextEdit[] edits) From 4e25c1d3259a3c3828091674fc3eccf8730c3c0b Mon Sep 17 00:00:00 2001 From: David Wengier Date: Thu, 4 Jul 2024 09:01:02 +1000 Subject: [PATCH 002/176] Unskip bound attribute test --- .../GoToDefinitionTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Razor/test/Microsoft.VisualStudio.Razor.IntegrationTests/GoToDefinitionTests.cs b/src/Razor/test/Microsoft.VisualStudio.Razor.IntegrationTests/GoToDefinitionTests.cs index a70cb0f3638..4fa2dbdf4fc 100644 --- a/src/Razor/test/Microsoft.VisualStudio.Razor.IntegrationTests/GoToDefinitionTests.cs +++ b/src/Razor/test/Microsoft.VisualStudio.Razor.IntegrationTests/GoToDefinitionTests.cs @@ -292,7 +292,7 @@ await TestServices.SolutionExplorer.AddFileAsync(RazorProjectConstants.BlazorPro await TestServices.Editor.WaitForCurrentLineTextAsync("public string FieldName { get; set; }", ControlledHangMitigatingCancellationToken); } - [ConditionalSkipIdeFact(Issue = "Flaky after multitarget work")] + [IdeFact] public async Task GoToDefinition_ComponentAttribute_BoundAttribute() { // Create the files From 254d9dee6d330950ee974afa3f18aa12023d23e3 Mon Sep 17 00:00:00 2001 From: David Wengier Date: Thu, 4 Jul 2024 15:58:24 +1000 Subject: [PATCH 003/176] Clean up code actions code --- .../AddUsingsCodeActionProviderHelper.cs | 2 +- .../CSharp/CSharpCodeActionResolver.cs | 6 +- .../CSharp/DefaultCSharpCodeActionResolver.cs | 39 ++---------- .../TypeAccessibilityCodeActionProvider.cs | 14 +---- ...mattedRemappingCSharpCodeActionResolver.cs | 31 +++------- .../CodeActions/CodeActionEndpoint.cs | 19 +++--- .../CodeActions/CodeActionResolveEndpoint.cs | 53 +++------------- .../Html/DefaultHtmlCodeActionProvider.cs | 9 +-- .../Html/DefaultHtmlCodeActionResolver.cs | 39 ++---------- .../Html/HtmlCodeActionResolver.cs | 6 +- .../Models/AddUsingsCodeActionParams.cs | 2 + .../Models/CodeActionExtensions.cs | 10 ---- .../Models/CreateComponentCodeActionParams.cs | 1 + .../Models/GenerateMethodCodeActionParams.cs | 2 +- .../Models/RazorCodeActionResolutionParams.cs | 2 +- .../Models/RazorVSInternalCodeAction.cs | 2 +- .../Razor/AddUsingsCodeActionResolver.cs | 35 +++-------- .../CodeActions/Razor/CodeBlockService.cs | 7 ++- ...omponentAccessibilityCodeActionProvider.cs | 39 +++++------- .../CreateComponentCodeActionResolver.cs | 18 ++---- .../ExtractToCodeBehindCodeActionProvider.cs | 28 ++------- .../ExtractToCodeBehindCodeActionResolver.cs | 60 +++++++++---------- .../Razor/GenerateMethodCodeActionProvider.cs | 12 ++-- .../Razor/GenerateMethodCodeActionResolver.cs | 60 ++++++++----------- .../CodeActions/RazorCodeActionContext.cs | 41 +++++-------- 25 files changed, 156 insertions(+), 381 deletions(-) diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/AddUsingsCodeActionProviderHelper.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/AddUsingsCodeActionProviderHelper.cs index 0010790ebaa..d60ea8bc994 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/AddUsingsCodeActionProviderHelper.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/AddUsingsCodeActionProviderHelper.cs @@ -48,7 +48,7 @@ public static async Task GetUsingStatementEditsAsync(RazorCodeDocume edits.AddRange(workspaceEdit.DocumentChanges!.Value.First.First().Edits); } - return edits.ToArray(); + return [.. edits]; } private static async Task> FindUsingDirectiveStringsAsync(SourceText originalCSharpText, CancellationToken cancellationToken) diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CSharp/CSharpCodeActionResolver.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CSharp/CSharpCodeActionResolver.cs index 6fb3a635b2b..bb2b1c3b5d9 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CSharp/CSharpCodeActionResolver.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CSharp/CSharpCodeActionResolver.cs @@ -5,10 +5,6 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer.CodeActions; -internal abstract class CSharpCodeActionResolver : BaseDelegatedCodeActionResolver +internal abstract class CSharpCodeActionResolver(IClientConnection clientConnection) : BaseDelegatedCodeActionResolver(clientConnection) { - public CSharpCodeActionResolver(IClientConnection clientConnection) - : base(clientConnection) - { - } } diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CSharp/DefaultCSharpCodeActionResolver.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CSharp/DefaultCSharpCodeActionResolver.cs index 692c9525d0a..9e62f694a04 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CSharp/DefaultCSharpCodeActionResolver.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CSharp/DefaultCSharpCodeActionResolver.cs @@ -16,7 +16,10 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer.CodeActions; -internal sealed class DefaultCSharpCodeActionResolver : CSharpCodeActionResolver +internal sealed class DefaultCSharpCodeActionResolver( + IDocumentContextFactory documentContextFactory, + IClientConnection clientConnection, + IRazorFormattingService razorFormattingService) : CSharpCodeActionResolver(clientConnection) { // Usually when we need to format code, we utilize the formatting options provided // by the platform. However, we aren't provided such options in the case of code actions @@ -33,28 +36,8 @@ internal sealed class DefaultCSharpCodeActionResolver : CSharpCodeActionResolver }, }; - private readonly IDocumentContextFactory _documentContextFactory; - private readonly IRazorFormattingService _razorFormattingService; - - public DefaultCSharpCodeActionResolver( - IDocumentContextFactory documentContextFactory, - IClientConnection clientConnection, - IRazorFormattingService razorFormattingService) - : base(clientConnection) - { - if (documentContextFactory is null) - { - throw new ArgumentNullException(nameof(documentContextFactory)); - } - - if (razorFormattingService is null) - { - throw new ArgumentNullException(nameof(razorFormattingService)); - } - - _documentContextFactory = documentContextFactory; - _razorFormattingService = razorFormattingService; - } + private readonly IDocumentContextFactory _documentContextFactory = documentContextFactory; + private readonly IRazorFormattingService _razorFormattingService = razorFormattingService; public override string Action => LanguageServerConstants.CodeActions.Default; @@ -63,16 +46,6 @@ public async override Task ResolveAsync( CodeAction codeAction, CancellationToken cancellationToken) { - if (csharpParams is null) - { - throw new ArgumentNullException(nameof(csharpParams)); - } - - if (codeAction is null) - { - throw new ArgumentNullException(nameof(codeAction)); - } - if (!_documentContextFactory.TryCreateForOpenDocument(csharpParams.RazorFileIdentifier, out var documentContext)) { return codeAction; diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CSharp/TypeAccessibilityCodeActionProvider.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CSharp/TypeAccessibilityCodeActionProvider.cs index 87f76c757c1..7763a850688 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CSharp/TypeAccessibilityCodeActionProvider.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CSharp/TypeAccessibilityCodeActionProvider.cs @@ -41,22 +41,12 @@ internal sealed class TypeAccessibilityCodeActionProvider : ICSharpCodeActionPro IEnumerable codeActions, CancellationToken cancellationToken) { - if (context is null) - { - throw new ArgumentNullException(nameof(context)); - } - - if (codeActions is null) - { - throw new ArgumentNullException(nameof(codeActions)); - } - if (context.Request?.Context?.Diagnostics is null) { return SpecializedTasks.AsNullable(SpecializedTasks.EmptyReadOnlyList()); } - if (codeActions is null || !codeActions.Any()) + if (!codeActions.Any()) { return SpecializedTasks.AsNullable(SpecializedTasks.EmptyReadOnlyList()); } @@ -276,7 +266,7 @@ private static RazorVSInternalCodeAction CreateFQNCodeAction( var fqnWorkspaceEditDocumentChange = new TextDocumentEdit() { TextDocument = codeDocumentIdentifier, - Edits = new[] { fqnTextEdit }, + Edits = [fqnTextEdit], }; var fqnWorkspaceEdit = new WorkspaceEdit() diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CSharp/UnformattedRemappingCSharpCodeActionResolver.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CSharp/UnformattedRemappingCSharpCodeActionResolver.cs index a7f33f3d93c..df9aaf7fe45 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CSharp/UnformattedRemappingCSharpCodeActionResolver.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CSharp/UnformattedRemappingCSharpCodeActionResolver.cs @@ -20,20 +20,13 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer.CodeActions; /// /// Resolves and remaps the code action, without running formatting passes. /// -internal sealed class UnformattedRemappingCSharpCodeActionResolver : CSharpCodeActionResolver +internal sealed class UnformattedRemappingCSharpCodeActionResolver( + IDocumentContextFactory documentContextFactory, + IClientConnection clientConnection, + IRazorDocumentMappingService documentMappingService) : CSharpCodeActionResolver(clientConnection) { - private readonly IDocumentContextFactory _documentContextFactory; - private readonly IRazorDocumentMappingService _documentMappingService; - - public UnformattedRemappingCSharpCodeActionResolver( - IDocumentContextFactory documentContextFactory, - IClientConnection clientConnection, - IRazorDocumentMappingService documentMappingService) - : base(clientConnection) - { - _documentContextFactory = documentContextFactory ?? throw new ArgumentNullException(nameof(documentContextFactory)); - _documentMappingService = documentMappingService ?? throw new ArgumentNullException(nameof(documentMappingService)); - } + private readonly IDocumentContextFactory _documentContextFactory = documentContextFactory; + private readonly IRazorDocumentMappingService _documentMappingService = documentMappingService; public override string Action => LanguageServerConstants.CodeActions.UnformattedRemap; @@ -42,16 +35,6 @@ public async override Task ResolveAsync( CodeAction codeAction, CancellationToken cancellationToken) { - if (csharpParams is null) - { - throw new ArgumentNullException(nameof(csharpParams)); - } - - if (codeAction is null) - { - throw new ArgumentNullException(nameof(codeAction)); - } - cancellationToken.ThrowIfCancellationRequested(); if (!_documentContextFactory.TryCreateForOpenDocument(csharpParams.RazorFileIdentifier, out var documentContext)) @@ -112,7 +95,7 @@ public async override Task ResolveAsync( new TextDocumentEdit() { TextDocument = codeDocumentIdentifier, - Edits = new[] { textEdit }, + Edits = [textEdit], } }, }; diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CodeActionEndpoint.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CodeActionEndpoint.cs index fe4609a615f..1872fb25a94 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CodeActionEndpoint.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CodeActionEndpoint.cs @@ -58,11 +58,6 @@ internal sealed class CodeActionEndpoint( public async Task[]?> HandleRequestAsync(VSCodeActionParams request, RazorRequestContext requestContext, CancellationToken cancellationToken) { - if (request is null) - { - throw new ArgumentNullException(nameof(request)); - } - var documentContext = requestContext.DocumentContext; if (documentContext is null) { @@ -127,12 +122,12 @@ public void ApplyCapabilities(VSInternalServerCapabilities serverCapabilities, V serverCapabilities.CodeActionProvider = new CodeActionOptions { - CodeActionKinds = new[] - { + CodeActionKinds = + [ CodeActionKind.RefactorExtract, CodeActionKind.QuickFix, CodeActionKind.Refactor - }, + ], ResolveProvider = true, }; } @@ -186,13 +181,13 @@ private async Task> GetDelegatedCodeAc // No point delegating if we're in a Razor context if (languageKind == RazorLanguageKind.Razor) { - return ImmutableArray.Empty; + return []; } var codeActions = await GetCodeActionsFromLanguageServerAsync(languageKind, documentContext, context, correlationId, cancellationToken).ConfigureAwait(false); if (codeActions is not [_, ..]) { - return ImmutableArray.Empty; + return []; } IEnumerable providers; @@ -268,7 +263,7 @@ internal async Task GetCodeActionsFromLanguageServe // For C# we have to map the ranges to the generated document if (!_documentMappingService.TryMapToGeneratedDocumentRange(context.CodeDocument.GetCSharpDocument(), context.Request.Range, out var projectedRange)) { - return Array.Empty(); + return []; } var newContext = context.Request.Context; @@ -301,7 +296,7 @@ internal async Task GetCodeActionsFromLanguageServe { _telemetryReporter?.ReportFault(e, "Error getting code actions from delegate language server for {languageKind}", languageKind); _logger.LogError(e, $"Error getting code actions from delegate language server for {languageKind}"); - return Array.Empty(); + return []; } } diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CodeActionResolveEndpoint.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CodeActionResolveEndpoint.cs index 3892f546301..1744a69d2a8 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CodeActionResolveEndpoint.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CodeActionResolveEndpoint.cs @@ -17,55 +17,21 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer.CodeActions; [RazorLanguageServerEndpoint(Methods.CodeActionResolveName)] -internal sealed class CodeActionResolveEndpoint : IRazorDocumentlessRequestHandler +internal sealed class CodeActionResolveEndpoint( + IEnumerable razorCodeActionResolvers, + IEnumerable csharpCodeActionResolvers, + IEnumerable htmlCodeActionResolvers, + ILoggerFactory loggerFactory) : IRazorDocumentlessRequestHandler { - private readonly ImmutableDictionary _razorCodeActionResolvers; - private readonly ImmutableDictionary _csharpCodeActionResolvers; - private readonly ImmutableDictionary _htmlCodeActionResolvers; - private readonly ILogger _logger; + private readonly ImmutableDictionary _razorCodeActionResolvers = CreateResolverMap(razorCodeActionResolvers); + private readonly ImmutableDictionary _csharpCodeActionResolvers = CreateResolverMap(csharpCodeActionResolvers); + private readonly ImmutableDictionary _htmlCodeActionResolvers = CreateResolverMap(htmlCodeActionResolvers); + private readonly ILogger _logger = loggerFactory.GetOrCreateLogger(); public bool MutatesSolutionState => false; - public CodeActionResolveEndpoint( - IEnumerable razorCodeActionResolvers, - IEnumerable csharpCodeActionResolvers, - IEnumerable htmlCodeActionResolvers, - ILoggerFactory loggerFactory) - { - if (razorCodeActionResolvers is null) - { - throw new ArgumentNullException(nameof(razorCodeActionResolvers)); - } - - if (htmlCodeActionResolvers is null) - { - throw new ArgumentNullException(nameof(htmlCodeActionResolvers)); - } - - if (csharpCodeActionResolvers is null) - { - throw new ArgumentNullException(nameof(csharpCodeActionResolvers)); - } - - if (loggerFactory is null) - { - throw new ArgumentNullException(nameof(loggerFactory)); - } - - _logger = loggerFactory.GetOrCreateLogger(); - - _razorCodeActionResolvers = CreateResolverMap(razorCodeActionResolvers); - _csharpCodeActionResolvers = CreateResolverMap(csharpCodeActionResolvers); - _htmlCodeActionResolvers = CreateResolverMap(htmlCodeActionResolvers); - } - public async Task HandleRequestAsync(CodeAction request, RazorRequestContext requestContext, CancellationToken cancellationToken) { - if (request is null) - { - throw new ArgumentNullException(nameof(request)); - } - if (request.Data is not JsonElement paramsObj) { _logger.LogError($"Invalid CodeAction Received '{request.Title}'."); @@ -73,7 +39,6 @@ public async Task HandleRequestAsync(CodeAction request, RazorReques } var resolutionParams = paramsObj.Deserialize(); - if (resolutionParams is null) { throw new ArgumentOutOfRangeException($"request.Data should be convertible to {nameof(RazorCodeActionResolutionParams)}"); diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Html/DefaultHtmlCodeActionProvider.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Html/DefaultHtmlCodeActionProvider.cs index 4fb7ee09b92..6c441da4187 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Html/DefaultHtmlCodeActionProvider.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Html/DefaultHtmlCodeActionProvider.cs @@ -13,14 +13,9 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer.CodeActions; -internal sealed class DefaultHtmlCodeActionProvider : IHtmlCodeActionProvider +internal sealed class DefaultHtmlCodeActionProvider(IRazorDocumentMappingService documentMappingService) : IHtmlCodeActionProvider { - private readonly IRazorDocumentMappingService _documentMappingService; - - public DefaultHtmlCodeActionProvider(IRazorDocumentMappingService documentMappingService) - { - _documentMappingService = documentMappingService; - } + private readonly IRazorDocumentMappingService _documentMappingService = documentMappingService; public async Task?> ProvideAsync( RazorCodeActionContext context, diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Html/DefaultHtmlCodeActionResolver.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Html/DefaultHtmlCodeActionResolver.cs index 8aaaefadca0..604f02a3458 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Html/DefaultHtmlCodeActionResolver.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Html/DefaultHtmlCodeActionResolver.cs @@ -13,30 +13,13 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer.CodeActions; -internal sealed class DefaultHtmlCodeActionResolver : HtmlCodeActionResolver +internal sealed class DefaultHtmlCodeActionResolver( + IDocumentContextFactory documentContextFactory, + IClientConnection clientConnection, + IRazorDocumentMappingService documentMappingService) : HtmlCodeActionResolver(clientConnection) { - private readonly IDocumentContextFactory _documentContextFactory; - private readonly IRazorDocumentMappingService _documentMappingService; - - public DefaultHtmlCodeActionResolver( - IDocumentContextFactory documentContextFactory, - IClientConnection clientConnection, - IRazorDocumentMappingService documentMappingService) - : base(clientConnection) - { - if (documentContextFactory is null) - { - throw new ArgumentNullException(nameof(documentContextFactory)); - } - - if (documentMappingService is null) - { - throw new ArgumentNullException(nameof(documentMappingService)); - } - - _documentContextFactory = documentContextFactory; - _documentMappingService = documentMappingService; - } + private readonly IDocumentContextFactory _documentContextFactory = documentContextFactory; + private readonly IRazorDocumentMappingService _documentMappingService = documentMappingService; public override string Action => LanguageServerConstants.CodeActions.Default; @@ -45,16 +28,6 @@ public async override Task ResolveAsync( CodeAction codeAction, CancellationToken cancellationToken) { - if (resolveParams is null) - { - throw new ArgumentNullException(nameof(resolveParams)); - } - - if (codeAction is null) - { - throw new ArgumentNullException(nameof(codeAction)); - } - if (!_documentContextFactory.TryCreateForOpenDocument(resolveParams.RazorFileIdentifier, out var documentContext)) { return codeAction; diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Html/HtmlCodeActionResolver.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Html/HtmlCodeActionResolver.cs index bb7c517b17d..ad685ba8291 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Html/HtmlCodeActionResolver.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Html/HtmlCodeActionResolver.cs @@ -5,10 +5,6 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer.CodeActions; -internal abstract class HtmlCodeActionResolver : BaseDelegatedCodeActionResolver +internal abstract class HtmlCodeActionResolver(IClientConnection clientConnection) : BaseDelegatedCodeActionResolver(clientConnection) { - public HtmlCodeActionResolver(IClientConnection clientConnection) - : base(clientConnection) - { - } } diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Models/AddUsingsCodeActionParams.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Models/AddUsingsCodeActionParams.cs index 9c9fe60a538..4f1bf25bcae 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Models/AddUsingsCodeActionParams.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Models/AddUsingsCodeActionParams.cs @@ -11,8 +11,10 @@ internal sealed class AddUsingsCodeActionParams { [JsonPropertyName("uri")] public required Uri Uri { get; set; } + [JsonPropertyName("namespace")] public required string Namespace { get; set; } + [JsonPropertyName("additionalEdit")] public TextDocumentEdit? AdditionalEdit { get; set; } } diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Models/CodeActionExtensions.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Models/CodeActionExtensions.cs index 47af3510f70..8d10ca7bb71 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Models/CodeActionExtensions.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Models/CodeActionExtensions.cs @@ -50,16 +50,6 @@ public static RazorVSInternalCodeAction WrapResolvableCodeAction( string language = LanguageServerConstants.CodeActions.Languages.CSharp, bool isOnAllowList = true) { - if (razorCodeAction is null) - { - throw new ArgumentNullException(nameof(razorCodeAction)); - } - - if (context is null) - { - throw new ArgumentNullException(nameof(context)); - } - var resolveParams = new CodeActionResolveParams() { Data = razorCodeAction.Data, diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Models/CreateComponentCodeActionParams.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Models/CreateComponentCodeActionParams.cs index 13e2ea5095c..6fcd3c10a66 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Models/CreateComponentCodeActionParams.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Models/CreateComponentCodeActionParams.cs @@ -10,6 +10,7 @@ internal sealed class CreateComponentCodeActionParams { [JsonPropertyName("uri")] public required Uri Uri { get; set; } + [JsonPropertyName("path")] public required string Path { get; set; } } diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Models/GenerateMethodCodeActionParams.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Models/GenerateMethodCodeActionParams.cs index e5a6c0020cc..317c4568e2c 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Models/GenerateMethodCodeActionParams.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Models/GenerateMethodCodeActionParams.cs @@ -6,7 +6,7 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer.CodeActions.Models; -internal class GenerateMethodCodeActionParams +internal sealed class GenerateMethodCodeActionParams { [JsonPropertyName("uri")] public required Uri Uri { get; set; } diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Models/RazorCodeActionResolutionParams.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Models/RazorCodeActionResolutionParams.cs index 5d47f9828db..149285fb64b 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Models/RazorCodeActionResolutionParams.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Models/RazorCodeActionResolutionParams.cs @@ -6,7 +6,7 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer.CodeActions.Models; -internal class RazorCodeActionResolutionParams +internal sealed class RazorCodeActionResolutionParams { [JsonPropertyName("action")] public required string Action { get; set; } diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Models/RazorVSInternalCodeAction.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Models/RazorVSInternalCodeAction.cs index cbd71e5e47e..dc53eff8e46 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Models/RazorVSInternalCodeAction.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Models/RazorVSInternalCodeAction.cs @@ -8,7 +8,7 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer.CodeActions.Models; [DataContract] -internal class RazorVSInternalCodeAction : VSInternalCodeAction +internal sealed class RazorVSInternalCodeAction : VSInternalCodeAction { [JsonPropertyName("name")] [DataMember(Name = "name")] diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/AddUsingsCodeActionResolver.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/AddUsingsCodeActionResolver.cs index f679b1566a5..99daa0c1982 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/AddUsingsCodeActionResolver.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/AddUsingsCodeActionResolver.cs @@ -21,14 +21,9 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer.CodeActions; -internal sealed class AddUsingsCodeActionResolver : IRazorCodeActionResolver +internal sealed class AddUsingsCodeActionResolver(IDocumentContextFactory documentContextFactory) : IRazorCodeActionResolver { - private readonly IDocumentContextFactory _documentContextFactory; - - public AddUsingsCodeActionResolver(IDocumentContextFactory documentContextFactory) - { - _documentContextFactory = documentContextFactory ?? throw new ArgumentNullException(nameof(documentContextFactory)); - } + private readonly IDocumentContextFactory _documentContextFactory = documentContextFactory; public string Action => LanguageServerConstants.CodeActions.AddUsing; @@ -47,12 +42,6 @@ public AddUsingsCodeActionResolver(IDocumentContextFactory documentContextFactor var documentSnapshot = documentContext.Snapshot; - var text = await documentSnapshot.GetTextAsync().ConfigureAwait(false); - if (text is null) - { - return null; - } - var codeDocument = await documentSnapshot.GetGeneratedOutputAsync().ConfigureAwait(false); if (codeDocument.IsUnsupported()) { @@ -150,7 +139,7 @@ private static TextDocumentEdit GenerateSingleUsingEditsInterpolated( return new TextDocumentEdit() { TextDocument = codeDocumentIdentifier, - Edits = edits.ToArray(), + Edits = [.. edits] }; } @@ -178,14 +167,14 @@ private static TextDocumentEdit GenerateSingleUsingEditsAtTop( return new TextDocumentEdit { TextDocument = codeDocumentIdentifier, - Edits = new[] - { + Edits = + [ new TextEdit() { NewText = string.Concat($"@using {newUsingNamespace}{Environment.NewLine}"), Range = range, } - } + ] }; } @@ -234,15 +223,9 @@ private static bool IsNamespaceOrPageDirective(SyntaxNode node) return false; } - private readonly struct RazorUsingDirective + private readonly struct RazorUsingDirective(RazorDirectiveSyntax node, AddImportChunkGenerator statement) { - readonly public RazorDirectiveSyntax Node { get; } - readonly public AddImportChunkGenerator Statement { get; } - - public RazorUsingDirective(RazorDirectiveSyntax node, AddImportChunkGenerator statement) - { - Node = node; - Statement = statement; - } + public readonly RazorDirectiveSyntax Node { get; } = node; + public readonly AddImportChunkGenerator Statement { get; } = statement; } } diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/CodeBlockService.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/CodeBlockService.cs index 0cea8fd3145..7b20beeda4b 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/CodeBlockService.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/CodeBlockService.cs @@ -80,7 +80,7 @@ public static TextEdit[] CreateFormattedTextEdit(RazorCodeDocument code, string Range = eofRange }; - return new TextEdit[] { start, method, end }; + return [start, method, end]; } // A well-formed @code block exists, generate the method within it. @@ -115,7 +115,7 @@ public static TextEdit[] CreateFormattedTextEdit(RazorCodeDocument code, string NewText = formattedGeneratedMethod }; - return new TextEdit[] { edit }; + return [edit]; } private static string FormatMethodInCodeBlock( @@ -171,5 +171,6 @@ private static string FormatMethodInCodeBlock( /// /// The line to check. /// true if the line is empty, otherwise false. - private static bool IsLineEmpty(TextLine textLine) => textLine.Start == textLine.End; + private static bool IsLineEmpty(TextLine textLine) + => textLine.Start == textLine.End; } diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/ComponentAccessibilityCodeActionProvider.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/ComponentAccessibilityCodeActionProvider.cs index 23c0c992019..e05a743feb8 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/ComponentAccessibilityCodeActionProvider.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/ComponentAccessibilityCodeActionProvider.cs @@ -85,13 +85,8 @@ private static bool IsApplicableTag(IStartTagSyntaxNode startTag) return true; } - private void AddCreateComponentFromTag(RazorCodeActionContext context, IStartTagSyntaxNode startTag, List container) + private static void AddCreateComponentFromTag(RazorCodeActionContext context, IStartTagSyntaxNode startTag, List container) { - if (context is null) - { - return; - } - if (!context.SupportsFileCreation) { return; @@ -126,7 +121,7 @@ private void AddCreateComponentFromTag(RazorCodeActionContext context, IStartTag container.Add(codeAction); } - private async Task AddComponentAccessFromTagAsync(RazorCodeActionContext context, IStartTagSyntaxNode startTag, List container, CancellationToken cancellationToken) + private static async Task AddComponentAccessFromTagAsync(RazorCodeActionContext context, IStartTagSyntaxNode startTag, List container, CancellationToken cancellationToken) { var haveAddedNonQualifiedFix = false; @@ -158,18 +153,18 @@ private async Task AddComponentAccessFromTagAsync(RazorCodeActionContext context // If they have a typo, eg and we've offered them above, then it would be odd to offer // them as well. We will offer them though, if it // exists. - if (!haveAddedNonQualifiedFix || !tagHelperPair._caseInsensitiveMatch) + if (!haveAddedNonQualifiedFix || !tagHelperPair.CaseInsensitiveMatch) { // if fqn contains a generic typeparam, we should strip it out. Otherwise, replacing tag name will leave generic parameters in razor code, which are illegal // e.g. -> /> - var fullyQualifiedName = DefaultRazorComponentSearchEngine.RemoveGenericContent(tagHelperPair._short.Name.AsMemory()).ToString(); + var fullyQualifiedName = DefaultRazorComponentSearchEngine.RemoveGenericContent(tagHelperPair.Short.Name.AsMemory()).ToString(); // If the match was case insensitive, then see if we can work out a new tag name to use as part of adding a using statement TextDocumentEdit? additionalEdit = null; string? newTagName = null; - if (tagHelperPair._caseInsensitiveMatch) + if (tagHelperPair.CaseInsensitiveMatch) { - newTagName = tagHelperPair._short.TagMatchingRules.FirstOrDefault()?.TagName; + newTagName = tagHelperPair.Short.TagMatchingRules.FirstOrDefault()?.TagName; if (newTagName is not null) { additionalEdit = CreateRenameTagEdit(context, startTag, newTagName).DocumentChanges!.Value.First().First.AssumeNotNull(); @@ -178,7 +173,7 @@ private async Task AddComponentAccessFromTagAsync(RazorCodeActionContext context // We only want to add a using statement if this was a case sensitive match, or if we were able to determine a new tag // name to give the tag. - if (!tagHelperPair._caseInsensitiveMatch || newTagName is not null) + if (!tagHelperPair.CaseInsensitiveMatch || newTagName is not null) { if (AddUsingsCodeActionProviderHelper.TryCreateAddUsingResolutionParams(fullyQualifiedName, context.Request.TextDocument.Uri, additionalEdit, out var @namespace, out var resolutionParams)) { @@ -195,7 +190,7 @@ private async Task AddComponentAccessFromTagAsync(RazorCodeActionContext context } } - private async Task> FindMatchingTagHelpersAsync(RazorCodeActionContext context, IStartTagSyntaxNode startTag, CancellationToken cancellationToken) + private static async Task> FindMatchingTagHelpersAsync(RazorCodeActionContext context, IStartTagSyntaxNode startTag, CancellationToken cancellationToken) { // Get all data necessary for matching var tagName = startTag.Name.Content; @@ -229,7 +224,7 @@ private async Task> FindMatchingTagHelpersAsync(RazorCodeAct { if (matching.TryGetValue(tagHelper.Name, out var tagHelperPair)) { - if (tagHelperPair != null && tagHelper != tagHelperPair._short) + if (tagHelperPair != null && tagHelper != tagHelperPair.Short) { tagHelperPair._fullyQualified = tagHelper; } @@ -239,7 +234,7 @@ private async Task> FindMatchingTagHelpersAsync(RazorCodeAct return new List(matching.Values); } - private bool SatisfiesRules(ImmutableArray tagMatchingRules, ReadOnlySpan tagNameWithoutPrefix, ReadOnlySpan parentTagNameWithoutPrefix, ImmutableArray> tagAttributes, out bool caseInsensitiveMatch) + private static bool SatisfiesRules(ImmutableArray tagMatchingRules, ReadOnlySpan tagNameWithoutPrefix, ReadOnlySpan parentTagNameWithoutPrefix, ImmutableArray> tagAttributes, out bool caseInsensitiveMatch) { caseInsensitiveMatch = false; @@ -308,7 +303,7 @@ private static WorkspaceEdit CreateRenameTagEdit(RazorCodeActionContext context, new TextDocumentEdit() { TextDocument = codeDocumentIdentifier, - Edits = textEdits.ToArray(), + Edits = [.. textEdits] } }, }; @@ -333,16 +328,10 @@ private static bool IsTagUnknown(IStartTagSyntaxNode startTag, RazorCodeActionCo return false; } - private class TagHelperPair + private class TagHelperPair(TagHelperDescriptor @short, bool caseInsensitiveMatch) { - public readonly TagHelperDescriptor _short; - public readonly bool _caseInsensitiveMatch; + public readonly TagHelperDescriptor Short = @short; + public readonly bool CaseInsensitiveMatch = caseInsensitiveMatch; public TagHelperDescriptor? _fullyQualified = null; - - public TagHelperPair(TagHelperDescriptor @short, bool caseInsensitiveMatch) - { - _short = @short; - _caseInsensitiveMatch = caseInsensitiveMatch; - } } } diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/CreateComponentCodeActionResolver.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/CreateComponentCodeActionResolver.cs index 0780869ae28..e3afbcfd3be 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/CreateComponentCodeActionResolver.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/CreateComponentCodeActionResolver.cs @@ -17,16 +17,10 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer.CodeActions; -internal sealed class CreateComponentCodeActionResolver : IRazorCodeActionResolver +internal sealed class CreateComponentCodeActionResolver(IDocumentContextFactory documentContextFactory, LanguageServerFeatureOptions languageServerFeatureOptions) : IRazorCodeActionResolver { - private readonly IDocumentContextFactory _documentContextFactory; - private readonly LanguageServerFeatureOptions _languageServerFeatureOptions; - - public CreateComponentCodeActionResolver(IDocumentContextFactory documentContextFactory, LanguageServerFeatureOptions languageServerFeatureOptions) - { - _documentContextFactory = documentContextFactory ?? throw new ArgumentNullException(nameof(documentContextFactory)); - _languageServerFeatureOptions = languageServerFeatureOptions ?? throw new ArgumentException(nameof(languageServerFeatureOptions)); - } + private readonly IDocumentContextFactory _documentContextFactory = documentContextFactory; + private readonly LanguageServerFeatureOptions _languageServerFeatureOptions = languageServerFeatureOptions; public string Action => LanguageServerConstants.CodeActions.CreateComponentFromTag; @@ -93,14 +87,14 @@ private static void TryAddNamespaceDirective(RazorCodeDocument codeDocument, Uri documentChanges.Add(new TextDocumentEdit { TextDocument = documentIdentifier, - Edits = new[] - { + Edits = + [ new TextEdit() { NewText = namespaceDirective.GetContent(), Range = new Range{ Start = new Position(0, 0), End = new Position(0, 0) }, } - } + ] }); } } diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/ExtractToCodeBehindCodeActionProvider.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/ExtractToCodeBehindCodeActionProvider.cs index 4b63a8d3c07..6457b46c0d6 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/ExtractToCodeBehindCodeActionProvider.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/ExtractToCodeBehindCodeActionProvider.cs @@ -20,27 +20,12 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer.CodeActions; -internal sealed class ExtractToCodeBehindCodeActionProvider : IRazorCodeActionProvider +internal sealed class ExtractToCodeBehindCodeActionProvider(ILoggerFactory loggerFactory) : IRazorCodeActionProvider { - private readonly ILogger _logger; - - public ExtractToCodeBehindCodeActionProvider(ILoggerFactory loggerFactory) - { - if (loggerFactory is null) - { - throw new ArgumentNullException(nameof(loggerFactory)); - } - - _logger = loggerFactory.GetOrCreateLogger(); - } + private readonly ILogger _logger = loggerFactory.GetOrCreateLogger(); public Task?> ProvideAsync(RazorCodeActionContext context, CancellationToken cancellationToken) { - if (context is null) - { - return SpecializedTasks.Null>(); - } - if (!context.SupportsFileCreation) { return SpecializedTasks.Null>(); @@ -64,7 +49,7 @@ public ExtractToCodeBehindCodeActionProvider(ILoggerFactory loggerFactory) return SpecializedTasks.Null>(); } - var directiveNode = owner?.Parent switch + var directiveNode = owner.Parent switch { // When the caret is '@code$$ {' or '@code$${' then tree is: // RazorDirective -> RazorDirectiveBody -> CSharpCodeBlock -> (MetaCode or TextLiteral) @@ -145,10 +130,5 @@ private static bool TryGetNamespace(RazorCodeDocument codeDocument, [NotNullWhen => codeDocument.TryComputeNamespace(fallbackToRootNamespace: true, out @namespace); private static bool HasUnsupportedChildren(Language.Syntax.SyntaxNode node) - { - return node.DescendantNodes().Any(n => - n is MarkupBlockSyntax || - n is CSharpTransitionSyntax || - n is RazorCommentBlockSyntax); - } + => node.DescendantNodes().Any(n => n is MarkupBlockSyntax or CSharpTransitionSyntax or RazorCommentBlockSyntax); } diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/ExtractToCodeBehindCodeActionResolver.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/ExtractToCodeBehindCodeActionResolver.cs index ae27499675c..4fc7b9fd4eb 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/ExtractToCodeBehindCodeActionResolver.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/ExtractToCodeBehindCodeActionResolver.cs @@ -25,23 +25,16 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer.CodeActions; -internal sealed class ExtractToCodeBehindCodeActionResolver : IRazorCodeActionResolver +internal sealed class ExtractToCodeBehindCodeActionResolver( + IDocumentContextFactory documentContextFactory, + LanguageServerFeatureOptions languageServerFeatureOptions, + IClientConnection clientConnection) : IRazorCodeActionResolver { private static readonly Workspace s_workspace = new AdhocWorkspace(); - private readonly IDocumentContextFactory _documentContextFactory; - private readonly LanguageServerFeatureOptions _languageServerFeatureOptions; - private readonly IClientConnection _clientConnection; - - public ExtractToCodeBehindCodeActionResolver( - IDocumentContextFactory documentContextFactory, - LanguageServerFeatureOptions languageServerFeatureOptions, - IClientConnection clientConnection) - { - _documentContextFactory = documentContextFactory ?? throw new ArgumentNullException(nameof(documentContextFactory)); - _languageServerFeatureOptions = languageServerFeatureOptions ?? throw new ArgumentNullException(nameof(languageServerFeatureOptions)); - _clientConnection = clientConnection ?? throw new ArgumentNullException(nameof(clientConnection)); - } + private readonly IDocumentContextFactory _documentContextFactory = documentContextFactory; + private readonly LanguageServerFeatureOptions _languageServerFeatureOptions = languageServerFeatureOptions; + private readonly IClientConnection _clientConnection = clientConnection; public string Action => LanguageServerConstants.CodeActions.ExtractToCodeBehindAction; @@ -86,10 +79,6 @@ public ExtractToCodeBehindCodeActionResolver( }.Uri; var text = await documentContext.GetSourceTextAsync(cancellationToken).ConfigureAwait(false); - if (text is null) - { - return null; - } var className = Path.GetFileNameWithoutExtension(path); var codeBlockContent = text.GetSubTextString(new CodeAnalysis.Text.TextSpan(actionParams.ExtractStart, actionParams.ExtractEnd - actionParams.ExtractStart)).Trim(); @@ -112,26 +101,30 @@ public ExtractToCodeBehindCodeActionResolver( new TextDocumentEdit { TextDocument = codeDocumentIdentifier, - Edits = new[] - { + Edits = + [ new TextEdit { NewText = string.Empty, Range = removeRange, } - }, + ], }, new TextDocumentEdit { TextDocument = codeBehindDocumentIdentifier, - Edits = new[] - { + Edits = + [ new TextEdit { NewText = codeBehindContent, - Range = new Range { Start = new Position(0, 0), End = new Position(0, 0) }, + Range = new Range + { + Start = new Position(0, 0), + End = new Position(0, 0) + }, } - }, + ], } }; @@ -150,17 +143,17 @@ public ExtractToCodeBehindCodeActionResolver( /// A non-existent file path with the same base name and a codebehind extension. private static string GenerateCodeBehindPath(string path) { + var baseFileName = Path.GetFileNameWithoutExtension(path); + var extension = Path.GetExtension(path); + var directoryName = Path.GetDirectoryName(path).AssumeNotNull(); + var n = 0; string codeBehindPath; do { var identifier = n > 0 ? n.ToString(CultureInfo.InvariantCulture) : string.Empty; // Make it look nice - var directoryName = Path.GetDirectoryName(path); - Assumes.NotNull(directoryName); - codeBehindPath = Path.Combine( - directoryName, - $"{Path.GetFileNameWithoutExtension(path)}{identifier}{Path.GetExtension(path)}.cs"); + codeBehindPath = Path.Combine(directoryName, $"{baseFileName}{identifier}{extension}.cs"); n++; } while (File.Exists(codeBehindPath)); @@ -168,13 +161,14 @@ private static string GenerateCodeBehindPath(string path) return codeBehindPath; } - private async Task GenerateCodeBehindClassAsync(CodeAnalysis.Razor.ProjectSystem.IProjectSnapshot project, Uri codeBehindUri, string className, string namespaceName, string contents, RazorCodeDocument razorCodeDocument, CancellationToken cancellationToken) + private async Task GenerateCodeBehindClassAsync(IProjectSnapshot project, Uri codeBehindUri, string className, string namespaceName, string contents, RazorCodeDocument razorCodeDocument, CancellationToken cancellationToken) { using var _ = StringBuilderPool.GetPooledObject(out var builder); var usingDirectives = razorCodeDocument .GetDocumentIntermediateNode() .FindDescendantNodes(); + foreach (var usingDirective in usingDirectives) { builder.Append("using "); @@ -219,8 +213,8 @@ private async Task GenerateCodeBehindClassAsync(CodeAnalysis.Razor.Proje { // Sadly we can't use a "real" workspace here, because we don't have access. If we use our workspace, it wouldn't have the right settings // for C# formatting, only Razor formatting, and we have no access to Roslyn's real workspace, since it could be in another process. - var node = await CSharpSyntaxTree.ParseText(newFileContent).GetRootAsync(cancellationToken).ConfigureAwait(false); - node = Formatter.Format(node, s_workspace); + var node = await CSharpSyntaxTree.ParseText(newFileContent, cancellationToken: cancellationToken).GetRootAsync(cancellationToken).ConfigureAwait(false); + node = Formatter.Format(node, s_workspace, cancellationToken: cancellationToken); return node.ToFullString(); } diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/GenerateMethodCodeActionProvider.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/GenerateMethodCodeActionProvider.cs index e89a7a35b0d..3399a4815de 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/GenerateMethodCodeActionProvider.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/GenerateMethodCodeActionProvider.cs @@ -18,7 +18,7 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer.CodeActions.Razor; -internal class GenerateMethodCodeActionProvider : IRazorCodeActionProvider +internal sealed class GenerateMethodCodeActionProvider : IRazorCodeActionProvider { public Task?> ProvideAsync(RazorCodeActionContext context, CancellationToken cancellationToken) { @@ -29,18 +29,14 @@ internal class GenerateMethodCodeActionProvider : IRazorCodeActionProvider } var syntaxTree = context.CodeDocument.GetSyntaxTree(); - var owner = syntaxTree.Root.FindToken(context.Location.AbsoluteIndex).Parent; - Assumes.NotNull(owner); + var owner = syntaxTree.Root.FindToken(context.Location.AbsoluteIndex).Parent.AssumeNotNull(); if (IsGenerateEventHandlerValid(owner, out var methodName, out var eventName)) { var uri = context.Request.TextDocument.Uri; - var codeActions = new List() - { + return Task.FromResult?>([ RazorCodeActionFactory.CreateGenerateMethod(uri, methodName, eventName), - RazorCodeActionFactory.CreateAsyncGenerateMethod(uri, methodName, eventName) - }; - return Task.FromResult?>(codeActions); + RazorCodeActionFactory.CreateAsyncGenerateMethod(uri, methodName, eventName)]); } return SpecializedTasks.Null>(); diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/GenerateMethodCodeActionResolver.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/GenerateMethodCodeActionResolver.cs index 6cf869bf21b..a928981eba7 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/GenerateMethodCodeActionResolver.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/GenerateMethodCodeActionResolver.cs @@ -25,40 +25,31 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer.CodeActions.Razor; -internal class GenerateMethodCodeActionResolver : IRazorCodeActionResolver +internal sealed class GenerateMethodCodeActionResolver( + IDocumentContextFactory documentContextFactory, + RazorLSPOptionsMonitor razorLSPOptionsMonitor, + IClientConnection clientConnection, + IRazorDocumentMappingService razorDocumentMappingService, + IRazorFormattingService razorFormattingService) : IRazorCodeActionResolver { - private readonly IDocumentContextFactory _documentContextFactory; - private readonly RazorLSPOptionsMonitor _razorLSPOptionsMonitor; - private readonly IClientConnection _clientConnection; - private readonly IRazorDocumentMappingService _documentMappingService; - private readonly IRazorFormattingService _razorFormattingService; - + private readonly IDocumentContextFactory _documentContextFactory = documentContextFactory; + private readonly RazorLSPOptionsMonitor _razorLSPOptionsMonitor = razorLSPOptionsMonitor; + private readonly IClientConnection _clientConnection = clientConnection; + private readonly IRazorDocumentMappingService _documentMappingService = razorDocumentMappingService; + private readonly IRazorFormattingService _razorFormattingService = razorFormattingService; + + private const string ReturnType = "$$ReturnType$$"; + private const string MethodName = "$$MethodName$$"; + private const string EventArgs = "$$EventArgs$$"; private static readonly string s_beginningIndents = $"{FormattingUtilities.InitialIndent}{FormattingUtilities.Indent}"; - private static readonly string s_returnType = "$$ReturnType$$"; - private static readonly string s_methodName = "$$MethodName$$"; - private static readonly string s_eventArgs = "$$EventArgs$$"; private static readonly string s_generateMethodTemplate = - $"{s_beginningIndents}private {s_returnType} {s_methodName}({s_eventArgs}){Environment.NewLine}" + + $"{s_beginningIndents}private {ReturnType} {MethodName}({EventArgs}){Environment.NewLine}" + s_beginningIndents + "{" + Environment.NewLine + $"{s_beginningIndents}{FormattingUtilities.Indent}throw new global::System.NotImplementedException();{Environment.NewLine}" + s_beginningIndents + "}"; public string Action => LanguageServerConstants.CodeActions.GenerateEventHandler; - public GenerateMethodCodeActionResolver( - IDocumentContextFactory documentContextFactory, - RazorLSPOptionsMonitor razorLSPOptionsMonitor, - IClientConnection clientConnection, - IRazorDocumentMappingService razorDocumentMappingService, - IRazorFormattingService razorFormattingService) - { - _documentContextFactory = documentContextFactory; - _razorLSPOptionsMonitor = razorLSPOptionsMonitor; - _clientConnection = clientConnection; - _documentMappingService = razorDocumentMappingService; - _razorFormattingService = razorFormattingService; - } - public async Task ResolveAsync(JsonElement data, CancellationToken cancellationToken) { var actionParams = data.Deserialize(); @@ -77,9 +68,9 @@ public GenerateMethodCodeActionResolver( var razorClassName = Path.GetFileNameWithoutExtension(uriPath); var codeBehindPath = $"{uriPath}.cs"; - if (!File.Exists(codeBehindPath) - || razorClassName is null - || !code.TryComputeNamespace(fallbackToRootNamespace: true, out var razorNamespace)) + if (!File.Exists(codeBehindPath) || + razorClassName is null || + !code.TryComputeNamespace(fallbackToRootNamespace: true, out var razorNamespace)) { return await GenerateMethodInCodeBlockAsync( code, @@ -136,13 +127,12 @@ public GenerateMethodCodeActionResolver( var result = await _clientConnection.SendRequestAsync( CustomMessageNames.RazorSimplifyMethodEndpointName, delegatedParams, - cancellationToken).ConfigureAwait(false) - ?? new TextEdit[] { edit }; + cancellationToken).ConfigureAwait(false); var codeBehindTextDocEdit = new TextDocumentEdit() { TextDocument = codeBehindTextDocumentIdentifier, - Edits = result + Edits = result ?? [edit] }; return new WorkspaceEdit() { DocumentChanges = new[] { codeBehindTextDocEdit } }; @@ -231,7 +221,7 @@ private async Task GenerateMethodInCodeBlockAsync( RazorLanguageKind.CSharp, result, formattingOptions, - CancellationToken.None).ConfigureAwait(false); + cancellationToken).ConfigureAwait(false); edits = formattedEdits; } @@ -248,10 +238,10 @@ private async Task GenerateMethodInCodeBlockAsync( private static async Task PopulateMethodSignatureAsync(VersionedDocumentContext documentContext, GenerateMethodCodeActionParams actionParams, CancellationToken cancellationToken) { - var templateWithMethodSignature = s_generateMethodTemplate.Replace(s_methodName, actionParams.MethodName); + var templateWithMethodSignature = s_generateMethodTemplate.Replace(MethodName, actionParams.MethodName); var returnType = actionParams.IsAsync ? "global::System.Threading.Tasks.Task" : "void"; - templateWithMethodSignature = templateWithMethodSignature.Replace(s_returnType, returnType); + templateWithMethodSignature = templateWithMethodSignature.Replace(ReturnType, returnType); var tagHelpers = await documentContext.Project.GetTagHelpersAsync(cancellationToken).ConfigureAwait(false); var eventTagHelper = tagHelpers @@ -260,7 +250,7 @@ private static async Task PopulateMethodSignatureAsync(VersionedDocument ? string.Empty // Couldn't find the params, generate no params instead. : $"global::{eventTagHelper.GetEventArgsType()} e"; - return templateWithMethodSignature.Replace(s_eventArgs, eventArgsType); + return templateWithMethodSignature.Replace(EventArgs, eventArgsType); } private static ClassDeclarationSyntax? GetCSharpClassDeclarationSyntax(string csharpContent, string razorNamespace, string razorClassName) diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/RazorCodeActionContext.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/RazorCodeActionContext.cs index 56bbf48e407..d5f737d51ae 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/RazorCodeActionContext.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/RazorCodeActionContext.cs @@ -9,31 +9,20 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer.CodeActions; -internal sealed class RazorCodeActionContext +internal sealed class RazorCodeActionContext( + VSCodeActionParams request, + IDocumentSnapshot documentSnapshot, + RazorCodeDocument codeDocument, + SourceLocation location, + SourceText sourceText, + bool supportsFileCreation, + bool supportsCodeActionResolve) { - public RazorCodeActionContext( - VSCodeActionParams request, - IDocumentSnapshot documentSnapshot, - RazorCodeDocument codeDocument, - SourceLocation location, - SourceText sourceText, - bool supportsFileCreation, - bool supportsCodeActionResolve) - { - Request = request ?? throw new ArgumentNullException(nameof(request)); - DocumentSnapshot = documentSnapshot ?? throw new ArgumentNullException(nameof(documentSnapshot)); - CodeDocument = codeDocument ?? throw new ArgumentNullException(nameof(codeDocument)); - Location = location; - SourceText = sourceText ?? throw new ArgumentNullException(nameof(sourceText)); - SupportsFileCreation = supportsFileCreation; - SupportsCodeActionResolve = supportsCodeActionResolve; - } - - public VSCodeActionParams Request { get; } - public IDocumentSnapshot DocumentSnapshot { get; } - public RazorCodeDocument CodeDocument { get; } - public SourceLocation Location { get; } - public SourceText SourceText { get; } - public bool SupportsFileCreation { get; } - public bool SupportsCodeActionResolve { get; } + public VSCodeActionParams Request { get; } = request; + public IDocumentSnapshot DocumentSnapshot { get; } = documentSnapshot; + public RazorCodeDocument CodeDocument { get; } = codeDocument; + public SourceLocation Location { get; } = location; + public SourceText SourceText { get; } = sourceText; + public bool SupportsFileCreation { get; } = supportsFileCreation; + public bool SupportsCodeActionResolve { get; } = supportsCodeActionResolve; } From 7731184dbe8312ef302bd9efd74ff83e5bd61a0b Mon Sep 17 00:00:00 2001 From: David Wengier Date: Thu, 4 Jul 2024 19:08:14 +1000 Subject: [PATCH 004/176] Centralize capabilities code --- .../VSInternalServerCapabilitiesExtensions.cs | 13 +++++++++++++ .../SignatureHelp/SignatureHelpEndpoint.cs | 13 +++++-------- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Hosting/VSInternalServerCapabilitiesExtensions.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Hosting/VSInternalServerCapabilitiesExtensions.cs index 62785fb5267..83b32a3dd23 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Hosting/VSInternalServerCapabilitiesExtensions.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Hosting/VSInternalServerCapabilitiesExtensions.cs @@ -40,6 +40,19 @@ public static SemanticTokensOptions EnableSemanticTokens(this SemanticTokensOpti return options; } + public static void EnableSignatureHelp(this VSInternalServerCapabilities serverCapabilities) + { + serverCapabilities.SignatureHelpProvider = new SignatureHelpOptions().EnableSignatureHelp(); + } + + public static SignatureHelpOptions EnableSignatureHelp(this SignatureHelpOptions options) + { + options.TriggerCharacters = ["(", ",", "<"]; + options.RetriggerCharacters = [">", ")"]; + + return options; + } + public static void EnableHoverProvider(this VSInternalServerCapabilities serverCapabilities) { serverCapabilities.HoverProvider = new HoverOptions() diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/SignatureHelp/SignatureHelpEndpoint.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/SignatureHelp/SignatureHelpEndpoint.cs index baa5d4b0000..657d878fc5d 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/SignatureHelp/SignatureHelpEndpoint.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/SignatureHelp/SignatureHelpEndpoint.cs @@ -1,4 +1,5 @@ -// Copyright (c) .NET Foundation. All rights reserved. + +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT license. See License.txt in the project root for license information. using System.Threading; @@ -11,7 +12,7 @@ using Microsoft.CodeAnalysis.Razor.Protocol; using Microsoft.CodeAnalysis.Razor.Workspaces; using Microsoft.VisualStudio.LanguageServer.Protocol; -using LS = Microsoft.VisualStudio.LanguageServer.Protocol; +using LSP = Microsoft.VisualStudio.LanguageServer.Protocol; namespace Microsoft.AspNetCore.Razor.LanguageServer.SignatureHelp; @@ -22,7 +23,7 @@ internal sealed class SignatureHelpEndpoint( IClientConnection clientConnection, RazorLSPOptionsMonitor optionsMonitor, ILoggerFactory loggerProvider) - : AbstractRazorDelegatingEndpoint( + : AbstractRazorDelegatingEndpoint( languageServerFeatureOptions, documentMappingService, clientConnection, @@ -33,11 +34,7 @@ internal sealed class SignatureHelpEndpoint( public void ApplyCapabilities(VSInternalServerCapabilities serverCapabilities, VSInternalClientCapabilities clientCapabilities) { - serverCapabilities.SignatureHelpProvider = new SignatureHelpOptions() - { - TriggerCharacters = new[] { "(", ",", "<" }, - RetriggerCharacters = new[] { ">", ")" } - }; + serverCapabilities.EnableSignatureHelp(); } protected override Task CreateDelegatedParamsAsync(SignatureHelpParams request, RazorRequestContext requestContext, DocumentPositionInfo positionInfo, CancellationToken cancellationToken) From afb03625935b51a01ba42d6b527586e780dd2314 Mon Sep 17 00:00:00 2001 From: David Wengier Date: Thu, 4 Jul 2024 19:46:36 +1000 Subject: [PATCH 005/176] Create basic endpoint and remote service definition --- .../SignatureHelp/RemoteSignatureHelp.cs | 26 +++++ .../RemoteSignatureInformation.cs | 23 +++++ .../Remote/IRemoteSignatureHelpService.cs | 16 +++ .../Cohost/CohostSignatureHelpEndpoint.cs | 98 +++++++++++++++++++ 4 files changed, 163 insertions(+) create mode 100644 src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Protocol/SignatureHelp/RemoteSignatureHelp.cs create mode 100644 src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Protocol/SignatureHelp/RemoteSignatureInformation.cs create mode 100644 src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteSignatureHelpService.cs create mode 100644 src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/CohostSignatureHelpEndpoint.cs diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Protocol/SignatureHelp/RemoteSignatureHelp.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Protocol/SignatureHelp/RemoteSignatureHelp.cs new file mode 100644 index 00000000000..ea41ff45c5a --- /dev/null +++ b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Protocol/SignatureHelp/RemoteSignatureHelp.cs @@ -0,0 +1,26 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT license. See License.txt in the project root for license information. + +using System.Collections.Generic; +using System.Linq; +using System.Runtime.Serialization; +using LSP = Microsoft.VisualStudio.LanguageServer.Protocol; + +namespace Microsoft.CodeAnalysis.Razor.Workspaces.Protocol.SignatureHelp; + +[DataContract] +internal readonly record struct RemoteSignatureHelp( + [property: DataMember(Order = 0)] int? ActiveParameter, + [property: DataMember(Order = 1)] int? ActiveSignature, + [property: DataMember(Order = 2)] RemoteSignatureInformation[] Signatures) +{ + public LSP.SignatureHelp ToSignatureHelp() + { + return new LSP.SignatureHelp() + { + ActiveParameter = this.ActiveParameter, + ActiveSignature = this.ActiveSignature, + Signatures = this.Signatures.Select(s => s.ToSignatureInformation()).ToArray() + }; + } +} diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Protocol/SignatureHelp/RemoteSignatureInformation.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Protocol/SignatureHelp/RemoteSignatureInformation.cs new file mode 100644 index 00000000000..985d1f6bca1 --- /dev/null +++ b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Protocol/SignatureHelp/RemoteSignatureInformation.cs @@ -0,0 +1,23 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT license. See License.txt in the project root for license information. + +using System.Runtime.Serialization; +using Microsoft.VisualStudio.LanguageServer.Protocol; + +namespace Microsoft.CodeAnalysis.Razor.Workspaces.Protocol.SignatureHelp; + +[DataContract] +internal readonly record struct RemoteSignatureInformation( + [property: DataMember(Order = 0)] string Label) +{ + internal SignatureInformation ToSignatureInformation() + { + return new SignatureInformation() + { + Label = this.Label, + Documentation = new MarkupContent() + { + } + }; + } +} diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteSignatureHelpService.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteSignatureHelpService.cs new file mode 100644 index 00000000000..34ffc8a1cf0 --- /dev/null +++ b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteSignatureHelpService.cs @@ -0,0 +1,16 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT license. See License.txt in the project root for license information. + +using System.Threading; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.ExternalAccess.Razor; +using Microsoft.CodeAnalysis.Razor.Workspaces.Protocol.SignatureHelp; +using Microsoft.CodeAnalysis.Text; +using Microsoft.VisualStudio.LanguageServer.Protocol; + +namespace Microsoft.CodeAnalysis.Razor.Remote; + +internal interface IRemoteSignatureHelpService +{ + ValueTask GetSignatureHelpAsync(RazorPinnedSolutionInfoWrapper solutionInfo, DocumentId id, LinePosition linePosition, SignatureHelpTriggerKind triggerKind, string? triggerCharacter, CancellationToken cancellationToken); +} diff --git a/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/CohostSignatureHelpEndpoint.cs b/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/CohostSignatureHelpEndpoint.cs new file mode 100644 index 00000000000..9e73c36fd52 --- /dev/null +++ b/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/CohostSignatureHelpEndpoint.cs @@ -0,0 +1,98 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT license. See License.txt in the project root for license information. + +using System.Composition; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Razor; +using Microsoft.AspNetCore.Razor.LanguageServer.Hosting; +using Microsoft.CodeAnalysis.ExternalAccess.Razor.Cohost; +using Microsoft.CodeAnalysis.Razor.Logging; +using Microsoft.CodeAnalysis.Razor.Remote; +using Microsoft.CodeAnalysis.Razor.Workspaces; +using Microsoft.CodeAnalysis.Razor.Workspaces.Protocol.SignatureHelp; +using Microsoft.VisualStudio.LanguageServer.ContainedLanguage; +using Microsoft.VisualStudio.LanguageServer.Protocol; +using Microsoft.VisualStudio.Razor.LanguageClient; +using Microsoft.VisualStudio.Razor.LanguageClient.Cohost; +using Microsoft.VisualStudio.Razor.LanguageClient.Extensions; + +namespace Microsoft.VisualStudio.LanguageServices.Razor.LanguageClient.Cohost; + +#pragma warning disable RS0030 // Do not use banned APIs +[Shared] +[CohostEndpoint(Methods.TextDocumentSignatureHelpName)] +[Export(typeof(IDynamicRegistrationProvider))] +[ExportCohostStatelessLspService(typeof(CohostSignatureHelpEndpoint))] +[method: ImportingConstructor] +#pragma warning restore RS0030 // Do not use banned APIs +internal class CohostSignatureHelpEndpoint( + IRemoteServiceProvider remoteServiceProvider, + IHtmlDocumentSynchronizer htmlDocumentSynchronizer, + LSPRequestInvoker requestInvoker, + ILoggerFactory loggerFactory) + : AbstractRazorCohostDocumentRequestHandler, IDynamicRegistrationProvider +{ + private readonly IRemoteServiceProvider _remoteServiceProvider = remoteServiceProvider; + private readonly IHtmlDocumentSynchronizer _htmlDocumentSynchronizer = htmlDocumentSynchronizer; + private readonly LSPRequestInvoker _requestInvoker = requestInvoker; + private readonly ILogger _logger = loggerFactory.GetOrCreateLogger(); + + protected override bool MutatesSolutionState => false; + + protected override bool RequiresLSPSolution => true; + + public Registration? GetRegistration(VSInternalClientCapabilities clientCapabilities, DocumentFilter[] filter, RazorCohostRequestContext requestContext) + { + if (clientCapabilities.TextDocument?.SignatureHelp?.DynamicRegistration == true) + { + return new Registration() + { + Method = Methods.TextDocumentSignatureHelpName, + RegisterOptions = new SignatureHelpRegistrationOptions() + { + DocumentSelector = filter + }.EnableSignatureHelp() + }; + } + + return null; + } + + protected override RazorTextDocumentIdentifier? GetRazorTextDocumentIdentifier(SignatureHelpParams request) + => request.TextDocument.ToRazorTextDocumentIdentifier(); + + protected async override Task HandleRequestAsync(SignatureHelpParams request, RazorCohostRequestContext context, CancellationToken cancellationToken) + { + var razorDocument = context.TextDocument.AssumeNotNull(); + + var data = await _remoteServiceProvider.TryInvokeAsync( + razorDocument.Project.Solution, + (service, solutionInfo, cancellationToken) => service.GetSignatureHelpAsync(solutionInfo, razorDocument.Id, request.Position.ToLinePosition(), request.Context.TriggerKind, request.Context.TriggerCharacter, cancellationToken), + cancellationToken).ConfigureAwait(false); + + // If we got a response back, then either Razor or C# wants to do something with this, so we're good to go + if (data is { } signatureHelp) + { + return signatureHelp.ToSignatureHelp(); + } + + // If we didn't get anything from Razor or Roslyn, lets ask Html what they want to do + var htmlDocument = await _htmlDocumentSynchronizer.TryGetSynchronizedHtmlDocumentAsync(razorDocument, cancellationToken).ConfigureAwait(false); + if (htmlDocument is null) + { + return null; + } + + request.TextDocument = request.TextDocument.WithUri(htmlDocument.Uri); + + var result = await _requestInvoker.ReinvokeRequestOnServerAsync( + htmlDocument.Buffer, + Methods.TextDocumentSignatureHelpName, + RazorLSPConstants.HtmlLanguageServerName, + request, + cancellationToken).ConfigureAwait(false); + + return result?.Response; + } +} From 50a650ad5b95a076bc39cd3397bdc380b373a0a0 Mon Sep 17 00:00:00 2001 From: David Wengier Date: Sun, 7 Jul 2024 22:24:19 +1000 Subject: [PATCH 006/176] Updates after merge --- .../Formatting/CSharpFormatter.cs | 45 +++++++++---------- .../Formatting/CSharpOnTypeFormattingPass.cs | 11 +++-- .../Formatting/FormattingOptionsExtensions.cs | 17 ++++--- .../Formatting/TestRazorFormattingService.cs | 42 ----------------- 4 files changed, 37 insertions(+), 78 deletions(-) diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Formatting/CSharpFormatter.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Formatting/CSharpFormatter.cs index f9761105bc2..0b50a43683e 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Formatting/CSharpFormatter.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Formatting/CSharpFormatter.cs @@ -7,15 +7,13 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.Razor.Language; -using Microsoft.AspNetCore.Razor.LanguageServer.Hosting; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Razor.DocumentMapping; -using Microsoft.CodeAnalysis.Razor.Workspaces; using Microsoft.CodeAnalysis.ExternalAccess.Razor; using Microsoft.CodeAnalysis.Razor; -using Microsoft.CodeAnalysis.Razor.Workspaces.Extensions; +using Microsoft.CodeAnalysis.Razor.DocumentMapping; +using Microsoft.CodeAnalysis.Razor.Workspaces; using Microsoft.CodeAnalysis.Text; using Microsoft.VisualStudio.LanguageServer.Protocol; @@ -79,22 +77,23 @@ private TextEdit[] MapEditsToHostDocument(RazorCodeDocument codeDocument, TextEd return actualEdits; } - private static async Task FormatOnServerAsync( - FormattingContext context, - Range projectedRange, - CancellationToken cancellationToken) - { - var csharpSourceText = context.CodeDocument.GetCSharpSourceText(); - var spanToFormat = projectedRange.AsTextSpan(csharpSourceText); - var root = await context.CSharpWorkspaceDocument.GetSyntaxRootAsync(cancellationToken); - Assumes.NotNull(root); + private static async Task GetFormattingEditsAsync( + FormattingContext context, + Range projectedRange, + CancellationToken cancellationToken) + { + var csharpSourceText = context.CodeDocument.GetCSharpSourceText(); + var spanToFormat = projectedRange.AsTextSpan(csharpSourceText); + var csharpDocument = context.CSharpWorkspaceDocument; + var root = await csharpDocument.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); + Assumes.NotNull(root); - var services = csharpDocument.Project.Solution.Workspace.Services; - var changes = RazorCSharpFormattingInteractionService.GetFormattedTextChanges(services, root, spanToFormat, context.Options.GetIndentationOptions(), cancellationToken); + var services = csharpDocument.Project.Solution.Workspace.Services; + var changes = RazorCSharpFormattingInteractionService.GetFormattedTextChanges(services, root, spanToFormat, context.Options.GetIndentationOptions(), cancellationToken); - var edits = changes.Select(c => c.AsTextEdit(csharpSourceText)).ToArray(); - return edits; - } + var edits = changes.Select(c => c.ToTextEdit(csharpSourceText)).ToArray(); + return edits; + } private static async Task> GetCSharpIndentationCoreAsync(FormattingContext context, List projectedDocumentLocations, CancellationToken cancellationToken) { @@ -110,11 +109,11 @@ private static async Task> GetCSharpIndentationCoreAsync(Fo root = AttachAnnotations(indentationMap, projectedDocumentLocations, root); - // At this point, we have added all the necessary markers and attached annotations. - // Let's invoke the C# formatter and hope for the best. - var services = context.CSharpWorkspaceDocument.Project.Solution.Workspace.Services; - var formattedRoot = RazorCSharpFormattingInteractionService.Format(services, root, context.Options.GetIndentationOptions(), cancellationToken); - var formattedText = formattedRoot.GetText(); + // At this point, we have added all the necessary markers and attached annotations. + // Let's invoke the C# formatter and hope for the best. + var services = context.CSharpWorkspaceDocument.Project.Solution.Workspace.Services; + var formattedRoot = RazorCSharpFormattingInteractionService.Format(services, root, context.Options.GetIndentationOptions(), cancellationToken); + var formattedText = formattedRoot.GetText(); var desiredIndentationMap = new Dictionary(); diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Formatting/CSharpOnTypeFormattingPass.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Formatting/CSharpOnTypeFormattingPass.cs index e37b594559a..b6f250950d7 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Formatting/CSharpOnTypeFormattingPass.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Formatting/CSharpOnTypeFormattingPass.cs @@ -31,6 +31,7 @@ internal sealed class CSharpOnTypeFormattingPass( : CSharpFormattingPassBase(documentMappingService) { private readonly ILogger _logger = loggerFactory.GetOrCreateLogger(); + public async override Task ExecuteAsync(FormattingContext context, FormattingResult result, CancellationToken cancellationToken) { if (!context.IsFormatOnType || result.Kind != RazorLanguageKind.CSharp) @@ -52,14 +53,16 @@ public async override Task ExecuteAsync(FormattingContext cont return result; } - // Ask C# for formatting changes. - - var formattingChanges = await RazorCSharpFormattingInteractionService.GetFormattingChangesAsync( + // Ask C# for formatting changes. + var autoFormattingOptions = new RazorAutoFormattingOptions( + formatOnReturn: true, formatOnTyping: true, formatOnSemicolon: true, formatOnCloseBrace: true); + + var formattingChanges = await RazorCSharpFormattingInteractionService.GetFormattingChangesAsync( context.CSharpWorkspaceDocument, typedChar: context.TriggerCharacter, projectedIndex, context.Options.GetIndentationOptions(), - _globalOptions.GetAutoFormattingOptions(), + autoFormattingOptions, indentStyle: CodeAnalysis.Formatting.FormattingOptions.IndentStyle.Smart, cancellationToken).ConfigureAwait(false); diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Formatting/FormattingOptionsExtensions.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Formatting/FormattingOptionsExtensions.cs index 3bd1a7df6cc..5271e0f9ec1 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Formatting/FormattingOptionsExtensions.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Formatting/FormattingOptionsExtensions.cs @@ -4,14 +4,13 @@ using Microsoft.CodeAnalysis.ExternalAccess.Razor; using Microsoft.VisualStudio.LanguageServer.Protocol; -namespace Microsoft.AspNetCore.Razor.LanguageServer.Formatting +namespace Microsoft.AspNetCore.Razor.LanguageServer.Formatting; + +internal static class FormattingOptionsExtensions { - internal static class FormattingOptionsExtensions - { - public static RazorIndentationOptions GetIndentationOptions(this FormattingOptions options) - => new( - UseTabs: !options.InsertSpaces, - TabSize: options.TabSize, - IndentationSize: options.TabSize); - } + public static RazorIndentationOptions GetIndentationOptions(this FormattingOptions options) + => new( + UseTabs: !options.InsertSpaces, + TabSize: options.TabSize, + IndentationSize: options.TabSize); } diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Formatting/TestRazorFormattingService.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Formatting/TestRazorFormattingService.cs index ec492dfd36e..648e368f8a8 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Formatting/TestRazorFormattingService.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Formatting/TestRazorFormattingService.cs @@ -5,9 +5,6 @@ using System; using System.Threading.Tasks; using Microsoft.AspNetCore.Razor.Language; -using Microsoft.AspNetCore.Razor.LanguageServer.Test; -using Microsoft.AspNetCore.Razor.LanguageServer.Test.Common; -using Microsoft.CodeAnalysis.ExternalAccess.Razor; using Microsoft.AspNetCore.Razor.LanguageServer.Hosting; using Microsoft.CodeAnalysis.Razor.Logging; using Microsoft.CodeAnalysis.Razor.ProjectSystem; @@ -19,45 +16,6 @@ internal static class TestRazorFormattingService { #pragma warning disable IDE0060 // Remove unused parameter - public static async Task CreateWithFullSupportAsync( - RazorCodeDocument? codeDocument = null, - DocumentSnapshot? documentSnapshot = null, - ILoggerFactory? loggerFactory = null) - { - codeDocument ??= TestRazorCodeDocument.CreateEmpty(); - loggerFactory ??= NullLoggerFactory.Instance; - - var mappingService = new DefaultRazorDocumentMappingService(TestLanguageServerFeatureOptions.Instance, new TestDocumentContextFactory(), loggerFactory); - - var dispatcher = new LSPProjectSnapshotManagerDispatcher(loggerFactory); - var versionCache = new DefaultDocumentVersionCache(dispatcher); - - var workspaceFactory = TestAdhocWorkspaceFactory.Instance; - var globalOptions = RazorGlobalOptions.GetGlobalOptions(workspaceFactory.Create()); - - if (documentSnapshot is not null) - { - await dispatcher.RunOnDispatcherThreadAsync(() => - { - versionCache.TrackDocumentVersion(documentSnapshot, version: 1); - }, CancellationToken.None); - } - - var client = new FormattingLanguageServerClient(); - client.AddCodeDocument(codeDocument); - - var passes = new List() - { - new HtmlFormattingPass(mappingService, client, versionCache, loggerFactory), - new CSharpFormattingPass(mappingService, client, loggerFactory), - new CSharpOnTypeFormattingPass(mappingService, client, globalOptions, loggerFactory), - new RazorFormattingPass(mappingService, client, loggerFactory), - new FormattingDiagnosticValidationPass(mappingService, client, loggerFactory), - new FormattingContentValidationPass(mappingService, client, loggerFactory), - }; - - return new DefaultRazorFormattingService(passes, loggerFactory, TestAdhocWorkspaceFactory.Instance); - } public static Task CreateWithFullSupportAsync( ILoggerFactory loggerFactory, RazorCodeDocument? codeDocument = null, From e0e78bb712af3d87fa3e5b67d97b6856d43de4f4 Mon Sep 17 00:00:00 2001 From: David Wengier Date: Mon, 8 Jul 2024 08:20:23 +1000 Subject: [PATCH 007/176] Actually fix the bug by not calling TryApplyChanges on the workspace --- .../Formatting/CSharpFormatter.cs | 2 +- .../Formatting/FormattingContext.cs | 23 +------------------ 2 files changed, 2 insertions(+), 23 deletions(-) diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Formatting/CSharpFormatter.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Formatting/CSharpFormatter.cs index 0b50a43683e..7f3f4d8680b 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Formatting/CSharpFormatter.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Formatting/CSharpFormatter.cs @@ -111,7 +111,7 @@ private static async Task> GetCSharpIndentationCoreAsync(Fo // At this point, we have added all the necessary markers and attached annotations. // Let's invoke the C# formatter and hope for the best. - var services = context.CSharpWorkspaceDocument.Project.Solution.Workspace.Services; + var services = context.CSharpWorkspace.Services; var formattedRoot = RazorCSharpFormattingInteractionService.Format(services, root, context.Options.GetIndentationOptions(), cancellationToken); var formattedText = formattedRoot.GetText(); diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Formatting/FormattingContext.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Formatting/FormattingContext.cs index de4352ddd17..a87dab72d9e 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Formatting/FormattingContext.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Formatting/FormattingContext.cs @@ -73,28 +73,7 @@ public Document CSharpWorkspaceDocument } } - public AdhocWorkspace CSharpWorkspace - { - get - { - if (_csharpWorkspace is null) - { - var adhocWorkspace = _workspaceFactory.Create(); - var csharpOptions = GetChangedOptionSet(adhocWorkspace.Options); - adhocWorkspace.TryApplyChanges(adhocWorkspace.CurrentSolution.WithOptions(csharpOptions)); - _csharpWorkspace = adhocWorkspace; - } - - return _csharpWorkspace; - } - } - - public CodeAnalysis.Options.OptionSet GetChangedOptionSet(CodeAnalysis.Options.OptionSet optionsSet) - { - return optionsSet.WithChangedOption(CodeAnalysis.Formatting.FormattingOptions.TabSize, LanguageNames.CSharp, Options.TabSize) - .WithChangedOption(CodeAnalysis.Formatting.FormattingOptions.IndentationSize, LanguageNames.CSharp, Options.TabSize) - .WithChangedOption(CodeAnalysis.Formatting.FormattingOptions.UseTabs, LanguageNames.CSharp, !Options.InsertSpaces); - } + public AdhocWorkspace CSharpWorkspace => _csharpWorkspace ??= _workspaceFactory.Create(); /// A Dictionary of int (line number) to IndentationContext. /// From dbacc56edaf74070b574b35e87198ec64d9bfc2e Mon Sep 17 00:00:00 2001 From: David Wengier Date: Mon, 8 Jul 2024 08:30:55 +1000 Subject: [PATCH 008/176] Whitespace --- .../Formatting/CSharpFormatter.cs | 14 ++++---------- .../Formatting/CSharpOnTypeFormattingPass.cs | 16 ++++++++-------- 2 files changed, 12 insertions(+), 18 deletions(-) diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Formatting/CSharpFormatter.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Formatting/CSharpFormatter.cs index 7f3f4d8680b..edb09ef5e9d 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Formatting/CSharpFormatter.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Formatting/CSharpFormatter.cs @@ -77,19 +77,14 @@ private TextEdit[] MapEditsToHostDocument(RazorCodeDocument codeDocument, TextEd return actualEdits; } - private static async Task GetFormattingEditsAsync( - FormattingContext context, - Range projectedRange, - CancellationToken cancellationToken) + private static async Task GetFormattingEditsAsync(FormattingContext context, Range projectedRange, CancellationToken cancellationToken) { var csharpSourceText = context.CodeDocument.GetCSharpSourceText(); var spanToFormat = projectedRange.AsTextSpan(csharpSourceText); - var csharpDocument = context.CSharpWorkspaceDocument; - var root = await csharpDocument.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); + var root = await context.CSharpWorkspaceDocument.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); Assumes.NotNull(root); - var services = csharpDocument.Project.Solution.Workspace.Services; - var changes = RazorCSharpFormattingInteractionService.GetFormattedTextChanges(services, root, spanToFormat, context.Options.GetIndentationOptions(), cancellationToken); + var changes = RazorCSharpFormattingInteractionService.GetFormattedTextChanges(context.CSharpWorkspace.Services, root, spanToFormat, context.Options.GetIndentationOptions(), cancellationToken); var edits = changes.Select(c => c.ToTextEdit(csharpSourceText)).ToArray(); return edits; @@ -111,8 +106,7 @@ private static async Task> GetCSharpIndentationCoreAsync(Fo // At this point, we have added all the necessary markers and attached annotations. // Let's invoke the C# formatter and hope for the best. - var services = context.CSharpWorkspace.Services; - var formattedRoot = RazorCSharpFormattingInteractionService.Format(services, root, context.Options.GetIndentationOptions(), cancellationToken); + var formattedRoot = RazorCSharpFormattingInteractionService.Format(context.CSharpWorkspace.Services, root, context.Options.GetIndentationOptions(), cancellationToken); var formattedText = formattedRoot.GetText(); var desiredIndentationMap = new Dictionary(); diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Formatting/CSharpOnTypeFormattingPass.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Formatting/CSharpOnTypeFormattingPass.cs index b6f250950d7..f900e4ae41b 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Formatting/CSharpOnTypeFormattingPass.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Formatting/CSharpOnTypeFormattingPass.cs @@ -55,16 +55,16 @@ public async override Task ExecuteAsync(FormattingContext cont // Ask C# for formatting changes. var autoFormattingOptions = new RazorAutoFormattingOptions( - formatOnReturn: true, formatOnTyping: true, formatOnSemicolon: true, formatOnCloseBrace: true); + formatOnReturn: true, formatOnTyping: true, formatOnSemicolon: true, formatOnCloseBrace: true); var formattingChanges = await RazorCSharpFormattingInteractionService.GetFormattingChangesAsync( - context.CSharpWorkspaceDocument, - typedChar: context.TriggerCharacter, - projectedIndex, - context.Options.GetIndentationOptions(), - autoFormattingOptions, - indentStyle: CodeAnalysis.Formatting.FormattingOptions.IndentStyle.Smart, - cancellationToken).ConfigureAwait(false); + context.CSharpWorkspaceDocument, + typedChar: context.TriggerCharacter, + projectedIndex, + context.Options.GetIndentationOptions(), + autoFormattingOptions, + indentStyle: CodeAnalysis.Formatting.FormattingOptions.IndentStyle.Smart, + cancellationToken).ConfigureAwait(false); if (formattingChanges.IsEmpty) { From c5de6625c4ae345759ffd6695efc329b60c15579 Mon Sep 17 00:00:00 2001 From: David Wengier Date: Mon, 8 Jul 2024 08:33:01 +1000 Subject: [PATCH 009/176] Make minimal --- .../Formatting/CSharpFormatter.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Formatting/CSharpFormatter.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Formatting/CSharpFormatter.cs index edb09ef5e9d..924e0c5df57 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Formatting/CSharpFormatter.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Formatting/CSharpFormatter.cs @@ -80,7 +80,7 @@ private TextEdit[] MapEditsToHostDocument(RazorCodeDocument codeDocument, TextEd private static async Task GetFormattingEditsAsync(FormattingContext context, Range projectedRange, CancellationToken cancellationToken) { var csharpSourceText = context.CodeDocument.GetCSharpSourceText(); - var spanToFormat = projectedRange.AsTextSpan(csharpSourceText); + var spanToFormat = projectedRange.ToTextSpan(csharpSourceText); var root = await context.CSharpWorkspaceDocument.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); Assumes.NotNull(root); From 63f6ad3fd4cbf59ab7a201d654b7f3a6473ecde2 Mon Sep 17 00:00:00 2001 From: Amadeusz Wieczorek Date: Mon, 8 Jul 2024 10:29:05 -0700 Subject: [PATCH 010/176] Get TextManager as needed to avoid UI thread dependency in the constructor --- .../RazorLSPTextViewConnectionListener.cs | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/RazorLSPTextViewConnectionListener.cs b/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/RazorLSPTextViewConnectionListener.cs index 70c141ac2b3..aef5ffe3a49 100644 --- a/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/RazorLSPTextViewConnectionListener.cs +++ b/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/RazorLSPTextViewConnectionListener.cs @@ -42,7 +42,7 @@ internal class RazorLSPTextViewConnectionListener : ITextViewConnectionListener private readonly ILspEditorFeatureDetector _editorFeatureDetector; private readonly IEditorOptionsFactoryService _editorOptionsFactory; private readonly IClientSettingsManager _editorSettingsManager; - private readonly IVsTextManager4 _textManager; + private IVsTextManager4? _textManager; /// /// Protects concurrent modifications to _activeTextViews and _textBuffer's @@ -69,11 +69,13 @@ public RazorLSPTextViewConnectionListener( _editorFeatureDetector = editorFeatureDetector; _editorOptionsFactory = editorOptionsFactory; _editorSettingsManager = editorSettingsManager; - _textManager = (IVsTextManager4)serviceProvider.GetService(typeof(SVsTextManager)); - - Assumes.Present(_textManager); } + /// + /// Gets instance of . This accesses COM object and requires to be called on the UI thread. + /// + private IVsTextManager4 TextManager => _textManager ??= (IVsTextManager4)_serviceProvider.GetService(typeof(SVsTextManager)); + public void SubjectBuffersConnected(ITextView textView, ConnectionReason reason, IReadOnlyCollection subjectBuffers) { if (textView is null) @@ -133,7 +135,8 @@ public void SubjectBuffersConnected(ITextView textView, ConnectionReason reason, // Initialize TextView options. We only need to do this once per TextView, as the options should // automatically update and they aren't options we care about keeping track of. - InitializeRazorTextViewOptions(_textManager, optionsTracker); + Assumes.Present(TextManager); + InitializeRazorTextViewOptions(TextManager, optionsTracker); // A change in Tools->Options settings only kicks off an options changed event in the view // and not the buffer, i.e. even if we listened for TextBuffer option changes, we would never @@ -201,7 +204,7 @@ private void RazorOptions_OptionChanged(object? sender, EditorOptionChangedEvent // Retrieve current space/tabs settings from from Tools->Options and update options in // the actual editor. - (ClientSpaceSettings ClientSpaceSettings, ClientCompletionSettings ClientCompletionSettings) settings = UpdateRazorEditorOptions(_textManager, optionsTracker); + (ClientSpaceSettings ClientSpaceSettings, ClientCompletionSettings ClientCompletionSettings) settings = UpdateRazorEditorOptions(TextManager, optionsTracker); // Keep track of accurate settings on the client side so we can easily retrieve the // options later when the server sends us a workspace/configuration request. From f7465617aa51c0a58c5b8e37881827df49cf89dc Mon Sep 17 00:00:00 2001 From: Alex Gavrilov Date: Mon, 8 Jul 2024 16:13:12 -0700 Subject: [PATCH 011/176] Removing unnecessary Razor Legacy Editor feature flag (#10591) * Removing unnecessary Razor Legacy Editor feature flag AFAIK it was introduced for new LSP editor rollout several years ago before we had Tools/Options/HTML Editor/Advanced/Use legacy Razor Editor option. Now that rollout is over, and there is a public non-preview mechanism for users to switch to the old editor if needed, the feature flag is no longer necessary and creates confusion (and extra code to test/maintain). * Fixing a unit test (test matrix) * Fixing spacing per CR suggestion Co-authored-by: David Wengier --------- Co-authored-by: David Wengier --- .../LspEditorFeatureDetector.cs | 19 ++------ .../WellKnownFeatureFlagNames.cs | 1 - ....VisualStudio.RazorExtension.Custom.pkgdef | 6 --- .../LspEditorFeatureDetectorTest.cs | 47 ++++++------------- .../AbstractRazorEditorTest.cs | 3 -- 5 files changed, 18 insertions(+), 58 deletions(-) diff --git a/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LspEditorFeatureDetector.cs b/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LspEditorFeatureDetector.cs index 20f0b709fa4..f6ba70da11a 100644 --- a/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LspEditorFeatureDetector.cs +++ b/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LspEditorFeatureDetector.cs @@ -25,7 +25,6 @@ internal sealed class LspEditorFeatureDetector : ILspEditorFeatureDetector, IDis [ImportingConstructor] public LspEditorFeatureDetector( - IVsService vsFeatureFlagsService, IVsService vsSettingsManagerService, IUIContextService uiContextService, IProjectCapabilityResolver projectCapabilityResolver, @@ -40,7 +39,7 @@ public LspEditorFeatureDetector( _disposeTokenSource = new(); _lazyLegacyEditorEnabled = new(() => - ComputeUseLegacyEditorAsync(vsFeatureFlagsService, vsSettingsManagerService, activityLog, _disposeTokenSource.Token), + ComputeUseLegacyEditorAsync(vsSettingsManagerService, activityLog, _disposeTokenSource.Token), _jtf); } @@ -56,22 +55,10 @@ public void Dispose() } private static async Task ComputeUseLegacyEditorAsync( - IVsService vsFeatureFlagsService, IVsService vsSettingsManagerService, RazorActivityLog activityLog, CancellationToken cancellationToken) { - var vsFeatureFlags = await vsFeatureFlagsService.GetValueAsync(cancellationToken).ConfigureAwaitRunInline(); - - // IVsFeatureFlags is free-threaded but VSTHRD010 seems to be reported anyway. -#pragma warning disable VSTHRD010 // Invoke single-threaded types on Main thread - if (vsFeatureFlags.IsFeatureEnabled(WellKnownFeatureFlagNames.UseLegacyRazorEditor, defaultValue: false)) -#pragma warning restore VSTHRD010 // Invoke single-threaded types on Main thread - { - activityLog.LogInfo($"Using legacy editor because the '{WellKnownFeatureFlagNames.UseLegacyRazorEditor}' feature flag is enabled."); - return true; - } - var settingsManager = await vsSettingsManagerService.GetValueAsync(cancellationToken).ConfigureAwaitRunInline(); var useLegacyEditorSetting = settingsManager.GetValueOrDefault(WellKnownSettingNames.UseLegacyASPNETCoreEditor); @@ -101,7 +88,7 @@ public bool IsLspEditorEnabled() if (useLegacyEditorEnabled) { - _activityLog.LogInfo("Using legacy editor because the option or feature flag was set to true"); + _activityLog.LogInfo("Using legacy editor because the option was set to true"); return false; } @@ -112,7 +99,7 @@ public bool IsLspEditorEnabled() /// public bool IsLspEditorSupported(string documentFilePath) { - // Regardless of whether the LSP is enabled via the feature flag or tools/options, the document's project + // Regardless of whether the LSP is enabled via tools/options, the document's project // might not support it. For example, .NET Framework projects don't support the LSP Razor editor. var useLegacyEditor = _projectCapabilityResolver.ResolveCapability(WellKnownProjectCapabilities.LegacyRazorEditor, documentFilePath); diff --git a/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/WellKnownFeatureFlagNames.cs b/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/WellKnownFeatureFlagNames.cs index ace4bbb297d..559d4318e51 100644 --- a/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/WellKnownFeatureFlagNames.cs +++ b/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/WellKnownFeatureFlagNames.cs @@ -11,5 +11,4 @@ internal static class WellKnownFeatureFlagNames public const string UseRazorCohostServer = "Razor.LSP.UseRazorCohostServer"; public const string DisableRazorLanguageServer = "Razor.LSP.DisableRazorLanguageServer"; public const string ForceRuntimeCodeGeneration = "Razor.LSP.ForceRuntimeCodeGeneration"; - public const string UseLegacyRazorEditor = "Razor.LSP.LegacyEditor"; } diff --git a/src/Razor/src/Microsoft.VisualStudio.RazorExtension/Microsoft.VisualStudio.RazorExtension.Custom.pkgdef b/src/Razor/src/Microsoft.VisualStudio.RazorExtension/Microsoft.VisualStudio.RazorExtension.Custom.pkgdef index 9b1c0111007..98918c86fc2 100644 --- a/src/Razor/src/Microsoft.VisualStudio.RazorExtension/Microsoft.VisualStudio.RazorExtension.Custom.pkgdef +++ b/src/Razor/src/Microsoft.VisualStudio.RazorExtension/Microsoft.VisualStudio.RazorExtension.Custom.pkgdef @@ -38,12 +38,6 @@ "ShowBraceCompletion"=dword:00000001 "ShowSmartIndent"=dword:00000001 -[$RootKey$\FeatureFlags\Razor\LSP\LegacyEditor] -"Description"="Uses the legacy Razor editor when editing Razor (ASP.NET Core)." -"Value"=dword:00000000 -"Title"="Use legacy Razor editor (requires restart)" -"PreviewPaneChannels"="int.main" - [$RootKey$\FeatureFlags\Razor\LSP\ShowAllCSharpCodeActions] "Description"="Show all C# code actions in Razor files. Note: This is experimental, some actions may not apply correctly, or at all!" "Value"=dword:00000000 diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/LspEditorFeatureDetectorTest.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/LspEditorFeatureDetectorTest.cs index 2ec11bb4725..1764382cc23 100644 --- a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/LspEditorFeatureDetectorTest.cs +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/LspEditorFeatureDetectorTest.cs @@ -18,21 +18,19 @@ namespace Microsoft.VisualStudio.Razor; public class LspEditorFeatureDetectorTest(ITestOutputHelper testOutput) : ToolingTestBase(testOutput) { - public static TheoryData IsLspEditorEnabledTestData { get; } = new() + public static TheoryData IsLspEditorEnabledTestData { get; } = new() { - // legacyEditorFeatureFlag, legacyEditorSetting, expectedResult - { false, false, true }, - { false, true, false }, - { true, false, false }, - { true, true, false } + // legacyEditorSetting, expectedResult + { false, true }, + { true, false }, }; [UITheory] [MemberData(nameof(IsLspEditorEnabledTestData))] - public void IsLspEditorEnabled(bool legacyEditorFeatureFlag, bool legacyEditorSetting, bool expectedResult) + public void IsLspEditorEnabled(bool legacyEditorSetting, bool expectedResult) { // Arrange - var featureDetector = CreateLspEditorFeatureDetector(legacyEditorFeatureFlag, legacyEditorSetting); + var featureDetector = CreateLspEditorFeatureDetector(legacyEditorSetting); // Act var result = featureDetector.IsLspEditorEnabled(); @@ -41,27 +39,25 @@ public void IsLspEditorEnabled(bool legacyEditorFeatureFlag, bool legacyEditorSe Assert.Equal(expectedResult, result); } - public static TheoryData IsLspEditorEnabledAndSupportedTestData { get; } = new() + public static TheoryData IsLspEditorEnabledAndSupportedTestData { get; } = new() { - // legacyEditorFeatureFlag, legacyEditorSetting, hasLegacyRazorEditorCapability, hasDotNetCoreCSharpCapability, expectedResult - { false, false, true, false, false }, // .Net Framework project - always non-LSP - { false, false, false, true, true }, // .Net Core project - { false, false, true, true, false }, // .Net Core project opts-in into legacy razor editor (exists in reality?) - { true, false, false, true, false }, // .Net Core project but legacy editor via feature flag - { false, true, false, true, false }, // .Net Core project but legacy editor via editor option + // legacyEditorSetting, hasLegacyRazorEditorCapability, hasDotNetCoreCSharpCapability, expectedResult + { false, true, false, false }, // .Net Framework project - always non-LSP + { false, false, true, true }, // .Net Core project + { false, true, true, false }, // .Net Core project opts-in into legacy razor editor (exists in reality?) + { true, false, true, false }, // .Net Core project but legacy editor via editor option }; [UITheory] [MemberData(nameof(IsLspEditorEnabledAndSupportedTestData))] public void IsLspEditorEnabledAndSupported( - bool legacyEditorFeatureFlag, bool legacyEditorSetting, bool hasLegacyRazorEditorCapability, bool hasDotNetCoreCSharpCapability, bool expectedResult) { // Arrange - var featureDetector = CreateLspEditorFeatureDetector(legacyEditorFeatureFlag, legacyEditorSetting, hasLegacyRazorEditorCapability, hasDotNetCoreCSharpCapability); + var featureDetector = CreateLspEditorFeatureDetector(legacyEditorSetting, hasLegacyRazorEditorCapability, hasDotNetCoreCSharpCapability); // Act var result = featureDetector.IsLspEditorEnabled() && @@ -124,19 +120,17 @@ public void IsLiveShareHost(bool liveShareHostActive, bool liveShareGuestActive, } private ILspEditorFeatureDetector CreateLspEditorFeatureDetector(IUIContextService uiContextService) - => CreateLspEditorFeatureDetector(legacyEditorFeatureFlag: false, legacyEditorSetting: false, uiContextService, hasLegacyRazorEditorCapability: false, hasDotNetCoreCSharpCapability: true); + => CreateLspEditorFeatureDetector(legacyEditorSetting: false, uiContextService, hasLegacyRazorEditorCapability: false, hasDotNetCoreCSharpCapability: true); private ILspEditorFeatureDetector CreateLspEditorFeatureDetector( - bool legacyEditorFeatureFlag = false, bool legacyEditorSetting = false, bool hasLegacyRazorEditorCapability = false, bool hasDotNetCoreCSharpCapability = true) { - return CreateLspEditorFeatureDetector(legacyEditorFeatureFlag, legacyEditorSetting, CreateUIContextService(), hasLegacyRazorEditorCapability, hasDotNetCoreCSharpCapability); + return CreateLspEditorFeatureDetector(legacyEditorSetting, CreateUIContextService(), hasLegacyRazorEditorCapability, hasDotNetCoreCSharpCapability); } private ILspEditorFeatureDetector CreateLspEditorFeatureDetector( - bool legacyEditorFeatureFlag, bool legacyEditorSetting, IUIContextService uiContextService, bool hasLegacyRazorEditorCapability, @@ -145,7 +139,6 @@ private ILspEditorFeatureDetector CreateLspEditorFeatureDetector( uiContextService ??= CreateUIContextService(); var featureDetector = new LspEditorFeatureDetector( - CreateVsFeatureFlagsService(legacyEditorFeatureFlag), CreateVsSettingsManagerService(legacyEditorSetting), uiContextService, CreateProjectCapabilityResolver(hasLegacyRazorEditorCapability, hasDotNetCoreCSharpCapability), @@ -157,16 +150,6 @@ private ILspEditorFeatureDetector CreateLspEditorFeatureDetector( return featureDetector; } - private static IVsService CreateVsFeatureFlagsService(bool useLegacyEditor) - { - var vsFeatureFlagsMock = new StrictMock(); - vsFeatureFlagsMock - .Setup(x => x.IsFeatureEnabled(WellKnownFeatureFlagNames.UseLegacyRazorEditor, It.IsAny())) - .Returns(useLegacyEditor); - - return VsMocks.CreateVsService(vsFeatureFlagsMock); - } - private static IVsService CreateVsSettingsManagerService(bool useLegacyEditor) { var vsSettingsManagerMock = new StrictMock(); diff --git a/src/Razor/test/Microsoft.VisualStudio.Razor.IntegrationTests/AbstractRazorEditorTest.cs b/src/Razor/test/Microsoft.VisualStudio.Razor.IntegrationTests/AbstractRazorEditorTest.cs index 06b9d9fefe1..1ae085f93af 100644 --- a/src/Razor/test/Microsoft.VisualStudio.Razor.IntegrationTests/AbstractRazorEditorTest.cs +++ b/src/Razor/test/Microsoft.VisualStudio.Razor.IntegrationTests/AbstractRazorEditorTest.cs @@ -144,9 +144,6 @@ private static void EnsureLSPEditorEnabled() { var settingsManager = (ISettingsManager)ServiceProvider.GlobalProvider.GetService(typeof(SVsSettingsPersistenceManager)); Assumes.Present(settingsManager); - var featureFlags = (IVsFeatureFlags)AsyncPackage.GetGlobalService(typeof(SVsFeatureFlags)); - var legacyEditorFeatureFlagEnabled = featureFlags.IsFeatureEnabled(WellKnownFeatureFlagNames.UseLegacyRazorEditor, defaultValue: false); - Assert.AreEqual(false, legacyEditorFeatureFlagEnabled, "Expected Legacy Editor Feature Flag to be disabled, but it was enabled"); var useLegacyEditor = settingsManager.GetValueOrDefault(WellKnownSettingNames.UseLegacyASPNETCoreEditor); Assert.AreEqual(false, useLegacyEditor, "Expected the Legacy Razor Editor to be disabled, but it was enabled"); From 9f9d250e428e5f16abf6accd310e65ad9d2b7a18 Mon Sep 17 00:00:00 2001 From: David Wengier Date: Thu, 4 Jul 2024 21:22:09 +1000 Subject: [PATCH 012/176] Allow services to use Json --- .../Remote/IRemoteJsonService.cs | 11 ++++++++++ .../Remote/IRemoteSignatureHelpService.cs | 10 ++++----- .../Remote/RazorServices.cs | 13 ++++++++--- .../Remote/RemoteServiceProvider.cs | 22 ++++++++++++++++++- 4 files changed, 47 insertions(+), 9 deletions(-) create mode 100644 src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteJsonService.cs diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteJsonService.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteJsonService.cs new file mode 100644 index 00000000000..4e193d31649 --- /dev/null +++ b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteJsonService.cs @@ -0,0 +1,11 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT license. See License.txt in the project root for license information. + +namespace Microsoft.CodeAnalysis.Razor.Remote; + +/// +/// Marker interface to indicate that an OOP service should use Json for communication +/// +internal interface IRemoteJsonService +{ +} diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteSignatureHelpService.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteSignatureHelpService.cs index 34ffc8a1cf0..82163933eef 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteSignatureHelpService.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteSignatureHelpService.cs @@ -4,13 +4,13 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.ExternalAccess.Razor; -using Microsoft.CodeAnalysis.Razor.Workspaces.Protocol.SignatureHelp; -using Microsoft.CodeAnalysis.Text; -using Microsoft.VisualStudio.LanguageServer.Protocol; +using Roslyn.LanguageServer.Protocol; namespace Microsoft.CodeAnalysis.Razor.Remote; -internal interface IRemoteSignatureHelpService +using SignatureHelp = Roslyn.LanguageServer.Protocol.SignatureHelp; + +internal interface IRemoteSignatureHelpService : IRemoteJsonService { - ValueTask GetSignatureHelpAsync(RazorPinnedSolutionInfoWrapper solutionInfo, DocumentId id, LinePosition linePosition, SignatureHelpTriggerKind triggerKind, string? triggerCharacter, CancellationToken cancellationToken); + ValueTask GetSignatureHelpAsync(JsonSerializableRazorPinnedSolutionInfoWrapper solutionInfo, JsonSerializableDocumentId documentId, Position linePosition, CancellationToken cancellationToken); } diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/RazorServices.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/RazorServices.cs index a4584786c06..5b79b2b5005 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/RazorServices.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/RazorServices.cs @@ -1,8 +1,6 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT license. See License.txt in the project root for license information. -using System.Collections.Immutable; -using MessagePack.Formatters; using Microsoft.AspNetCore.Razor.Serialization.MessagePack.Resolvers; using Microsoft.CodeAnalysis.ExternalAccess.Razor; @@ -15,7 +13,7 @@ internal static class RazorServices public static readonly RazorServiceDescriptorsWrapper Descriptors = new( ComponentName, featureDisplayNameProvider: feature => $"Razor {feature} Feature", - additionalFormatters: ImmutableArray.Empty, + additionalFormatters: [], additionalResolvers: TopLevelResolvers.All, interfaces: [ @@ -27,4 +25,13 @@ internal static class RazorServices (typeof(IRemoteUriPresentationService), null), (typeof(IRemoteFoldingRangeService), null) ]); + + public static readonly RazorServiceDescriptorsWrapper JsonDescriptors = new( + ComponentName, // Needs to match the above because so much of our ServiceHub infrastructure is convention based + featureDisplayNameProvider: feature => $"Razor {feature} Feature", + jsonConverters: RazorServiceDescriptorsWrapper.GetLspConverters(), + interfaces: + [ + (typeof(IRemoteSignatureHelpService), null), + ]); } diff --git a/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/Remote/RemoteServiceProvider.cs b/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/Remote/RemoteServiceProvider.cs index 7f3a4c438f7..ebbcf00cc3b 100644 --- a/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/Remote/RemoteServiceProvider.cs +++ b/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/Remote/RemoteServiceProvider.cs @@ -49,7 +49,9 @@ internal sealed class RemoteServiceProvider( [CallerMemberName] string? callerMemberName = null) where TService : class { - var client = await TryGetClientAsync(cancellationToken).ConfigureAwait(false); + var client = typeof(IRemoteJsonService).IsAssignableFrom(typeof(TService)) + ? await TryGetJsonClientAsync(cancellationToken).ConfigureAwait(false) + : await TryGetClientAsync(cancellationToken).ConfigureAwait(false); if (client is null) { _logger.LogError($"Couldn't get remote client for {typeof(TService).Name} service"); @@ -97,6 +99,24 @@ internal sealed class RemoteServiceProvider( return remoteClient; } + private async Task TryGetJsonClientAsync(CancellationToken cancellationToken) + { + // Even if we're getting a service that wants to use Json, we still have to initialize the OOP client + // so we get the regular (MessagePack) client too. + if (!_fullyInitialized) + { + _ = await TryGetClientAsync(cancellationToken); + } + + var workspace = _workspaceProvider.GetWorkspace(); + + return await RazorRemoteHostClient.TryGetClientAsync( + workspace.Services, + RazorServices.JsonDescriptors, + RazorRemoteServiceCallbackDispatcherRegistry.Empty, + cancellationToken).ConfigureAwait(false); + } + private async Task InitializeRemoteClientAsync(RazorRemoteHostClient remoteClient, CancellationToken cancellationToken) { if (_fullyInitialized) From 3707cb34015c38cff1d88f99e18bef485add9494 Mon Sep 17 00:00:00 2001 From: David Wengier Date: Tue, 9 Jul 2024 11:18:34 +1000 Subject: [PATCH 013/176] Create remote signature help service --- eng/targets/Services.props | 1 + .../RazorLanguageServer.cs | 2 +- .../RemoteSignatureHelpService.cs | 52 +++++++++++++++++++ .../RemoteSignatureHelpServiceFactory.cs | 28 ++++++++++ .../Cohost/CohostSignatureHelpEndpoint.cs | 18 ++++--- 5 files changed, 92 insertions(+), 9 deletions(-) create mode 100644 src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/SignatureHelp/RemoteSignatureHelpService.cs create mode 100644 src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/SignatureHelp/RemoteSignatureHelpServiceFactory.cs diff --git a/eng/targets/Services.props b/eng/targets/Services.props index 9b8e60c7d2f..bd55024d8ab 100644 --- a/eng/targets/Services.props +++ b/eng/targets/Services.props @@ -22,5 +22,6 @@ + diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/RazorLanguageServer.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/RazorLanguageServer.cs index 17c412bd72b..d28cb50e47c 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/RazorLanguageServer.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/RazorLanguageServer.cs @@ -178,7 +178,6 @@ static void AddHandlers(IServiceCollection services, LanguageServerFeatureOption services.AddTransient(sp => sp.GetRequiredService()); services.AddHandlerWithCapabilities(); - services.AddHandlerWithCapabilities(); services.AddHandlerWithCapabilities(); services.AddHandlerWithCapabilities(); @@ -187,6 +186,7 @@ static void AddHandlers(IServiceCollection services, LanguageServerFeatureOption if (!featureOptions.UseRazorCohostServer) { + services.AddHandlerWithCapabilities(); services.AddHandlerWithCapabilities(); services.AddHandlerWithCapabilities(); } diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/SignatureHelp/RemoteSignatureHelpService.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/SignatureHelp/RemoteSignatureHelpService.cs new file mode 100644 index 00000000000..042e76f934b --- /dev/null +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/SignatureHelp/RemoteSignatureHelpService.cs @@ -0,0 +1,52 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT license. See License.txt in the project root for license information. + +using System.Threading; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Razor.Language; +using Microsoft.CodeAnalysis.ExternalAccess.Razor; +using Microsoft.CodeAnalysis.Razor.DocumentMapping; +using Microsoft.CodeAnalysis.Razor.Remote; +using Microsoft.CodeAnalysis.Razor.Workspaces; +using Microsoft.CodeAnalysis.Remote.Razor.ProjectSystem; +using Microsoft.CodeAnalysis.Text; +using Microsoft.ServiceHub.Framework; +using Roslyn.LanguageServer.Protocol; + +namespace Microsoft.CodeAnalysis.Remote.Razor; + +using SignatureHelp = Roslyn.LanguageServer.Protocol.SignatureHelp; + +internal sealed class RemoteSignatureHelpService( + IServiceBroker serviceBroker, + DocumentSnapshotFactory documentSnapshotFactory, + IFilePathService filePathService, + IRazorDocumentMappingService documentMappingService) + : RazorDocumentServiceBase(serviceBroker, documentSnapshotFactory), IRemoteSignatureHelpService +{ + private readonly IFilePathService _filePathService = filePathService; + private readonly IRazorDocumentMappingService _documentMappingService = documentMappingService; + + public ValueTask GetSignatureHelpAsync(JsonSerializableRazorPinnedSolutionInfoWrapper solutionInfo, JsonSerializableDocumentId documentId, Position position, CancellationToken cancellationToken) + => RunServiceAsync( + solutionInfo, + documentId, + context => GetSignatureHelpsAsync(context, position, cancellationToken), + cancellationToken); + + private async ValueTask GetSignatureHelpsAsync(RemoteDocumentContext context, Position position, CancellationToken cancellationToken) + { + var codeDocument = await context.GetCodeDocumentAsync(cancellationToken).ConfigureAwait(false); + var linePosition = new LinePosition(position.Line, position.Character); + var absoluteIndex = linePosition.GetRequiredAbsoluteIndex(codeDocument.Source.Text, logger: null); + + var generatedDocument = await context.GetGeneratedDocumentAsync(_filePathService, cancellationToken).ConfigureAwait(false); + + if (_documentMappingService.TryMapToGeneratedDocumentPosition(codeDocument.GetCSharpDocument(), absoluteIndex, out var mappedPosition, out _)) + { + return await ExternalAccess.Razor.Cohost.Handlers.SignatureHelp.GetSignatureHelpAsync(generatedDocument, mappedPosition, supportsVisualStudioExtensions: true, cancellationToken); + } + + return null; + } +} diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/SignatureHelp/RemoteSignatureHelpServiceFactory.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/SignatureHelp/RemoteSignatureHelpServiceFactory.cs new file mode 100644 index 00000000000..a7b42c9f564 --- /dev/null +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/SignatureHelp/RemoteSignatureHelpServiceFactory.cs @@ -0,0 +1,28 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT license. See License.txt in the project root for license information. + +using Microsoft.CodeAnalysis.Razor.DocumentMapping; +using Microsoft.CodeAnalysis.Razor.Remote; +using Microsoft.CodeAnalysis.Razor.Workspaces; +using Microsoft.CodeAnalysis.Remote.Razor.ProjectSystem; +using Microsoft.ServiceHub.Framework; +using Microsoft.VisualStudio.Composition; + +namespace Microsoft.CodeAnalysis.Remote.Razor; + +internal sealed class RemoteSignatureHelpServiceFactory : RazorServiceFactoryBase +{ + // WARNING: We must always have a parameterless constructor in order to be properly handled by ServiceHub. + public RemoteSignatureHelpServiceFactory() + : base(RazorServices.JsonDescriptors) + { + } + + protected override IRemoteSignatureHelpService CreateService(IServiceBroker serviceBroker, ExportProvider exportProvider) + { + var documentSnapshotFactory = exportProvider.GetExportedValue(); + var filePathService = exportProvider.GetExportedValue(); + var documentMappingService = exportProvider.GetExportedValue(); + return new RemoteSignatureHelpService(serviceBroker, documentSnapshotFactory, filePathService, documentMappingService); + } +} diff --git a/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/CohostSignatureHelpEndpoint.cs b/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/CohostSignatureHelpEndpoint.cs index 9e73c36fd52..c62481c67e0 100644 --- a/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/CohostSignatureHelpEndpoint.cs +++ b/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/CohostSignatureHelpEndpoint.cs @@ -9,13 +9,12 @@ using Microsoft.CodeAnalysis.ExternalAccess.Razor.Cohost; using Microsoft.CodeAnalysis.Razor.Logging; using Microsoft.CodeAnalysis.Razor.Remote; -using Microsoft.CodeAnalysis.Razor.Workspaces; -using Microsoft.CodeAnalysis.Razor.Workspaces.Protocol.SignatureHelp; using Microsoft.VisualStudio.LanguageServer.ContainedLanguage; using Microsoft.VisualStudio.LanguageServer.Protocol; using Microsoft.VisualStudio.Razor.LanguageClient; using Microsoft.VisualStudio.Razor.LanguageClient.Cohost; using Microsoft.VisualStudio.Razor.LanguageClient.Extensions; +using RLSP = Roslyn.LanguageServer.Protocol; namespace Microsoft.VisualStudio.LanguageServices.Razor.LanguageClient.Cohost; @@ -31,7 +30,7 @@ internal class CohostSignatureHelpEndpoint( IHtmlDocumentSynchronizer htmlDocumentSynchronizer, LSPRequestInvoker requestInvoker, ILoggerFactory loggerFactory) - : AbstractRazorCohostDocumentRequestHandler, IDynamicRegistrationProvider + : AbstractRazorCohostDocumentRequestHandler?>, IDynamicRegistrationProvider { private readonly IRemoteServiceProvider _remoteServiceProvider = remoteServiceProvider; private readonly IHtmlDocumentSynchronizer _htmlDocumentSynchronizer = htmlDocumentSynchronizer; @@ -60,21 +59,24 @@ internal class CohostSignatureHelpEndpoint( } protected override RazorTextDocumentIdentifier? GetRazorTextDocumentIdentifier(SignatureHelpParams request) - => request.TextDocument.ToRazorTextDocumentIdentifier(); + => new RazorTextDocumentIdentifier(request.TextDocument.Uri, (request.TextDocument as VSTextDocumentIdentifier)?.ProjectContext?.Id); - protected async override Task HandleRequestAsync(SignatureHelpParams request, RazorCohostRequestContext context, CancellationToken cancellationToken) + // NOTE: The use of SumType here is a little odd, but it allows us to return Roslyn LSP types from the Roslyn call, and VS LSP types from the Html + // call. It works because both sets of types are attributed the right way, so the Json ends up looking the same and the client doesn't + // care. Ideally eventually we will be able to move all of this to just Roslyn LSP types, but we might have to wait for Web Tools + protected async override Task?> HandleRequestAsync(SignatureHelpParams request, RazorCohostRequestContext context, CancellationToken cancellationToken) { var razorDocument = context.TextDocument.AssumeNotNull(); - var data = await _remoteServiceProvider.TryInvokeAsync( + var data = await _remoteServiceProvider.TryInvokeAsync( razorDocument.Project.Solution, - (service, solutionInfo, cancellationToken) => service.GetSignatureHelpAsync(solutionInfo, razorDocument.Id, request.Position.ToLinePosition(), request.Context.TriggerKind, request.Context.TriggerCharacter, cancellationToken), + (service, solutionInfo, cancellationToken) => service.GetSignatureHelpAsync(solutionInfo, razorDocument.Id, new RLSP.Position(request.Position.Line, request.Position.Character), cancellationToken), cancellationToken).ConfigureAwait(false); // If we got a response back, then either Razor or C# wants to do something with this, so we're good to go if (data is { } signatureHelp) { - return signatureHelp.ToSignatureHelp(); + return signatureHelp; } // If we didn't get anything from Razor or Roslyn, lets ask Html what they want to do From e14fff4e8944fe921cd4aef85b573d57a666d3f7 Mon Sep 17 00:00:00 2001 From: David Wengier Date: Tue, 9 Jul 2024 11:19:43 +1000 Subject: [PATCH 014/176] Cleanup --- .../SignatureHelp/RemoteSignatureHelp.cs | 26 ------------------- .../RemoteSignatureInformation.cs | 23 ---------------- 2 files changed, 49 deletions(-) delete mode 100644 src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Protocol/SignatureHelp/RemoteSignatureHelp.cs delete mode 100644 src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Protocol/SignatureHelp/RemoteSignatureInformation.cs diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Protocol/SignatureHelp/RemoteSignatureHelp.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Protocol/SignatureHelp/RemoteSignatureHelp.cs deleted file mode 100644 index ea41ff45c5a..00000000000 --- a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Protocol/SignatureHelp/RemoteSignatureHelp.cs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the MIT license. See License.txt in the project root for license information. - -using System.Collections.Generic; -using System.Linq; -using System.Runtime.Serialization; -using LSP = Microsoft.VisualStudio.LanguageServer.Protocol; - -namespace Microsoft.CodeAnalysis.Razor.Workspaces.Protocol.SignatureHelp; - -[DataContract] -internal readonly record struct RemoteSignatureHelp( - [property: DataMember(Order = 0)] int? ActiveParameter, - [property: DataMember(Order = 1)] int? ActiveSignature, - [property: DataMember(Order = 2)] RemoteSignatureInformation[] Signatures) -{ - public LSP.SignatureHelp ToSignatureHelp() - { - return new LSP.SignatureHelp() - { - ActiveParameter = this.ActiveParameter, - ActiveSignature = this.ActiveSignature, - Signatures = this.Signatures.Select(s => s.ToSignatureInformation()).ToArray() - }; - } -} diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Protocol/SignatureHelp/RemoteSignatureInformation.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Protocol/SignatureHelp/RemoteSignatureInformation.cs deleted file mode 100644 index 985d1f6bca1..00000000000 --- a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Protocol/SignatureHelp/RemoteSignatureInformation.cs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the MIT license. See License.txt in the project root for license information. - -using System.Runtime.Serialization; -using Microsoft.VisualStudio.LanguageServer.Protocol; - -namespace Microsoft.CodeAnalysis.Razor.Workspaces.Protocol.SignatureHelp; - -[DataContract] -internal readonly record struct RemoteSignatureInformation( - [property: DataMember(Order = 0)] string Label) -{ - internal SignatureInformation ToSignatureInformation() - { - return new SignatureInformation() - { - Label = this.Label, - Documentation = new MarkupContent() - { - } - }; - } -} From e8bb55ec4db502d8147e4c64f154491f57d12b04 Mon Sep 17 00:00:00 2001 From: David Wengier Date: Tue, 9 Jul 2024 11:29:15 +1000 Subject: [PATCH 015/176] Don't offer if the option is off --- .../SignatureHelp/SignatureHelpEndpoint.cs | 3 +-- .../Cohost/CohostSignatureHelpEndpoint.cs | 10 ++++++++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/SignatureHelp/SignatureHelpEndpoint.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/SignatureHelp/SignatureHelpEndpoint.cs index 657d878fc5d..167ee99201a 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/SignatureHelp/SignatureHelpEndpoint.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/SignatureHelp/SignatureHelpEndpoint.cs @@ -1,5 +1,4 @@ - -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT license. See License.txt in the project root for license information. using System.Threading; diff --git a/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/CohostSignatureHelpEndpoint.cs b/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/CohostSignatureHelpEndpoint.cs index c62481c67e0..5e9164491d0 100644 --- a/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/CohostSignatureHelpEndpoint.cs +++ b/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/CohostSignatureHelpEndpoint.cs @@ -14,6 +14,7 @@ using Microsoft.VisualStudio.Razor.LanguageClient; using Microsoft.VisualStudio.Razor.LanguageClient.Cohost; using Microsoft.VisualStudio.Razor.LanguageClient.Extensions; +using Microsoft.VisualStudio.Razor.Settings; using RLSP = Roslyn.LanguageServer.Protocol; namespace Microsoft.VisualStudio.LanguageServices.Razor.LanguageClient.Cohost; @@ -27,12 +28,14 @@ namespace Microsoft.VisualStudio.LanguageServices.Razor.LanguageClient.Cohost; #pragma warning restore RS0030 // Do not use banned APIs internal class CohostSignatureHelpEndpoint( IRemoteServiceProvider remoteServiceProvider, + IClientSettingsManager clientSettingsManager, IHtmlDocumentSynchronizer htmlDocumentSynchronizer, LSPRequestInvoker requestInvoker, ILoggerFactory loggerFactory) : AbstractRazorCohostDocumentRequestHandler?>, IDynamicRegistrationProvider { private readonly IRemoteServiceProvider _remoteServiceProvider = remoteServiceProvider; + private readonly IClientSettingsManager _clientSettingsManager = clientSettingsManager; private readonly IHtmlDocumentSynchronizer _htmlDocumentSynchronizer = htmlDocumentSynchronizer; private readonly LSPRequestInvoker _requestInvoker = requestInvoker; private readonly ILogger _logger = loggerFactory.GetOrCreateLogger(); @@ -66,6 +69,13 @@ internal class CohostSignatureHelpEndpoint( // care. Ideally eventually we will be able to move all of this to just Roslyn LSP types, but we might have to wait for Web Tools protected async override Task?> HandleRequestAsync(SignatureHelpParams request, RazorCohostRequestContext context, CancellationToken cancellationToken) { + // Return nothing if "Parameter Information" option is disabled unless signature help is invoked explicitly via command as opposed to typing or content change + if (request.Context is { TriggerKind: not SignatureHelpTriggerKind.Invoked } && + !_clientSettingsManager.GetClientSettings().ClientCompletionSettings.AutoListParams) + { + return null; + } + var razorDocument = context.TextDocument.AssumeNotNull(); var data = await _remoteServiceProvider.TryInvokeAsync( From 6e170ed71e2ee27ddc33b655766a22f3d4f288f4 Mon Sep 17 00:00:00 2001 From: David Wengier Date: Tue, 9 Jul 2024 11:35:16 +1000 Subject: [PATCH 016/176] Missed a spot --- .../SignatureHelp/RemoteSignatureHelpService.cs | 2 +- .../Remote/RemoteServiceProvider.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/SignatureHelp/RemoteSignatureHelpService.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/SignatureHelp/RemoteSignatureHelpService.cs index 042e76f934b..1546f2d991b 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/SignatureHelp/RemoteSignatureHelpService.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/SignatureHelp/RemoteSignatureHelpService.cs @@ -44,7 +44,7 @@ internal sealed class RemoteSignatureHelpService( if (_documentMappingService.TryMapToGeneratedDocumentPosition(codeDocument.GetCSharpDocument(), absoluteIndex, out var mappedPosition, out _)) { - return await ExternalAccess.Razor.Cohost.Handlers.SignatureHelp.GetSignatureHelpAsync(generatedDocument, mappedPosition, supportsVisualStudioExtensions: true, cancellationToken); + return await ExternalAccess.Razor.Cohost.Handlers.SignatureHelp.GetSignatureHelpAsync(generatedDocument, mappedPosition, supportsVisualStudioExtensions: true, cancellationToken).ConfigureAwait(false); } return null; diff --git a/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/Remote/RemoteServiceProvider.cs b/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/Remote/RemoteServiceProvider.cs index ebbcf00cc3b..2fe3c3c2768 100644 --- a/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/Remote/RemoteServiceProvider.cs +++ b/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/Remote/RemoteServiceProvider.cs @@ -105,7 +105,7 @@ internal sealed class RemoteServiceProvider( // so we get the regular (MessagePack) client too. if (!_fullyInitialized) { - _ = await TryGetClientAsync(cancellationToken); + _ = await TryGetClientAsync(cancellationToken).ConfigureAwait(false); } var workspace = _workspaceProvider.GetWorkspace(); From dfdb3146b7b79ed0874976bc27c78fef58bf9331 Mon Sep 17 00:00:00 2001 From: David Wengier Date: Tue, 9 Jul 2024 11:59:57 +1000 Subject: [PATCH 017/176] PR Feedback (except things that could cause conflicts) --- .../Razor/AddUsingsCodeActionResolver.cs | 6 +---- ...omponentAccessibilityCodeActionProvider.cs | 12 ++++----- .../Razor/GenerateMethodCodeActionResolver.cs | 10 ++++---- .../CodeActions/RazorCodeActionContext.cs | 25 ++++++------------- .../Formatting/FormattingUtilities.cs | 4 +-- 5 files changed, 21 insertions(+), 36 deletions(-) diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/AddUsingsCodeActionResolver.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/AddUsingsCodeActionResolver.cs index 99daa0c1982..20c49f36af1 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/AddUsingsCodeActionResolver.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/AddUsingsCodeActionResolver.cs @@ -223,9 +223,5 @@ private static bool IsNamespaceOrPageDirective(SyntaxNode node) return false; } - private readonly struct RazorUsingDirective(RazorDirectiveSyntax node, AddImportChunkGenerator statement) - { - public readonly RazorDirectiveSyntax Node { get; } = node; - public readonly AddImportChunkGenerator Statement { get; } = statement; - } + private readonly record struct RazorUsingDirective(RazorDirectiveSyntax Node, AddImportChunkGenerator Statement); } diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/ComponentAccessibilityCodeActionProvider.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/ComponentAccessibilityCodeActionProvider.cs index e05a743feb8..880a9123192 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/ComponentAccessibilityCodeActionProvider.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/ComponentAccessibilityCodeActionProvider.cs @@ -145,7 +145,7 @@ private static async Task AddComponentAccessFromTagAsync(RazorCodeActionContext // For all the matches, add options for add @using and fully qualify foreach (var tagHelperPair in matching) { - if (tagHelperPair._fullyQualified is null) + if (tagHelperPair.FullyQualified is null) { continue; } @@ -215,7 +215,7 @@ private static async Task> FindMatchingTagHelpersAsync(Razor { if (SatisfiesRules(tagHelper.TagMatchingRules, tagName.AsSpan(), parentTagName.AsSpan(), attributes, out var caseInsensitiveMatch)) { - matching.Add(tagHelper.Name, new TagHelperPair(@short: tagHelper, caseInsensitiveMatch)); + matching.Add(tagHelper.Name, new TagHelperPair(tagHelper, caseInsensitiveMatch)); } } @@ -226,7 +226,7 @@ private static async Task> FindMatchingTagHelpersAsync(Razor { if (tagHelperPair != null && tagHelper != tagHelperPair.Short) { - tagHelperPair._fullyQualified = tagHelper; + tagHelperPair.FullyQualified = tagHelper; } } } @@ -328,10 +328,8 @@ private static bool IsTagUnknown(IStartTagSyntaxNode startTag, RazorCodeActionCo return false; } - private class TagHelperPair(TagHelperDescriptor @short, bool caseInsensitiveMatch) + private sealed record class TagHelperPair(TagHelperDescriptor Short, bool CaseInsensitiveMatch) { - public readonly TagHelperDescriptor Short = @short; - public readonly bool CaseInsensitiveMatch = caseInsensitiveMatch; - public TagHelperDescriptor? _fullyQualified = null; + public TagHelperDescriptor? FullyQualified { get; set; } } } diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/GenerateMethodCodeActionResolver.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/GenerateMethodCodeActionResolver.cs index a928981eba7..ea478048fed 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/GenerateMethodCodeActionResolver.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/GenerateMethodCodeActionResolver.cs @@ -41,12 +41,12 @@ internal sealed class GenerateMethodCodeActionResolver( private const string ReturnType = "$$ReturnType$$"; private const string MethodName = "$$MethodName$$"; private const string EventArgs = "$$EventArgs$$"; - private static readonly string s_beginningIndents = $"{FormattingUtilities.InitialIndent}{FormattingUtilities.Indent}"; + private const string BeginningIndents = $"{FormattingUtilities.InitialIndent}{FormattingUtilities.Indent}"; private static readonly string s_generateMethodTemplate = - $"{s_beginningIndents}private {ReturnType} {MethodName}({EventArgs}){Environment.NewLine}" + - s_beginningIndents + "{" + Environment.NewLine + - $"{s_beginningIndents}{FormattingUtilities.Indent}throw new global::System.NotImplementedException();{Environment.NewLine}" + - s_beginningIndents + "}"; + $"{BeginningIndents}private {ReturnType} {MethodName}({EventArgs}){Environment.NewLine}" + + BeginningIndents + "{" + Environment.NewLine + + $"{BeginningIndents}{FormattingUtilities.Indent}throw new global::System.NotImplementedException();{Environment.NewLine}" + + BeginningIndents + "}"; public string Action => LanguageServerConstants.CodeActions.GenerateEventHandler; diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/RazorCodeActionContext.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/RazorCodeActionContext.cs index d5f737d51ae..0fc4c9e384f 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/RazorCodeActionContext.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/RazorCodeActionContext.cs @@ -9,20 +9,11 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer.CodeActions; -internal sealed class RazorCodeActionContext( - VSCodeActionParams request, - IDocumentSnapshot documentSnapshot, - RazorCodeDocument codeDocument, - SourceLocation location, - SourceText sourceText, - bool supportsFileCreation, - bool supportsCodeActionResolve) -{ - public VSCodeActionParams Request { get; } = request; - public IDocumentSnapshot DocumentSnapshot { get; } = documentSnapshot; - public RazorCodeDocument CodeDocument { get; } = codeDocument; - public SourceLocation Location { get; } = location; - public SourceText SourceText { get; } = sourceText; - public bool SupportsFileCreation { get; } = supportsFileCreation; - public bool SupportsCodeActionResolve { get; } = supportsCodeActionResolve; -} +internal sealed record class RazorCodeActionContext( + VSCodeActionParams Request, + IDocumentSnapshot DocumentSnapshot, + RazorCodeDocument CodeDocument, + SourceLocation Location, + SourceText SourceText, + bool SupportsFileCreation, + bool SupportsCodeActionResolve); diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Formatting/FormattingUtilities.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Formatting/FormattingUtilities.cs index 97895c105f3..9cd27d17513 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Formatting/FormattingUtilities.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Formatting/FormattingUtilities.cs @@ -8,8 +8,8 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer.Formatting; internal static class FormattingUtilities { - public static readonly string Indent = "$$Indent$$"; - public static readonly string InitialIndent = "$$InitialIndent$$"; + public const string Indent = "$$Indent$$"; + public const string InitialIndent = "$$InitialIndent$$"; /// /// Adds indenting to the method. From ce9be80f6cbc7b6e21cc572fefb1d8475c8e212a Mon Sep 17 00:00:00 2001 From: David Wengier Date: Tue, 9 Jul 2024 13:47:01 +1000 Subject: [PATCH 018/176] Fix build --- .../CSharp/TypeAccessibilityCodeActionProviderTest.cs | 2 +- .../Razor/ComponentAccessibilityCodeActionProviderTest.cs | 3 +-- .../Razor/ExtractToCodeBehindCodeActionProviderTest.cs | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/CSharp/TypeAccessibilityCodeActionProviderTest.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/CSharp/TypeAccessibilityCodeActionProviderTest.cs index 292c08cd818..faebcb9c5c5 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/CSharp/TypeAccessibilityCodeActionProviderTest.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/CSharp/TypeAccessibilityCodeActionProviderTest.cs @@ -479,7 +479,7 @@ private static RazorCodeActionContext CreateRazorCodeActionContext( var sourceText = SourceText.From(text); - var context = new RazorCodeActionContext(request, documentSnapshot, codeDocument, location, sourceText, supportsFileCreation, supportsCodeActionResolve: supportsCodeActionResolve); + var context = new RazorCodeActionContext(request, documentSnapshot, codeDocument, location, sourceText, supportsFileCreation, supportsCodeActionResolve); return context; } diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/Razor/ComponentAccessibilityCodeActionProviderTest.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/Razor/ComponentAccessibilityCodeActionProviderTest.cs index 14b5da0614e..d8be67e5eb2 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/Razor/ComponentAccessibilityCodeActionProviderTest.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/Razor/ComponentAccessibilityCodeActionProviderTest.cs @@ -2,7 +2,6 @@ // Licensed under the MIT license. See License.txt in the project root for license information. using System; -using System.Collections.Generic; using System.Collections.Immutable; using System.Threading; using System.Threading.Tasks; @@ -480,7 +479,7 @@ private static RazorCodeActionContext CreateRazorCodeActionContext(VSCodeActionP var sourceText = SourceText.From(text); - var context = new RazorCodeActionContext(request, documentSnapshot, codeDocument, location, sourceText, supportsFileCreation, supportsCodeActionResolve: true); + var context = new RazorCodeActionContext(request, documentSnapshot, codeDocument, location, sourceText, supportsFileCreation, SupportsCodeActionResolve: true); return context; } diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/Razor/ExtractToCodeBehindCodeActionProviderTest.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/Razor/ExtractToCodeBehindCodeActionProviderTest.cs index 524fb6746f2..4b5b94fd9cb 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/Razor/ExtractToCodeBehindCodeActionProviderTest.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/Razor/ExtractToCodeBehindCodeActionProviderTest.cs @@ -405,7 +405,7 @@ private static RazorCodeActionContext CreateRazorCodeActionContext(VSCodeActionP var sourceText = SourceText.From(text); - var context = new RazorCodeActionContext(request, documentSnapshot, codeDocument, location, sourceText, supportsFileCreation, supportsCodeActionResolve: true); + var context = new RazorCodeActionContext(request, documentSnapshot, codeDocument, location, sourceText, supportsFileCreation, SupportsCodeActionResolve: true); return context; } From e90920af7f43ce453175ae1032cd7a7e1ca447a0 Mon Sep 17 00:00:00 2001 From: David Wengier Date: Tue, 9 Jul 2024 18:13:22 +1000 Subject: [PATCH 019/176] Allow tests to intercept a static method call --- .../IBrokeredServiceInterceptor.cs | 20 +++++++++++++++++++ .../RazorServiceBase.cs | 6 ++++-- 2 files changed, 24 insertions(+), 2 deletions(-) create mode 100644 src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/IBrokeredServiceInterceptor.cs diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/IBrokeredServiceInterceptor.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/IBrokeredServiceInterceptor.cs new file mode 100644 index 00000000000..a2a3c23a48b --- /dev/null +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/IBrokeredServiceInterceptor.cs @@ -0,0 +1,20 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT license. See License.txt in the project root for license information. + +using System; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.ExternalAccess.Razor; +using Microsoft.CodeAnalysis.ExternalAccess.Razor.Api; + +namespace Microsoft.CodeAnalysis.Remote.Razor; + +/// +/// An abstraction to avoid calling the static helper defined in Roslyn +/// +internal interface IBrokeredServiceInterceptor +{ + ValueTask RunServiceAsync(Func implementation, CancellationToken cancellationToken); + + ValueTask RunServiceAsync(RazorPinnedSolutionInfoWrapper solutionInfo, Func> implementation, CancellationToken cancellationToken); +} diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorServiceBase.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorServiceBase.cs index 28f1d6accbb..35855fe0acb 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorServiceBase.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorServiceBase.cs @@ -13,17 +13,19 @@ namespace Microsoft.CodeAnalysis.Remote.Razor; internal abstract class RazorServiceBase : IDisposable { private readonly ServiceBrokerClient _serviceBrokerClient; + private readonly IBrokeredServiceInterceptor? _brokeredServiceInterceptor; public RazorServiceBase(IServiceBroker serviceBroker) { + _brokeredServiceInterceptor = serviceBroker as IBrokeredServiceInterceptor; _serviceBrokerClient = new ServiceBrokerClient(serviceBroker, joinableTaskFactory: null); } protected ValueTask RunServiceAsync(Func implementation, CancellationToken cancellationToken) - => RazorBrokeredServiceImplementation.RunServiceAsync(implementation, cancellationToken); + => _brokeredServiceInterceptor?.RunServiceAsync(implementation, cancellationToken) ?? RazorBrokeredServiceImplementation.RunServiceAsync(implementation, cancellationToken); protected ValueTask RunServiceAsync(RazorPinnedSolutionInfoWrapper solutionInfo, Func> implementation, CancellationToken cancellationToken) - => RazorBrokeredServiceImplementation.RunServiceAsync(solutionInfo, _serviceBrokerClient, implementation, cancellationToken); + => _brokeredServiceInterceptor?.RunServiceAsync(solutionInfo, implementation, cancellationToken) ?? RazorBrokeredServiceImplementation.RunServiceAsync(solutionInfo, _serviceBrokerClient, implementation, cancellationToken); public void Dispose() { From e0373016d88a504bd13b029d84ec2862a9d06971 Mon Sep 17 00:00:00 2001 From: David Wengier Date: Tue, 9 Jul 2024 18:13:39 +1000 Subject: [PATCH 020/176] Allow tests to call into the endpoint --- .../CohostLinkedEditingRangeEndpoint.cs | 22 ++++++++++++++----- 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/CohostLinkedEditingRangeEndpoint.cs b/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/CohostLinkedEditingRangeEndpoint.cs index a05924cdf51..d78eaa7a225 100644 --- a/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/CohostLinkedEditingRangeEndpoint.cs +++ b/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/CohostLinkedEditingRangeEndpoint.cs @@ -5,6 +5,7 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.Razor; +using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.ExternalAccess.Razor.Cohost; using Microsoft.CodeAnalysis.Razor.LinkedEditingRange; using Microsoft.CodeAnalysis.Razor.Logging; @@ -53,14 +54,15 @@ internal class CohostLinkedEditingRangeEndpoint(IRemoteServiceProvider remoteSer protected override RazorTextDocumentIdentifier? GetRazorTextDocumentIdentifier(LinkedEditingRangeParams request) => request.TextDocument.ToRazorTextDocumentIdentifier(); - protected override async Task HandleRequestAsync(LinkedEditingRangeParams request, RazorCohostRequestContext context, CancellationToken cancellationToken) - { - var razorDocument = context.TextDocument.AssumeNotNull(); + protected override Task HandleRequestAsync(LinkedEditingRangeParams request, RazorCohostRequestContext context, CancellationToken cancellationToken) + => HandleRequestAsync(request, context.TextDocument.AssumeNotNull(), cancellationToken); + private async Task HandleRequestAsync(LinkedEditingRangeParams request, TextDocument razorDocument, CancellationToken cancellationToken) + { var linkedRanges = await _remoteServiceProvider.TryInvokeAsync( - razorDocument.Project.Solution, - (service, solutionInfo, cancellationToken) => service.GetRangesAsync(solutionInfo, razorDocument.Id, request.Position.ToLinePosition(), cancellationToken), - cancellationToken).ConfigureAwait(false); + razorDocument.Project.Solution, + (service, solutionInfo, cancellationToken) => service.GetRangesAsync(solutionInfo, razorDocument.Id, request.Position.ToLinePosition(), cancellationToken), + cancellationToken).ConfigureAwait(false); if (linkedRanges is [{ } span1, { } span2]) { @@ -73,4 +75,12 @@ internal class CohostLinkedEditingRangeEndpoint(IRemoteServiceProvider remoteSer return null; } + + internal TestAccessor GetTestAccessor() => new(this); + + internal readonly struct TestAccessor(CohostLinkedEditingRangeEndpoint instance) + { + public Task HandleRequestAsync(LinkedEditingRangeParams request, TextDocument razorDocument, CancellationToken cancellationToken) + => instance.HandleRequestAsync(request, razorDocument, cancellationToken); + } } From 93b8b84bda5228b214c6cc999c44991a1595bf61 Mon Sep 17 00:00:00 2001 From: David Wengier Date: Tue, 9 Jul 2024 18:13:56 +1000 Subject: [PATCH 021/176] Add tests and test infra --- ...Microsoft.CodeAnalysis.Remote.Razor.csproj | 1 + .../Cohost/CohostLinkedEditingRangeTest.cs | 81 +++++++++++++++++++ .../Cohost/CohostTestBase.cs | 57 +++++++++++++ .../Cohost/InterceptingServiceBroker.cs | 38 +++++++++ .../ShortCircuitingRemoteServiceProvider.cs | 73 +++++++++++++++++ .../Cohost/TestTraceSourceProvider.cs | 52 ++++++++++++ ...lStudio.LanguageServices.Razor.Test.csproj | 1 + 7 files changed, 303 insertions(+) create mode 100644 src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostLinkedEditingRangeTest.cs create mode 100644 src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostTestBase.cs create mode 100644 src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/InterceptingServiceBroker.cs create mode 100644 src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/ShortCircuitingRemoteServiceProvider.cs create mode 100644 src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/TestTraceSourceProvider.cs diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Microsoft.CodeAnalysis.Remote.Razor.csproj b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Microsoft.CodeAnalysis.Remote.Razor.csproj index e56c17ac547..3357fd1eb79 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Microsoft.CodeAnalysis.Remote.Razor.csproj +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Microsoft.CodeAnalysis.Remote.Razor.csproj @@ -54,6 +54,7 @@ + diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostLinkedEditingRangeTest.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostLinkedEditingRangeTest.cs new file mode 100644 index 00000000000..0420d4d9b67 --- /dev/null +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostLinkedEditingRangeTest.cs @@ -0,0 +1,81 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT license. See License.txt in the project root for license information. + +using System.Collections.Immutable; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.ExternalAccess.Razor; +using Microsoft.CodeAnalysis.Razor.LinkedEditingRange; +using Microsoft.CodeAnalysis.Razor.Workspaces; +using Microsoft.CodeAnalysis.Testing; +using Microsoft.CodeAnalysis.Text; +using Microsoft.VisualStudio.LanguageServer.Protocol; +using Microsoft.VisualStudio.Razor.LanguageClient.Cohost; +using Xunit; +using Xunit.Abstractions; + +namespace Microsoft.VisualStudio.LanguageServices.Razor.Test.Cohost; + +public class CohostLinkedEditingRangeTest(ITestOutputHelper testOutputHelper) : CohostTestBase(testOutputHelper) +{ + [Fact] + public async Task StartTag() + { + var input = """ + This is a Razor document. + + <[|$$div|]> + Here is some content. + + + The end. + """; + + await VerifyLinkedEditingRangeAsync(input); + } + + [Fact] + public async Task EndTag() + { + var input = """ + This is a Razor document. + + <[|div|]> + Here is some content. + + + The end. + """; + + await VerifyLinkedEditingRangeAsync(input); + } + + private async Task VerifyLinkedEditingRangeAsync(string input) + { + TestFileMarkupParser.GetPositionAndSpans(input, out input, out int cursorPosition, out ImmutableArray spans); + var document = CreateRazorDocument(input); + var sourceText = await document.GetTextAsync(DisposalToken); + sourceText.GetLineAndOffset(cursorPosition, out var lineIndex, out var characterIndex); + + var endpoint = new CohostLinkedEditingRangeEndpoint(RemoteServiceProvider, LoggerFactory); + + var request = new LinkedEditingRangeParams() + { + TextDocument = new TextDocumentIdentifier() + { + Uri = document.CreateUri() + }, + Position = new Position() + { + Line = lineIndex, + Character = characterIndex + } + }; + + var result = await endpoint.GetTestAccessor().HandleRequestAsync(request, document, DisposalToken); + + Assert.NotNull(result); + Assert.Equal(LinkedEditingRangeHelper.WordPattern, result.WordPattern); + Assert.Equal(spans[0], result.Ranges[0].ToTextSpan(sourceText)); + Assert.Equal(spans[1], result.Ranges[1].ToTextSpan(sourceText)); + } +} diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostTestBase.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostTestBase.cs new file mode 100644 index 00000000000..d4a7baff69a --- /dev/null +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostTestBase.cs @@ -0,0 +1,57 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT license. See License.txt in the project root for license information. + +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Razor; +using Microsoft.AspNetCore.Razor.Test.Common; +using Microsoft.AspNetCore.Razor.Test.Common.Workspaces; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Razor.Remote; +using Microsoft.CodeAnalysis.Text; +using Xunit.Abstractions; + +namespace Microsoft.VisualStudio.LanguageServices.Razor.Test.Cohost; + +public class CohostTestBase(ITestOutputHelper testOutputHelper) : WorkspaceTestBase(testOutputHelper) +{ + private readonly ITestOutputHelper _testOutputHelper = testOutputHelper; + + private IRemoteServiceProvider? _remoteServiceProvider; + + internal IRemoteServiceProvider RemoteServiceProvider => _remoteServiceProvider.AssumeNotNull(); + + protected override Task InitializeAsync() + { + _remoteServiceProvider = new ShortCircuitingRemoteServiceProvider(_testOutputHelper); + + return base.InitializeAsync(); + } + + protected TextDocument CreateRazorDocument(string input) + { + var hostProject = TestProjectData.SomeProject; + var hostDocument = TestProjectData.SomeProjectComponentFile1; + + var sourceText = SourceText.From(input); + + var solution = Workspace.CurrentSolution.AddProject(ProjectInfo.Create( + ProjectId.CreateNewId(Path.GetFileNameWithoutExtension(hostProject.FilePath)), + VersionStamp.Create(), + Path.GetFileNameWithoutExtension(hostDocument.FilePath), + Path.GetFileNameWithoutExtension(hostDocument.FilePath), + LanguageNames.CSharp, + hostDocument.FilePath)); + + solution = solution.AddAdditionalDocument( + DocumentId.CreateNewId(solution.ProjectIds.Single(), hostDocument.FilePath), + hostDocument.FilePath, + sourceText, + filePath: hostDocument.FilePath); + + var document = solution.Projects.Single().AdditionalDocuments.Single(); + + return document; + } +} diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/InterceptingServiceBroker.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/InterceptingServiceBroker.cs new file mode 100644 index 00000000000..0cee8db4187 --- /dev/null +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/InterceptingServiceBroker.cs @@ -0,0 +1,38 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT license. See License.txt in the project root for license information. + +using System; +using System.IO.Pipelines; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.ExternalAccess.Razor; +using Microsoft.CodeAnalysis.Remote.Razor; +using Microsoft.ServiceHub.Framework; + +namespace Microsoft.VisualStudio.LanguageServices.Razor.Test.Cohost; + +internal class InterceptingServiceBroker(Solution solution) : IServiceBroker, IBrokeredServiceInterceptor +{ + public event EventHandler? AvailabilityChanged { add { } remove { } } + + public ValueTask GetPipeAsync(ServiceMoniker serviceMoniker, ServiceActivationOptions options = default, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public ValueTask GetProxyAsync(ServiceRpcDescriptor serviceDescriptor, ServiceActivationOptions options = default, CancellationToken cancellationToken = default) where T : class + { + throw new NotImplementedException(); + } + + public ValueTask RunServiceAsync(Func implementation, CancellationToken cancellationToken) + { + return implementation(cancellationToken); + } + + public ValueTask RunServiceAsync(RazorPinnedSolutionInfoWrapper solutionInfo, Func> implementation, CancellationToken cancellationToken) + { + return implementation(solution); + } +} diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/ShortCircuitingRemoteServiceProvider.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/ShortCircuitingRemoteServiceProvider.cs new file mode 100644 index 00000000000..5c5f8dde01f --- /dev/null +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/ShortCircuitingRemoteServiceProvider.cs @@ -0,0 +1,73 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT license. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.ExternalAccess.Razor; +using Microsoft.CodeAnalysis.Razor.Remote; +using Microsoft.CodeAnalysis.Remote.Razor; +using Microsoft.ServiceHub.Framework; +using Nerdbank.Streams; +using Xunit; +using Xunit.Abstractions; + +namespace Microsoft.VisualStudio.LanguageServices.Razor.Test.Cohost; + +/// +/// An implementation of IRemoteServiceProvider that doesn't actually do anything remote, but rather directly calls service methods +/// +internal class ShortCircuitingRemoteServiceProvider(ITestOutputHelper testOutputHelper) : IRemoteServiceProvider +{ + private static Dictionary _factoryMap = BuildFactoryMap(); + + private readonly IServiceProvider _serviceProvider = new TestTraceSourceProvider(testOutputHelper); + + private static Dictionary BuildFactoryMap() + { + var result = new Dictionary(); + + foreach (var type in typeof(RazorServiceFactoryBase<>).Assembly.GetTypes()) + { + if (!type.IsAbstract && + typeof(IServiceHubServiceFactory).IsAssignableFrom(type)) + { + Debug.Assert(type.BaseType.GetGenericTypeDefinition() == typeof(RazorServiceFactoryBase<>)); + + var genericType = type.BaseType.GetGenericArguments().FirstOrDefault(); + if (genericType != null) + { + // ServiceHub requires a parameterless constructor, so we can safely rely on it existing too + var factory = (IServiceHubServiceFactory)Activator.CreateInstance(type); + result.Add(genericType, factory); + } + } + } + + return result; + } + + public async ValueTask TryInvokeAsync(Solution solution, Func> invocation, CancellationToken cancellationToken, [CallerFilePath] string? callerFilePath = null, [CallerMemberName] string? callerMemberName = null) where TService : class + { + Assert.True(_factoryMap.TryGetValue(typeof(TService), out var factory)); + + var testServiceBroker = new InterceptingServiceBroker(solution); + + // We don't ever use this stream, because we never really use ServiceHub, but going through its factory method means the + // remote services under test are using their full MEF composition etc. so we get excellent coverage. + var (stream, _) = FullDuplexStream.CreatePair(); + var service = (TService)await factory.CreateAsync(stream, _serviceProvider, serviceActivationOptions: default, testServiceBroker, authorizationServiceClient: default!); + + // This is never used, we short-circuited things by passing the solution direct to the InterceptingServiceBroker + var solutionInfo = new RazorPinnedSolutionInfoWrapper(); + + testOutputHelper.WriteLine($"Pretend OOP call for {typeof(TService).Name}, invocation: {Path.GetFileNameWithoutExtension(callerFilePath)}.{callerMemberName}"); + return await invocation(service, solutionInfo, cancellationToken); + } +} diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/TestTraceSourceProvider.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/TestTraceSourceProvider.cs new file mode 100644 index 00000000000..b61b1a61d3c --- /dev/null +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/TestTraceSourceProvider.cs @@ -0,0 +1,52 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT license. See License.txt in the project root for license information. + +using System; +using System.Diagnostics; +using Xunit.Abstractions; + +namespace Microsoft.VisualStudio.LanguageServices.Razor.Test.Cohost; + +/// +/// An implementation of IServiceProvider that only provides a TraceSource, that writes to test output +/// +internal class TestTraceSourceProvider(ITestOutputHelper testOutputHelper) : IServiceProvider +{ + public object GetService(Type serviceType) + { + if (serviceType == typeof(TraceSource)) + { + return new TestOutputTraceSource(testOutputHelper); + } + + throw new NotImplementedException(); + } + + private class TestOutputTraceSource : TraceSource + { + public TestOutputTraceSource(ITestOutputHelper testOutputHelper) + : base("OOP", SourceLevels.All) + { + Listeners.Add(new TestOutputTraceListener(testOutputHelper)); + } + + private class TestOutputTraceListener(ITestOutputHelper testOutputHelper) : TraceListener + { + public override void Write(string message) + { + // ITestOutputHelper doesn't have a Write method, but all we lose is some extra ServiceHub details like log level + } + + public override void WriteLine(string message) + { + // Ignore some specific ServiceHub noise, since we're not using ServiceHub anyway + if (message.StartsWith("Added local RPC method") || message == "Listening started.") + { + return; + } + + testOutputHelper.WriteLine(message); + } + } + } +} diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Microsoft.VisualStudio.LanguageServices.Razor.Test.csproj b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Microsoft.VisualStudio.LanguageServices.Razor.Test.csproj index ace810bf8ac..264ae60a47e 100644 --- a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Microsoft.VisualStudio.LanguageServices.Razor.Test.csproj +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Microsoft.VisualStudio.LanguageServices.Razor.Test.csproj @@ -24,6 +24,7 @@ + From b3711a86d7a26803f4e8baa725377b33ec63dc67 Mon Sep 17 00:00:00 2001 From: David Wengier Date: Tue, 9 Jul 2024 18:14:01 +1000 Subject: [PATCH 022/176] Minor fix --- .../Remote/RemoteServiceProvider.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/Remote/RemoteServiceProvider.cs b/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/Remote/RemoteServiceProvider.cs index 7f3a4c438f7..77361646138 100644 --- a/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/Remote/RemoteServiceProvider.cs +++ b/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/Remote/RemoteServiceProvider.cs @@ -71,7 +71,7 @@ internal sealed class RemoteServiceProvider( catch (Exception ex) when (ex is not OperationCanceledException) { var approximateCallingClassName = Path.GetFileNameWithoutExtension(callerFilePath); - _logger.LogError(ex, $"Error calling remote method for {typeof(TService).Name} service, invocation: ${approximateCallingClassName}.{callerMemberName}"); + _logger.LogError(ex, $"Error calling remote method for {typeof(TService).Name} service, invocation: {approximateCallingClassName}.{callerMemberName}"); _telemetryReporter.ReportFault(ex, "Exception calling remote method for {service}, invocation: {class}.{method}", typeof(TService).FullName, approximateCallingClassName, callerMemberName); return default; } From c467559911b97942bb9054fc05bd0c03d9f0b450 Mon Sep 17 00:00:00 2001 From: David Wengier Date: Tue, 9 Jul 2024 18:21:40 +1000 Subject: [PATCH 023/176] Whitespace --- .../Cohost/CohostLinkedEditingRangeEndpoint.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/CohostLinkedEditingRangeEndpoint.cs b/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/CohostLinkedEditingRangeEndpoint.cs index d78eaa7a225..a288d8c4883 100644 --- a/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/CohostLinkedEditingRangeEndpoint.cs +++ b/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/CohostLinkedEditingRangeEndpoint.cs @@ -60,9 +60,9 @@ internal class CohostLinkedEditingRangeEndpoint(IRemoteServiceProvider remoteSer private async Task HandleRequestAsync(LinkedEditingRangeParams request, TextDocument razorDocument, CancellationToken cancellationToken) { var linkedRanges = await _remoteServiceProvider.TryInvokeAsync( - razorDocument.Project.Solution, - (service, solutionInfo, cancellationToken) => service.GetRangesAsync(solutionInfo, razorDocument.Id, request.Position.ToLinePosition(), cancellationToken), - cancellationToken).ConfigureAwait(false); + razorDocument.Project.Solution, + (service, solutionInfo, cancellationToken) => service.GetRangesAsync(solutionInfo, razorDocument.Id, request.Position.ToLinePosition(), cancellationToken), + cancellationToken).ConfigureAwait(false); if (linkedRanges is [{ } span1, { } span2]) { From 068df13f6c2cfca909cf3520b8eaaa944210ae71 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Tue, 9 Jul 2024 11:51:59 +0200 Subject: [PATCH 024/176] [main] Update dependencies from dotnet/arcade (#10590) * Update dependencies from https://github.com/dotnet/arcade build 20240702.2 Microsoft.SourceBuild.Intermediate.arcade , Microsoft.DotNet.Arcade.Sdk From Version 8.0.0-beta.24352.1 -> To Version 9.0.0-beta.24352.2 * Install .NET 8 runtime * Update dependencies from https://github.com/dotnet/arcade build 20240702.2 Microsoft.SourceBuild.Intermediate.arcade , Microsoft.DotNet.Arcade.Sdk From Version 8.0.0-beta.24352.1 -> To Version 9.0.0-beta.24352.2 * Disable BuildWithNetFrameworkHostedCompiler --------- Co-authored-by: dotnet-maestro[bot] Co-authored-by: Jan Jones --- Directory.Build.props | 6 + azure-pipelines.yml | 8 + eng/Version.Details.xml | 8 +- eng/Versions.props | 2 +- eng/common/SetupNugetSources.ps1 | 52 +-- eng/common/SetupNugetSources.sh | 60 ++-- eng/common/build.cmd | 3 + eng/common/build.ps1 | 3 + eng/common/build.sh | 15 +- eng/common/core-templates/job/job.yml | 252 +++++++++++++ eng/common/core-templates/job/onelocbuild.yml | 121 +++++++ .../job/publish-build-assets.yml | 176 ++++++++++ .../core-templates/job/source-build.yml | 93 +++++ .../job/source-index-stage1.yml | 79 +++++ .../core-templates/jobs/codeql-build.yml | 33 ++ eng/common/core-templates/jobs/jobs.yml | 119 +++++++ .../core-templates/jobs/source-build.yml | 58 +++ .../post-build/common-variables.yml | 22 ++ .../core-templates/post-build/post-build.yml | 315 +++++++++++++++++ .../post-build/setup-maestro-vars.yml | 74 ++++ .../steps/component-governance.yml | 16 + .../steps/enable-internal-runtimes.yml | 32 ++ .../steps/enable-internal-sources.yml | 47 +++ .../core-templates/steps/generate-sbom.yml | 54 +++ .../steps/get-delegation-sas.yml | 46 +++ .../steps/get-federated-access-token.yml | 28 ++ .../steps/publish-build-artifacts.yml | 20 ++ .../core-templates/steps/publish-logs.yml | 59 ++++ .../steps/publish-pipeline-artifacts.yml | 20 ++ .../core-templates/steps/retain-build.yml | 28 ++ .../core-templates/steps/send-to-helix.yml | 93 +++++ .../core-templates/steps/source-build.yml | 129 +++++++ .../variables/pool-providers.yml | 8 + eng/common/cross/arm/sources.list.bionic | 11 - eng/common/cross/arm/sources.list.focal | 11 - eng/common/cross/arm/sources.list.jammy | 11 - eng/common/cross/arm/sources.list.jessie | 3 - eng/common/cross/arm/sources.list.xenial | 11 - eng/common/cross/arm/sources.list.zesty | 11 - eng/common/cross/arm64/sources.list.bionic | 11 - eng/common/cross/arm64/sources.list.buster | 11 - eng/common/cross/arm64/sources.list.focal | 11 - eng/common/cross/arm64/sources.list.jammy | 11 - eng/common/cross/arm64/sources.list.stretch | 12 - eng/common/cross/arm64/sources.list.xenial | 11 - eng/common/cross/arm64/sources.list.zesty | 11 - eng/common/cross/armel/sources.list.jessie | 3 - eng/common/cross/armv6/sources.list.buster | 2 - eng/common/cross/build-android-rootfs.sh | 8 +- eng/common/cross/build-rootfs.sh | 256 ++++++++++---- eng/common/cross/ppc64le/sources.list.bionic | 11 - eng/common/cross/riscv64/sources.list.sid | 1 - eng/common/cross/riscv64/tizen/tizen.patch | 9 + eng/common/cross/s390x/sources.list.bionic | 11 - eng/common/cross/tizen-build-rootfs.sh | 21 ++ eng/common/cross/tizen-fetch.sh | 19 +- eng/common/cross/toolchain.cmake | 33 +- eng/common/cross/x86/sources.list.bionic | 11 - eng/common/cross/x86/sources.list.focal | 11 - eng/common/cross/x86/sources.list.jammy | 11 - eng/common/cross/x86/sources.list.xenial | 11 - eng/common/dotnet-install.sh | 5 +- eng/common/helixpublish.proj | 1 + eng/common/internal/Directory.Build.props | 7 + eng/common/internal/Tools.csproj | 3 +- eng/common/native/CommonLibrary.psm1 | 3 +- eng/common/native/init-compiler.sh | 87 +++-- eng/common/native/init-distro-rid.sh | 76 ++-- eng/common/native/init-os-and-arch.sh | 7 +- .../post-build/add-build-to-channel.ps1 | 48 --- .../post-build/check-channel-consistency.ps1 | 12 +- eng/common/post-build/nuget-validation.ps1 | 20 +- eng/common/post-build/nuget-verification.ps1 | 121 +++++++ eng/common/post-build/post-build-utils.ps1 | 91 ----- eng/common/post-build/publish-using-darc.ps1 | 7 +- eng/common/post-build/redact-logs.ps1 | 89 +++++ .../post-build/sourcelink-validation.ps1 | 10 +- eng/common/post-build/symbols-validation.ps1 | 2 - .../post-build/trigger-subscriptions.ps1 | 64 ---- eng/common/sdk-task.ps1 | 2 +- eng/common/sdl/trim-assets-version.ps1 | 2 +- eng/common/template-guidance.md | 133 +++++++ eng/common/templates-official/job/job.yml | 327 ++++------------- .../templates-official/job/onelocbuild.yml | 115 +----- .../job/publish-build-assets.yml | 160 +-------- .../templates-official/job/source-build.yml | 78 +--- .../job/source-index-stage1.yml | 86 +---- .../templates-official/jobs/codeql-build.yml | 32 +- eng/common/templates-official/jobs/jobs.yml | 100 +----- .../templates-official/jobs/source-build.yml | 57 +-- .../post-build/common-variables.yml | 26 +- .../post-build/post-build.yml | 291 +-------------- .../post-build/setup-maestro-vars.yml | 74 +--- .../post-build/trigger-subscription.yml | 13 - .../steps/add-build-to-channel.yml | 13 - .../templates-official/steps/build-reason.yml | 12 - .../steps/component-governance.yml | 18 +- .../steps/enable-internal-runtimes.yml | 31 +- .../steps/enable-internal-sources.yml | 7 + .../steps/execute-codeql.yml | 32 -- .../templates-official/steps/execute-sdl.yml | 88 ----- .../steps/generate-sbom.yml | 51 +-- .../steps/get-delegation-sas.yml | 46 +-- .../steps/get-federated-access-token.yml | 33 +- .../steps/publish-build-artifacts.yml | 41 +++ .../templates-official/steps/publish-logs.yml | 26 +- .../steps/publish-pipeline-artifacts.yml | 28 ++ .../templates-official/steps/retain-build.yml | 33 +- .../steps/send-to-helix.yml | 96 +---- .../templates-official/steps/source-build.yml | 132 +------ eng/common/templates/job/execute-sdl.yml | 139 -------- eng/common/templates/job/job.yml | 332 +++++------------- eng/common/templates/job/onelocbuild.yml | 112 +----- .../templates/job/publish-build-assets.yml | 156 +------- eng/common/templates/job/source-build.yml | 77 +--- .../templates/job/source-index-stage1.yml | 85 +---- eng/common/templates/jobs/codeql-build.yml | 32 +- eng/common/templates/jobs/jobs.yml | 100 +----- eng/common/templates/jobs/source-build.yml | 57 +-- .../templates/post-build/common-variables.yml | 26 +- .../templates/post-build/post-build.yml | 287 +-------------- .../post-build/setup-maestro-vars.yml | 74 +--- .../post-build/trigger-subscription.yml | 13 - .../templates/steps/add-build-to-channel.yml | 13 - eng/common/templates/steps/build-reason.yml | 12 - .../templates/steps/component-governance.yml | 18 +- .../steps/enable-internal-runtimes.yml | 30 +- .../steps/enable-internal-sources.yml | 7 + eng/common/templates/steps/execute-codeql.yml | 32 -- eng/common/templates/steps/execute-sdl.yml | 88 ----- eng/common/templates/steps/generate-sbom.yml | 51 +-- .../templates/steps/get-delegation-sas.yml | 46 +-- .../steps/get-federated-access-token.yml | 33 +- .../steps/publish-build-artifacts.yml | 40 +++ eng/common/templates/steps/publish-logs.yml | 26 +- .../steps/publish-pipeline-artifacts.yml | 34 ++ eng/common/templates/steps/retain-build.yml | 33 +- eng/common/templates/steps/run-on-unix.yml | 7 - eng/common/templates/steps/run-on-windows.yml | 7 - .../steps/run-script-ifequalelse.yml | 33 -- eng/common/templates/steps/send-to-helix.yml | 96 +---- eng/common/templates/steps/source-build.yml | 132 +------ eng/common/templates/steps/telemetry-end.yml | 102 ------ .../templates/steps/telemetry-start.yml | 241 ------------- .../templates/variables/pool-providers.yml | 54 +-- .../templates/variables/sdl-variables.yml | 7 - eng/common/tools.ps1 | 62 ++-- eng/common/tools.sh | 39 +- global.json | 6 +- 149 files changed, 3370 insertions(+), 4838 deletions(-) create mode 100644 eng/common/build.cmd create mode 100644 eng/common/core-templates/job/job.yml create mode 100644 eng/common/core-templates/job/onelocbuild.yml create mode 100644 eng/common/core-templates/job/publish-build-assets.yml create mode 100644 eng/common/core-templates/job/source-build.yml create mode 100644 eng/common/core-templates/job/source-index-stage1.yml create mode 100644 eng/common/core-templates/jobs/codeql-build.yml create mode 100644 eng/common/core-templates/jobs/jobs.yml create mode 100644 eng/common/core-templates/jobs/source-build.yml create mode 100644 eng/common/core-templates/post-build/common-variables.yml create mode 100644 eng/common/core-templates/post-build/post-build.yml create mode 100644 eng/common/core-templates/post-build/setup-maestro-vars.yml create mode 100644 eng/common/core-templates/steps/component-governance.yml create mode 100644 eng/common/core-templates/steps/enable-internal-runtimes.yml create mode 100644 eng/common/core-templates/steps/enable-internal-sources.yml create mode 100644 eng/common/core-templates/steps/generate-sbom.yml create mode 100644 eng/common/core-templates/steps/get-delegation-sas.yml create mode 100644 eng/common/core-templates/steps/get-federated-access-token.yml create mode 100644 eng/common/core-templates/steps/publish-build-artifacts.yml create mode 100644 eng/common/core-templates/steps/publish-logs.yml create mode 100644 eng/common/core-templates/steps/publish-pipeline-artifacts.yml create mode 100644 eng/common/core-templates/steps/retain-build.yml create mode 100644 eng/common/core-templates/steps/send-to-helix.yml create mode 100644 eng/common/core-templates/steps/source-build.yml create mode 100644 eng/common/core-templates/variables/pool-providers.yml delete mode 100644 eng/common/cross/arm/sources.list.bionic delete mode 100644 eng/common/cross/arm/sources.list.focal delete mode 100644 eng/common/cross/arm/sources.list.jammy delete mode 100644 eng/common/cross/arm/sources.list.jessie delete mode 100644 eng/common/cross/arm/sources.list.xenial delete mode 100644 eng/common/cross/arm/sources.list.zesty delete mode 100644 eng/common/cross/arm64/sources.list.bionic delete mode 100644 eng/common/cross/arm64/sources.list.buster delete mode 100644 eng/common/cross/arm64/sources.list.focal delete mode 100644 eng/common/cross/arm64/sources.list.jammy delete mode 100644 eng/common/cross/arm64/sources.list.stretch delete mode 100644 eng/common/cross/arm64/sources.list.xenial delete mode 100644 eng/common/cross/arm64/sources.list.zesty delete mode 100644 eng/common/cross/armel/sources.list.jessie delete mode 100644 eng/common/cross/armv6/sources.list.buster delete mode 100644 eng/common/cross/ppc64le/sources.list.bionic delete mode 100644 eng/common/cross/riscv64/sources.list.sid create mode 100644 eng/common/cross/riscv64/tizen/tizen.patch delete mode 100644 eng/common/cross/s390x/sources.list.bionic delete mode 100644 eng/common/cross/x86/sources.list.bionic delete mode 100644 eng/common/cross/x86/sources.list.focal delete mode 100644 eng/common/cross/x86/sources.list.jammy delete mode 100644 eng/common/cross/x86/sources.list.xenial delete mode 100644 eng/common/post-build/add-build-to-channel.ps1 create mode 100644 eng/common/post-build/nuget-verification.ps1 delete mode 100644 eng/common/post-build/post-build-utils.ps1 create mode 100644 eng/common/post-build/redact-logs.ps1 delete mode 100644 eng/common/post-build/trigger-subscriptions.ps1 create mode 100644 eng/common/template-guidance.md delete mode 100644 eng/common/templates-official/post-build/trigger-subscription.yml delete mode 100644 eng/common/templates-official/steps/add-build-to-channel.yml delete mode 100644 eng/common/templates-official/steps/build-reason.yml create mode 100644 eng/common/templates-official/steps/enable-internal-sources.yml delete mode 100644 eng/common/templates-official/steps/execute-codeql.yml delete mode 100644 eng/common/templates-official/steps/execute-sdl.yml create mode 100644 eng/common/templates-official/steps/publish-build-artifacts.yml create mode 100644 eng/common/templates-official/steps/publish-pipeline-artifacts.yml delete mode 100644 eng/common/templates/job/execute-sdl.yml delete mode 100644 eng/common/templates/post-build/trigger-subscription.yml delete mode 100644 eng/common/templates/steps/add-build-to-channel.yml delete mode 100644 eng/common/templates/steps/build-reason.yml create mode 100644 eng/common/templates/steps/enable-internal-sources.yml delete mode 100644 eng/common/templates/steps/execute-codeql.yml delete mode 100644 eng/common/templates/steps/execute-sdl.yml create mode 100644 eng/common/templates/steps/publish-build-artifacts.yml create mode 100644 eng/common/templates/steps/publish-pipeline-artifacts.yml delete mode 100644 eng/common/templates/steps/run-on-unix.yml delete mode 100644 eng/common/templates/steps/run-on-windows.yml delete mode 100644 eng/common/templates/steps/run-script-ifequalelse.yml delete mode 100644 eng/common/templates/steps/telemetry-end.yml delete mode 100644 eng/common/templates/steps/telemetry-start.yml delete mode 100644 eng/common/templates/variables/sdl-variables.yml diff --git a/Directory.Build.props b/Directory.Build.props index 46ae24b7b81..d2e322d1332 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -42,6 +42,12 @@ true net472 + + + false - + https://github.com/dotnet/arcade - 8b879da4e449c48d99f3f642fc429379a64e8fe8 + 4a7d983f833d6b86365ea1b2b4d6ee72fbdbf944 diff --git a/eng/Versions.props b/eng/Versions.props index 2ccc43bcf3f..ab3d814a8d8 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -50,7 +50,7 @@ 6.0.2-servicing.22064.6 6.0.1 9.0.0-alpha.1.24304.1 - 8.0.0-beta.24352.1 + 9.0.0-beta.24352.2 1.0.0-beta.23475.1 1.0.0-beta.23475.1 4.11.0-3.24303.3 diff --git a/eng/common/SetupNugetSources.ps1 b/eng/common/SetupNugetSources.ps1 index efa2fd72bfa..2b0a5c9e665 100644 --- a/eng/common/SetupNugetSources.ps1 +++ b/eng/common/SetupNugetSources.ps1 @@ -1,17 +1,10 @@ -# This file is a temporary workaround for internal builds to be able to restore from private AzDO feeds. -# This file should be removed as part of this issue: https://github.com/dotnet/arcade/issues/4080 +# This script adds internal feeds required to build commits that depend on internal package sources. For instance, +# dotnet6-internal would be added automatically if dotnet6 was found in the nuget.config file. In addition also enables +# disabled internal Maestro (darc-int*) feeds. # -# What the script does is iterate over all package sources in the pointed NuGet.config and add a credential entry -# under for each Maestro managed private feed. Two additional credential -# entries are also added for the two private static internal feeds: dotnet3-internal and dotnet3-internal-transport. +# Optionally, this script also adds a credential entry for each of the internal feeds if supplied. # -# This script needs to be called in every job that will restore packages and which the base repo has -# private AzDO feeds in the NuGet.config. -# -# See example YAML call for this script below. Note the use of the variable `$(dn-bot-dnceng-artifact-feeds-rw)` -# from the AzureDevOps-Artifact-Feeds-Pats variable group. -# -# Any disabledPackageSources entries which start with "darc-int" will be re-enabled as part of this script executing +# See example call for this script below. # # - task: PowerShell@2 # displayName: Setup Private Feeds Credentials @@ -21,11 +14,18 @@ # arguments: -ConfigFile $(Build.SourcesDirectory)/NuGet.config -Password $Env:Token # env: # Token: $(dn-bot-dnceng-artifact-feeds-rw) +# +# Note that the NuGetAuthenticate task should be called after SetupNugetSources. +# This ensures that: +# - Appropriate creds are set for the added internal feeds (if not supplied to the scrupt) +# - The credential provider is installed. +# +# This logic is also abstracted into enable-internal-sources.yml. [CmdletBinding()] param ( [Parameter(Mandatory = $true)][string]$ConfigFile, - [Parameter(Mandatory = $true)][string]$Password + $Password ) $ErrorActionPreference = "Stop" @@ -48,11 +48,17 @@ function AddPackageSource($sources, $SourceName, $SourceEndPoint, $creds, $Usern else { Write-Host "Package source $SourceName already present." } + AddCredential -Creds $creds -Source $SourceName -Username $Username -pwd $pwd } # Add a credential node for the specified source function AddCredential($creds, $source, $username, $pwd) { + # If no cred supplied, don't do anything. + if (!$pwd) { + return; + } + # Looks for credential configuration for the given SourceName. Create it if none is found. $sourceElement = $creds.SelectSingleNode($Source) if ($sourceElement -eq $null) @@ -110,11 +116,6 @@ if (!(Test-Path $ConfigFile -PathType Leaf)) { ExitWithExitCode 1 } -if (!$Password) { - Write-PipelineTelemetryError -Category 'Build' -Message 'Eng/common/SetupNugetSources.ps1 returned a non-zero exit code. Please supply a valid PAT' - ExitWithExitCode 1 -} - # Load NuGet.config $doc = New-Object System.Xml.XmlDocument $filename = (Get-Item $ConfigFile).FullName @@ -127,11 +128,14 @@ if ($sources -eq $null) { $doc.DocumentElement.AppendChild($sources) | Out-Null } -# Looks for a node. Create it if none is found. -$creds = $doc.DocumentElement.SelectSingleNode("packageSourceCredentials") -if ($creds -eq $null) { - $creds = $doc.CreateElement("packageSourceCredentials") - $doc.DocumentElement.AppendChild($creds) | Out-Null +$creds = $null +if ($Password) { + # Looks for a node. Create it if none is found. + $creds = $doc.DocumentElement.SelectSingleNode("packageSourceCredentials") + if ($creds -eq $null) { + $creds = $doc.CreateElement("packageSourceCredentials") + $doc.DocumentElement.AppendChild($creds) | Out-Null + } } # Check for disabledPackageSources; we'll enable any darc-int ones we find there @@ -164,4 +168,4 @@ foreach ($dotnetVersion in $dotnetVersions) { } } -$doc.Save($filename) \ No newline at end of file +$doc.Save($filename) diff --git a/eng/common/SetupNugetSources.sh b/eng/common/SetupNugetSources.sh index d387c7eac95..b493479a1da 100644 --- a/eng/common/SetupNugetSources.sh +++ b/eng/common/SetupNugetSources.sh @@ -1,28 +1,27 @@ #!/usr/bin/env bash -# This file is a temporary workaround for internal builds to be able to restore from private AzDO feeds. -# This file should be removed as part of this issue: https://github.com/dotnet/arcade/issues/4080 +# This script adds internal feeds required to build commits that depend on internal package sources. For instance, +# dotnet6-internal would be added automatically if dotnet6 was found in the nuget.config file. In addition also enables +# disabled internal Maestro (darc-int*) feeds. +# +# Optionally, this script also adds a credential entry for each of the internal feeds if supplied. # -# What the script does is iterate over all package sources in the pointed NuGet.config and add a credential entry -# under for each Maestro's managed private feed. Two additional credential -# entries are also added for the two private static internal feeds: dotnet3-internal and dotnet3-internal-transport. -# -# This script needs to be called in every job that will restore packages and which the base repo has -# private AzDO feeds in the NuGet.config. -# -# See example YAML call for this script below. Note the use of the variable `$(dn-bot-dnceng-artifact-feeds-rw)` -# from the AzureDevOps-Artifact-Feeds-Pats variable group. -# -# Any disabledPackageSources entries which start with "darc-int" will be re-enabled as part of this script executing. +# See example call for this script below. # # - task: Bash@3 -# displayName: Setup Private Feeds Credentials +# displayName: Setup Internal Feeds # inputs: # filePath: $(Build.SourcesDirectory)/eng/common/SetupNugetSources.sh -# arguments: $(Build.SourcesDirectory)/NuGet.config $Token +# arguments: $(Build.SourcesDirectory)/NuGet.config # condition: ne(variables['Agent.OS'], 'Windows_NT') -# env: -# Token: $(dn-bot-dnceng-artifact-feeds-rw) +# - task: NuGetAuthenticate@1 +# +# Note that the NuGetAuthenticate task should be called after SetupNugetSources. +# This ensures that: +# - Appropriate creds are set for the added internal feeds (if not supplied to the scrupt) +# - The credential provider is installed. +# +# This logic is also abstracted into enable-internal-sources.yml. ConfigFile=$1 CredToken=$2 @@ -48,11 +47,6 @@ if [ ! -f "$ConfigFile" ]; then ExitWithExitCode 1 fi -if [ -z "$CredToken" ]; then - Write-PipelineTelemetryError -category 'Build' "Error: Eng/common/SetupNugetSources.sh returned a non-zero exit code. Please supply a valid PAT" - ExitWithExitCode 1 -fi - if [[ `uname -s` == "Darwin" ]]; then NL=$'\\\n' TB='' @@ -140,18 +134,20 @@ PackageSources+="$IFS" PackageSources+=$(grep -oh '"darc-int-[^"]*"' $ConfigFile | tr -d '"') IFS=$PrevIFS -for FeedName in ${PackageSources[@]} ; do - # Check if there is no existing credential for this FeedName - grep -i "<$FeedName>" $ConfigFile - if [ "$?" != "0" ]; then - echo "Adding credentials for $FeedName." +if [ "$CredToken" ]; then + for FeedName in ${PackageSources[@]} ; do + # Check if there is no existing credential for this FeedName + grep -i "<$FeedName>" $ConfigFile + if [ "$?" != "0" ]; then + echo "Adding credentials for $FeedName." - PackageSourceCredentialsNodeFooter="" - NewCredential="${TB}${TB}<$FeedName>${NL}${NL}${NL}" + PackageSourceCredentialsNodeFooter="" + NewCredential="${TB}${TB}<$FeedName>${NL}${NL}${NL}" - sed -i.bak "s|$PackageSourceCredentialsNodeFooter|$NewCredential${NL}$PackageSourceCredentialsNodeFooter|" $ConfigFile - fi -done + sed -i.bak "s|$PackageSourceCredentialsNodeFooter|$NewCredential${NL}$PackageSourceCredentialsNodeFooter|" $ConfigFile + fi + done +fi # Re-enable any entries in disabledPackageSources where the feed name contains darc-int grep -i "" $ConfigFile diff --git a/eng/common/build.cmd b/eng/common/build.cmd new file mode 100644 index 00000000000..99daf368aba --- /dev/null +++ b/eng/common/build.cmd @@ -0,0 +1,3 @@ +@echo off +powershell -ExecutionPolicy ByPass -NoProfile -command "& """%~dp0build.ps1""" %*" +exit /b %ErrorLevel% diff --git a/eng/common/build.ps1 b/eng/common/build.ps1 index 33a6f2d0e24..438f9920c43 100644 --- a/eng/common/build.ps1 +++ b/eng/common/build.ps1 @@ -19,6 +19,7 @@ Param( [switch] $pack, [switch] $publish, [switch] $clean, + [switch][Alias('pb')]$productBuild, [switch][Alias('bl')]$binaryLog, [switch][Alias('nobl')]$excludeCIBinarylog, [switch] $ci, @@ -58,6 +59,7 @@ function Print-Usage() { Write-Host " -sign Sign build outputs" Write-Host " -publish Publish artifacts (e.g. symbols)" Write-Host " -clean Clean the solution" + Write-Host " -productBuild Build the solution in the way it will be built in the full .NET product (VMR) build (short: -pb)" Write-Host "" Write-Host "Advanced settings:" @@ -120,6 +122,7 @@ function Build { /p:Deploy=$deploy ` /p:Test=$test ` /p:Pack=$pack ` + /p:DotNetBuildRepo=$productBuild ` /p:IntegrationTest=$integrationTest ` /p:PerformanceTest=$performanceTest ` /p:Sign=$sign ` diff --git a/eng/common/build.sh b/eng/common/build.sh index 50af40cdd2c..ac1ee8620cd 100755 --- a/eng/common/build.sh +++ b/eng/common/build.sh @@ -22,6 +22,9 @@ usage() echo " --sourceBuild Source-build the solution (short: -sb)" echo " Will additionally trigger the following actions: --restore, --build, --pack" echo " If --configuration is not set explicitly, will also set it to 'Release'" + echo " --productBuild Build the solution in the way it will be built in the full .NET product (VMR) build (short: -pb)" + echo " Will additionally trigger the following actions: --restore, --build, --pack" + echo " If --configuration is not set explicitly, will also set it to 'Release'" echo " --rebuild Rebuild solution" echo " --test Run all unit tests in the solution (short: -t)" echo " --integrationTest Run all integration tests in the solution" @@ -59,6 +62,7 @@ scriptroot="$( cd -P "$( dirname "$source" )" && pwd )" restore=false build=false source_build=false +product_build=false rebuild=false test=false integration_test=false @@ -105,7 +109,7 @@ while [[ $# > 0 ]]; do -binarylog|-bl) binary_log=true ;; - -excludeCIBinarylog|-nobl) + -excludecibinarylog|-nobl) exclude_ci_binary_log=true ;; -pipelineslog|-pl) @@ -126,6 +130,13 @@ while [[ $# > 0 ]]; do -sourcebuild|-sb) build=true source_build=true + product_build=true + restore=true + pack=true + ;; + -productBuild|-pb) + build=true + product_build=true restore=true pack=true ;; @@ -219,7 +230,9 @@ function Build { /p:RepoRoot="$repo_root" \ /p:Restore=$restore \ /p:Build=$build \ + /p:DotNetBuildRepo=$product_build \ /p:ArcadeBuildFromSource=$source_build \ + /p:DotNetBuildSourceOnly=$source_build \ /p:Rebuild=$rebuild \ /p:Test=$test \ /p:Pack=$pack \ diff --git a/eng/common/core-templates/job/job.yml b/eng/common/core-templates/job/job.yml new file mode 100644 index 00000000000..c732bee9f4a --- /dev/null +++ b/eng/common/core-templates/job/job.yml @@ -0,0 +1,252 @@ +parameters: +# Job schema parameters - https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=vsts&tabs=schema#job + cancelTimeoutInMinutes: '' + condition: '' + container: '' + continueOnError: false + dependsOn: '' + displayName: '' + pool: '' + steps: [] + strategy: '' + timeoutInMinutes: '' + variables: [] + workspace: '' + templateContext: {} + +# Job base template specific parameters + # See schema documentation - https://github.com/dotnet/arcade/blob/master/Documentation/AzureDevOps/TemplateSchema.md + # publishing defaults + artifacts: '' + enableMicrobuild: false + enablePublishBuildArtifacts: false + enablePublishBuildAssets: false + enablePublishTestResults: false + enablePublishUsingPipelines: false + enableBuildRetry: false + mergeTestResults: false + testRunTitle: '' + testResultsFormat: '' + name: '' + componentGovernanceSteps: [] + preSteps: [] + artifactPublishSteps: [] + runAsPublic: false + +# Sbom related params + enableSbom: true + PackageVersion: 9.0.0 + BuildDropPath: '$(Build.SourcesDirectory)/artifacts' + +# 1es specific parameters + is1ESPipeline: '' + +jobs: +- job: ${{ parameters.name }} + + ${{ if ne(parameters.cancelTimeoutInMinutes, '') }}: + cancelTimeoutInMinutes: ${{ parameters.cancelTimeoutInMinutes }} + + ${{ if ne(parameters.condition, '') }}: + condition: ${{ parameters.condition }} + + ${{ if ne(parameters.container, '') }}: + container: ${{ parameters.container }} + + ${{ if ne(parameters.continueOnError, '') }}: + continueOnError: ${{ parameters.continueOnError }} + + ${{ if ne(parameters.dependsOn, '') }}: + dependsOn: ${{ parameters.dependsOn }} + + ${{ if ne(parameters.displayName, '') }}: + displayName: ${{ parameters.displayName }} + + ${{ if ne(parameters.pool, '') }}: + pool: ${{ parameters.pool }} + + ${{ if ne(parameters.strategy, '') }}: + strategy: ${{ parameters.strategy }} + + ${{ if ne(parameters.timeoutInMinutes, '') }}: + timeoutInMinutes: ${{ parameters.timeoutInMinutes }} + + ${{ if ne(parameters.templateContext, '') }}: + templateContext: ${{ parameters.templateContext }} + + variables: + - ${{ if ne(parameters.enableTelemetry, 'false') }}: + - name: DOTNET_CLI_TELEMETRY_PROFILE + value: '$(Build.Repository.Uri)' + - ${{ if eq(parameters.enableRichCodeNavigation, 'true') }}: + - name: EnableRichCodeNavigation + value: 'true' + # Retry signature validation up to three times, waiting 2 seconds between attempts. + # See https://learn.microsoft.com/en-us/nuget/reference/errors-and-warnings/nu3028#retry-untrusted-root-failures + - name: NUGET_EXPERIMENTAL_CHAIN_BUILD_RETRY_POLICY + value: 3,2000 + - ${{ each variable in parameters.variables }}: + # handle name-value variable syntax + # example: + # - name: [key] + # value: [value] + - ${{ if ne(variable.name, '') }}: + - name: ${{ variable.name }} + value: ${{ variable.value }} + + # handle variable groups + - ${{ if ne(variable.group, '') }}: + - group: ${{ variable.group }} + + # handle template variable syntax + # example: + # - template: path/to/template.yml + # parameters: + # [key]: [value] + - ${{ if ne(variable.template, '') }}: + - template: ${{ variable.template }} + ${{ if ne(variable.parameters, '') }}: + parameters: ${{ variable.parameters }} + + # handle key-value variable syntax. + # example: + # - [key]: [value] + - ${{ if and(eq(variable.name, ''), eq(variable.group, ''), eq(variable.template, '')) }}: + - ${{ each pair in variable }}: + - name: ${{ pair.key }} + value: ${{ pair.value }} + + # DotNet-HelixApi-Access provides 'HelixApiAccessToken' for internal builds + - ${{ if and(eq(parameters.enableTelemetry, 'true'), eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: + - group: DotNet-HelixApi-Access + + ${{ if ne(parameters.workspace, '') }}: + workspace: ${{ parameters.workspace }} + + steps: + - ${{ if eq(parameters.is1ESPipeline, '') }}: + - 'Illegal entry point, is1ESPipeline is not defined. Repository yaml should not directly reference templates in core-templates folder.': error + + - ${{ if ne(parameters.preSteps, '') }}: + - ${{ each preStep in parameters.preSteps }}: + - ${{ preStep }} + + - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: + - ${{ if eq(parameters.enableMicrobuild, 'true') }}: + - task: MicroBuildSigningPlugin@4 + displayName: Install MicroBuild plugin + inputs: + signType: $(_SignType) + zipSources: false + feedSource: https://dnceng.pkgs.visualstudio.com/_packaging/MicroBuildToolset/nuget/v3/index.json + env: + TeamName: $(_TeamName) + MicroBuildOutputFolderOverride: '$(Agent.TempDirectory)' + continueOnError: ${{ parameters.continueOnError }} + condition: and(succeeded(), in(variables['_SignType'], 'real', 'test'), eq(variables['Agent.Os'], 'Windows_NT')) + + - ${{ if and(eq(parameters.runAsPublic, 'false'), eq(variables['System.TeamProject'], 'internal')) }}: + - task: NuGetAuthenticate@1 + + - ${{ if and(ne(parameters.artifacts.download, 'false'), ne(parameters.artifacts.download, '')) }}: + - task: DownloadPipelineArtifact@2 + inputs: + buildType: current + artifactName: ${{ coalesce(parameters.artifacts.download.name, 'Artifacts_$(Agent.OS)_$(_BuildConfig)') }} + targetPath: ${{ coalesce(parameters.artifacts.download.path, 'artifacts') }} + itemPattern: ${{ coalesce(parameters.artifacts.download.pattern, '**') }} + + - ${{ each step in parameters.steps }}: + - ${{ step }} + + - ${{ if eq(parameters.enableRichCodeNavigation, true) }}: + - task: RichCodeNavIndexer@0 + displayName: RichCodeNav Upload + inputs: + languages: ${{ coalesce(parameters.richCodeNavigationLanguage, 'csharp') }} + environment: ${{ coalesce(parameters.richCodeNavigationEnvironment, 'internal') }} + richNavLogOutputDirectory: $(Build.SourcesDirectory)/artifacts/bin + uploadRichNavArtifacts: ${{ coalesce(parameters.richCodeNavigationUploadArtifacts, false) }} + continueOnError: true + + - ${{ each step in parameters.componentGovernanceSteps }}: + - ${{ step }} + + - ${{ if eq(parameters.enableMicrobuild, 'true') }}: + - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: + - task: MicroBuildCleanup@1 + displayName: Execute Microbuild cleanup tasks + condition: and(always(), in(variables['_SignType'], 'real', 'test'), eq(variables['Agent.Os'], 'Windows_NT')) + continueOnError: ${{ parameters.continueOnError }} + env: + TeamName: $(_TeamName) + + # Publish test results + - ${{ if or(and(eq(parameters.enablePublishTestResults, 'true'), eq(parameters.testResultsFormat, '')), eq(parameters.testResultsFormat, 'xunit')) }}: + - task: PublishTestResults@2 + displayName: Publish XUnit Test Results + inputs: + testResultsFormat: 'xUnit' + testResultsFiles: '*.xml' + searchFolder: '$(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig)' + testRunTitle: ${{ coalesce(parameters.testRunTitle, parameters.name, '$(System.JobName)') }}-xunit + mergeTestResults: ${{ parameters.mergeTestResults }} + continueOnError: true + condition: always() + - ${{ if or(and(eq(parameters.enablePublishTestResults, 'true'), eq(parameters.testResultsFormat, '')), eq(parameters.testResultsFormat, 'vstest')) }}: + - task: PublishTestResults@2 + displayName: Publish TRX Test Results + inputs: + testResultsFormat: 'VSTest' + testResultsFiles: '*.trx' + searchFolder: '$(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig)' + testRunTitle: ${{ coalesce(parameters.testRunTitle, parameters.name, '$(System.JobName)') }}-trx + mergeTestResults: ${{ parameters.mergeTestResults }} + continueOnError: true + condition: always() + + # gather artifacts + - ${{ if ne(parameters.artifacts.publish, '') }}: + - ${{ if and(ne(parameters.artifacts.publish.artifacts, 'false'), ne(parameters.artifacts.publish.artifacts, '')) }}: + - task: CopyFiles@2 + displayName: Gather binaries for publish to artifacts + inputs: + SourceFolder: 'artifacts/bin' + Contents: '**' + TargetFolder: '$(Build.ArtifactStagingDirectory)/artifacts/bin' + - task: CopyFiles@2 + displayName: Gather packages for publish to artifacts + inputs: + SourceFolder: 'artifacts/packages' + Contents: '**' + TargetFolder: '$(Build.ArtifactStagingDirectory)/artifacts/packages' + - ${{ if and(ne(parameters.artifacts.publish.logs, 'false'), ne(parameters.artifacts.publish.logs, '')) }}: + - task: CopyFiles@2 + displayName: Gather logs for publish to artifacts + inputs: + SourceFolder: 'artifacts/log' + Contents: '**' + TargetFolder: '$(Build.ArtifactStagingDirectory)/artifacts/log' + continueOnError: true + condition: always() + + - ${{ if eq(parameters.enablePublishBuildArtifacts, 'true') }}: + - task: CopyFiles@2 + displayName: Gather logs for publish to artifacts + inputs: + SourceFolder: 'artifacts/log/$(_BuildConfig)' + Contents: '**' + TargetFolder: '$(Build.ArtifactStagingDirectory)/artifacts/log/$(_BuildConfig)' + continueOnError: true + condition: always() + - ${{ if eq(parameters.enableBuildRetry, 'true') }}: + - task: CopyFiles@2 + displayName: Gather buildconfiguration for build retry + inputs: + SourceFolder: '$(Build.SourcesDirectory)/eng/common/BuildConfiguration' + Contents: '**' + TargetFolder: '$(Build.ArtifactStagingDirectory)/eng/common/BuildConfiguration' + continueOnError: true + condition: always() + - ${{ each step in parameters.artifactPublishSteps }}: + - ${{ step }} diff --git a/eng/common/core-templates/job/onelocbuild.yml b/eng/common/core-templates/job/onelocbuild.yml new file mode 100644 index 00000000000..00feec8ebbc --- /dev/null +++ b/eng/common/core-templates/job/onelocbuild.yml @@ -0,0 +1,121 @@ +parameters: + # Optional: dependencies of the job + dependsOn: '' + + # Optional: A defined YAML pool - https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=vsts&tabs=schema#pool + pool: '' + + CeapexPat: $(dn-bot-ceapex-package-r) # PAT for the loc AzDO instance https://dev.azure.com/ceapex + GithubPat: $(BotAccount-dotnet-bot-repo-PAT) + + SourcesDirectory: $(Build.SourcesDirectory) + CreatePr: true + AutoCompletePr: false + ReusePr: true + UseLfLineEndings: true + UseCheckedInLocProjectJson: false + SkipLocProjectJsonGeneration: false + LanguageSet: VS_Main_Languages + LclSource: lclFilesInRepo + LclPackageId: '' + RepoType: gitHub + GitHubOrg: dotnet + MirrorRepo: '' + MirrorBranch: main + condition: '' + JobNameSuffix: '' + is1ESPipeline: '' +jobs: +- job: OneLocBuild${{ parameters.JobNameSuffix }} + + dependsOn: ${{ parameters.dependsOn }} + + displayName: OneLocBuild${{ parameters.JobNameSuffix }} + + variables: + - group: OneLocBuildVariables # Contains the CeapexPat and GithubPat + - name: _GenerateLocProjectArguments + value: -SourcesDirectory ${{ parameters.SourcesDirectory }} + -LanguageSet "${{ parameters.LanguageSet }}" + -CreateNeutralXlfs + - ${{ if eq(parameters.UseCheckedInLocProjectJson, 'true') }}: + - name: _GenerateLocProjectArguments + value: ${{ variables._GenerateLocProjectArguments }} -UseCheckedInLocProjectJson + - template: /eng/common/core-templates/variables/pool-providers.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + + ${{ if ne(parameters.pool, '') }}: + pool: ${{ parameters.pool }} + ${{ if eq(parameters.pool, '') }}: + pool: + # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) + ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: + name: AzurePipelines-EO + image: 1ESPT-Windows2022 + demands: Cmd + os: windows + # If it's not devdiv, it's dnceng + ${{ if ne(variables['System.TeamProject'], 'DevDiv') }}: + name: $(DncEngInternalBuildPool) + image: 1es-windows-2022 + os: windows + + steps: + - ${{ if eq(parameters.is1ESPipeline, '') }}: + - 'Illegal entry point, is1ESPipeline is not defined. Repository yaml should not directly reference templates in core-templates folder.': error + + - ${{ if ne(parameters.SkipLocProjectJsonGeneration, 'true') }}: + - task: Powershell@2 + inputs: + filePath: $(Build.SourcesDirectory)/eng/common/generate-locproject.ps1 + arguments: $(_GenerateLocProjectArguments) + displayName: Generate LocProject.json + condition: ${{ parameters.condition }} + + - task: OneLocBuild@2 + displayName: OneLocBuild + env: + SYSTEM_ACCESSTOKEN: $(System.AccessToken) + inputs: + locProj: eng/Localize/LocProject.json + outDir: $(Build.ArtifactStagingDirectory) + lclSource: ${{ parameters.LclSource }} + lclPackageId: ${{ parameters.LclPackageId }} + isCreatePrSelected: ${{ parameters.CreatePr }} + isAutoCompletePrSelected: ${{ parameters.AutoCompletePr }} + ${{ if eq(parameters.CreatePr, true) }}: + isUseLfLineEndingsSelected: ${{ parameters.UseLfLineEndings }} + ${{ if eq(parameters.RepoType, 'gitHub') }}: + isShouldReusePrSelected: ${{ parameters.ReusePr }} + packageSourceAuth: patAuth + patVariable: ${{ parameters.CeapexPat }} + ${{ if eq(parameters.RepoType, 'gitHub') }}: + repoType: ${{ parameters.RepoType }} + gitHubPatVariable: "${{ parameters.GithubPat }}" + ${{ if ne(parameters.MirrorRepo, '') }}: + isMirrorRepoSelected: true + gitHubOrganization: ${{ parameters.GitHubOrg }} + mirrorRepo: ${{ parameters.MirrorRepo }} + mirrorBranch: ${{ parameters.MirrorBranch }} + condition: ${{ parameters.condition }} + + - template: /eng/common/core-templates/steps/publish-build-artifacts.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + args: + displayName: Publish Localization Files + pathToPublish: '$(Build.ArtifactStagingDirectory)/loc' + publishLocation: Container + artifactName: Loc + condition: ${{ parameters.condition }} + + - template: /eng/common/core-templates/steps/publish-build-artifacts.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + args: + displayName: Publish LocProject.json + pathToPublish: '$(Build.SourcesDirectory)/eng/Localize/' + publishLocation: Container + artifactName: Loc + condition: ${{ parameters.condition }} \ No newline at end of file diff --git a/eng/common/core-templates/job/publish-build-assets.yml b/eng/common/core-templates/job/publish-build-assets.yml new file mode 100644 index 00000000000..d99a1a3b284 --- /dev/null +++ b/eng/common/core-templates/job/publish-build-assets.yml @@ -0,0 +1,176 @@ +parameters: + configuration: 'Debug' + + # Optional: condition for the job to run + condition: '' + + # Optional: 'true' if future jobs should run even if this job fails + continueOnError: false + + # Optional: dependencies of the job + dependsOn: '' + + # Optional: Include PublishBuildArtifacts task + enablePublishBuildArtifacts: false + + # Optional: A defined YAML pool - https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=vsts&tabs=schema#pool + pool: {} + + # Optional: should run as a public build even in the internal project + # if 'true', the build won't run any of the internal only steps, even if it is running in non-public projects. + runAsPublic: false + + # Optional: whether the build's artifacts will be published using release pipelines or direct feed publishing + publishUsingPipelines: false + + # Optional: whether the build's artifacts will be published using release pipelines or direct feed publishing + publishAssetsImmediately: false + + artifactsPublishingAdditionalParameters: '' + + signingValidationAdditionalParameters: '' + + is1ESPipeline: '' + +jobs: +- job: Asset_Registry_Publish + + dependsOn: ${{ parameters.dependsOn }} + timeoutInMinutes: 150 + + ${{ if eq(parameters.publishAssetsImmediately, 'true') }}: + displayName: Publish Assets + ${{ else }}: + displayName: Publish to Build Asset Registry + + variables: + - template: /eng/common/core-templates/variables/pool-providers.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: + - group: Publish-Build-Assets + - group: AzureDevOps-Artifact-Feeds-Pats + - name: runCodesignValidationInjection + value: false + # unconditional - needed for logs publishing (redactor tool version) + - template: /eng/common/core-templates/post-build/common-variables.yml + + pool: + # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) + ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: + name: AzurePipelines-EO + image: 1ESPT-Windows2022 + demands: Cmd + os: windows + # If it's not devdiv, it's dnceng + ${{ if ne(variables['System.TeamProject'], 'DevDiv') }}: + name: NetCore1ESPool-Publishing-Internal + image: windows.vs2019.amd64 + os: windows + steps: + - ${{ if eq(parameters.is1ESPipeline, '') }}: + - 'Illegal entry point, is1ESPipeline is not defined. Repository yaml should not directly reference templates in core-templates folder.': error + + - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: + - checkout: self + fetchDepth: 3 + clean: true + + - task: DownloadBuildArtifacts@0 + displayName: Download artifact + inputs: + artifactName: AssetManifests + downloadPath: '$(Build.StagingDirectory)/Download' + checkDownloadedFiles: true + condition: ${{ parameters.condition }} + continueOnError: ${{ parameters.continueOnError }} + + - task: NuGetAuthenticate@1 + + - task: AzureCLI@2 + displayName: Publish Build Assets + inputs: + azureSubscription: "Darc: Maestro Production" + scriptType: ps + scriptLocation: scriptPath + scriptPath: $(Build.SourcesDirectory)/eng/common/sdk-task.ps1 + arguments: -task PublishBuildAssets -restore -msbuildEngine dotnet + /p:ManifestsPath='$(Build.StagingDirectory)/Download/AssetManifests' + /p:MaestroApiEndpoint=https://maestro.dot.net + /p:PublishUsingPipelines=${{ parameters.publishUsingPipelines }} + /p:OfficialBuildId=$(Build.BuildNumber) + condition: ${{ parameters.condition }} + continueOnError: ${{ parameters.continueOnError }} + + - task: powershell@2 + displayName: Create ReleaseConfigs Artifact + inputs: + targetType: inline + script: | + New-Item -Path "$(Build.StagingDirectory)/ReleaseConfigs" -ItemType Directory -Force + $filePath = "$(Build.StagingDirectory)/ReleaseConfigs/ReleaseConfigs.txt" + Add-Content -Path $filePath -Value $(BARBuildId) + Add-Content -Path $filePath -Value "$(DefaultChannels)" + Add-Content -Path $filePath -Value $(IsStableBuild) + + - template: /eng/common/core-templates/steps/publish-build-artifacts.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + args: + displayName: Publish ReleaseConfigs Artifact + pathToPublish: '$(Build.StagingDirectory)/ReleaseConfigs' + publishLocation: Container + artifactName: ReleaseConfigs + + - task: powershell@2 + displayName: Check if SymbolPublishingExclusionsFile.txt exists + inputs: + targetType: inline + script: | + $symbolExclusionfile = "$(Build.SourcesDirectory)/eng/SymbolPublishingExclusionsFile.txt" + if(Test-Path -Path $symbolExclusionfile) + { + Write-Host "SymbolExclusionFile exists" + Write-Host "##vso[task.setvariable variable=SymbolExclusionFile]true" + } + else{ + Write-Host "Symbols Exclusion file does not exist" + Write-Host "##vso[task.setvariable variable=SymbolExclusionFile]false" + } + + - template: /eng/common/core-templates/steps/publish-build-artifacts.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + args: + displayName: Publish SymbolPublishingExclusionsFile Artifact + condition: eq(variables['SymbolExclusionFile'], 'true') + pathToPublish: '$(Build.SourcesDirectory)/eng/SymbolPublishingExclusionsFile.txt' + publishLocation: Container + artifactName: ReleaseConfigs + + - ${{ if eq(parameters.publishAssetsImmediately, 'true') }}: + - template: /eng/common/core-templates/post-build/setup-maestro-vars.yml + parameters: + BARBuildId: ${{ parameters.BARBuildId }} + PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} + is1ESPipeline: ${{ parameters.is1ESPipeline }} + + - task: AzureCLI@2 + displayName: Publish Using Darc + inputs: + azureSubscription: "Darc: Maestro Production" + scriptType: ps + scriptLocation: scriptPath + scriptPath: $(Build.SourcesDirectory)/eng/common/post-build/publish-using-darc.ps1 + arguments: -BuildId $(BARBuildId) + -PublishingInfraVersion 3 + -AzdoToken '$(publishing-dnceng-devdiv-code-r-build-re)' + -WaitPublishingFinish true + -ArtifactsPublishingAdditionalParameters '${{ parameters.artifactsPublishingAdditionalParameters }}' + -SymbolPublishingAdditionalParameters '${{ parameters.symbolPublishingAdditionalParameters }}' + + - ${{ if eq(parameters.enablePublishBuildArtifacts, 'true') }}: + - template: /eng/common/core-templates/steps/publish-logs.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + JobLabel: 'Publish_Artifacts_Logs' diff --git a/eng/common/core-templates/job/source-build.yml b/eng/common/core-templates/job/source-build.yml new file mode 100644 index 00000000000..c4713c8b6ed --- /dev/null +++ b/eng/common/core-templates/job/source-build.yml @@ -0,0 +1,93 @@ +parameters: + # This template adds arcade-powered source-build to CI. The template produces a server job with a + # default ID 'Source_Build_Complete' to put in a dependency list if necessary. + + # Specifies the prefix for source-build jobs added to pipeline. Use this if disambiguation needed. + jobNamePrefix: 'Source_Build' + + # Defines the platform on which to run the job. By default, a linux-x64 machine, suitable for + # managed-only repositories. This is an object with these properties: + # + # name: '' + # The name of the job. This is included in the job ID. + # targetRID: '' + # The name of the target RID to use, instead of the one auto-detected by Arcade. + # nonPortable: false + # Enables non-portable mode. This means a more specific RID (e.g. fedora.32-x64 rather than + # linux-x64), and compiling against distro-provided packages rather than portable ones. + # skipPublishValidation: false + # Disables publishing validation. By default, a check is performed to ensure no packages are + # published by source-build. + # container: '' + # A container to use. Runs in docker. + # pool: {} + # A pool to use. Runs directly on an agent. + # buildScript: '' + # Specifies the build script to invoke to perform the build in the repo. The default + # './build.sh' should work for typical Arcade repositories, but this is customizable for + # difficult situations. + # jobProperties: {} + # A list of job properties to inject at the top level, for potential extensibility beyond + # container and pool. + platform: {} + + is1ESPipeline: '' + + # If set to true and running on a non-public project, + # Internal nuget and blob storage locations will be enabled. + # This is not enabled by default because many repositories do not need internal sources + # and do not need to have the required service connections approved in the pipeline. + enableInternalSources: false + +jobs: +- job: ${{ parameters.jobNamePrefix }}_${{ parameters.platform.name }} + displayName: Source-Build (${{ parameters.platform.name }}) + + ${{ each property in parameters.platform.jobProperties }}: + ${{ property.key }}: ${{ property.value }} + + ${{ if ne(parameters.platform.container, '') }}: + container: ${{ parameters.platform.container }} + + ${{ if eq(parameters.platform.pool, '') }}: + # The default VM host AzDO pool. This should be capable of running Docker containers: almost all + # source-build builds run in Docker, including the default managed platform. + # /eng/common/core-templates/variables/pool-providers.yml can't be used here (some customers declare variables already), so duplicate its logic + ${{ if eq(parameters.is1ESPipeline, 'true') }}: + pool: + ${{ if eq(variables['System.TeamProject'], 'public') }}: + name: $[replace(replace(eq(contains(coalesce(variables['System.PullRequest.TargetBranch'], variables['Build.SourceBranch'], 'refs/heads/main'), 'release'), 'true'), True, 'NetCore-Svc-Public' ), False, 'NetCore-Public')] + demands: ImageOverride -equals build.ubuntu.2004.amd64 + ${{ if eq(variables['System.TeamProject'], 'internal') }}: + name: $[replace(replace(eq(contains(coalesce(variables['System.PullRequest.TargetBranch'], variables['Build.SourceBranch'], 'refs/heads/main'), 'release'), 'true'), True, 'NetCore1ESPool-Svc-Internal'), False, 'NetCore1ESPool-Internal')] + image: 1es-mariner-2 + os: linux + ${{ else }}: + pool: + ${{ if eq(variables['System.TeamProject'], 'public') }}: + name: $[replace(replace(eq(contains(coalesce(variables['System.PullRequest.TargetBranch'], variables['Build.SourceBranch'], 'refs/heads/main'), 'release'), 'true'), True, 'NetCore-Svc-Public' ), False, 'NetCore-Public')] + demands: ImageOverride -equals Build.Ubuntu.2204.Amd64.Open + ${{ if eq(variables['System.TeamProject'], 'internal') }}: + name: $[replace(replace(eq(contains(coalesce(variables['System.PullRequest.TargetBranch'], variables['Build.SourceBranch'], 'refs/heads/main'), 'release'), 'true'), True, 'NetCore1ESPool-Svc-Internal'), False, 'NetCore1ESPool-Internal')] + demands: ImageOverride -equals Build.Ubuntu.2204.Amd64 + ${{ if ne(parameters.platform.pool, '') }}: + pool: ${{ parameters.platform.pool }} + + workspace: + clean: all + + steps: + - ${{ if eq(parameters.is1ESPipeline, '') }}: + - 'Illegal entry point, is1ESPipeline is not defined. Repository yaml should not directly reference templates in core-templates folder.': error + + - ${{ if eq(parameters.enableInternalSources, true) }}: + - template: /eng/common/core-templates/steps/enable-internal-sources.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + - template: /eng/common/core-templates/steps/enable-internal-runtimes.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + - template: /eng/common/core-templates/steps/source-build.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + platform: ${{ parameters.platform }} diff --git a/eng/common/core-templates/job/source-index-stage1.yml b/eng/common/core-templates/job/source-index-stage1.yml new file mode 100644 index 00000000000..945c1c19e82 --- /dev/null +++ b/eng/common/core-templates/job/source-index-stage1.yml @@ -0,0 +1,79 @@ +parameters: + runAsPublic: false + sourceIndexUploadPackageVersion: 2.0.0-20240522.1 + sourceIndexProcessBinlogPackageVersion: 1.0.1-20240522.1 + sourceIndexPackageSource: https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json + sourceIndexBuildCommand: powershell -NoLogo -NoProfile -ExecutionPolicy Bypass -Command "eng/common/build.ps1 -restore -build -binarylog -ci" + preSteps: [] + binlogPath: artifacts/log/Debug/Build.binlog + condition: '' + dependsOn: '' + pool: '' + is1ESPipeline: '' + +jobs: +- job: SourceIndexStage1 + dependsOn: ${{ parameters.dependsOn }} + condition: ${{ parameters.condition }} + variables: + - name: SourceIndexUploadPackageVersion + value: ${{ parameters.sourceIndexUploadPackageVersion }} + - name: SourceIndexProcessBinlogPackageVersion + value: ${{ parameters.sourceIndexProcessBinlogPackageVersion }} + - name: SourceIndexPackageSource + value: ${{ parameters.sourceIndexPackageSource }} + - name: BinlogPath + value: ${{ parameters.binlogPath }} + - template: /eng/common/core-templates/variables/pool-providers.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + + ${{ if ne(parameters.pool, '') }}: + pool: ${{ parameters.pool }} + ${{ if eq(parameters.pool, '') }}: + pool: + ${{ if eq(variables['System.TeamProject'], 'public') }}: + name: $(DncEngPublicBuildPool) + image: windows.vs2022.amd64.open + ${{ if eq(variables['System.TeamProject'], 'internal') }}: + name: $(DncEngInternalBuildPool) + image: windows.vs2022.amd64 + + steps: + - ${{ if eq(parameters.is1ESPipeline, '') }}: + - 'Illegal entry point, is1ESPipeline is not defined. Repository yaml should not directly reference templates in core-templates folder.': error + + - ${{ each preStep in parameters.preSteps }}: + - ${{ preStep }} + + - task: UseDotNet@2 + displayName: Use .NET 8 SDK + inputs: + packageType: sdk + version: 8.0.x + installationPath: $(Agent.TempDirectory)/dotnet + workingDirectory: $(Agent.TempDirectory) + + - script: | + $(Agent.TempDirectory)/dotnet/dotnet tool install BinLogToSln --version $(sourceIndexProcessBinlogPackageVersion) --add-source $(SourceIndexPackageSource) --tool-path $(Agent.TempDirectory)/.source-index/tools + $(Agent.TempDirectory)/dotnet/dotnet tool install UploadIndexStage1 --version $(sourceIndexUploadPackageVersion) --add-source $(SourceIndexPackageSource) --tool-path $(Agent.TempDirectory)/.source-index/tools + displayName: Download Tools + # Set working directory to temp directory so 'dotnet' doesn't try to use global.json and use the repo's sdk. + workingDirectory: $(Agent.TempDirectory) + + - script: ${{ parameters.sourceIndexBuildCommand }} + displayName: Build Repository + + - script: $(Agent.TempDirectory)/.source-index/tools/BinLogToSln -i $(BinlogPath) -r $(Build.SourcesDirectory) -n $(Build.Repository.Name) -o .source-index/stage1output + displayName: Process Binlog into indexable sln + + - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: + - task: AzureCLI@2 + displayName: Log in to Azure and upload stage1 artifacts to source index + inputs: + azureSubscription: 'SourceDotNet Stage1 Publish' + addSpnToEnvironment: true + scriptType: 'ps' + scriptLocation: 'inlineScript' + inlineScript: | + $(Agent.TempDirectory)/.source-index/tools/UploadIndexStage1 -i .source-index/stage1output -n $(Build.Repository.Name) -s netsourceindexstage1 -b stage1 diff --git a/eng/common/core-templates/jobs/codeql-build.yml b/eng/common/core-templates/jobs/codeql-build.yml new file mode 100644 index 00000000000..f2144252cc6 --- /dev/null +++ b/eng/common/core-templates/jobs/codeql-build.yml @@ -0,0 +1,33 @@ +parameters: + # See schema documentation in /Documentation/AzureDevOps/TemplateSchema.md + continueOnError: false + # Required: A collection of jobs to run - https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=vsts&tabs=schema#job + jobs: [] + # Optional: if specified, restore and use this version of Guardian instead of the default. + overrideGuardianVersion: '' + is1ESPipeline: '' + +jobs: +- template: /eng/common/core-templates/jobs/jobs.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + enableMicrobuild: false + enablePublishBuildArtifacts: false + enablePublishTestResults: false + enablePublishBuildAssets: false + enablePublishUsingPipelines: false + enableTelemetry: true + + variables: + - group: Publish-Build-Assets + # The Guardian version specified in 'eng/common/sdl/packages.config'. This value must be kept in + # sync with the packages.config file. + - name: DefaultGuardianVersion + value: 0.109.0 + - name: GuardianPackagesConfigFile + value: $(Build.SourcesDirectory)\eng\common\sdl\packages.config + - name: GuardianVersion + value: ${{ coalesce(parameters.overrideGuardianVersion, '$(DefaultGuardianVersion)') }} + + jobs: ${{ parameters.jobs }} + diff --git a/eng/common/core-templates/jobs/jobs.yml b/eng/common/core-templates/jobs/jobs.yml new file mode 100644 index 00000000000..ea69be4341c --- /dev/null +++ b/eng/common/core-templates/jobs/jobs.yml @@ -0,0 +1,119 @@ +parameters: + # See schema documentation in /Documentation/AzureDevOps/TemplateSchema.md + continueOnError: false + + # Optional: Include PublishBuildArtifacts task + enablePublishBuildArtifacts: false + + # Optional: Enable publishing using release pipelines + enablePublishUsingPipelines: false + + # Optional: Enable running the source-build jobs to build repo from source + enableSourceBuild: false + + # Optional: Parameters for source-build template. + # See /eng/common/core-templates/jobs/source-build.yml for options + sourceBuildParameters: [] + + graphFileGeneration: + # Optional: Enable generating the graph files at the end of the build + enabled: false + # Optional: Include toolset dependencies in the generated graph files + includeToolset: false + + # Required: A collection of jobs to run - https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=vsts&tabs=schema#job + jobs: [] + + # Optional: Override automatically derived dependsOn value for "publish build assets" job + publishBuildAssetsDependsOn: '' + + # Optional: Publish the assets as soon as the publish to BAR stage is complete, rather doing so in a separate stage. + publishAssetsImmediately: false + + # Optional: If using publishAssetsImmediately and additional parameters are needed, can be used to send along additional parameters (normally sent to post-build.yml) + artifactsPublishingAdditionalParameters: '' + signingValidationAdditionalParameters: '' + + # Optional: should run as a public build even in the internal project + # if 'true', the build won't run any of the internal only steps, even if it is running in non-public projects. + runAsPublic: false + + enableSourceIndex: false + sourceIndexParams: {} + + artifacts: {} + is1ESPipeline: '' + +# Internal resources (telemetry, microbuild) can only be accessed from non-public projects, +# and some (Microbuild) should only be applied to non-PR cases for internal builds. + +jobs: +- ${{ each job in parameters.jobs }}: + - ${{ if eq(parameters.is1ESPipeline, 'true') }}: + - template: /eng/common/templates-official/job/job.yml + parameters: + # pass along parameters + ${{ each parameter in parameters }}: + ${{ if ne(parameter.key, 'jobs') }}: + ${{ parameter.key }}: ${{ parameter.value }} + + # pass along job properties + ${{ each property in job }}: + ${{ if ne(property.key, 'job') }}: + ${{ property.key }}: ${{ property.value }} + + name: ${{ job.job }} + + - ${{ else }}: + - template: /eng/common/templates/job/job.yml + parameters: + # pass along parameters + ${{ each parameter in parameters }}: + ${{ if ne(parameter.key, 'jobs') }}: + ${{ parameter.key }}: ${{ parameter.value }} + + # pass along job properties + ${{ each property in job }}: + ${{ if ne(property.key, 'job') }}: + ${{ property.key }}: ${{ property.value }} + + name: ${{ job.job }} + +- ${{ if eq(parameters.enableSourceBuild, true) }}: + - template: /eng/common/core-templates/jobs/source-build.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + allCompletedJobId: Source_Build_Complete + ${{ each parameter in parameters.sourceBuildParameters }}: + ${{ parameter.key }}: ${{ parameter.value }} + +- ${{ if eq(parameters.enableSourceIndex, 'true') }}: + - template: ../job/source-index-stage1.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + runAsPublic: ${{ parameters.runAsPublic }} + ${{ each parameter in parameters.sourceIndexParams }}: + ${{ parameter.key }}: ${{ parameter.value }} + +- ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: + - ${{ if or(eq(parameters.enablePublishBuildAssets, true), eq(parameters.artifacts.publish.manifests, 'true'), ne(parameters.artifacts.publish.manifests, '')) }}: + - template: ../job/publish-build-assets.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + continueOnError: ${{ parameters.continueOnError }} + dependsOn: + - ${{ if ne(parameters.publishBuildAssetsDependsOn, '') }}: + - ${{ each job in parameters.publishBuildAssetsDependsOn }}: + - ${{ job.job }} + - ${{ if eq(parameters.publishBuildAssetsDependsOn, '') }}: + - ${{ each job in parameters.jobs }}: + - ${{ job.job }} + - ${{ if eq(parameters.enableSourceBuild, true) }}: + - Source_Build_Complete + + runAsPublic: ${{ parameters.runAsPublic }} + publishUsingPipelines: ${{ parameters.enablePublishUsingPipelines }} + publishAssetsImmediately: ${{ parameters.publishAssetsImmediately }} + enablePublishBuildArtifacts: ${{ parameters.enablePublishBuildArtifacts }} + artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} + signingValidationAdditionalParameters: ${{ parameters.signingValidationAdditionalParameters }} diff --git a/eng/common/core-templates/jobs/source-build.yml b/eng/common/core-templates/jobs/source-build.yml new file mode 100644 index 00000000000..a10ccfbee6d --- /dev/null +++ b/eng/common/core-templates/jobs/source-build.yml @@ -0,0 +1,58 @@ +parameters: + # This template adds arcade-powered source-build to CI. A job is created for each platform, as + # well as an optional server job that completes when all platform jobs complete. + + # The name of the "join" job for all source-build platforms. If set to empty string, the job is + # not included. Existing repo pipelines can use this job depend on all source-build jobs + # completing without maintaining a separate list of every single job ID: just depend on this one + # server job. By default, not included. Recommended name if used: 'Source_Build_Complete'. + allCompletedJobId: '' + + # See /eng/common/core-templates/job/source-build.yml + jobNamePrefix: 'Source_Build' + + # This is the default platform provided by Arcade, intended for use by a managed-only repo. + defaultManagedPlatform: + name: 'Managed' + container: 'mcr.microsoft.com/dotnet-buildtools/prereqs:centos-stream9' + + # Defines the platforms on which to run build jobs. One job is created for each platform, and the + # object in this array is sent to the job template as 'platform'. If no platforms are specified, + # one job runs on 'defaultManagedPlatform'. + platforms: [] + + is1ESPipeline: '' + + # If set to true and running on a non-public project, + # Internal nuget and blob storage locations will be enabled. + # This is not enabled by default because many repositories do not need internal sources + # and do not need to have the required service connections approved in the pipeline. + enableInternalSources: false + +jobs: + +- ${{ if ne(parameters.allCompletedJobId, '') }}: + - job: ${{ parameters.allCompletedJobId }} + displayName: Source-Build Complete + pool: server + dependsOn: + - ${{ each platform in parameters.platforms }}: + - ${{ parameters.jobNamePrefix }}_${{ platform.name }} + - ${{ if eq(length(parameters.platforms), 0) }}: + - ${{ parameters.jobNamePrefix }}_${{ parameters.defaultManagedPlatform.name }} + +- ${{ each platform in parameters.platforms }}: + - template: /eng/common/core-templates/job/source-build.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + jobNamePrefix: ${{ parameters.jobNamePrefix }} + platform: ${{ platform }} + enableInternalSources: ${{ parameters.enableInternalSources }} + +- ${{ if eq(length(parameters.platforms), 0) }}: + - template: /eng/common/core-templates/job/source-build.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + jobNamePrefix: ${{ parameters.jobNamePrefix }} + platform: ${{ parameters.defaultManagedPlatform }} + enableInternalSources: ${{ parameters.enableInternalSources }} diff --git a/eng/common/core-templates/post-build/common-variables.yml b/eng/common/core-templates/post-build/common-variables.yml new file mode 100644 index 00000000000..d5627a994ae --- /dev/null +++ b/eng/common/core-templates/post-build/common-variables.yml @@ -0,0 +1,22 @@ +variables: + - group: Publish-Build-Assets + + # Whether the build is internal or not + - name: IsInternalBuild + value: ${{ and(ne(variables['System.TeamProject'], 'public'), contains(variables['Build.SourceBranch'], 'internal')) }} + + # Default Maestro++ API Endpoint and API Version + - name: MaestroApiEndPoint + value: "https://maestro.dot.net" + - name: MaestroApiVersion + value: "2020-02-20" + + - name: SourceLinkCLIVersion + value: 3.0.0 + - name: SymbolToolVersion + value: 1.0.1 + - name: BinlogToolVersion + value: 1.0.11 + + - name: runCodesignValidationInjection + value: false diff --git a/eng/common/core-templates/post-build/post-build.yml b/eng/common/core-templates/post-build/post-build.yml new file mode 100644 index 00000000000..20924366b8a --- /dev/null +++ b/eng/common/core-templates/post-build/post-build.yml @@ -0,0 +1,315 @@ +parameters: + # Which publishing infra should be used. THIS SHOULD MATCH THE VERSION ON THE BUILD MANIFEST. + # Publishing V1 is no longer supported + # Publishing V2 is no longer supported + # Publishing V3 is the default + - name: publishingInfraVersion + displayName: Which version of publishing should be used to promote the build definition? + type: number + default: 3 + values: + - 3 + + - name: BARBuildId + displayName: BAR Build Id + type: number + default: 0 + + - name: PromoteToChannelIds + displayName: Channel to promote BARBuildId to + type: string + default: '' + + - name: enableSourceLinkValidation + displayName: Enable SourceLink validation + type: boolean + default: false + + - name: enableSigningValidation + displayName: Enable signing validation + type: boolean + default: true + + - name: enableSymbolValidation + displayName: Enable symbol validation + type: boolean + default: false + + - name: enableNugetValidation + displayName: Enable NuGet validation + type: boolean + default: true + + - name: publishInstallersAndChecksums + displayName: Publish installers and checksums + type: boolean + default: true + + - name: SDLValidationParameters + type: object + default: + enable: false + publishGdn: false + continueOnError: false + params: '' + artifactNames: '' + downloadArtifacts: true + + # These parameters let the user customize the call to sdk-task.ps1 for publishing + # symbols & general artifacts as well as for signing validation + - name: symbolPublishingAdditionalParameters + displayName: Symbol publishing additional parameters + type: string + default: '' + + - name: artifactsPublishingAdditionalParameters + displayName: Artifact publishing additional parameters + type: string + default: '' + + - name: signingValidationAdditionalParameters + displayName: Signing validation additional parameters + type: string + default: '' + + # Which stages should finish execution before post-build stages start + - name: validateDependsOn + type: object + default: + - build + + - name: publishDependsOn + type: object + default: + - Validate + + # Optional: Call asset publishing rather than running in a separate stage + - name: publishAssetsImmediately + type: boolean + default: false + + - name: is1ESPipeline + type: boolean + default: false + +stages: +- ${{ if or(eq( parameters.enableNugetValidation, 'true'), eq(parameters.enableSigningValidation, 'true'), eq(parameters.enableSourceLinkValidation, 'true'), eq(parameters.SDLValidationParameters.enable, 'true')) }}: + - stage: Validate + dependsOn: ${{ parameters.validateDependsOn }} + displayName: Validate Build Assets + variables: + - template: /eng/common/core-templates/post-build/common-variables.yml + - template: /eng/common/core-templates/variables/pool-providers.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + jobs: + - job: + displayName: NuGet Validation + condition: and(succeededOrFailed(), eq( ${{ parameters.enableNugetValidation }}, 'true')) + pool: + # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) + ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: + name: AzurePipelines-EO + image: 1ESPT-Windows2022 + demands: Cmd + os: windows + # If it's not devdiv, it's dnceng + ${{ else }}: + ${{ if eq(parameters.is1ESPipeline, true) }}: + name: $(DncEngInternalBuildPool) + image: windows.vs2022.amd64 + os: windows + ${{ else }}: + name: $(DncEngInternalBuildPool) + demands: ImageOverride -equals windows.vs2022.amd64 + + steps: + - template: /eng/common/core-templates/post-build/setup-maestro-vars.yml + parameters: + BARBuildId: ${{ parameters.BARBuildId }} + PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} + is1ESPipeline: ${{ parameters.is1ESPipeline }} + + - task: DownloadBuildArtifacts@0 + displayName: Download Package Artifacts + inputs: + buildType: specific + buildVersionToDownload: specific + project: $(AzDOProjectName) + pipeline: $(AzDOPipelineId) + buildId: $(AzDOBuildId) + artifactName: PackageArtifacts + checkDownloadedFiles: true + + - task: PowerShell@2 + displayName: Validate + inputs: + filePath: $(Build.SourcesDirectory)/eng/common/post-build/nuget-validation.ps1 + arguments: -PackagesPath $(Build.ArtifactStagingDirectory)/PackageArtifacts/ + + - job: + displayName: Signing Validation + condition: and( eq( ${{ parameters.enableSigningValidation }}, 'true'), ne( variables['PostBuildSign'], 'true')) + pool: + # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) + ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: + name: AzurePipelines-EO + image: 1ESPT-Windows2022 + demands: Cmd + os: windows + # If it's not devdiv, it's dnceng + ${{ else }}: + ${{ if eq(parameters.is1ESPipeline, true) }}: + name: $(DncEngInternalBuildPool) + image: 1es-windows-2022 + os: windows + ${{ else }}: + name: $(DncEngInternalBuildPool) + demands: ImageOverride -equals windows.vs2022.amd64 + steps: + - template: /eng/common/core-templates/post-build/setup-maestro-vars.yml + parameters: + BARBuildId: ${{ parameters.BARBuildId }} + PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} + is1ESPipeline: ${{ parameters.is1ESPipeline }} + + - task: DownloadBuildArtifacts@0 + displayName: Download Package Artifacts + inputs: + buildType: specific + buildVersionToDownload: specific + project: $(AzDOProjectName) + pipeline: $(AzDOPipelineId) + buildId: $(AzDOBuildId) + artifactName: PackageArtifacts + checkDownloadedFiles: true + itemPattern: | + ** + !**/Microsoft.SourceBuild.Intermediate.*.nupkg + + # This is necessary whenever we want to publish/restore to an AzDO private feed + # Since sdk-task.ps1 tries to restore packages we need to do this authentication here + # otherwise it'll complain about accessing a private feed. + - task: NuGetAuthenticate@1 + displayName: 'Authenticate to AzDO Feeds' + + # Signing validation will optionally work with the buildmanifest file which is downloaded from + # Azure DevOps above. + - task: PowerShell@2 + displayName: Validate + inputs: + filePath: eng\common\sdk-task.ps1 + arguments: -task SigningValidation -restore -msbuildEngine vs + /p:PackageBasePath='$(Build.ArtifactStagingDirectory)/PackageArtifacts' + /p:SignCheckExclusionsFile='$(Build.SourcesDirectory)/eng/SignCheckExclusionsFile.txt' + ${{ parameters.signingValidationAdditionalParameters }} + + - template: /eng/common/core-templates/steps/publish-logs.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + StageLabel: 'Validation' + JobLabel: 'Signing' + BinlogToolVersion: $(BinlogToolVersion) + + - job: + displayName: SourceLink Validation + condition: eq( ${{ parameters.enableSourceLinkValidation }}, 'true') + pool: + # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) + ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: + name: AzurePipelines-EO + image: 1ESPT-Windows2022 + demands: Cmd + os: windows + # If it's not devdiv, it's dnceng + ${{ else }}: + ${{ if eq(parameters.is1ESPipeline, true) }}: + name: $(DncEngInternalBuildPool) + image: 1es-windows-2022 + os: windows + ${{ else }}: + name: $(DncEngInternalBuildPool) + demands: ImageOverride -equals windows.vs2022.amd64 + steps: + - template: /eng/common/core-templates/post-build/setup-maestro-vars.yml + parameters: + BARBuildId: ${{ parameters.BARBuildId }} + PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} + is1ESPipeline: ${{ parameters.is1ESPipeline }} + + - task: DownloadBuildArtifacts@0 + displayName: Download Blob Artifacts + inputs: + buildType: specific + buildVersionToDownload: specific + project: $(AzDOProjectName) + pipeline: $(AzDOPipelineId) + buildId: $(AzDOBuildId) + artifactName: BlobArtifacts + checkDownloadedFiles: true + + - task: PowerShell@2 + displayName: Validate + inputs: + filePath: $(Build.SourcesDirectory)/eng/common/post-build/sourcelink-validation.ps1 + arguments: -InputPath $(Build.ArtifactStagingDirectory)/BlobArtifacts/ + -ExtractPath $(Agent.BuildDirectory)/Extract/ + -GHRepoName $(Build.Repository.Name) + -GHCommit $(Build.SourceVersion) + -SourcelinkCliVersion $(SourceLinkCLIVersion) + continueOnError: true + +- ${{ if ne(parameters.publishAssetsImmediately, 'true') }}: + - stage: publish_using_darc + ${{ if or(eq(parameters.enableNugetValidation, 'true'), eq(parameters.enableSigningValidation, 'true'), eq(parameters.enableSourceLinkValidation, 'true'), eq(parameters.SDLValidationParameters.enable, 'true')) }}: + dependsOn: ${{ parameters.publishDependsOn }} + ${{ else }}: + dependsOn: ${{ parameters.validateDependsOn }} + displayName: Publish using Darc + variables: + - template: /eng/common/core-templates/post-build/common-variables.yml + - template: /eng/common/core-templates/variables/pool-providers.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + jobs: + - job: + displayName: Publish Using Darc + timeoutInMinutes: 120 + pool: + # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) + ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: + name: AzurePipelines-EO + image: 1ESPT-Windows2022 + demands: Cmd + os: windows + # If it's not devdiv, it's dnceng + ${{ else }}: + ${{ if eq(parameters.is1ESPipeline, true) }}: + name: NetCore1ESPool-Publishing-Internal + image: windows.vs2019.amd64 + os: windows + ${{ else }}: + name: NetCore1ESPool-Publishing-Internal + demands: ImageOverride -equals windows.vs2019.amd64 + steps: + - template: /eng/common/core-templates/post-build/setup-maestro-vars.yml + parameters: + BARBuildId: ${{ parameters.BARBuildId }} + PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} + is1ESPipeline: ${{ parameters.is1ESPipeline }} + + - task: NuGetAuthenticate@1 + + - task: AzureCLI@2 + displayName: Publish Using Darc + inputs: + azureSubscription: "Darc: Maestro Production" + scriptType: ps + scriptLocation: scriptPath + scriptPath: $(Build.SourcesDirectory)/eng/common/post-build/publish-using-darc.ps1 + arguments: -BuildId $(BARBuildId) + -PublishingInfraVersion ${{ parameters.publishingInfraVersion }} + -AzdoToken '$(publishing-dnceng-devdiv-code-r-build-re)' + -WaitPublishingFinish true + -ArtifactsPublishingAdditionalParameters '${{ parameters.artifactsPublishingAdditionalParameters }}' + -SymbolPublishingAdditionalParameters '${{ parameters.symbolPublishingAdditionalParameters }}' diff --git a/eng/common/core-templates/post-build/setup-maestro-vars.yml b/eng/common/core-templates/post-build/setup-maestro-vars.yml new file mode 100644 index 00000000000..f7602980dbe --- /dev/null +++ b/eng/common/core-templates/post-build/setup-maestro-vars.yml @@ -0,0 +1,74 @@ +parameters: + BARBuildId: '' + PromoteToChannelIds: '' + is1ESPipeline: '' + +steps: + - ${{ if eq(parameters.is1ESPipeline, '') }}: + - 'Illegal entry point, is1ESPipeline is not defined. Repository yaml should not directly reference templates in core-templates folder.': error + + - ${{ if eq(coalesce(parameters.PromoteToChannelIds, 0), 0) }}: + - task: DownloadBuildArtifacts@0 + displayName: Download Release Configs + inputs: + buildType: current + artifactName: ReleaseConfigs + checkDownloadedFiles: true + + - task: AzureCLI@2 + name: setReleaseVars + displayName: Set Release Configs Vars + inputs: + azureSubscription: "Darc: Maestro Production" + scriptType: pscore + scriptLocation: inlineScript + inlineScript: | + try { + if (!$Env:PromoteToMaestroChannels -or $Env:PromoteToMaestroChannels.Trim() -eq '') { + $Content = Get-Content $(Build.StagingDirectory)/ReleaseConfigs/ReleaseConfigs.txt + + $BarId = $Content | Select -Index 0 + $Channels = $Content | Select -Index 1 + $IsStableBuild = $Content | Select -Index 2 + + $AzureDevOpsProject = $Env:System_TeamProject + $AzureDevOpsBuildDefinitionId = $Env:System_DefinitionId + $AzureDevOpsBuildId = $Env:Build_BuildId + } + else { + . $(Build.SourcesDirectory)\eng\common\tools.ps1 + $darc = Get-Darc + $buildInfo = & $darc get-build ` + --id ${{ parameters.BARBuildId }} ` + --extended ` + --output-format json ` + --ci ` + | convertFrom-Json + + $BarId = ${{ parameters.BARBuildId }} + $Channels = $Env:PromoteToMaestroChannels -split "," + $Channels = $Channels -join "][" + $Channels = "[$Channels]" + + $IsStableBuild = $buildInfo.stable + $AzureDevOpsProject = $buildInfo.azureDevOpsProject + $AzureDevOpsBuildDefinitionId = $buildInfo.azureDevOpsBuildDefinitionId + $AzureDevOpsBuildId = $buildInfo.azureDevOpsBuildId + } + + Write-Host "##vso[task.setvariable variable=BARBuildId]$BarId" + Write-Host "##vso[task.setvariable variable=TargetChannels]$Channels" + Write-Host "##vso[task.setvariable variable=IsStableBuild]$IsStableBuild" + + Write-Host "##vso[task.setvariable variable=AzDOProjectName]$AzureDevOpsProject" + Write-Host "##vso[task.setvariable variable=AzDOPipelineId]$AzureDevOpsBuildDefinitionId" + Write-Host "##vso[task.setvariable variable=AzDOBuildId]$AzureDevOpsBuildId" + } + catch { + Write-Host $_ + Write-Host $_.Exception + Write-Host $_.ScriptStackTrace + exit 1 + } + env: + PromoteToMaestroChannels: ${{ parameters.PromoteToChannelIds }} diff --git a/eng/common/core-templates/steps/component-governance.yml b/eng/common/core-templates/steps/component-governance.yml new file mode 100644 index 00000000000..cf0649aa956 --- /dev/null +++ b/eng/common/core-templates/steps/component-governance.yml @@ -0,0 +1,16 @@ +parameters: + disableComponentGovernance: false + componentGovernanceIgnoreDirectories: '' + is1ESPipeline: false + displayName: 'Component Detection' + +steps: +- ${{ if eq(parameters.disableComponentGovernance, 'true') }}: + - script: echo "##vso[task.setvariable variable=skipComponentGovernanceDetection]true" + displayName: Set skipComponentGovernanceDetection variable +- ${{ if ne(parameters.disableComponentGovernance, 'true') }}: + - task: ComponentGovernanceComponentDetection@0 + continueOnError: true + displayName: ${{ parameters.displayName }} + inputs: + ignoreDirectories: ${{ parameters.componentGovernanceIgnoreDirectories }} diff --git a/eng/common/core-templates/steps/enable-internal-runtimes.yml b/eng/common/core-templates/steps/enable-internal-runtimes.yml new file mode 100644 index 00000000000..6bdbf62ac50 --- /dev/null +++ b/eng/common/core-templates/steps/enable-internal-runtimes.yml @@ -0,0 +1,32 @@ +# Obtains internal runtime download credentials and populates the 'dotnetbuilds-internal-container-read-token-base64' +# variable with the base64-encoded SAS token, by default + +parameters: +- name: federatedServiceConnection + type: string + default: 'dotnetbuilds-internal-read' +- name: outputVariableName + type: string + default: 'dotnetbuilds-internal-container-read-token-base64' +- name: expiryInHours + type: number + default: 1 +- name: base64Encode + type: boolean + default: true +- name: is1ESPipeline + type: boolean + default: false + +steps: +- ${{ if ne(variables['System.TeamProject'], 'public') }}: + - template: /eng/common/core-templates/steps/get-delegation-sas.yml + parameters: + federatedServiceConnection: ${{ parameters.federatedServiceConnection }} + outputVariableName: ${{ parameters.outputVariableName }} + expiryInHours: ${{ parameters.expiryInHours }} + base64Encode: ${{ parameters.base64Encode }} + storageAccount: dotnetbuilds + container: internal + permissions: rl + is1ESPipeline: ${{ parameters.is1ESPipeline }} \ No newline at end of file diff --git a/eng/common/core-templates/steps/enable-internal-sources.yml b/eng/common/core-templates/steps/enable-internal-sources.yml new file mode 100644 index 00000000000..64f881bffc3 --- /dev/null +++ b/eng/common/core-templates/steps/enable-internal-sources.yml @@ -0,0 +1,47 @@ +parameters: +# This is the Azure federated service connection that we log into to get an access token. +- name: nugetFederatedServiceConnection + type: string + default: 'dnceng-artifacts-feeds-read' +- name: is1ESPipeline + type: boolean + default: false +# Legacy parameters to allow for PAT usage +- name: legacyCredential + type: string + default: '' + +steps: +- ${{ if ne(variables['System.TeamProject'], 'public') }}: + - ${{ if ne(parameters.legacyCredential, '') }}: + - task: PowerShell@2 + displayName: Setup Internal Feeds + inputs: + filePath: $(Build.SourcesDirectory)/eng/common/SetupNugetSources.ps1 + arguments: -ConfigFile $(Build.SourcesDirectory)/NuGet.config -Password $Env:Token + env: + Token: ${{ parameters.legacyCredential }} + # If running on dnceng (internal project), just use the default behavior for NuGetAuthenticate. + # If running on DevDiv, NuGetAuthenticate is not really an option. It's scoped to a single feed, and we have many feeds that + # may be added. Instead, we'll use the traditional approach (add cred to nuget.config), but use an account token. + - ${{ else }}: + - ${{ if eq(variables['System.TeamProject'], 'internal') }}: + - task: PowerShell@2 + displayName: Setup Internal Feeds + inputs: + filePath: $(Build.SourcesDirectory)/eng/common/SetupNugetSources.ps1 + arguments: -ConfigFile $(Build.SourcesDirectory)/NuGet.config + - ${{ else }}: + - template: /eng/common/templates/steps/get-federated-access-token.yml + parameters: + federatedServiceConnection: ${{ parameters.nugetFederatedServiceConnection }} + outputVariableName: 'dnceng-artifacts-feeds-read-access-token' + - task: PowerShell@2 + displayName: Setup Internal Feeds + inputs: + filePath: $(Build.SourcesDirectory)/eng/common/SetupNugetSources.ps1 + arguments: -ConfigFile $(Build.SourcesDirectory)/NuGet.config -Password $(dnceng-artifacts-feeds-read-access-token) + # This is required in certain scenarios to install the ADO credential provider. + # It installed by default in some msbuild invocations (e.g. VS msbuild), but needs to be installed for others + # (e.g. dotnet msbuild). + - task: NuGetAuthenticate@1 diff --git a/eng/common/core-templates/steps/generate-sbom.yml b/eng/common/core-templates/steps/generate-sbom.yml new file mode 100644 index 00000000000..d938b60e1bb --- /dev/null +++ b/eng/common/core-templates/steps/generate-sbom.yml @@ -0,0 +1,54 @@ +# BuildDropPath - The root folder of the drop directory for which the manifest file will be generated. +# PackageName - The name of the package this SBOM represents. +# PackageVersion - The version of the package this SBOM represents. +# ManifestDirPath - The path of the directory where the generated manifest files will be placed +# IgnoreDirectories - Directories to ignore for SBOM generation. This will be passed through to the CG component detector. + +parameters: + PackageVersion: 9.0.0 + BuildDropPath: '$(Build.SourcesDirectory)/artifacts' + PackageName: '.NET' + ManifestDirPath: $(Build.ArtifactStagingDirectory)/sbom + IgnoreDirectories: '' + sbomContinueOnError: true + is1ESPipeline: false + # disable publishArtifacts if some other step is publishing the artifacts (like job.yml). + publishArtifacts: true + +steps: +- task: PowerShell@2 + displayName: Prep for SBOM generation in (Non-linux) + condition: or(eq(variables['Agent.Os'], 'Windows_NT'), eq(variables['Agent.Os'], 'Darwin')) + inputs: + filePath: ./eng/common/generate-sbom-prep.ps1 + arguments: ${{parameters.manifestDirPath}} + +# Chmodding is a workaround for https://github.com/dotnet/arcade/issues/8461 +- script: | + chmod +x ./eng/common/generate-sbom-prep.sh + ./eng/common/generate-sbom-prep.sh ${{parameters.manifestDirPath}} + displayName: Prep for SBOM generation in (Linux) + condition: eq(variables['Agent.Os'], 'Linux') + continueOnError: ${{ parameters.sbomContinueOnError }} + +- task: AzureArtifacts.manifest-generator-task.manifest-generator-task.ManifestGeneratorTask@0 + displayName: 'Generate SBOM manifest' + continueOnError: ${{ parameters.sbomContinueOnError }} + inputs: + PackageName: ${{ parameters.packageName }} + BuildDropPath: ${{ parameters.buildDropPath }} + PackageVersion: ${{ parameters.packageVersion }} + ManifestDirPath: ${{ parameters.manifestDirPath }} + ${{ if ne(parameters.IgnoreDirectories, '') }}: + AdditionalComponentDetectorArgs: '--IgnoreDirectories ${{ parameters.IgnoreDirectories }}' + +- ${{ if eq(parameters.publishArtifacts, 'true')}}: + - template: /eng/common/core-templates/steps/publish-pipeline-artifacts.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + args: + displayName: Publish SBOM manifest + continueOnError: ${{parameters.sbomContinueOnError}} + targetPath: '${{ parameters.manifestDirPath }}' + artifactName: $(ARTIFACT_NAME) + diff --git a/eng/common/core-templates/steps/get-delegation-sas.yml b/eng/common/core-templates/steps/get-delegation-sas.yml new file mode 100644 index 00000000000..d2901470a7f --- /dev/null +++ b/eng/common/core-templates/steps/get-delegation-sas.yml @@ -0,0 +1,46 @@ +parameters: +- name: federatedServiceConnection + type: string +- name: outputVariableName + type: string +- name: expiryInHours + type: number + default: 1 +- name: base64Encode + type: boolean + default: false +- name: storageAccount + type: string +- name: container + type: string +- name: permissions + type: string + default: 'rl' +- name: is1ESPipeline + type: boolean + default: false + +steps: +- task: AzureCLI@2 + displayName: 'Generate delegation SAS Token for ${{ parameters.storageAccount }}/${{ parameters.container }}' + inputs: + azureSubscription: ${{ parameters.federatedServiceConnection }} + scriptType: 'pscore' + scriptLocation: 'inlineScript' + inlineScript: | + # Calculate the expiration of the SAS token and convert to UTC + $expiry = (Get-Date).AddHours(${{ parameters.expiryInHours }}).ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ") + + $sas = az storage container generate-sas --account-name ${{ parameters.storageAccount }} --name ${{ parameters.container }} --permissions ${{ parameters.permissions }} --expiry $expiry --auth-mode login --as-user -o tsv + + if ($LASTEXITCODE -ne 0) { + Write-Error "Failed to generate SAS token." + exit 1 + } + + if ('${{ parameters.base64Encode }}' -eq 'true') { + $sas = [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($sas)) + } + + Write-Host "Setting '${{ parameters.outputVariableName }}' with the access token value" + Write-Host "##vso[task.setvariable variable=${{ parameters.outputVariableName }};issecret=true]$sas" diff --git a/eng/common/core-templates/steps/get-federated-access-token.yml b/eng/common/core-templates/steps/get-federated-access-token.yml new file mode 100644 index 00000000000..c8c49cc0e8f --- /dev/null +++ b/eng/common/core-templates/steps/get-federated-access-token.yml @@ -0,0 +1,28 @@ +parameters: +- name: federatedServiceConnection + type: string +- name: outputVariableName + type: string +# Resource to get a token for. Common values include: +# - '499b84ac-1321-427f-aa17-267ca6975798' for Azure DevOps +# - 'https://storage.azure.com/' for storage +# Defaults to Azure DevOps +- name: resource + type: string + default: '499b84ac-1321-427f-aa17-267ca6975798' + +steps: +- task: AzureCLI@2 + displayName: 'Getting federated access token for feeds' + inputs: + azureSubscription: ${{ parameters.federatedServiceConnection }} + scriptType: 'pscore' + scriptLocation: 'inlineScript' + inlineScript: | + $accessToken = az account get-access-token --query accessToken --resource ${{ parameters.resource }} --output tsv + if ($LASTEXITCODE -ne 0) { + Write-Error "Failed to get access token for resource '${{ parameters.resource }}'" + exit 1 + } + Write-Host "Setting '${{ parameters.outputVariableName }}' with the access token value" + Write-Host "##vso[task.setvariable variable=${{ parameters.outputVariableName }};issecret=true]$accessToken" \ No newline at end of file diff --git a/eng/common/core-templates/steps/publish-build-artifacts.yml b/eng/common/core-templates/steps/publish-build-artifacts.yml new file mode 100644 index 00000000000..f24ce346684 --- /dev/null +++ b/eng/common/core-templates/steps/publish-build-artifacts.yml @@ -0,0 +1,20 @@ +parameters: +- name: is1ESPipeline + type: boolean + default: false +- name: args + type: object + default: {} +steps: +- ${{ if ne(parameters.is1ESPipeline, true) }}: + - template: /eng/common/templates/steps/publish-build-artifacts.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + ${{ each parameter in parameters.args }}: + ${{ parameter.key }}: ${{ parameter.value }} +- ${{ else }}: + - template: /eng/common/templates-official/steps/publish-build-artifacts.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + ${{ each parameter in parameters.args }}: + ${{ parameter.key }}: ${{ parameter.value }} \ No newline at end of file diff --git a/eng/common/core-templates/steps/publish-logs.yml b/eng/common/core-templates/steps/publish-logs.yml new file mode 100644 index 00000000000..8c5ea77b586 --- /dev/null +++ b/eng/common/core-templates/steps/publish-logs.yml @@ -0,0 +1,59 @@ +parameters: + StageLabel: '' + JobLabel: '' + CustomSensitiveDataList: '' + # A default - in case value from eng/common/core-templates/post-build/common-variables.yml is not passed + BinlogToolVersion: '1.0.11' + is1ESPipeline: false + +steps: +- task: Powershell@2 + displayName: Prepare Binlogs to Upload + inputs: + targetType: inline + script: | + New-Item -ItemType Directory $(Build.SourcesDirectory)/PostBuildLogs/${{parameters.StageLabel}}/${{parameters.JobLabel}}/ + Move-Item -Path $(Build.SourcesDirectory)/artifacts/log/Debug/* $(Build.SourcesDirectory)/PostBuildLogs/${{parameters.StageLabel}}/${{parameters.JobLabel}}/ + continueOnError: true + condition: always() + +- task: PowerShell@2 + displayName: Redact Logs + inputs: + filePath: $(Build.SourcesDirectory)/eng/common/post-build/redact-logs.ps1 + # For now this needs to have explicit list of all sensitive data. Taken from eng/publishing/v3/publish.yml + # Sensitive data can as well be added to $(Build.SourcesDirectory)/eng/BinlogSecretsRedactionFile.txt' + # If the file exists - sensitive data for redaction will be sourced from it + # (single entry per line, lines starting with '# ' are considered comments and skipped) + arguments: -InputPath '$(Build.SourcesDirectory)/PostBuildLogs' + -BinlogToolVersion ${{parameters.BinlogToolVersion}} + -TokensFilePath '$(Build.SourcesDirectory)/eng/BinlogSecretsRedactionFile.txt' + '$(publishing-dnceng-devdiv-code-r-build-re)' + '$(MaestroAccessToken)' + '$(dn-bot-all-orgs-artifact-feeds-rw)' + '$(akams-client-id)' + '$(akams-client-secret)' + '$(microsoft-symbol-server-pat)' + '$(symweb-symbol-server-pat)' + '$(dn-bot-all-orgs-build-rw-code-rw)' + ${{parameters.CustomSensitiveDataList}} + continueOnError: true + condition: always() + +- task: CopyFiles@2 + displayName: Gather post build logs + inputs: + SourceFolder: '$(Build.SourcesDirectory)/PostBuildLogs' + Contents: '**' + TargetFolder: '$(Build.ArtifactStagingDirectory)/PostBuildLogs' + +- template: /eng/common/core-templates/steps/publish-build-artifacts.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + args: + displayName: Publish Logs + pathToPublish: '$(Build.ArtifactStagingDirectory)/PostBuildLogs' + publishLocation: Container + artifactName: PostBuildLogs + continueOnError: true + condition: always() diff --git a/eng/common/core-templates/steps/publish-pipeline-artifacts.yml b/eng/common/core-templates/steps/publish-pipeline-artifacts.yml new file mode 100644 index 00000000000..2efec04dc2c --- /dev/null +++ b/eng/common/core-templates/steps/publish-pipeline-artifacts.yml @@ -0,0 +1,20 @@ +parameters: +- name: is1ESPipeline + type: boolean + default: false + +- name: args + type: object + default: {} + +steps: +- ${{ if ne(parameters.is1ESPipeline, true) }}: + - template: /eng/common/templates/steps/publish-pipeline-artifacts.yml + parameters: + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} +- ${{ else }}: + - template: /eng/common/templates-official/steps/publish-pipeline-artifacts.yml + parameters: + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/core-templates/steps/retain-build.yml b/eng/common/core-templates/steps/retain-build.yml new file mode 100644 index 00000000000..83d97a26a01 --- /dev/null +++ b/eng/common/core-templates/steps/retain-build.yml @@ -0,0 +1,28 @@ +parameters: + # Optional azure devops PAT with build execute permissions for the build's organization, + # only needed if the build that should be retained ran on a different organization than + # the pipeline where this template is executing from + Token: '' + # Optional BuildId to retain, defaults to the current running build + BuildId: '' + # Azure devops Organization URI for the build in the https://dev.azure.com/ format. + # Defaults to the organization the current pipeline is running on + AzdoOrgUri: '$(System.CollectionUri)' + # Azure devops project for the build. Defaults to the project the current pipeline is running on + AzdoProject: '$(System.TeamProject)' + +steps: + - task: powershell@2 + inputs: + targetType: 'filePath' + filePath: eng/common/retain-build.ps1 + pwsh: true + arguments: > + -AzdoOrgUri: ${{parameters.AzdoOrgUri}} + -AzdoProject ${{parameters.AzdoProject}} + -Token ${{coalesce(parameters.Token, '$env:SYSTEM_ACCESSTOKEN') }} + -BuildId ${{coalesce(parameters.BuildId, '$env:BUILD_ID')}} + displayName: Enable permanent build retention + env: + SYSTEM_ACCESSTOKEN: $(System.AccessToken) + BUILD_ID: $(Build.BuildId) \ No newline at end of file diff --git a/eng/common/core-templates/steps/send-to-helix.yml b/eng/common/core-templates/steps/send-to-helix.yml new file mode 100644 index 00000000000..68fa739c4ab --- /dev/null +++ b/eng/common/core-templates/steps/send-to-helix.yml @@ -0,0 +1,93 @@ +# Please remember to update the documentation if you make changes to these parameters! +parameters: + HelixSource: 'pr/default' # required -- sources must start with pr/, official/, prodcon/, or agent/ + HelixType: 'tests/default/' # required -- Helix telemetry which identifies what type of data this is; should include "test" for clarity and must end in '/' + HelixBuild: $(Build.BuildNumber) # required -- the build number Helix will use to identify this -- automatically set to the AzDO build number + HelixTargetQueues: '' # required -- semicolon-delimited list of Helix queues to test on; see https://helix.dot.net/ for a list of queues + HelixAccessToken: '' # required -- access token to make Helix API requests; should be provided by the appropriate variable group + HelixProjectPath: 'eng/common/helixpublish.proj' # optional -- path to the project file to build relative to BUILD_SOURCESDIRECTORY + HelixProjectArguments: '' # optional -- arguments passed to the build command + HelixConfiguration: '' # optional -- additional property attached to a job + HelixPreCommands: '' # optional -- commands to run before Helix work item execution + HelixPostCommands: '' # optional -- commands to run after Helix work item execution + WorkItemDirectory: '' # optional -- a payload directory to zip up and send to Helix; requires WorkItemCommand; incompatible with XUnitProjects + WorkItemCommand: '' # optional -- a command to execute on the payload; requires WorkItemDirectory; incompatible with XUnitProjects + WorkItemTimeout: '' # optional -- a timeout in TimeSpan.Parse-ready value (e.g. 00:02:00) for the work item command; requires WorkItemDirectory; incompatible with XUnitProjects + CorrelationPayloadDirectory: '' # optional -- a directory to zip up and send to Helix as a correlation payload + XUnitProjects: '' # optional -- semicolon-delimited list of XUnitProjects to parse and send to Helix; requires XUnitRuntimeTargetFramework, XUnitPublishTargetFramework, XUnitRunnerVersion, and IncludeDotNetCli=true + XUnitWorkItemTimeout: '' # optional -- the workitem timeout in seconds for all workitems created from the xUnit projects specified by XUnitProjects + XUnitPublishTargetFramework: '' # optional -- framework to use to publish your xUnit projects + XUnitRuntimeTargetFramework: '' # optional -- framework to use for the xUnit console runner + XUnitRunnerVersion: '' # optional -- version of the xUnit nuget package you wish to use on Helix; required for XUnitProjects + IncludeDotNetCli: false # optional -- true will download a version of the .NET CLI onto the Helix machine as a correlation payload; requires DotNetCliPackageType and DotNetCliVersion + DotNetCliPackageType: '' # optional -- either 'sdk', 'runtime' or 'aspnetcore-runtime'; determines whether the sdk or runtime will be sent to Helix; see https://raw.githubusercontent.com/dotnet/core/main/release-notes/releases-index.json + DotNetCliVersion: '' # optional -- version of the CLI to send to Helix; based on this: https://raw.githubusercontent.com/dotnet/core/main/release-notes/releases-index.json + WaitForWorkItemCompletion: true # optional -- true will make the task wait until work items have been completed and fail the build if work items fail. False is "fire and forget." + IsExternal: false # [DEPRECATED] -- doesn't do anything, jobs are external if HelixAccessToken is empty and Creator is set + HelixBaseUri: 'https://helix.dot.net/' # optional -- sets the Helix API base URI (allows targeting https://helix.int-dot.net ) + Creator: '' # optional -- if the build is external, use this to specify who is sending the job + DisplayNamePrefix: 'Run Tests' # optional -- rename the beginning of the displayName of the steps in AzDO + condition: succeeded() # optional -- condition for step to execute; defaults to succeeded() + continueOnError: false # optional -- determines whether to continue the build if the step errors; defaults to false + +steps: + - powershell: 'powershell "$env:BUILD_SOURCESDIRECTORY\eng\common\msbuild.ps1 $env:BUILD_SOURCESDIRECTORY/${{ parameters.HelixProjectPath }} /restore /p:TreatWarningsAsErrors=false ${{ parameters.HelixProjectArguments }} /t:Test /bl:$env:BUILD_SOURCESDIRECTORY\artifacts\log\$env:BuildConfig\SendToHelix.binlog"' + displayName: ${{ parameters.DisplayNamePrefix }} (Windows) + env: + BuildConfig: $(_BuildConfig) + HelixSource: ${{ parameters.HelixSource }} + HelixType: ${{ parameters.HelixType }} + HelixBuild: ${{ parameters.HelixBuild }} + HelixConfiguration: ${{ parameters.HelixConfiguration }} + HelixTargetQueues: ${{ parameters.HelixTargetQueues }} + HelixAccessToken: ${{ parameters.HelixAccessToken }} + HelixPreCommands: ${{ parameters.HelixPreCommands }} + HelixPostCommands: ${{ parameters.HelixPostCommands }} + WorkItemDirectory: ${{ parameters.WorkItemDirectory }} + WorkItemCommand: ${{ parameters.WorkItemCommand }} + WorkItemTimeout: ${{ parameters.WorkItemTimeout }} + CorrelationPayloadDirectory: ${{ parameters.CorrelationPayloadDirectory }} + XUnitProjects: ${{ parameters.XUnitProjects }} + XUnitWorkItemTimeout: ${{ parameters.XUnitWorkItemTimeout }} + XUnitPublishTargetFramework: ${{ parameters.XUnitPublishTargetFramework }} + XUnitRuntimeTargetFramework: ${{ parameters.XUnitRuntimeTargetFramework }} + XUnitRunnerVersion: ${{ parameters.XUnitRunnerVersion }} + IncludeDotNetCli: ${{ parameters.IncludeDotNetCli }} + DotNetCliPackageType: ${{ parameters.DotNetCliPackageType }} + DotNetCliVersion: ${{ parameters.DotNetCliVersion }} + WaitForWorkItemCompletion: ${{ parameters.WaitForWorkItemCompletion }} + HelixBaseUri: ${{ parameters.HelixBaseUri }} + Creator: ${{ parameters.Creator }} + SYSTEM_ACCESSTOKEN: $(System.AccessToken) + condition: and(${{ parameters.condition }}, eq(variables['Agent.Os'], 'Windows_NT')) + continueOnError: ${{ parameters.continueOnError }} + - script: $BUILD_SOURCESDIRECTORY/eng/common/msbuild.sh $BUILD_SOURCESDIRECTORY/${{ parameters.HelixProjectPath }} /restore /p:TreatWarningsAsErrors=false ${{ parameters.HelixProjectArguments }} /t:Test /bl:$BUILD_SOURCESDIRECTORY/artifacts/log/$BuildConfig/SendToHelix.binlog + displayName: ${{ parameters.DisplayNamePrefix }} (Unix) + env: + BuildConfig: $(_BuildConfig) + HelixSource: ${{ parameters.HelixSource }} + HelixType: ${{ parameters.HelixType }} + HelixBuild: ${{ parameters.HelixBuild }} + HelixConfiguration: ${{ parameters.HelixConfiguration }} + HelixTargetQueues: ${{ parameters.HelixTargetQueues }} + HelixAccessToken: ${{ parameters.HelixAccessToken }} + HelixPreCommands: ${{ parameters.HelixPreCommands }} + HelixPostCommands: ${{ parameters.HelixPostCommands }} + WorkItemDirectory: ${{ parameters.WorkItemDirectory }} + WorkItemCommand: ${{ parameters.WorkItemCommand }} + WorkItemTimeout: ${{ parameters.WorkItemTimeout }} + CorrelationPayloadDirectory: ${{ parameters.CorrelationPayloadDirectory }} + XUnitProjects: ${{ parameters.XUnitProjects }} + XUnitWorkItemTimeout: ${{ parameters.XUnitWorkItemTimeout }} + XUnitPublishTargetFramework: ${{ parameters.XUnitPublishTargetFramework }} + XUnitRuntimeTargetFramework: ${{ parameters.XUnitRuntimeTargetFramework }} + XUnitRunnerVersion: ${{ parameters.XUnitRunnerVersion }} + IncludeDotNetCli: ${{ parameters.IncludeDotNetCli }} + DotNetCliPackageType: ${{ parameters.DotNetCliPackageType }} + DotNetCliVersion: ${{ parameters.DotNetCliVersion }} + WaitForWorkItemCompletion: ${{ parameters.WaitForWorkItemCompletion }} + HelixBaseUri: ${{ parameters.HelixBaseUri }} + Creator: ${{ parameters.Creator }} + SYSTEM_ACCESSTOKEN: $(System.AccessToken) + condition: and(${{ parameters.condition }}, ne(variables['Agent.Os'], 'Windows_NT')) + continueOnError: ${{ parameters.continueOnError }} diff --git a/eng/common/core-templates/steps/source-build.yml b/eng/common/core-templates/steps/source-build.yml new file mode 100644 index 00000000000..2915d29bb7f --- /dev/null +++ b/eng/common/core-templates/steps/source-build.yml @@ -0,0 +1,129 @@ +parameters: + # This template adds arcade-powered source-build to CI. + + # This is a 'steps' template, and is intended for advanced scenarios where the existing build + # infra has a careful build methodology that must be followed. For example, a repo + # (dotnet/runtime) might choose to clone the GitHub repo only once and store it as a pipeline + # artifact for all subsequent jobs to use, to reduce dependence on a strong network connection to + # GitHub. Using this steps template leaves room for that infra to be included. + + # Defines the platform on which to run the steps. See 'eng/common/core-templates/job/source-build.yml' + # for details. The entire object is described in the 'job' template for simplicity, even though + # the usage of the properties on this object is split between the 'job' and 'steps' templates. + platform: {} + is1ESPipeline: false + +steps: +# Build. Keep it self-contained for simple reusability. (No source-build-specific job variables.) +- script: | + set -x + df -h + + # If file changes are detected, set CopyWipIntoInnerSourceBuildRepo to copy the WIP changes into the inner source build repo. + internalRestoreArgs= + if ! git diff --quiet; then + internalRestoreArgs='/p:CopyWipIntoInnerSourceBuildRepo=true' + # The 'Copy WIP' feature of source build uses git stash to apply changes from the original repo. + # This only works if there is a username/email configured, which won't be the case in most CI runs. + git config --get user.email + if [ $? -ne 0 ]; then + git config user.email dn-bot@microsoft.com + git config user.name dn-bot + fi + fi + + # If building on the internal project, the internal storage variable may be available (usually only if needed) + # In that case, add variables to allow the download of internal runtimes if the specified versions are not found + # in the default public locations. + internalRuntimeDownloadArgs= + if [ '$(dotnetbuilds-internal-container-read-token-base64)' != '$''(dotnetbuilds-internal-container-read-token-base64)' ]; then + internalRuntimeDownloadArgs='/p:DotNetRuntimeSourceFeed=https://dotnetbuilds.blob.core.windows.net/internal /p:DotNetRuntimeSourceFeedKey=$(dotnetbuilds-internal-container-read-token-base64) --runtimesourcefeed https://dotnetbuilds.blob.core.windows.net/internal --runtimesourcefeedkey $(dotnetbuilds-internal-container-read-token-base64)' + fi + + buildConfig=Release + # Check if AzDO substitutes in a build config from a variable, and use it if so. + if [ '$(_BuildConfig)' != '$''(_BuildConfig)' ]; then + buildConfig='$(_BuildConfig)' + fi + + officialBuildArgs= + if [ '${{ and(ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}' = 'True' ]; then + officialBuildArgs='/p:DotNetPublishUsingPipelines=true /p:OfficialBuildId=$(BUILD.BUILDNUMBER)' + fi + + targetRidArgs= + if [ '${{ parameters.platform.targetRID }}' != '' ]; then + targetRidArgs='/p:TargetRid=${{ parameters.platform.targetRID }}' + fi + + runtimeOsArgs= + if [ '${{ parameters.platform.runtimeOS }}' != '' ]; then + runtimeOsArgs='/p:RuntimeOS=${{ parameters.platform.runtimeOS }}' + fi + + baseOsArgs= + if [ '${{ parameters.platform.baseOS }}' != '' ]; then + baseOsArgs='/p:BaseOS=${{ parameters.platform.baseOS }}' + fi + + publishArgs= + if [ '${{ parameters.platform.skipPublishValidation }}' != 'true' ]; then + publishArgs='--publish' + fi + + assetManifestFileName=SourceBuild_RidSpecific.xml + if [ '${{ parameters.platform.name }}' != '' ]; then + assetManifestFileName=SourceBuild_${{ parameters.platform.name }}.xml + fi + + ${{ coalesce(parameters.platform.buildScript, './build.sh') }} --ci \ + --configuration $buildConfig \ + --restore --build --pack $publishArgs -bl \ + $officialBuildArgs \ + $internalRuntimeDownloadArgs \ + $internalRestoreArgs \ + $targetRidArgs \ + $runtimeOsArgs \ + $baseOsArgs \ + /p:SourceBuildNonPortable=${{ parameters.platform.nonPortable }} \ + /p:ArcadeBuildFromSource=true \ + /p:DotNetBuildSourceOnly=true \ + /p:DotNetBuildRepo=true \ + /p:AssetManifestFileName=$assetManifestFileName + displayName: Build + +# Upload build logs for diagnosis. +- task: CopyFiles@2 + displayName: Prepare BuildLogs staging directory + inputs: + SourceFolder: '$(Build.SourcesDirectory)' + Contents: | + **/*.log + **/*.binlog + artifacts/sb/prebuilt-report/** + TargetFolder: '$(Build.StagingDirectory)/BuildLogs' + CleanTargetFolder: true + continueOnError: true + condition: succeededOrFailed() + +- template: /eng/common/core-templates/steps/publish-pipeline-artifacts.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + args: + displayName: Publish BuildLogs + targetPath: '$(Build.StagingDirectory)/BuildLogs' + artifactName: BuildLogs_SourceBuild_${{ parameters.platform.name }}_Attempt$(System.JobAttempt) + continueOnError: true + condition: succeededOrFailed() + sbomEnabled: false # we don't need SBOM for logs + +# Manually inject component detection so that we can ignore the source build upstream cache, which contains +# a nupkg cache of input packages (a local feed). +# This path must match the upstream cache path in property 'CurrentRepoSourceBuiltNupkgCacheDir' +# in src\Microsoft.DotNet.Arcade.Sdk\tools\SourceBuild\SourceBuildArcade.targets +- template: /eng/common/core-templates/steps/component-governance.yml + parameters: + displayName: Component Detection (Exclude upstream cache) + is1ESPipeline: ${{ parameters.is1ESPipeline }} + componentGovernanceIgnoreDirectories: '$(Build.SourcesDirectory)/artifacts/sb/src/artifacts/obj/source-built-upstream-cache' + disableComponentGovernance: ${{ eq(variables['System.TeamProject'], 'public') }} diff --git a/eng/common/core-templates/variables/pool-providers.yml b/eng/common/core-templates/variables/pool-providers.yml new file mode 100644 index 00000000000..41053d382a2 --- /dev/null +++ b/eng/common/core-templates/variables/pool-providers.yml @@ -0,0 +1,8 @@ +parameters: + is1ESPipeline: false + +variables: + - ${{ if eq(parameters.is1ESPipeline, 'true') }}: + - template: /eng/common/templates-official/variables/pool-providers.yml + - ${{ else }}: + - template: /eng/common/templates/variables/pool-providers.yml \ No newline at end of file diff --git a/eng/common/cross/arm/sources.list.bionic b/eng/common/cross/arm/sources.list.bionic deleted file mode 100644 index 21095574095..00000000000 --- a/eng/common/cross/arm/sources.list.bionic +++ /dev/null @@ -1,11 +0,0 @@ -deb http://ports.ubuntu.com/ubuntu-ports/ bionic main restricted universe -deb-src http://ports.ubuntu.com/ubuntu-ports/ bionic main restricted universe - -deb http://ports.ubuntu.com/ubuntu-ports/ bionic-updates main restricted universe -deb-src http://ports.ubuntu.com/ubuntu-ports/ bionic-updates main restricted universe - -deb http://ports.ubuntu.com/ubuntu-ports/ bionic-backports main restricted -deb-src http://ports.ubuntu.com/ubuntu-ports/ bionic-backports main restricted - -deb http://ports.ubuntu.com/ubuntu-ports/ bionic-security main restricted universe multiverse -deb-src http://ports.ubuntu.com/ubuntu-ports/ bionic-security main restricted universe multiverse diff --git a/eng/common/cross/arm/sources.list.focal b/eng/common/cross/arm/sources.list.focal deleted file mode 100644 index 4de2600c174..00000000000 --- a/eng/common/cross/arm/sources.list.focal +++ /dev/null @@ -1,11 +0,0 @@ -deb http://ports.ubuntu.com/ubuntu-ports/ focal main restricted universe -deb-src http://ports.ubuntu.com/ubuntu-ports/ focal main restricted universe - -deb http://ports.ubuntu.com/ubuntu-ports/ focal-updates main restricted universe -deb-src http://ports.ubuntu.com/ubuntu-ports/ focal-updates main restricted universe - -deb http://ports.ubuntu.com/ubuntu-ports/ focal-backports main restricted -deb-src http://ports.ubuntu.com/ubuntu-ports/ focal-backports main restricted - -deb http://ports.ubuntu.com/ubuntu-ports/ focal-security main restricted universe multiverse -deb-src http://ports.ubuntu.com/ubuntu-ports/ focal-security main restricted universe multiverse diff --git a/eng/common/cross/arm/sources.list.jammy b/eng/common/cross/arm/sources.list.jammy deleted file mode 100644 index 6bb0453029c..00000000000 --- a/eng/common/cross/arm/sources.list.jammy +++ /dev/null @@ -1,11 +0,0 @@ -deb http://ports.ubuntu.com/ubuntu-ports/ jammy main restricted universe -deb-src http://ports.ubuntu.com/ubuntu-ports/ jammy main restricted universe - -deb http://ports.ubuntu.com/ubuntu-ports/ jammy-updates main restricted universe -deb-src http://ports.ubuntu.com/ubuntu-ports/ jammy-updates main restricted universe - -deb http://ports.ubuntu.com/ubuntu-ports/ jammy-backports main restricted -deb-src http://ports.ubuntu.com/ubuntu-ports/ jammy-backports main restricted - -deb http://ports.ubuntu.com/ubuntu-ports/ jammy-security main restricted universe multiverse -deb-src http://ports.ubuntu.com/ubuntu-ports/ jammy-security main restricted universe multiverse diff --git a/eng/common/cross/arm/sources.list.jessie b/eng/common/cross/arm/sources.list.jessie deleted file mode 100644 index 4d142ac9b10..00000000000 --- a/eng/common/cross/arm/sources.list.jessie +++ /dev/null @@ -1,3 +0,0 @@ -# Debian (sid) # UNSTABLE -deb http://ftp.debian.org/debian/ sid main contrib non-free -deb-src http://ftp.debian.org/debian/ sid main contrib non-free diff --git a/eng/common/cross/arm/sources.list.xenial b/eng/common/cross/arm/sources.list.xenial deleted file mode 100644 index 56fbb36a59f..00000000000 --- a/eng/common/cross/arm/sources.list.xenial +++ /dev/null @@ -1,11 +0,0 @@ -deb http://ports.ubuntu.com/ubuntu-ports/ xenial main restricted universe -deb-src http://ports.ubuntu.com/ubuntu-ports/ xenial main restricted universe - -deb http://ports.ubuntu.com/ubuntu-ports/ xenial-updates main restricted universe -deb-src http://ports.ubuntu.com/ubuntu-ports/ xenial-updates main restricted universe - -deb http://ports.ubuntu.com/ubuntu-ports/ xenial-backports main restricted -deb-src http://ports.ubuntu.com/ubuntu-ports/ xenial-backports main restricted - -deb http://ports.ubuntu.com/ubuntu-ports/ xenial-security main restricted universe multiverse -deb-src http://ports.ubuntu.com/ubuntu-ports/ xenial-security main restricted universe multiverse diff --git a/eng/common/cross/arm/sources.list.zesty b/eng/common/cross/arm/sources.list.zesty deleted file mode 100644 index ea2c14a7874..00000000000 --- a/eng/common/cross/arm/sources.list.zesty +++ /dev/null @@ -1,11 +0,0 @@ -deb http://ports.ubuntu.com/ubuntu-ports/ zesty main restricted universe -deb-src http://ports.ubuntu.com/ubuntu-ports/ zesty main restricted universe - -deb http://ports.ubuntu.com/ubuntu-ports/ zesty-updates main restricted universe -deb-src http://ports.ubuntu.com/ubuntu-ports/ zesty-updates main restricted universe - -deb http://ports.ubuntu.com/ubuntu-ports/ zesty-backports main restricted -deb-src http://ports.ubuntu.com/ubuntu-ports/ zesty-backports main restricted - -deb http://ports.ubuntu.com/ubuntu-ports/ zesty-security main restricted universe multiverse -deb-src http://ports.ubuntu.com/ubuntu-ports/ zesty-security main restricted universe multiverse diff --git a/eng/common/cross/arm64/sources.list.bionic b/eng/common/cross/arm64/sources.list.bionic deleted file mode 100644 index 21095574095..00000000000 --- a/eng/common/cross/arm64/sources.list.bionic +++ /dev/null @@ -1,11 +0,0 @@ -deb http://ports.ubuntu.com/ubuntu-ports/ bionic main restricted universe -deb-src http://ports.ubuntu.com/ubuntu-ports/ bionic main restricted universe - -deb http://ports.ubuntu.com/ubuntu-ports/ bionic-updates main restricted universe -deb-src http://ports.ubuntu.com/ubuntu-ports/ bionic-updates main restricted universe - -deb http://ports.ubuntu.com/ubuntu-ports/ bionic-backports main restricted -deb-src http://ports.ubuntu.com/ubuntu-ports/ bionic-backports main restricted - -deb http://ports.ubuntu.com/ubuntu-ports/ bionic-security main restricted universe multiverse -deb-src http://ports.ubuntu.com/ubuntu-ports/ bionic-security main restricted universe multiverse diff --git a/eng/common/cross/arm64/sources.list.buster b/eng/common/cross/arm64/sources.list.buster deleted file mode 100644 index 7194ac64a96..00000000000 --- a/eng/common/cross/arm64/sources.list.buster +++ /dev/null @@ -1,11 +0,0 @@ -deb http://deb.debian.org/debian buster main -deb-src http://deb.debian.org/debian buster main - -deb http://deb.debian.org/debian-security/ buster/updates main -deb-src http://deb.debian.org/debian-security/ buster/updates main - -deb http://deb.debian.org/debian buster-updates main -deb-src http://deb.debian.org/debian buster-updates main - -deb http://deb.debian.org/debian buster-backports main contrib non-free -deb-src http://deb.debian.org/debian buster-backports main contrib non-free diff --git a/eng/common/cross/arm64/sources.list.focal b/eng/common/cross/arm64/sources.list.focal deleted file mode 100644 index 4de2600c174..00000000000 --- a/eng/common/cross/arm64/sources.list.focal +++ /dev/null @@ -1,11 +0,0 @@ -deb http://ports.ubuntu.com/ubuntu-ports/ focal main restricted universe -deb-src http://ports.ubuntu.com/ubuntu-ports/ focal main restricted universe - -deb http://ports.ubuntu.com/ubuntu-ports/ focal-updates main restricted universe -deb-src http://ports.ubuntu.com/ubuntu-ports/ focal-updates main restricted universe - -deb http://ports.ubuntu.com/ubuntu-ports/ focal-backports main restricted -deb-src http://ports.ubuntu.com/ubuntu-ports/ focal-backports main restricted - -deb http://ports.ubuntu.com/ubuntu-ports/ focal-security main restricted universe multiverse -deb-src http://ports.ubuntu.com/ubuntu-ports/ focal-security main restricted universe multiverse diff --git a/eng/common/cross/arm64/sources.list.jammy b/eng/common/cross/arm64/sources.list.jammy deleted file mode 100644 index 6bb0453029c..00000000000 --- a/eng/common/cross/arm64/sources.list.jammy +++ /dev/null @@ -1,11 +0,0 @@ -deb http://ports.ubuntu.com/ubuntu-ports/ jammy main restricted universe -deb-src http://ports.ubuntu.com/ubuntu-ports/ jammy main restricted universe - -deb http://ports.ubuntu.com/ubuntu-ports/ jammy-updates main restricted universe -deb-src http://ports.ubuntu.com/ubuntu-ports/ jammy-updates main restricted universe - -deb http://ports.ubuntu.com/ubuntu-ports/ jammy-backports main restricted -deb-src http://ports.ubuntu.com/ubuntu-ports/ jammy-backports main restricted - -deb http://ports.ubuntu.com/ubuntu-ports/ jammy-security main restricted universe multiverse -deb-src http://ports.ubuntu.com/ubuntu-ports/ jammy-security main restricted universe multiverse diff --git a/eng/common/cross/arm64/sources.list.stretch b/eng/common/cross/arm64/sources.list.stretch deleted file mode 100644 index 0e121577436..00000000000 --- a/eng/common/cross/arm64/sources.list.stretch +++ /dev/null @@ -1,12 +0,0 @@ -deb http://deb.debian.org/debian stretch main -deb-src http://deb.debian.org/debian stretch main - -deb http://deb.debian.org/debian-security/ stretch/updates main -deb-src http://deb.debian.org/debian-security/ stretch/updates main - -deb http://deb.debian.org/debian stretch-updates main -deb-src http://deb.debian.org/debian stretch-updates main - -deb http://deb.debian.org/debian stretch-backports main contrib non-free -deb-src http://deb.debian.org/debian stretch-backports main contrib non-free - diff --git a/eng/common/cross/arm64/sources.list.xenial b/eng/common/cross/arm64/sources.list.xenial deleted file mode 100644 index 56fbb36a59f..00000000000 --- a/eng/common/cross/arm64/sources.list.xenial +++ /dev/null @@ -1,11 +0,0 @@ -deb http://ports.ubuntu.com/ubuntu-ports/ xenial main restricted universe -deb-src http://ports.ubuntu.com/ubuntu-ports/ xenial main restricted universe - -deb http://ports.ubuntu.com/ubuntu-ports/ xenial-updates main restricted universe -deb-src http://ports.ubuntu.com/ubuntu-ports/ xenial-updates main restricted universe - -deb http://ports.ubuntu.com/ubuntu-ports/ xenial-backports main restricted -deb-src http://ports.ubuntu.com/ubuntu-ports/ xenial-backports main restricted - -deb http://ports.ubuntu.com/ubuntu-ports/ xenial-security main restricted universe multiverse -deb-src http://ports.ubuntu.com/ubuntu-ports/ xenial-security main restricted universe multiverse diff --git a/eng/common/cross/arm64/sources.list.zesty b/eng/common/cross/arm64/sources.list.zesty deleted file mode 100644 index ea2c14a7874..00000000000 --- a/eng/common/cross/arm64/sources.list.zesty +++ /dev/null @@ -1,11 +0,0 @@ -deb http://ports.ubuntu.com/ubuntu-ports/ zesty main restricted universe -deb-src http://ports.ubuntu.com/ubuntu-ports/ zesty main restricted universe - -deb http://ports.ubuntu.com/ubuntu-ports/ zesty-updates main restricted universe -deb-src http://ports.ubuntu.com/ubuntu-ports/ zesty-updates main restricted universe - -deb http://ports.ubuntu.com/ubuntu-ports/ zesty-backports main restricted -deb-src http://ports.ubuntu.com/ubuntu-ports/ zesty-backports main restricted - -deb http://ports.ubuntu.com/ubuntu-ports/ zesty-security main restricted universe multiverse -deb-src http://ports.ubuntu.com/ubuntu-ports/ zesty-security main restricted universe multiverse diff --git a/eng/common/cross/armel/sources.list.jessie b/eng/common/cross/armel/sources.list.jessie deleted file mode 100644 index 3d9c3059d89..00000000000 --- a/eng/common/cross/armel/sources.list.jessie +++ /dev/null @@ -1,3 +0,0 @@ -# Debian (jessie) # Stable -deb http://ftp.debian.org/debian/ jessie main contrib non-free -deb-src http://ftp.debian.org/debian/ jessie main contrib non-free diff --git a/eng/common/cross/armv6/sources.list.buster b/eng/common/cross/armv6/sources.list.buster deleted file mode 100644 index f27fc4fb346..00000000000 --- a/eng/common/cross/armv6/sources.list.buster +++ /dev/null @@ -1,2 +0,0 @@ -deb http://raspbian.raspberrypi.org/raspbian/ buster main contrib non-free rpi -deb-src http://raspbian.raspberrypi.org/raspbian/ buster main contrib non-free rpi diff --git a/eng/common/cross/build-android-rootfs.sh b/eng/common/cross/build-android-rootfs.sh index f163fb9dae9..7e9ba2b75ed 100755 --- a/eng/common/cross/build-android-rootfs.sh +++ b/eng/common/cross/build-android-rootfs.sh @@ -5,15 +5,15 @@ __NDK_Version=r21 usage() { echo "Creates a toolchain and sysroot used for cross-compiling for Android." - echo. + echo echo "Usage: $0 [BuildArch] [ApiLevel]" - echo. + echo echo "BuildArch is the target architecture of Android. Currently only arm64 is supported." echo "ApiLevel is the target Android API level. API levels usually match to Android releases. See https://source.android.com/source/build-numbers.html" - echo. + echo echo "By default, the toolchain and sysroot will be generated in cross/android-rootfs/toolchain/[BuildArch]. You can change this behavior" echo "by setting the TOOLCHAIN_DIR environment variable" - echo. + echo echo "By default, the NDK will be downloaded into the cross/android-rootfs/android-ndk-$__NDK_Version directory. If you already have an NDK installation," echo "you can set the NDK_DIR environment variable to have this script use that installation of the NDK." echo "By default, this script will generate a file, android_platform, in the root of the ROOTFS_DIR directory that contains the RID for the supported and tested Android build: android.28-arm64. This file is to replace '/etc/os-release', which is not available for Android." diff --git a/eng/common/cross/build-rootfs.sh b/eng/common/cross/build-rootfs.sh index 9caf9b021db..eb1a9080464 100755 --- a/eng/common/cross/build-rootfs.sh +++ b/eng/common/cross/build-rootfs.sh @@ -8,7 +8,7 @@ usage() echo "BuildArch can be: arm(default), arm64, armel, armv6, ppc64le, riscv64, s390x, x64, x86" echo "CodeName - optional, Code name for Linux, can be: xenial(default), zesty, bionic, alpine" echo " for alpine can be specified with version: alpineX.YY or alpineedge" - echo " for FreeBSD can be: freebsd12, freebsd13" + echo " for FreeBSD can be: freebsd13, freebsd14" echo " for illumos can be: illumos" echo " for Haiku can be: haiku." echo "lldbx.y - optional, LLDB version, can be: lldb3.9(default), lldb4.0, lldb5.0, lldb6.0 no-lldb. Ignored for alpine and FreeBSD" @@ -30,7 +30,8 @@ __IllumosArch=arm7 __HaikuArch=arm __QEMUArch=arm __UbuntuArch=armhf -__UbuntuRepo="http://ports.ubuntu.com/" +__UbuntuRepo= +__UbuntuSuites="updates security backports" __LLDB_Package="liblldb-3.9-dev" __SkipUnmount=0 @@ -71,9 +72,9 @@ __AlpinePackages+=" krb5-dev" __AlpinePackages+=" openssl-dev" __AlpinePackages+=" zlib-dev" -__FreeBSDBase="12.4-RELEASE" +__FreeBSDBase="13.2-RELEASE" __FreeBSDPkg="1.17.0" -__FreeBSDABI="12" +__FreeBSDABI="13" __FreeBSDPackages="libunwind" __FreeBSDPackages+=" icu" __FreeBSDPackages+=" libinotify" @@ -129,6 +130,7 @@ __AlpineKeys=' 616db30d:MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAnpUpyWDWjlUk3smlWeA0\nlIMW+oJ38t92CRLHH3IqRhyECBRW0d0aRGtq7TY8PmxjjvBZrxTNDpJT6KUk4LRm\na6A6IuAI7QnNK8SJqM0DLzlpygd7GJf8ZL9SoHSH+gFsYF67Cpooz/YDqWrlN7Vw\ntO00s0B+eXy+PCXYU7VSfuWFGK8TGEv6HfGMALLjhqMManyvfp8hz3ubN1rK3c8C\nUS/ilRh1qckdbtPvoDPhSbTDmfU1g/EfRSIEXBrIMLg9ka/XB9PvWRrekrppnQzP\nhP9YE3x/wbFc5QqQWiRCYyQl/rgIMOXvIxhkfe8H5n1Et4VAorkpEAXdsfN8KSVv\nLSMazVlLp9GYq5SUpqYX3KnxdWBgN7BJoZ4sltsTpHQ/34SXWfu3UmyUveWj7wp0\nx9hwsPirVI00EEea9AbP7NM2rAyu6ukcm4m6ATd2DZJIViq2es6m60AE6SMCmrQF\nwmk4H/kdQgeAELVfGOm2VyJ3z69fQuywz7xu27S6zTKi05Qlnohxol4wVb6OB7qG\nLPRtK9ObgzRo/OPumyXqlzAi/Yvyd1ZQk8labZps3e16bQp8+pVPiumWioMFJDWV\nGZjCmyMSU8V6MB6njbgLHoyg2LCukCAeSjbPGGGYhnKLm1AKSoJh3IpZuqcKCk5C\n8CM1S15HxV78s9dFntEqIokCAwEAAQ== ' __Keyring= +__KeyringFile="/usr/share/keyrings/ubuntu-archive-keyring.gpg" __SkipSigCheck=0 __UseMirror=0 @@ -142,7 +144,6 @@ while :; do case $lowerI in -\?|-h|--help) usage - exit 1 ;; arm) __BuildArch=arm @@ -163,6 +164,7 @@ while :; do __UbuntuArch=armel __UbuntuRepo="http://ftp.debian.org/debian/" __CodeName=jessie + __KeyringFile="/usr/share/keyrings/debian-archive-keyring.gpg" ;; armv6) __BuildArch=armv6 @@ -170,10 +172,12 @@ while :; do __QEMUArch=arm __UbuntuRepo="http://raspbian.raspberrypi.org/raspbian/" __CodeName=buster + __KeyringFile="/usr/share/keyrings/raspbian-archive-keyring.gpg" __LLDB_Package="liblldb-6.0-dev" + __UbuntuSuites= - if [[ -e "/usr/share/keyrings/raspbian-archive-keyring.gpg" ]]; then - __Keyring="--keyring /usr/share/keyrings/raspbian-archive-keyring.gpg" + if [[ -e "$__KeyringFile" ]]; then + __Keyring="--keyring $__KeyringFile" fi ;; riscv64) @@ -182,13 +186,8 @@ while :; do __AlpinePackages="${__AlpinePackages// lldb-dev/}" __QEMUArch=riscv64 __UbuntuArch=riscv64 - __UbuntuRepo="http://deb.debian.org/debian-ports" __UbuntuPackages="${__UbuntuPackages// libunwind8-dev/}" unset __LLDB_Package - - if [[ -e "/usr/share/keyrings/debian-ports-archive-keyring.gpg" ]]; then - __Keyring="--keyring /usr/share/keyrings/debian-ports-archive-keyring.gpg --include=debian-ports-archive-keyring" - fi ;; ppc64le) __BuildArch=ppc64le @@ -229,12 +228,19 @@ while :; do __UbuntuRepo="http://archive.ubuntu.com/ubuntu/" ;; lldb*) - version="${lowerI/lldb/}" - parts=(${version//./ }) + version="$(echo "$lowerI" | tr -d '[:alpha:]-=')" + majorVersion="${version%%.*}" + + [ -z "${version##*.*}" ] && minorVersion="${version#*.}" + if [ -z "$minorVersion" ]; then + minorVersion=0 + fi # for versions > 6.0, lldb has dropped the minor version - if [[ "${parts[0]}" -gt 6 ]]; then - version="${parts[0]}" + if [ "$majorVersion" -le 6 ]; then + version="$majorVersion.$minorVersion" + else + version="$majorVersion" fi __LLDB_Package="liblldb-${version}-dev" @@ -243,15 +249,19 @@ while :; do unset __LLDB_Package ;; llvm*) - version="${lowerI/llvm/}" - parts=(${version//./ }) - __LLVM_MajorVersion="${parts[0]}" - __LLVM_MinorVersion="${parts[1]}" - - # for versions > 6.0, llvm has dropped the minor version - if [[ -z "$__LLVM_MinorVersion" && "$__LLVM_MajorVersion" -le 6 ]]; then - __LLVM_MinorVersion=0; + version="$(echo "$lowerI" | tr -d '[:alpha:]-=')" + __LLVM_MajorVersion="${version%%.*}" + + [ -z "${version##*.*}" ] && __LLVM_MinorVersion="${version#*.}" + if [ -z "$__LLVM_MinorVersion" ]; then + __LLVM_MinorVersion=0 + fi + + # for versions > 6.0, lldb has dropped the minor version + if [ "$__LLVM_MajorVersion" -gt 6 ]; then + __LLVM_MinorVersion= fi + ;; xenial) # Ubuntu 16.04 if [[ "$__CodeName" != "jessie" ]]; then @@ -278,8 +288,17 @@ while :; do __CodeName=jammy fi ;; + noble) # Ubuntu 24.04 + if [[ "$__CodeName" != "jessie" ]]; then + __CodeName=noble + fi + if [[ -n "$__LLDB_Package" ]]; then + __LLDB_Package="liblldb-18-dev" + fi + ;; jessie) # Debian 8 __CodeName=jessie + __KeyringFile="/usr/share/keyrings/debian-archive-keyring.gpg" if [[ -z "$__UbuntuRepo" ]]; then __UbuntuRepo="http://ftp.debian.org/debian/" @@ -288,6 +307,7 @@ while :; do stretch) # Debian 9 __CodeName=stretch __LLDB_Package="liblldb-6.0-dev" + __KeyringFile="/usr/share/keyrings/debian-archive-keyring.gpg" if [[ -z "$__UbuntuRepo" ]]; then __UbuntuRepo="http://ftp.debian.org/debian/" @@ -296,6 +316,7 @@ while :; do buster) # Debian 10 __CodeName=buster __LLDB_Package="liblldb-6.0-dev" + __KeyringFile="/usr/share/keyrings/debian-archive-keyring.gpg" if [[ -z "$__UbuntuRepo" ]]; then __UbuntuRepo="http://ftp.debian.org/debian/" @@ -303,6 +324,15 @@ while :; do ;; bullseye) # Debian 11 __CodeName=bullseye + __KeyringFile="/usr/share/keyrings/debian-archive-keyring.gpg" + + if [[ -z "$__UbuntuRepo" ]]; then + __UbuntuRepo="http://ftp.debian.org/debian/" + fi + ;; + bookworm) # Debian 12 + __CodeName=bookworm + __KeyringFile="/usr/share/keyrings/debian-archive-keyring.gpg" if [[ -z "$__UbuntuRepo" ]]; then __UbuntuRepo="http://ftp.debian.org/debian/" @@ -310,6 +340,7 @@ while :; do ;; sid) # Debian sid __CodeName=sid + __KeyringFile="/usr/share/keyrings/debian-archive-keyring.gpg" if [[ -z "$__UbuntuRepo" ]]; then __UbuntuRepo="http://ftp.debian.org/debian/" @@ -323,25 +354,24 @@ while :; do alpine*) __CodeName=alpine __UbuntuRepo= - version="${lowerI/alpine/}" - if [[ "$version" == "edge" ]]; then + if [[ "$lowerI" == "alpineedge" ]]; then __AlpineVersion=edge else - parts=(${version//./ }) - __AlpineMajorVersion="${parts[0]}" - __AlpineMinoVersion="${parts[1]}" - __AlpineVersion="$__AlpineMajorVersion.$__AlpineMinoVersion" + version="$(echo "$lowerI" | tr -d '[:alpha:]-=')" + __AlpineMajorVersion="${version%%.*}" + __AlpineMinorVersion="${version#*.}" + __AlpineVersion="$__AlpineMajorVersion.$__AlpineMinorVersion" fi ;; - freebsd12) + freebsd13) __CodeName=freebsd __SkipUnmount=1 ;; - freebsd13) + freebsd14) __CodeName=freebsd - __FreeBSDBase="13.2-RELEASE" - __FreeBSDABI="13" + __FreeBSDBase="14.0-RELEASE" + __FreeBSDABI="14" __SkipUnmount=1 ;; illumos) @@ -420,6 +450,10 @@ fi __UbuntuPackages+=" ${__LLDB_Package:-}" +if [[ -z "$__UbuntuRepo" ]]; then + __UbuntuRepo="http://ports.ubuntu.com/" +fi + if [[ -n "$__LLVM_MajorVersion" ]]; then __UbuntuPackages+=" libclang-common-${__LLVM_MajorVersion}${__LLVM_MinorVersion:+.$__LLVM_MinorVersion}-dev" fi @@ -442,13 +476,39 @@ fi mkdir -p "$__RootfsDir" __RootfsDir="$( cd "$__RootfsDir" && pwd )" +__hasWget= +ensureDownloadTool() +{ + if command -v wget &> /dev/null; then + __hasWget=1 + elif command -v curl &> /dev/null; then + __hasWget=0 + else + >&2 echo "ERROR: either wget or curl is required by this script." + exit 1 + fi +} + if [[ "$__CodeName" == "alpine" ]]; then __ApkToolsVersion=2.12.11 - __ApkToolsSHA512SUM=53e57b49230da07ef44ee0765b9592580308c407a8d4da7125550957bb72cb59638e04f8892a18b584451c8d841d1c7cb0f0ab680cc323a3015776affaa3be33 __ApkToolsDir="$(mktemp -d)" __ApkKeysDir="$(mktemp -d)" + arch="$(uname -m)" - wget "https://gitlab.alpinelinux.org/api/v4/projects/5/packages/generic//v$__ApkToolsVersion/x86_64/apk.static" -P "$__ApkToolsDir" + ensureDownloadTool + + if [[ "$__hasWget" == 1 ]]; then + wget -P "$__ApkToolsDir" "https://gitlab.alpinelinux.org/api/v4/projects/5/packages/generic/v$__ApkToolsVersion/$arch/apk.static" + else + curl -SLO --create-dirs --output-dir "$__ApkToolsDir" "https://gitlab.alpinelinux.org/api/v4/projects/5/packages/generic/v$__ApkToolsVersion/$arch/apk.static" + fi + if [[ "$arch" == "x86_64" ]]; then + __ApkToolsSHA512SUM="53e57b49230da07ef44ee0765b9592580308c407a8d4da7125550957bb72cb59638e04f8892a18b584451c8d841d1c7cb0f0ab680cc323a3015776affaa3be33" + elif [[ "$arch" == "aarch64" ]]; then + __ApkToolsSHA512SUM="9e2b37ecb2b56c05dad23d379be84fd494c14bd730b620d0d576bda760588e1f2f59a7fcb2f2080577e0085f23a0ca8eadd993b4e61c2ab29549fdb71969afd0" + else + echo "WARNING: add missing hash for your host architecture. To find the value, use: 'find /tmp -name apk.static -exec sha512sum {} \;'" + fi echo "$__ApkToolsSHA512SUM $__ApkToolsDir/apk.static" | sha512sum -c chmod +x "$__ApkToolsDir/apk.static" @@ -477,20 +537,23 @@ if [[ "$__CodeName" == "alpine" ]]; then fi # initialize DB + # shellcheck disable=SC2086 "$__ApkToolsDir/apk.static" \ -X "http://dl-cdn.alpinelinux.org/alpine/$version/main" \ -X "http://dl-cdn.alpinelinux.org/alpine/$version/community" \ -U $__ApkSignatureArg --root "$__RootfsDir" --arch "$__AlpineArch" --initdb add if [[ "$__AlpineLlvmLibsLookup" == 1 ]]; then + # shellcheck disable=SC2086 __AlpinePackages+=" $("$__ApkToolsDir/apk.static" \ -X "http://dl-cdn.alpinelinux.org/alpine/$version/main" \ -X "http://dl-cdn.alpinelinux.org/alpine/$version/community" \ -U $__ApkSignatureArg --root "$__RootfsDir" --arch "$__AlpineArch" \ - search 'llvm*-libs' | sort | tail -1 | sed 's/-[^-]*//2g')" + search 'llvm*-libs' | grep -E '^llvm' | sort | tail -1 | sed 's/-[^-]*//2g')" fi # install all packages in one go + # shellcheck disable=SC2086 "$__ApkToolsDir/apk.static" \ -X "http://dl-cdn.alpinelinux.org/alpine/$version/main" \ -X "http://dl-cdn.alpinelinux.org/alpine/$version/community" \ @@ -501,12 +564,23 @@ if [[ "$__CodeName" == "alpine" ]]; then elif [[ "$__CodeName" == "freebsd" ]]; then mkdir -p "$__RootfsDir"/usr/local/etc JOBS=${MAXJOBS:="$(getconf _NPROCESSORS_ONLN)"} - wget -O - "https://download.freebsd.org/ftp/releases/${__FreeBSDArch}/${__FreeBSDMachineArch}/${__FreeBSDBase}/base.txz" | tar -C "$__RootfsDir" -Jxf - ./lib ./usr/lib ./usr/libdata ./usr/include ./usr/share/keys ./etc ./bin/freebsd-version + + ensureDownloadTool + + if [[ "$__hasWget" == 1 ]]; then + wget -O- "https://download.freebsd.org/ftp/releases/${__FreeBSDArch}/${__FreeBSDMachineArch}/${__FreeBSDBase}/base.txz" | tar -C "$__RootfsDir" -Jxf - ./lib ./usr/lib ./usr/libdata ./usr/include ./usr/share/keys ./etc ./bin/freebsd-version + else + curl -SL "https://download.freebsd.org/ftp/releases/${__FreeBSDArch}/${__FreeBSDMachineArch}/${__FreeBSDBase}/base.txz" | tar -C "$__RootfsDir" -Jxf - ./lib ./usr/lib ./usr/libdata ./usr/include ./usr/share/keys ./etc ./bin/freebsd-version + fi echo "ABI = \"FreeBSD:${__FreeBSDABI}:${__FreeBSDMachineArch}\"; FINGERPRINTS = \"${__RootfsDir}/usr/share/keys\"; REPOS_DIR = [\"${__RootfsDir}/etc/pkg\"]; REPO_AUTOUPDATE = NO; RUN_SCRIPTS = NO;" > "${__RootfsDir}"/usr/local/etc/pkg.conf echo "FreeBSD: { url: \"pkg+http://pkg.FreeBSD.org/\${ABI}/quarterly\", mirror_type: \"srv\", signature_type: \"fingerprints\", fingerprints: \"${__RootfsDir}/usr/share/keys/pkg\", enabled: yes }" > "${__RootfsDir}"/etc/pkg/FreeBSD.conf mkdir -p "$__RootfsDir"/tmp # get and build package manager - wget -O - "https://github.com/freebsd/pkg/archive/${__FreeBSDPkg}.tar.gz" | tar -C "$__RootfsDir"/tmp -zxf - + if [[ "$__hasWget" == 1 ]]; then + wget -O- "https://github.com/freebsd/pkg/archive/${__FreeBSDPkg}.tar.gz" | tar -C "$__RootfsDir"/tmp -zxf - + else + curl -SL "https://github.com/freebsd/pkg/archive/${__FreeBSDPkg}.tar.gz" | tar -C "$__RootfsDir"/tmp -zxf - + fi cd "$__RootfsDir/tmp/pkg-${__FreeBSDPkg}" # needed for install to succeed mkdir -p "$__RootfsDir"/host/etc @@ -514,20 +588,36 @@ elif [[ "$__CodeName" == "freebsd" ]]; then rm -rf "$__RootfsDir/tmp/pkg-${__FreeBSDPkg}" # install packages we need. INSTALL_AS_USER=$(whoami) "$__RootfsDir"/host/sbin/pkg -r "$__RootfsDir" -C "$__RootfsDir"/usr/local/etc/pkg.conf update + # shellcheck disable=SC2086 INSTALL_AS_USER=$(whoami) "$__RootfsDir"/host/sbin/pkg -r "$__RootfsDir" -C "$__RootfsDir"/usr/local/etc/pkg.conf install --yes $__FreeBSDPackages elif [[ "$__CodeName" == "illumos" ]]; then mkdir "$__RootfsDir/tmp" pushd "$__RootfsDir/tmp" JOBS=${MAXJOBS:="$(getconf _NPROCESSORS_ONLN)"} + + ensureDownloadTool + echo "Downloading sysroot." - wget -O - https://github.com/illumos/sysroot/releases/download/20181213-de6af22ae73b-v1/illumos-sysroot-i386-20181213-de6af22ae73b-v1.tar.gz | tar -C "$__RootfsDir" -xzf - + if [[ "$__hasWget" == 1 ]]; then + wget -O- https://github.com/illumos/sysroot/releases/download/20181213-de6af22ae73b-v1/illumos-sysroot-i386-20181213-de6af22ae73b-v1.tar.gz | tar -C "$__RootfsDir" -xzf - + else + curl -SL https://github.com/illumos/sysroot/releases/download/20181213-de6af22ae73b-v1/illumos-sysroot-i386-20181213-de6af22ae73b-v1.tar.gz | tar -C "$__RootfsDir" -xzf - + fi echo "Building binutils. Please wait.." - wget -O - https://ftp.gnu.org/gnu/binutils/binutils-2.33.1.tar.bz2 | tar -xjf - + if [[ "$__hasWget" == 1 ]]; then + wget -O- https://ftp.gnu.org/gnu/binutils/binutils-2.33.1.tar.bz2 | tar -xjf - + else + curl -SL https://ftp.gnu.org/gnu/binutils/binutils-2.33.1.tar.bz2 | tar -xjf - + fi mkdir build-binutils && cd build-binutils ../binutils-2.33.1/configure --prefix="$__RootfsDir" --target="${__illumosArch}-sun-solaris2.10" --program-prefix="${__illumosArch}-illumos-" --with-sysroot="$__RootfsDir" make -j "$JOBS" && make install && cd .. echo "Building gcc. Please wait.." - wget -O - https://ftp.gnu.org/gnu/gcc/gcc-8.4.0/gcc-8.4.0.tar.xz | tar -xJf - + if [[ "$__hasWget" == 1 ]]; then + wget -O- https://ftp.gnu.org/gnu/gcc/gcc-8.4.0/gcc-8.4.0.tar.xz | tar -xJf - + else + curl -SL https://ftp.gnu.org/gnu/gcc/gcc-8.4.0/gcc-8.4.0.tar.xz | tar -xJf - + fi CFLAGS="-fPIC" CXXFLAGS="-fPIC" CXXFLAGS_FOR_TARGET="-fPIC" @@ -544,7 +634,11 @@ elif [[ "$__CodeName" == "illumos" ]]; then fi BaseUrl="$BaseUrl/packages/SmartOS/trunk/${__illumosArch}/All" echo "Downloading manifest" - wget "$BaseUrl" + if [[ "$__hasWget" == 1 ]]; then + wget "$BaseUrl" + else + curl -SLO "$BaseUrl" + fi echo "Downloading dependencies." read -ra array <<<"$__IllumosPackages" for package in "${array[@]}"; do @@ -552,7 +646,11 @@ elif [[ "$__CodeName" == "illumos" ]]; then # find last occurrence of package in listing and extract its name package="$(sed -En '/.*href="('"$package"'-[0-9].*).tgz".*/h;$!d;g;s//\1/p' All)" echo "Resolved name '$package'" - wget "$BaseUrl"/"$package".tgz + if [[ "$__hasWget" == 1 ]]; then + wget "$BaseUrl"/"$package".tgz + else + curl -SLO "$BaseUrl"/"$package".tgz + fi ar -x "$package".tgz tar --skip-old-files -xzf "$package".tmp.tg* -C "$__RootfsDir" 2>/dev/null done @@ -561,10 +659,17 @@ elif [[ "$__CodeName" == "illumos" ]]; then rm -rf "$__RootfsDir"/{tmp,+*} mkdir -p "$__RootfsDir"/usr/include/net mkdir -p "$__RootfsDir"/usr/include/netpacket - wget -P "$__RootfsDir"/usr/include/net https://raw.githubusercontent.com/illumos/illumos-gate/master/usr/src/uts/common/io/bpf/net/bpf.h - wget -P "$__RootfsDir"/usr/include/net https://raw.githubusercontent.com/illumos/illumos-gate/master/usr/src/uts/common/io/bpf/net/dlt.h - wget -P "$__RootfsDir"/usr/include/netpacket https://raw.githubusercontent.com/illumos/illumos-gate/master/usr/src/uts/common/inet/sockmods/netpacket/packet.h - wget -P "$__RootfsDir"/usr/include/sys https://raw.githubusercontent.com/illumos/illumos-gate/master/usr/src/uts/common/sys/sdt.h + if [[ "$__hasWget" == 1 ]]; then + wget -P "$__RootfsDir"/usr/include/net https://raw.githubusercontent.com/illumos/illumos-gate/master/usr/src/uts/common/io/bpf/net/bpf.h + wget -P "$__RootfsDir"/usr/include/net https://raw.githubusercontent.com/illumos/illumos-gate/master/usr/src/uts/common/io/bpf/net/dlt.h + wget -P "$__RootfsDir"/usr/include/netpacket https://raw.githubusercontent.com/illumos/illumos-gate/master/usr/src/uts/common/inet/sockmods/netpacket/packet.h + wget -P "$__RootfsDir"/usr/include/sys https://raw.githubusercontent.com/illumos/illumos-gate/master/usr/src/uts/common/sys/sdt.h + else + curl -SLO --create-dirs --output-dir "$__RootfsDir"/usr/include/net https://raw.githubusercontent.com/illumos/illumos-gate/master/usr/src/uts/common/io/bpf/net/bpf.h + curl -SLO --create-dirs --output-dir "$__RootfsDir"/usr/include/net https://raw.githubusercontent.com/illumos/illumos-gate/master/usr/src/uts/common/io/bpf/net/dlt.h + curl -SLO --create-dirs --output-dir "$__RootfsDir"/usr/include/netpacket https://raw.githubusercontent.com/illumos/illumos-gate/master/usr/src/uts/common/inet/sockmods/netpacket/packet.h + curl -SLO --create-dirs --output-dir "$__RootfsDir"/usr/include/sys https://raw.githubusercontent.com/illumos/illumos-gate/master/usr/src/uts/common/sys/sdt.h + fi elif [[ "$__CodeName" == "haiku" ]]; then JOBS=${MAXJOBS:="$(getconf _NPROCESSORS_ONLN)"} @@ -574,9 +679,16 @@ elif [[ "$__CodeName" == "haiku" ]]; then mkdir "$__RootfsDir/tmp/download" + ensureDownloadTool + echo "Downloading Haiku package tool" - git clone https://github.com/haiku/haiku-toolchains-ubuntu --depth 1 $__RootfsDir/tmp/script - wget -O "$__RootfsDir/tmp/download/hosttools.zip" $($__RootfsDir/tmp/script/fetch.sh --hosttools) + git clone https://github.com/haiku/haiku-toolchains-ubuntu --depth 1 "$__RootfsDir/tmp/script" + if [[ "$__hasWget" == 1 ]]; then + wget -O "$__RootfsDir/tmp/download/hosttools.zip" "$("$__RootfsDir/tmp/script/fetch.sh" --hosttools)" + else + curl -SLo "$__RootfsDir/tmp/download/hosttools.zip" "$("$__RootfsDir/tmp/script/fetch.sh" --hosttools)" + fi + unzip -o "$__RootfsDir/tmp/download/hosttools.zip" -d "$__RootfsDir/tmp/bin" DepotBaseUrl="https://depot.haiku-os.org/__api/v2/pkg/get-pkg" @@ -589,14 +701,25 @@ elif [[ "$__CodeName" == "haiku" ]]; then echo "Downloading $package..." # API documented here: https://github.com/haiku/haikudepotserver/blob/master/haikudepotserver-api2/src/main/resources/api2/pkg.yaml#L60 # The schema here: https://github.com/haiku/haikudepotserver/blob/master/haikudepotserver-api2/src/main/resources/api2/pkg.yaml#L598 - hpkgDownloadUrl="$(wget -qO- --post-data='{"name":"'"$package"'","repositorySourceCode":"haikuports_'$__HaikuArch'","versionType":"LATEST","naturalLanguageCode":"en"}' \ - --header='Content-Type:application/json' "$DepotBaseUrl" | jq -r '.result.versions[].hpkgDownloadURL')" - wget -P "$__RootfsDir/tmp/download" "$hpkgDownloadUrl" + if [[ "$__hasWget" == 1 ]]; then + hpkgDownloadUrl="$(wget -qO- --post-data '{"name":"'"$package"'","repositorySourceCode":"haikuports_'$__HaikuArch'","versionType":"LATEST","naturalLanguageCode":"en"}' \ + --header 'Content-Type:application/json' "$DepotBaseUrl" | jq -r '.result.versions[].hpkgDownloadURL')" + wget -P "$__RootfsDir/tmp/download" "$hpkgDownloadUrl" + else + hpkgDownloadUrl="$(curl -sSL -XPOST --data '{"name":"'"$package"'","repositorySourceCode":"haikuports_'$__HaikuArch'","versionType":"LATEST","naturalLanguageCode":"en"}' \ + --header 'Content-Type:application/json' "$DepotBaseUrl" | jq -r '.result.versions[].hpkgDownloadURL')" + curl -SLO --create-dirs --output-dir "$__RootfsDir/tmp/download" "$hpkgDownloadUrl" + fi done for package in haiku haiku_devel; do echo "Downloading $package..." - hpkgVersion="$(wget -qO- $HpkgBaseUrl | sed -n 's/^.*version: "\([^"]*\)".*$/\1/p')" - wget -P "$__RootfsDir/tmp/download" "$HpkgBaseUrl/packages/$package-$hpkgVersion-1-$__HaikuArch.hpkg" + if [[ "$__hasWget" == 1 ]]; then + hpkgVersion="$(wget -qO- "$HpkgBaseUrl" | sed -n 's/^.*version: "\([^"]*\)".*$/\1/p')" + wget -P "$__RootfsDir/tmp/download" "$HpkgBaseUrl/packages/$package-$hpkgVersion-1-$__HaikuArch.hpkg" + else + hpkgVersion="$(curl -sSL "$HpkgBaseUrl" | sed -n 's/^.*version: "\([^"]*\)".*$/\1/p')" + curl -SLO --create-dirs --output-dir "$__RootfsDir/tmp/download" "$HpkgBaseUrl/packages/$package-$hpkgVersion-1-$__HaikuArch.hpkg" + fi done # Set up the sysroot @@ -609,7 +732,11 @@ elif [[ "$__CodeName" == "haiku" ]]; then # Download buildtools echo "Downloading Haiku buildtools" - wget -O "$__RootfsDir/tmp/download/buildtools.zip" $($__RootfsDir/tmp/script/fetch.sh --buildtools --arch=$__HaikuArch) + if [[ "$__hasWget" == 1 ]]; then + wget -O "$__RootfsDir/tmp/download/buildtools.zip" "$("$__RootfsDir/tmp/script/fetch.sh" --buildtools --arch=$__HaikuArch)" + else + curl -SLo "$__RootfsDir/tmp/download/buildtools.zip" "$("$__RootfsDir/tmp/script/fetch.sh" --buildtools --arch=$__HaikuArch)" + fi unzip -o "$__RootfsDir/tmp/download/buildtools.zip" -d "$__RootfsDir" # Cleaning up temporary files @@ -622,10 +749,22 @@ elif [[ -n "$__CodeName" ]]; then __Keyring="$__Keyring --force-check-gpg" fi + # shellcheck disable=SC2086 + echo running debootstrap "--variant=minbase" $__Keyring --arch "$__UbuntuArch" "$__CodeName" "$__RootfsDir" "$__UbuntuRepo" debootstrap "--variant=minbase" $__Keyring --arch "$__UbuntuArch" "$__CodeName" "$__RootfsDir" "$__UbuntuRepo" - cp "$__CrossDir/$__BuildArch/sources.list.$__CodeName" "$__RootfsDir/etc/apt/sources.list" + + mkdir -p "$__RootfsDir/etc/apt/sources.list.d/" + cat > "$__RootfsDir/etc/apt/sources.list.d/$__CodeName.sources" <>Start configuring Tizen rootfs" ln -sfn asm-${LINK_ARCH} ./usr/include/asm patch -p1 < $__TIZEN_CROSSDIR/tizen.patch +if [[ "$TIZEN_ARCH" == "riscv64" ]]; then + echo "Fixing broken symlinks in $PWD" + rm ./usr/lib64/libresolv.so + ln -s ../../lib64/libresolv.so.2 ./usr/lib64/libresolv.so + rm ./usr/lib64/libpthread.so + ln -s ../../lib64/libpthread.so.0 ./usr/lib64/libpthread.so + rm ./usr/lib64/libdl.so + ln -s ../../lib64/libdl.so.2 ./usr/lib64/libdl.so + rm ./usr/lib64/libutil.so + ln -s ../../lib64/libutil.so.1 ./usr/lib64/libutil.so + rm ./usr/lib64/libm.so + ln -s ../../lib64/libm.so.6 ./usr/lib64/libm.so + rm ./usr/lib64/librt.so + ln -s ../../lib64/librt.so.1 ./usr/lib64/librt.so + rm ./lib/ld-linux-riscv64-lp64d.so.1 + ln -s ../lib64/ld-linux-riscv64-lp64d.so.1 ./lib/ld-linux-riscv64-lp64d.so.1 +fi echo "<:--stdlib=${CLR_CMAKE_CXX_STANDARD_LIBRARY}>) + add_link_options($<$:--stdlib=${CLR_CMAKE_CXX_STANDARD_LIBRARY}>) +endif() + +option(CLR_CMAKE_CXX_STANDARD_LIBRARY_STATIC "Statically link against the C++ standard library" OFF) +if(CLR_CMAKE_CXX_STANDARD_LIBRARY_STATIC) + add_link_options($<$:-static-libstdc++>) +endif() + +set(CLR_CMAKE_CXX_ABI_LIBRARY "" CACHE STRING "C++ ABI implementation library to link against. Only supported with the Clang compiler.") +if (CLR_CMAKE_CXX_ABI_LIBRARY) + # The user may specify the ABI library with the 'lib' prefix, like 'libstdc++'. Strip the prefix here so the linker finds the right library. + string(REGEX REPLACE "^lib(.+)" "\\1" CLR_CMAKE_CXX_ABI_LIBRARY ${CLR_CMAKE_CXX_ABI_LIBRARY}) + # We need to specify this as a linker-backend option as Clang will filter this option out when linking to libc++. + add_link_options("LINKER:-l${CLR_CMAKE_CXX_ABI_LIBRARY}") +endif() + set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) diff --git a/eng/common/cross/x86/sources.list.bionic b/eng/common/cross/x86/sources.list.bionic deleted file mode 100644 index a71ccadcffa..00000000000 --- a/eng/common/cross/x86/sources.list.bionic +++ /dev/null @@ -1,11 +0,0 @@ -deb http://archive.ubuntu.com/ubuntu/ bionic main restricted universe -deb-src http://archive.ubuntu.com/ubuntu/ bionic main restricted universe - -deb http://archive.ubuntu.com/ubuntu/ bionic-updates main restricted universe -deb-src http://archive.ubuntu.com/ubuntu/ bionic-updates main restricted universe - -deb http://archive.ubuntu.com/ubuntu/ bionic-backports main restricted -deb-src http://archive.ubuntu.com/ubuntu/ bionic-backports main restricted - -deb http://archive.ubuntu.com/ubuntu/ bionic-security main restricted universe multiverse -deb-src http://archive.ubuntu.com/ubuntu/ bionic-security main restricted universe multiverse diff --git a/eng/common/cross/x86/sources.list.focal b/eng/common/cross/x86/sources.list.focal deleted file mode 100644 index 99d5731330e..00000000000 --- a/eng/common/cross/x86/sources.list.focal +++ /dev/null @@ -1,11 +0,0 @@ -deb http://archive.ubuntu.com/ubuntu/ focal main restricted universe -deb-src http://archive.ubuntu.com/ubuntu/ focal main restricted universe - -deb http://archive.ubuntu.com/ubuntu/ focal-updates main restricted universe -deb-src http://archive.ubuntu.com/ubuntu/ focal-updates main restricted universe - -deb http://archive.ubuntu.com/ubuntu/ focal-backports main restricted -deb-src http://archive.ubuntu.com/ubuntu/ focal-backports main restricted - -deb http://archive.ubuntu.com/ubuntu/ focal-security main restricted universe multiverse -deb-src http://archive.ubuntu.com/ubuntu/ focal-security main restricted universe multiverse diff --git a/eng/common/cross/x86/sources.list.jammy b/eng/common/cross/x86/sources.list.jammy deleted file mode 100644 index af1c1feaeac..00000000000 --- a/eng/common/cross/x86/sources.list.jammy +++ /dev/null @@ -1,11 +0,0 @@ -deb http://archive.ubuntu.com/ubuntu/ jammy main restricted universe -deb-src http://archive.ubuntu.com/ubuntu/ jammy main restricted universe - -deb http://archive.ubuntu.com/ubuntu/ jammy-updates main restricted universe -deb-src http://archive.ubuntu.com/ubuntu/ jammy-updates main restricted universe - -deb http://archive.ubuntu.com/ubuntu/ jammy-backports main restricted -deb-src http://archive.ubuntu.com/ubuntu/ jammy-backports main restricted - -deb http://archive.ubuntu.com/ubuntu/ jammy-security main restricted universe multiverse -deb-src http://archive.ubuntu.com/ubuntu/ jammy-security main restricted universe multiverse diff --git a/eng/common/cross/x86/sources.list.xenial b/eng/common/cross/x86/sources.list.xenial deleted file mode 100644 index ad9c5a0144e..00000000000 --- a/eng/common/cross/x86/sources.list.xenial +++ /dev/null @@ -1,11 +0,0 @@ -deb http://archive.ubuntu.com/ubuntu/ xenial main restricted universe -deb-src http://archive.ubuntu.com/ubuntu/ xenial main restricted universe - -deb http://archive.ubuntu.com/ubuntu/ xenial-updates main restricted universe -deb-src http://archive.ubuntu.com/ubuntu/ xenial-updates main restricted universe - -deb http://archive.ubuntu.com/ubuntu/ xenial-backports main restricted -deb-src http://archive.ubuntu.com/ubuntu/ xenial-backports main restricted - -deb http://archive.ubuntu.com/ubuntu/ xenial-security main restricted universe multiverse -deb-src http://archive.ubuntu.com/ubuntu/ xenial-security main restricted universe multiverse diff --git a/eng/common/dotnet-install.sh b/eng/common/dotnet-install.sh index 7e69e3a9e24..7b9d97e3bd4 100755 --- a/eng/common/dotnet-install.sh +++ b/eng/common/dotnet-install.sh @@ -71,6 +71,9 @@ case $cpuname in i[3-6]86) buildarch=x86 ;; + riscv64) + buildarch=riscv64 + ;; *) echo "Unknown CPU $cpuname detected, treating it as x64" buildarch=x64 @@ -82,7 +85,7 @@ if [[ $architecture != "" ]] && [[ $architecture != $buildarch ]]; then dotnetRoot="$dotnetRoot/$architecture" fi -InstallDotNet $dotnetRoot $version "$architecture" $runtime true $runtimeSourceFeed $runtimeSourceFeedKey || { +InstallDotNet "$dotnetRoot" $version "$architecture" $runtime true $runtimeSourceFeed $runtimeSourceFeedKey || { local exit_code=$? Write-PipelineTelemetryError -Category 'InitializeToolset' -Message "dotnet-install.sh failed (exit code '$exit_code')." >&2 ExitWithExitCode $exit_code diff --git a/eng/common/helixpublish.proj b/eng/common/helixpublish.proj index d7f185856e7..c1323bf4121 100644 --- a/eng/common/helixpublish.proj +++ b/eng/common/helixpublish.proj @@ -1,3 +1,4 @@ + diff --git a/eng/common/internal/Directory.Build.props b/eng/common/internal/Directory.Build.props index dbf99d82a5c..f1d041c33da 100644 --- a/eng/common/internal/Directory.Build.props +++ b/eng/common/internal/Directory.Build.props @@ -1,4 +1,11 @@ + + + false + false + + + diff --git a/eng/common/internal/Tools.csproj b/eng/common/internal/Tools.csproj index 7f5ce6d6081..e925952d566 100644 --- a/eng/common/internal/Tools.csproj +++ b/eng/common/internal/Tools.csproj @@ -1,8 +1,8 @@ + net472 - false false @@ -27,4 +27,5 @@ + diff --git a/eng/common/native/CommonLibrary.psm1 b/eng/common/native/CommonLibrary.psm1 index ca38268c44d..f71f6af6cdb 100644 --- a/eng/common/native/CommonLibrary.psm1 +++ b/eng/common/native/CommonLibrary.psm1 @@ -277,7 +277,8 @@ function Get-MachineArchitecture { if (($ProcessorArchitecture -Eq "AMD64") -Or ($ProcessorArchitecture -Eq "IA64") -Or ($ProcessorArchitecture -Eq "ARM64") -Or - ($ProcessorArchitecture -Eq "LOONGARCH64")) { + ($ProcessorArchitecture -Eq "LOONGARCH64") -Or + ($ProcessorArchitecture -Eq "RISCV64")) { return "x64" } return "x86" diff --git a/eng/common/native/init-compiler.sh b/eng/common/native/init-compiler.sh index 2d5660642b8..62900e12b21 100644 --- a/eng/common/native/init-compiler.sh +++ b/eng/common/native/init-compiler.sh @@ -2,7 +2,9 @@ # # This file detects the C/C++ compiler and exports it to the CC/CXX environment variables # -# NOTE: some scripts source this file and rely on stdout being empty, make sure to not output anything here! +# NOTE: some scripts source this file and rely on stdout being empty, make sure +# to not output *anything* here, unless it is an error message that fails the +# build. if [ -z "$build_arch" ] || [ -z "$compiler" ]; then echo "Usage..." @@ -58,13 +60,33 @@ check_version_exists() { echo "$desired_version" } +__baseOS="$(uname)" +set_compiler_version_from_CC() { + if [ "$__baseOS" = "Darwin" ]; then + # On Darwin, the versions from -version/-dumpversion refer to Xcode + # versions, not llvm versions, so we can't rely on them. + return + fi + + version="$("$CC" -dumpversion)" + if [ -z "$version" ]; then + echo "Error: $CC -dumpversion didn't provide a version" + exit 1 + fi + + # gcc and clang often display 3 part versions. However, gcc can show only 1 part in some environments. + IFS=. read -r majorVersion minorVersion _ < /dev/null; then - if [ "$(uname)" != "Darwin" ]; then - echo "Warning: Specific version of $compiler not found, falling back to use the one in PATH." - fi - CC="$(command -v "$compiler")" - CXX="$(command -v "$cxxCompiler")" - else - echo "No usable version of $compiler found." + if ! command -v "$compiler" > /dev/null; then + echo "Error: No usable version of $compiler found." exit 1 fi + + CC="$(command -v "$compiler" 2> /dev/null)" + CXX="$(command -v "$cxxCompiler" 2> /dev/null)" + set_compiler_version_from_CC else - if [ "$compiler" = "clang" ] && [ "$majorVersion" -lt 5 ]; then - if [ "$build_arch" = "arm" ] || [ "$build_arch" = "armel" ]; then - if command -v "$compiler" > /dev/null; then - echo "Warning: Found clang version $majorVersion which is not supported on arm/armel architectures, falling back to use clang from PATH." - CC="$(command -v "$compiler")" - CXX="$(command -v "$cxxCompiler")" - else - echo "Found clang version $majorVersion which is not supported on arm/armel architectures, and there is no clang in PATH." - exit 1 - fi + if [ "$compiler" = "clang" ] && [ "$majorVersion" -lt 5 ] && { [ "$build_arch" = "arm" ] || [ "$build_arch" = "armel" ]; }; then + # If a major version was provided explicitly, and it was too old, find a newer compiler instead + if ! command -v "$compiler" > /dev/null; then + echo "Error: Found clang version $majorVersion which is not supported on arm/armel architectures, and there is no clang in PATH." + exit 1 fi + + CC="$(command -v "$compiler" 2> /dev/null)" + CXX="$(command -v "$cxxCompiler" 2> /dev/null)" + set_compiler_version_from_CC fi fi else desired_version="$(check_version_exists "$majorVersion" "$minorVersion")" if [ "$desired_version" = "-1" ]; then - echo "Could not find specific version of $compiler: $majorVersion $minorVersion." + echo "Error: Could not find specific version of $compiler: $majorVersion $minorVersion." exit 1 fi fi if [ -z "$CC" ]; then - CC="$(command -v "$compiler$desired_version")" - CXX="$(command -v "$cxxCompiler$desired_version")" - if [ -z "$CXX" ]; then CXX="$(command -v "$cxxCompiler")"; fi + CC="$(command -v "$compiler$desired_version" 2> /dev/null)" + CXX="$(command -v "$cxxCompiler$desired_version" 2> /dev/null)" + if [ -z "$CXX" ]; then CXX="$(command -v "$cxxCompiler" 2> /dev/null)"; fi + set_compiler_version_from_CC fi else if [ ! -f "$CLR_CC" ]; then - echo "CLR_CC is set but path '$CLR_CC' does not exist" + echo "Error: CLR_CC is set but path '$CLR_CC' does not exist" exit 1 fi CC="$CLR_CC" CXX="$CLR_CXX" + set_compiler_version_from_CC fi if [ -z "$CC" ]; then - echo "Unable to find $compiler." + echo "Error: Unable to find $compiler." exit 1 fi -# Only lld version >= 9 can be considered stable. lld doesn't support s390x. -if [ "$compiler" = "clang" ] && [ -n "$majorVersion" ] && [ "$majorVersion" -ge 9 ] && [ "$build_arch" != "s390x" ]; then - if "$CC" -fuse-ld=lld -Wl,--version >/dev/null 2>&1; then - LDFLAGS="-fuse-ld=lld" +if [ "$__baseOS" != "Darwin" ]; then + # On Darwin, we always want to use the Apple linker. + + # Only lld version >= 9 can be considered stable. lld supports s390x starting from 18.0. + if [ "$compiler" = "clang" ] && [ -n "$majorVersion" ] && [ "$majorVersion" -ge 9 ] && { [ "$build_arch" != "s390x" ] || [ "$majorVersion" -ge 18 ]; }; then + if "$CC" -fuse-ld=lld -Wl,--version >/dev/null 2>&1; then + LDFLAGS="-fuse-ld=lld" + fi fi fi -SCAN_BUILD_COMMAND="$(command -v "scan-build$desired_version")" +SCAN_BUILD_COMMAND="$(command -v "scan-build$desired_version" 2> /dev/null)" export CC CXX LDFLAGS SCAN_BUILD_COMMAND diff --git a/eng/common/native/init-distro-rid.sh b/eng/common/native/init-distro-rid.sh index de1687b2ccb..83ea7aab0e0 100644 --- a/eng/common/native/init-distro-rid.sh +++ b/eng/common/native/init-distro-rid.sh @@ -1,4 +1,4 @@ -#!/usr/bin/env bash +#!/bin/sh # getNonPortableDistroRid # @@ -11,21 +11,16 @@ # non-portable rid getNonPortableDistroRid() { - local targetOs="$1" - local targetArch="$2" - local rootfsDir="$3" - local nonPortableRid="" + targetOs="$1" + targetArch="$2" + rootfsDir="$3" + nonPortableRid="" if [ "$targetOs" = "linux" ]; then + # shellcheck disable=SC1091 if [ -e "${rootfsDir}/etc/os-release" ]; then - source "${rootfsDir}/etc/os-release" - - if [[ "${ID}" == "rhel" || "${ID}" == "rocky" || "${ID}" == "alpine" ]]; then - # remove the last version digit - VERSION_ID="${VERSION_ID%.*}" - fi - - if [[ "${VERSION_ID:-}" =~ ^([[:digit:]]|\.)+$ ]]; then + . "${rootfsDir}/etc/os-release" + if echo "${VERSION_ID:-}" | grep -qE '^([[:digit:]]|\.)+$'; then nonPortableRid="${ID}.${VERSION_ID}-${targetArch}" else # Rolling release distros either do not set VERSION_ID, set it as blank or @@ -33,45 +28,33 @@ getNonPortableDistroRid() # so omit it here to be consistent with everything else. nonPortableRid="${ID}-${targetArch}" fi - elif [ -e "${rootfsDir}/android_platform" ]; then - source "$rootfsDir"/android_platform + # shellcheck disable=SC1091 + . "${rootfsDir}/android_platform" nonPortableRid="$RID" fi fi if [ "$targetOs" = "freebsd" ]; then - # $rootfsDir can be empty. freebsd-version is shell script and it should always work. - __freebsd_major_version=$($rootfsDir/bin/freebsd-version | { read v; echo "${v%%.*}"; }) + # $rootfsDir can be empty. freebsd-version is a shell script and should always work. + __freebsd_major_version=$("$rootfsDir"/bin/freebsd-version | cut -d'.' -f1) nonPortableRid="freebsd.$__freebsd_major_version-${targetArch}" - elif command -v getprop && getprop ro.product.system.model 2>&1 | grep -qi android; then + elif command -v getprop >/dev/null && getprop ro.product.system.model | grep -qi android; then __android_sdk_version=$(getprop ro.build.version.sdk) nonPortableRid="android.$__android_sdk_version-${targetArch}" elif [ "$targetOs" = "illumos" ]; then __uname_version=$(uname -v) - case "$__uname_version" in - omnios-*) - __omnios_major_version=$(echo "${__uname_version:8:2}") - nonPortableRid=omnios."$__omnios_major_version"-"$targetArch" - ;; - joyent_*) - __smartos_major_version=$(echo "${__uname_version:7:4}") - nonPortableRid=smartos."$__smartos_major_version"-"$targetArch" - ;; - illumos_*) - nonPortableRid=openindiana-"$targetArch" - ;; - esac + nonPortableRid="illumos-${targetArch}" elif [ "$targetOs" = "solaris" ]; then __uname_version=$(uname -v) - __solaris_major_version=$(echo "${__uname_version%.*}") - nonPortableRid=solaris."$__solaris_major_version"-"$targetArch" + __solaris_major_version=$(echo "$__uname_version" | cut -d'.' -f1) + nonPortableRid="solaris.$__solaris_major_version-${targetArch}" elif [ "$targetOs" = "haiku" ]; then - __uname_release=$(uname -r) + __uname_release="$(uname -r)" nonPortableRid=haiku.r"$__uname_release"-"$targetArch" fi - echo "$(echo $nonPortableRid | tr '[:upper:]' '[:lower:]')" + echo "$nonPortableRid" | tr '[:upper:]' '[:lower:]' } # initDistroRidGlobal @@ -85,26 +68,23 @@ getNonPortableDistroRid() # None # # Notes: -# -# It is important to note that the function does not return anything, but it -# exports the following variables on success: -# -# __DistroRid : Non-portable rid of the target platform. -# __PortableTargetOS : OS-part of the portable rid that corresponds to the target platform. -# +# It is important to note that the function does not return anything, but it +# exports the following variables on success: +# __DistroRid : Non-portable rid of the target platform. +# __PortableTargetOS : OS-part of the portable rid that corresponds to the target platform. initDistroRidGlobal() { - local targetOs="$1" - local targetArch="$2" - local rootfsDir="" - if [ "$#" -ge 3 ]; then + targetOs="$1" + targetArch="$2" + rootfsDir="" + if [ $# -ge 3 ]; then rootfsDir="$3" fi if [ -n "${rootfsDir}" ]; then # We may have a cross build. Check for the existence of the rootfsDir if [ ! -e "${rootfsDir}" ]; then - echo "Error rootfsDir has been passed, but the location is not valid." + echo "Error: rootfsDir has been passed, but the location is not valid." exit 1 fi fi @@ -119,7 +99,7 @@ initDistroRidGlobal() STRINGS="$(command -v llvm-strings || true)" fi - # Check for musl-based distros (e.g Alpine Linux, Void Linux). + # Check for musl-based distros (e.g. Alpine Linux, Void Linux). if "${rootfsDir}/usr/bin/ldd" --version 2>&1 | grep -q musl || ( [ -n "$STRINGS" ] && "$STRINGS" "${rootfsDir}/usr/bin/ldd" 2>&1 | grep -q musl ); then __PortableTargetOS="linux-musl" diff --git a/eng/common/native/init-os-and-arch.sh b/eng/common/native/init-os-and-arch.sh index e693617a6c2..38921d4338f 100644 --- a/eng/common/native/init-os-and-arch.sh +++ b/eng/common/native/init-os-and-arch.sh @@ -1,4 +1,4 @@ -#!/usr/bin/env bash +#!/bin/sh # Use uname to determine what the OS is. OSName=$(uname -s | tr '[:upper:]' '[:lower:]') @@ -35,6 +35,10 @@ fi case "$CPUName" in arm64|aarch64) arch=arm64 + if [ "$(getconf LONG_BIT)" -lt 64 ]; then + # This is 32-bit OS running on 64-bit CPU (for example Raspberry Pi OS) + arch=arm + fi ;; loongarch64) @@ -50,6 +54,7 @@ case "$CPUName" in ;; armv7l|armv8l) + # shellcheck disable=SC1091 if (NAME=""; . /etc/os-release; test "$NAME" = "Tizen"); then arch=armel else diff --git a/eng/common/post-build/add-build-to-channel.ps1 b/eng/common/post-build/add-build-to-channel.ps1 deleted file mode 100644 index 49938f0c89f..00000000000 --- a/eng/common/post-build/add-build-to-channel.ps1 +++ /dev/null @@ -1,48 +0,0 @@ -param( - [Parameter(Mandatory=$true)][int] $BuildId, - [Parameter(Mandatory=$true)][int] $ChannelId, - [Parameter(Mandatory=$true)][string] $MaestroApiAccessToken, - [Parameter(Mandatory=$false)][string] $MaestroApiEndPoint = 'https://maestro.dot.net', - [Parameter(Mandatory=$false)][string] $MaestroApiVersion = '2019-01-16' -) - -try { - . $PSScriptRoot\post-build-utils.ps1 - - # Check that the channel we are going to promote the build to exist - $channelInfo = Get-MaestroChannel -ChannelId $ChannelId - - if (!$channelInfo) { - Write-PipelineTelemetryCategory -Category 'PromoteBuild' -Message "Channel with BAR ID $ChannelId was not found in BAR!" - ExitWithExitCode 1 - } - - # Get info about which channel(s) the build has already been promoted to - $buildInfo = Get-MaestroBuild -BuildId $BuildId - - if (!$buildInfo) { - Write-PipelineTelemetryError -Category 'PromoteBuild' -Message "Build with BAR ID $BuildId was not found in BAR!" - ExitWithExitCode 1 - } - - # Find whether the build is already assigned to the channel or not - if ($buildInfo.channels) { - foreach ($channel in $buildInfo.channels) { - if ($channel.Id -eq $ChannelId) { - Write-Host "The build with BAR ID $BuildId is already on channel $ChannelId!" - ExitWithExitCode 0 - } - } - } - - Write-Host "Promoting build '$BuildId' to channel '$ChannelId'." - - Assign-BuildToChannel -BuildId $BuildId -ChannelId $ChannelId - - Write-Host 'done.' -} -catch { - Write-Host $_ - Write-PipelineTelemetryError -Category 'PromoteBuild' -Message "There was an error while trying to promote build '$BuildId' to channel '$ChannelId'" - ExitWithExitCode 1 -} diff --git a/eng/common/post-build/check-channel-consistency.ps1 b/eng/common/post-build/check-channel-consistency.ps1 index 63f3464c986..61208d2d135 100644 --- a/eng/common/post-build/check-channel-consistency.ps1 +++ b/eng/common/post-build/check-channel-consistency.ps1 @@ -4,10 +4,18 @@ param( ) try { - . $PSScriptRoot\post-build-utils.ps1 + $ErrorActionPreference = 'Stop' + Set-StrictMode -Version 2.0 + + # `tools.ps1` checks $ci to perform some actions. Since the post-build + # scripts don't necessarily execute in the same agent that run the + # build.ps1/sh script this variable isn't automatically set. + $ci = $true + $disableConfigureToolsetImport = $true + . $PSScriptRoot\..\tools.ps1 if ($PromoteToChannels -eq "") { - Write-PipelineTaskError -Type 'warning' -Message "This build won't publish assets as it's not configured to any Maestro channel. If that wasn't intended use Darc to configure a default channel using add-default-channel for this branch or to promote it to a channel using add-build-to-channel. See https://github.com/dotnet/arcade/blob/master/Documentation/Darc.md#assigning-an-individual-build-to-a-channel for more info." + Write-PipelineTaskError -Type 'warning' -Message "This build won't publish assets as it's not configured to any Maestro channel. If that wasn't intended use Darc to configure a default channel using add-default-channel for this branch or to promote it to a channel using add-build-to-channel. See https://github.com/dotnet/arcade/blob/main/Documentation/Darc.md#assigning-an-individual-build-to-a-channel for more info." ExitWithExitCode 0 } diff --git a/eng/common/post-build/nuget-validation.ps1 b/eng/common/post-build/nuget-validation.ps1 index dab3534ab53..e5de00c8983 100644 --- a/eng/common/post-build/nuget-validation.ps1 +++ b/eng/common/post-build/nuget-validation.ps1 @@ -2,20 +2,18 @@ # tool: https://github.com/NuGet/NuGetGallery/tree/jver-verify/src/VerifyMicrosoftPackage param( - [Parameter(Mandatory=$true)][string] $PackagesPath, # Path to where the packages to be validated are - [Parameter(Mandatory=$true)][string] $ToolDestinationPath # Where the validation tool should be downloaded to + [Parameter(Mandatory=$true)][string] $PackagesPath # Path to where the packages to be validated are ) -try { - . $PSScriptRoot\post-build-utils.ps1 - - $url = 'https://raw.githubusercontent.com/NuGet/NuGetGallery/3e25ad135146676bcab0050a516939d9958bfa5d/src/VerifyMicrosoftPackage/verify.ps1' - - New-Item -ItemType 'directory' -Path ${ToolDestinationPath} -Force +# `tools.ps1` checks $ci to perform some actions. Since the post-build +# scripts don't necessarily execute in the same agent that run the +# build.ps1/sh script this variable isn't automatically set. +$ci = $true +$disableConfigureToolsetImport = $true +. $PSScriptRoot\..\tools.ps1 - Invoke-WebRequest $url -OutFile ${ToolDestinationPath}\verify.ps1 - - & ${ToolDestinationPath}\verify.ps1 ${PackagesPath}\*.nupkg +try { + & $PSScriptRoot\nuget-verification.ps1 ${PackagesPath}\*.nupkg } catch { Write-Host $_.ScriptStackTrace diff --git a/eng/common/post-build/nuget-verification.ps1 b/eng/common/post-build/nuget-verification.ps1 new file mode 100644 index 00000000000..a365194a938 --- /dev/null +++ b/eng/common/post-build/nuget-verification.ps1 @@ -0,0 +1,121 @@ +<# +.SYNOPSIS + Verifies that Microsoft NuGet packages have proper metadata. +.DESCRIPTION + Downloads a verification tool and runs metadata validation on the provided NuGet packages. This script writes an + error if any of the provided packages fail validation. All arguments provided to this PowerShell script that do not + match PowerShell parameters are passed on to the verification tool downloaded during the execution of this script. +.PARAMETER NuGetExePath + The path to the nuget.exe binary to use. If not provided, nuget.exe will be downloaded into the -DownloadPath + directory. +.PARAMETER PackageSource + The package source to use to download the verification tool. If not provided, nuget.org will be used. +.PARAMETER DownloadPath + The directory path to download the verification tool and nuget.exe to. If not provided, + %TEMP%\NuGet.VerifyNuGetPackage will be used. +.PARAMETER args + Arguments that will be passed to the verification tool. +.EXAMPLE + PS> .\verify.ps1 *.nupkg + Verifies the metadata of all .nupkg files in the currect working directory. +.EXAMPLE + PS> .\verify.ps1 --help + Displays the help text of the downloaded verifiction tool. +.LINK + https://github.com/NuGet/NuGetGallery/blob/master/src/VerifyMicrosoftPackage/README.md +#> + +# This script was copied from https://github.com/NuGet/NuGetGallery/blob/3e25ad135146676bcab0050a516939d9958bfa5d/src/VerifyMicrosoftPackage/verify.ps1 + +[CmdletBinding(PositionalBinding = $false)] +param( + [string]$NuGetExePath, + [string]$PackageSource = "https://api.nuget.org/v3/index.json", + [string]$DownloadPath, + [Parameter(ValueFromRemainingArguments = $true)] + [string[]]$args +) + +# The URL to download nuget.exe. +$nugetExeUrl = "https://dist.nuget.org/win-x86-commandline/v4.9.4/nuget.exe" + +# The package ID of the verification tool. +$packageId = "NuGet.VerifyMicrosoftPackage" + +# The location that nuget.exe and the verification tool will be downloaded to. +if (!$DownloadPath) { + $DownloadPath = (Join-Path $env:TEMP "NuGet.VerifyMicrosoftPackage") +} + +$fence = New-Object -TypeName string -ArgumentList '=', 80 + +# Create the download directory, if it doesn't already exist. +if (!(Test-Path $DownloadPath)) { + New-Item -ItemType Directory $DownloadPath | Out-Null +} +Write-Host "Using download path: $DownloadPath" + +if ($NuGetExePath) { + $nuget = $NuGetExePath +} else { + $downloadedNuGetExe = Join-Path $DownloadPath "nuget.exe" + + # Download nuget.exe, if it doesn't already exist. + if (!(Test-Path $downloadedNuGetExe)) { + Write-Host "Downloading nuget.exe from $nugetExeUrl..." + $ProgressPreference = 'SilentlyContinue' + try { + Invoke-WebRequest $nugetExeUrl -OutFile $downloadedNuGetExe + $ProgressPreference = 'Continue' + } catch { + $ProgressPreference = 'Continue' + Write-Error $_ + Write-Error "nuget.exe failed to download." + exit + } + } + + $nuget = $downloadedNuGetExe +} + +Write-Host "Using nuget.exe path: $nuget" +Write-Host " " + +# Download the latest version of the verification tool. +Write-Host "Downloading the latest version of $packageId from $packageSource..." +Write-Host $fence +& $nuget install $packageId ` + -Prerelease ` + -OutputDirectory $DownloadPath ` + -Source $PackageSource +Write-Host $fence +Write-Host " " + +if ($LASTEXITCODE -ne 0) { + Write-Error "nuget.exe failed to fetch the verify tool." + exit +} + +# Find the most recently downloaded tool +Write-Host "Finding the most recently downloaded verification tool." +$verifyProbePath = Join-Path $DownloadPath "$packageId.*" +$verifyPath = Get-ChildItem -Path $verifyProbePath -Directory ` + | Sort-Object -Property LastWriteTime -Descending ` + | Select-Object -First 1 +$verify = Join-Path $verifyPath "tools\NuGet.VerifyMicrosoftPackage.exe" +Write-Host "Using verification tool: $verify" +Write-Host " " + +# Execute the verification tool. +Write-Host "Executing the verify tool..." +Write-Host $fence +& $verify $args +Write-Host $fence +Write-Host " " + +# Respond to the exit code. +if ($LASTEXITCODE -ne 0) { + Write-Error "The verify tool found some problems." +} else { + Write-Output "The verify tool succeeded." +} diff --git a/eng/common/post-build/post-build-utils.ps1 b/eng/common/post-build/post-build-utils.ps1 deleted file mode 100644 index 534f6988d5b..00000000000 --- a/eng/common/post-build/post-build-utils.ps1 +++ /dev/null @@ -1,91 +0,0 @@ -# Most of the functions in this file require the variables `MaestroApiEndPoint`, -# `MaestroApiVersion` and `MaestroApiAccessToken` to be globally available. - -$ErrorActionPreference = 'Stop' -Set-StrictMode -Version 2.0 - -# `tools.ps1` checks $ci to perform some actions. Since the post-build -# scripts don't necessarily execute in the same agent that run the -# build.ps1/sh script this variable isn't automatically set. -$ci = $true -$disableConfigureToolsetImport = $true -. $PSScriptRoot\..\tools.ps1 - -function Create-MaestroApiRequestHeaders([string]$ContentType = 'application/json') { - Validate-MaestroVars - - $headers = New-Object 'System.Collections.Generic.Dictionary[[String],[String]]' - $headers.Add('Accept', $ContentType) - $headers.Add('Authorization',"Bearer $MaestroApiAccessToken") - return $headers -} - -function Get-MaestroChannel([int]$ChannelId) { - Validate-MaestroVars - - $apiHeaders = Create-MaestroApiRequestHeaders - $apiEndpoint = "$MaestroApiEndPoint/api/channels/${ChannelId}?api-version=$MaestroApiVersion" - - $result = try { Invoke-WebRequest -Method Get -Uri $apiEndpoint -Headers $apiHeaders | ConvertFrom-Json } catch { Write-Host "Error: $_" } - return $result -} - -function Get-MaestroBuild([int]$BuildId) { - Validate-MaestroVars - - $apiHeaders = Create-MaestroApiRequestHeaders -AuthToken $MaestroApiAccessToken - $apiEndpoint = "$MaestroApiEndPoint/api/builds/${BuildId}?api-version=$MaestroApiVersion" - - $result = try { return Invoke-WebRequest -Method Get -Uri $apiEndpoint -Headers $apiHeaders | ConvertFrom-Json } catch { Write-Host "Error: $_" } - return $result -} - -function Get-MaestroSubscriptions([string]$SourceRepository, [int]$ChannelId) { - Validate-MaestroVars - - $SourceRepository = [System.Web.HttpUtility]::UrlEncode($SourceRepository) - $apiHeaders = Create-MaestroApiRequestHeaders -AuthToken $MaestroApiAccessToken - $apiEndpoint = "$MaestroApiEndPoint/api/subscriptions?sourceRepository=$SourceRepository&channelId=$ChannelId&api-version=$MaestroApiVersion" - - $result = try { Invoke-WebRequest -Method Get -Uri $apiEndpoint -Headers $apiHeaders | ConvertFrom-Json } catch { Write-Host "Error: $_" } - return $result -} - -function Assign-BuildToChannel([int]$BuildId, [int]$ChannelId) { - Validate-MaestroVars - - $apiHeaders = Create-MaestroApiRequestHeaders -AuthToken $MaestroApiAccessToken - $apiEndpoint = "$MaestroApiEndPoint/api/channels/${ChannelId}/builds/${BuildId}?api-version=$MaestroApiVersion" - Invoke-WebRequest -Method Post -Uri $apiEndpoint -Headers $apiHeaders | Out-Null -} - -function Trigger-Subscription([string]$SubscriptionId) { - Validate-MaestroVars - - $apiHeaders = Create-MaestroApiRequestHeaders -AuthToken $MaestroApiAccessToken - $apiEndpoint = "$MaestroApiEndPoint/api/subscriptions/$SubscriptionId/trigger?api-version=$MaestroApiVersion" - Invoke-WebRequest -Uri $apiEndpoint -Headers $apiHeaders -Method Post | Out-Null -} - -function Validate-MaestroVars { - try { - Get-Variable MaestroApiEndPoint | Out-Null - Get-Variable MaestroApiVersion | Out-Null - Get-Variable MaestroApiAccessToken | Out-Null - - if (!($MaestroApiEndPoint -Match '^http[s]?://maestro-(int|prod).westus2.cloudapp.azure.com$')) { - Write-PipelineTelemetryError -Category 'MaestroVars' -Message "MaestroApiEndPoint is not a valid Maestro URL. '$MaestroApiEndPoint'" - ExitWithExitCode 1 - } - - if (!($MaestroApiVersion -Match '^[0-9]{4}-[0-9]{2}-[0-9]{2}$')) { - Write-PipelineTelemetryError -Category 'MaestroVars' -Message "MaestroApiVersion does not match a version string in the format yyyy-MM-DD. '$MaestroApiVersion'" - ExitWithExitCode 1 - } - } - catch { - Write-PipelineTelemetryError -Category 'MaestroVars' -Message 'Error: Variables `MaestroApiEndPoint`, `MaestroApiVersion` and `MaestroApiAccessToken` are required while using this script.' - Write-Host $_ - ExitWithExitCode 1 - } -} diff --git a/eng/common/post-build/publish-using-darc.ps1 b/eng/common/post-build/publish-using-darc.ps1 index 238945cb5ab..4ff587ca46a 100644 --- a/eng/common/post-build/publish-using-darc.ps1 +++ b/eng/common/post-build/publish-using-darc.ps1 @@ -9,7 +9,12 @@ param( ) try { - . $PSScriptRoot\post-build-utils.ps1 + # `tools.ps1` checks $ci to perform some actions. Since the post-build + # scripts don't necessarily execute in the same agent that run the + # build.ps1/sh script this variable isn't automatically set. + $ci = $true + $disableConfigureToolsetImport = $true + . $PSScriptRoot\..\tools.ps1 $darc = Get-Darc diff --git a/eng/common/post-build/redact-logs.ps1 b/eng/common/post-build/redact-logs.ps1 new file mode 100644 index 00000000000..b7fc1959150 --- /dev/null +++ b/eng/common/post-build/redact-logs.ps1 @@ -0,0 +1,89 @@ +[CmdletBinding(PositionalBinding=$False)] +param( + [Parameter(Mandatory=$true, Position=0)][string] $InputPath, + [Parameter(Mandatory=$true)][string] $BinlogToolVersion, + [Parameter(Mandatory=$false)][string] $DotnetPath, + [Parameter(Mandatory=$false)][string] $PackageFeed = 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public/nuget/v3/index.json', + # File with strings to redact - separated by newlines. + # For comments start the line with '# ' - such lines are ignored + [Parameter(Mandatory=$false)][string] $TokensFilePath, + [Parameter(ValueFromRemainingArguments=$true)][String[]]$TokensToRedact +) + +try { + $ErrorActionPreference = 'Stop' + Set-StrictMode -Version 2.0 + + # `tools.ps1` checks $ci to perform some actions. Since the post-build + # scripts don't necessarily execute in the same agent that run the + # build.ps1/sh script this variable isn't automatically set. + $ci = $true + $disableConfigureToolsetImport = $true + . $PSScriptRoot\..\tools.ps1 + + $packageName = 'binlogtool' + + $dotnet = $DotnetPath + + if (!$dotnet) { + $dotnetRoot = InitializeDotNetCli -install:$true + $dotnet = "$dotnetRoot\dotnet.exe" + } + + $toolList = & "$dotnet" tool list -g + + if ($toolList -like "*$packageName*") { + & "$dotnet" tool uninstall $packageName -g + } + + $toolPath = "$PSScriptRoot\..\..\..\.tools" + $verbosity = 'minimal' + + New-Item -ItemType Directory -Force -Path $toolPath + + Push-Location -Path $toolPath + + try { + Write-Host "Installing Binlog redactor CLI..." + Write-Host "'$dotnet' new tool-manifest" + & "$dotnet" new tool-manifest + Write-Host "'$dotnet' tool install $packageName --local --add-source '$PackageFeed' -v $verbosity --version $BinlogToolVersion" + & "$dotnet" tool install $packageName --local --add-source "$PackageFeed" -v $verbosity --version $BinlogToolVersion + + if (Test-Path $TokensFilePath) { + Write-Host "Adding additional sensitive data for redaction from file: " $TokensFilePath + $TokensToRedact += Get-Content -Path $TokensFilePath | Foreach {$_.Trim()} | Where { $_ -notmatch "^# " } + } + + $optionalParams = [System.Collections.ArrayList]::new() + + Foreach ($p in $TokensToRedact) + { + if($p -match '^\$\(.*\)$') + { + Write-Host ("Ignoring token {0} as it is probably unexpanded AzDO variable" -f $p) + } + elseif($p) + { + $optionalParams.Add("-p:" + $p) | Out-Null + } + } + + & $dotnet binlogtool redact --input:$InputPath --recurse --in-place ` + @optionalParams + + if ($LastExitCode -ne 0) { + Write-PipelineTelemetryError -Category 'Redactor' -Type 'warning' -Message "Problems using Redactor tool (exit code: $LastExitCode). But ignoring them now." + } + } + finally { + Pop-Location + } + + Write-Host 'done.' +} +catch { + Write-Host $_ + Write-PipelineTelemetryError -Category 'Redactor' -Message "There was an error while trying to redact logs. Error: $_" + ExitWithExitCode 1 +} diff --git a/eng/common/post-build/sourcelink-validation.ps1 b/eng/common/post-build/sourcelink-validation.ps1 index 4011d324e73..1976ef70fb8 100644 --- a/eng/common/post-build/sourcelink-validation.ps1 +++ b/eng/common/post-build/sourcelink-validation.ps1 @@ -6,7 +6,15 @@ param( [Parameter(Mandatory=$true)][string] $SourcelinkCliVersion # Version of SourceLink CLI to use ) -. $PSScriptRoot\post-build-utils.ps1 +$ErrorActionPreference = 'Stop' +Set-StrictMode -Version 2.0 + +# `tools.ps1` checks $ci to perform some actions. Since the post-build +# scripts don't necessarily execute in the same agent that run the +# build.ps1/sh script this variable isn't automatically set. +$ci = $true +$disableConfigureToolsetImport = $true +. $PSScriptRoot\..\tools.ps1 # Cache/HashMap (File -> Exist flag) used to consult whether a file exist # in the repository at a specific commit point. This is populated by inserting diff --git a/eng/common/post-build/symbols-validation.ps1 b/eng/common/post-build/symbols-validation.ps1 index cd2181bafa0..7146e593ffa 100644 --- a/eng/common/post-build/symbols-validation.ps1 +++ b/eng/common/post-build/symbols-validation.ps1 @@ -322,8 +322,6 @@ function InstallDotnetSymbol { } try { - . $PSScriptRoot\post-build-utils.ps1 - InstallDotnetSymbol foreach ($Job in @(Get-Job)) { diff --git a/eng/common/post-build/trigger-subscriptions.ps1 b/eng/common/post-build/trigger-subscriptions.ps1 deleted file mode 100644 index ac9a95778fc..00000000000 --- a/eng/common/post-build/trigger-subscriptions.ps1 +++ /dev/null @@ -1,64 +0,0 @@ -param( - [Parameter(Mandatory=$true)][string] $SourceRepo, - [Parameter(Mandatory=$true)][int] $ChannelId, - [Parameter(Mandatory=$true)][string] $MaestroApiAccessToken, - [Parameter(Mandatory=$false)][string] $MaestroApiEndPoint = 'https://maestro.dot.net', - [Parameter(Mandatory=$false)][string] $MaestroApiVersion = '2019-01-16' -) - -try { - . $PSScriptRoot\post-build-utils.ps1 - - # Get all the $SourceRepo subscriptions - $normalizedSourceRepo = $SourceRepo.Replace('dnceng@', '') - $subscriptions = Get-MaestroSubscriptions -SourceRepository $normalizedSourceRepo -ChannelId $ChannelId - - if (!$subscriptions) { - Write-PipelineTelemetryError -Category 'TriggerSubscriptions' -Message "No subscriptions found for source repo '$normalizedSourceRepo' in channel '$ChannelId'" - ExitWithExitCode 0 - } - - $subscriptionsToTrigger = New-Object System.Collections.Generic.List[string] - $failedTriggeredSubscription = $false - - # Get all enabled subscriptions that need dependency flow on 'everyBuild' - foreach ($subscription in $subscriptions) { - if ($subscription.enabled -and $subscription.policy.updateFrequency -like 'everyBuild' -and $subscription.channel.id -eq $ChannelId) { - Write-Host "Should trigger this subscription: ${$subscription.id}" - [void]$subscriptionsToTrigger.Add($subscription.id) - } - } - - foreach ($subscriptionToTrigger in $subscriptionsToTrigger) { - try { - Write-Host "Triggering subscription '$subscriptionToTrigger'." - - Trigger-Subscription -SubscriptionId $subscriptionToTrigger - - Write-Host 'done.' - } - catch - { - Write-Host "There was an error while triggering subscription '$subscriptionToTrigger'" - Write-Host $_ - Write-Host $_.ScriptStackTrace - $failedTriggeredSubscription = $true - } - } - - if ($subscriptionsToTrigger.Count -eq 0) { - Write-Host "No subscription matched source repo '$normalizedSourceRepo' and channel ID '$ChannelId'." - } - elseif ($failedTriggeredSubscription) { - Write-PipelineTelemetryError -Category 'TriggerSubscriptions' -Message 'At least one subscription failed to be triggered...' - ExitWithExitCode 1 - } - else { - Write-Host 'All subscriptions were triggered successfully!' - } -} -catch { - Write-Host $_.ScriptStackTrace - Write-PipelineTelemetryError -Category 'TriggerSubscriptions' -Message $_ - ExitWithExitCode 1 -} diff --git a/eng/common/sdk-task.ps1 b/eng/common/sdk-task.ps1 index 73828dd30d3..aab40de3fd9 100644 --- a/eng/common/sdk-task.ps1 +++ b/eng/common/sdk-task.ps1 @@ -64,7 +64,7 @@ try { $GlobalJson.tools | Add-Member -Name "vs" -Value (ConvertFrom-Json "{ `"version`": `"16.5`" }") -MemberType NoteProperty } if( -not ($GlobalJson.tools.PSObject.Properties.Name -match "xcopy-msbuild" )) { - $GlobalJson.tools | Add-Member -Name "xcopy-msbuild" -Value "17.8.1-2" -MemberType NoteProperty + $GlobalJson.tools | Add-Member -Name "xcopy-msbuild" -Value "17.10.0-pre.4.0" -MemberType NoteProperty } if ($GlobalJson.tools."xcopy-msbuild".Trim() -ine "none") { $xcopyMSBuildToolsFolder = InitializeXCopyMSBuild $GlobalJson.tools."xcopy-msbuild" -install $true diff --git a/eng/common/sdl/trim-assets-version.ps1 b/eng/common/sdl/trim-assets-version.ps1 index a2e00487704..0daa2a9e946 100644 --- a/eng/common/sdl/trim-assets-version.ps1 +++ b/eng/common/sdl/trim-assets-version.ps1 @@ -72,4 +72,4 @@ catch { Write-Host $_ Write-PipelineTelemetryError -Force -Category 'Sdl' -Message $_ ExitWithExitCode 1 -} \ No newline at end of file +} diff --git a/eng/common/template-guidance.md b/eng/common/template-guidance.md new file mode 100644 index 00000000000..5ef6c30ba92 --- /dev/null +++ b/eng/common/template-guidance.md @@ -0,0 +1,133 @@ +# Overview + +Arcade provides templates for public (`/templates`) and 1ES pipeline templates (`/templates-official`) scenarios. Pipelines which are required to be managed by 1ES pipeline templates should reference `/templates-offical`, all other pipelines may reference `/templates`. + +## How to use + +Basic guidance is: + +- 1ES Pipeline Template or 1ES Microbuild template runs should reference `eng/common/templates-official`. Any internal production-graded pipeline should use these templates. + +- All other runs should reference `eng/common/templates`. + +See [azure-pipelines.yml](../../azure-pipelines.yml) (templates-official example) or [azure-pipelines-pr.yml](../../azure-pipelines-pr.yml) (templates example) for examples. + +#### The `templateIs1ESManaged` parameter + +The `templateIs1ESManaged` is available on most templates and affects which of the variants is used for nested templates. See [Development Notes](#development-notes) below for more information on the `templateIs1ESManaged1 parameter. + +- For templates under `job/`, `jobs/`, `steps`, or `post-build/`, this parameter must be explicitly set. + +## Multiple outputs + +1ES pipeline templates impose a policy where every publish artifact execution results in additional security scans being injected into your pipeline. When using `templates-official/jobs/jobs.yml`, Arcade reduces the number of additional security injections by gathering all publishing outputs into the [Build.ArtifactStagingDirectory](https://learn.microsoft.com/en-us/azure/devops/pipelines/build/variables?view=azure-devops&tabs=yaml#build-variables-devops-services), and utilizing the [outputParentDirectory](https://eng.ms/docs/cloud-ai-platform/devdiv/one-engineering-system-1es/1es-docs/1es-pipeline-templates/features/outputs#multiple-outputs) feature of 1ES pipeline templates. When implementing your pipeline, if you ensure publish artifacts are located in the `$(Build.ArtifactStagingDirectory)`, and utilize the 1ES provided template context, then you can reduce the number of security scans for your pipeline. + +Example: +``` yaml +# azure-pipelines.yml +extends: + template: azure-pipelines/MicroBuild.1ES.Official.yml@MicroBuildTemplate + parameters: + stages: + - stage: build + jobs: + - template: /eng/common/templates-official/jobs/jobs.yml@self + parameters: + # 1ES makes use of outputs to reduce security task injection overhead + templateContext: + outputs: + - output: pipelineArtifact + displayName: 'Publish logs from source' + continueOnError: true + condition: always() + targetPath: $(Build.ArtifactStagingDirectory)/artifacts/log + artifactName: Logs + jobs: + - job: Windows + steps: + - script: echo "friendly neighborhood" > artifacts/marvel/spiderman.txt + # copy build outputs to artifact staging directory for publishing + - task: CopyFiles@2 + displayName: Gather build output + inputs: + SourceFolder: '$(Build.SourcesDirectory)/artifacts/marvel' + Contents: '**' + TargetFolder: '$(Build.ArtifactStagingDirectory)/artifacts/marvel' +``` + +Note: Multiple outputs are ONLY applicable to 1ES PT publishing (only usable when referencing `templates-official`). + +# Development notes + +**Folder / file structure** + +``` text +eng\common\ + [templates || templates-official]\ + job\ + job.yml (shim + artifact publishing logic) + onelocbuild.yml (shim) + publish-build-assets.yml (shim) + source-build.yml (shim) + source-index-stage1.yml (shim) + jobs\ + codeql-build.yml (shim) + jobs.yml (shim) + source-build.yml (shim) + post-build\ + post-build.yml (shim) + common-variabls.yml (shim) + setup-maestro-vars.yml (shim) + steps\ + publish-build-artifacts.yml (logic) + publish-pipeline-artifacts.yml (logic) + component-governance.yml (shim) + generate-sbom.yml (shim) + publish-logs.yml (shim) + retain-build.yml (shim) + send-to-helix.yml (shim) + source-build.yml (shim) + variables\ + pool-providers.yml (logic + redirect) # templates/variables/pool-providers.yml will redirect to templates-official/variables/pool-providers.yml if you are running in the internal project + sdl-variables.yml (logic) + core-templates\ + job\ + job.yml (logic) + onelocbuild.yml (logic) + publish-build-assets.yml (logic) + source-build.yml (logic) + source-index-stage1.yml (logic) + jobs\ + codeql-build.yml (logic) + jobs.yml (logic) + source-build.yml (logic) + post-build\ + common-variabls.yml (logic) + post-build.yml (logic) + setup-maestro-vars.yml (logic) + steps\ + component-governance.yml (logic) + generate-sbom.yml (logic) + publish-build-artifacts.yml (redirect) + publish-logs.yml (logic) + publish-pipeline-artifacts.yml (redirect) + retain-build.yml (logic) + send-to-helix.yml (logic) + source-build.yml (logic) + variables\ + pool-providers.yml (redirect) +``` + +In the table above, a file is designated as "shim", "logic", or "redirect". + +- shim - represents a yaml file which is an intermediate step between pipeline logic and .Net Core Engineering's templates (`core-templates`) and defines the `is1ESPipeline` parameter value. + +- logic - represents actual base template logic. + +- redirect- represents a file in `core-templates` which redirects to the "logic" file in either `templates` or `templates-official`. + +Logic for Arcade's templates live **primarily** in the `core-templates` folder. The exceptions to the location of the logic files are around artifact publishing, which is handled differently between 1es pipeline templates and standard templates. `templates` and `templates-official` provide shim entry points which redirect to `core-templates` while also defining the `is1ESPipeline` parameter. If a shim is referenced in `templates`, then `is1ESPipeline` is set to `false`. If a shim is referenced in `templates-official`, then `is1ESPipeline` is set to `true`. + +Within `templates` and `templates-official`, the templates at the "stages", and "jobs" / "job" level have been replaced with shims. Templates at the "steps" and "variables" level are typically too granular to be replaced with shims and instead persist logic which is directly applicable to either scenario. + +Within `core-templates`, there are a handful of places where logic is dependent on which shim entry point was used. In those places, we redirect back to the respective logic file in `templates` or `templates-official`. diff --git a/eng/common/templates-official/job/job.yml b/eng/common/templates-official/job/job.yml index 1f035fee73f..0c2928d5c79 100644 --- a/eng/common/templates-official/job/job.yml +++ b/eng/common/templates-official/job/job.yml @@ -1,264 +1,65 @@ -# Internal resources (telemetry, microbuild) can only be accessed from non-public projects, -# and some (Microbuild) should only be applied to non-PR cases for internal builds. - -parameters: -# Job schema parameters - https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=vsts&tabs=schema#job - cancelTimeoutInMinutes: '' - condition: '' - container: '' - continueOnError: false - dependsOn: '' - displayName: '' - pool: '' - steps: [] - strategy: '' - timeoutInMinutes: '' - variables: [] - workspace: '' - templateContext: '' - -# Job base template specific parameters - # See schema documentation - https://github.com/dotnet/arcade/blob/master/Documentation/AzureDevOps/TemplateSchema.md - artifacts: '' - enableMicrobuild: false - enablePublishBuildArtifacts: false - enablePublishBuildAssets: false - enablePublishTestResults: false - enablePublishUsingPipelines: false - enableBuildRetry: false - disableComponentGovernance: '' - componentGovernanceIgnoreDirectories: '' - mergeTestResults: false - testRunTitle: '' - testResultsFormat: '' - name: '' - preSteps: [] - runAsPublic: false -# Sbom related params - enableSbom: true - PackageVersion: 7.0.0 - BuildDropPath: '$(Build.SourcesDirectory)/artifacts' - jobs: -- job: ${{ parameters.name }} - - ${{ if ne(parameters.cancelTimeoutInMinutes, '') }}: - cancelTimeoutInMinutes: ${{ parameters.cancelTimeoutInMinutes }} - - ${{ if ne(parameters.condition, '') }}: - condition: ${{ parameters.condition }} - - ${{ if ne(parameters.container, '') }}: - container: ${{ parameters.container }} - - ${{ if ne(parameters.continueOnError, '') }}: - continueOnError: ${{ parameters.continueOnError }} - - ${{ if ne(parameters.dependsOn, '') }}: - dependsOn: ${{ parameters.dependsOn }} - - ${{ if ne(parameters.displayName, '') }}: - displayName: ${{ parameters.displayName }} - - ${{ if ne(parameters.pool, '') }}: - pool: ${{ parameters.pool }} - - ${{ if ne(parameters.strategy, '') }}: - strategy: ${{ parameters.strategy }} - - ${{ if ne(parameters.timeoutInMinutes, '') }}: - timeoutInMinutes: ${{ parameters.timeoutInMinutes }} - - ${{ if ne(parameters.templateContext, '') }}: - templateContext: ${{ parameters.templateContext }} - - variables: - - ${{ if ne(parameters.enableTelemetry, 'false') }}: - - name: DOTNET_CLI_TELEMETRY_PROFILE - value: '$(Build.Repository.Uri)' - - ${{ if eq(parameters.enableRichCodeNavigation, 'true') }}: - - name: EnableRichCodeNavigation - value: 'true' - # Retry signature validation up to three times, waiting 2 seconds between attempts. - # See https://learn.microsoft.com/en-us/nuget/reference/errors-and-warnings/nu3028#retry-untrusted-root-failures - - name: NUGET_EXPERIMENTAL_CHAIN_BUILD_RETRY_POLICY - value: 3,2000 - - ${{ each variable in parameters.variables }}: - # handle name-value variable syntax - # example: - # - name: [key] - # value: [value] - - ${{ if ne(variable.name, '') }}: - - name: ${{ variable.name }} - value: ${{ variable.value }} - - # handle variable groups - - ${{ if ne(variable.group, '') }}: - - group: ${{ variable.group }} - - # handle template variable syntax - # example: - # - template: path/to/template.yml - # parameters: - # [key]: [value] - - ${{ if ne(variable.template, '') }}: - - template: ${{ variable.template }} - ${{ if ne(variable.parameters, '') }}: - parameters: ${{ variable.parameters }} - - # handle key-value variable syntax. - # example: - # - [key]: [value] - - ${{ if and(eq(variable.name, ''), eq(variable.group, ''), eq(variable.template, '')) }}: - - ${{ each pair in variable }}: - - name: ${{ pair.key }} - value: ${{ pair.value }} - - # DotNet-HelixApi-Access provides 'HelixApiAccessToken' for internal builds - - ${{ if and(eq(parameters.enableTelemetry, 'true'), eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - - group: DotNet-HelixApi-Access - - ${{ if ne(parameters.workspace, '') }}: - workspace: ${{ parameters.workspace }} - - steps: - - ${{ if ne(parameters.preSteps, '') }}: - - ${{ each preStep in parameters.preSteps }}: - - ${{ preStep }} - - - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - - ${{ if eq(parameters.enableMicrobuild, 'true') }}: - - task: MicroBuildSigningPlugin@4 - displayName: Install MicroBuild plugin - inputs: - signType: $(_SignType) - zipSources: false - feedSource: https://dnceng.pkgs.visualstudio.com/_packaging/MicroBuildToolset/nuget/v3/index.json - env: - TeamName: $(_TeamName) - MicroBuildOutputFolderOverride: '$(Agent.TempDirectory)' - continueOnError: ${{ parameters.continueOnError }} - condition: and(succeeded(), in(variables['_SignType'], 'real', 'test'), eq(variables['Agent.Os'], 'Windows_NT')) - - - ${{ if and(eq(parameters.runAsPublic, 'false'), eq(variables['System.TeamProject'], 'internal')) }}: - - task: NuGetAuthenticate@1 - - - ${{ if and(ne(parameters.artifacts.download, 'false'), ne(parameters.artifacts.download, '')) }}: - - task: DownloadPipelineArtifact@2 - inputs: - buildType: current - artifactName: ${{ coalesce(parameters.artifacts.download.name, 'Artifacts_$(Agent.OS)_$(_BuildConfig)') }} - targetPath: ${{ coalesce(parameters.artifacts.download.path, 'artifacts') }} - itemPattern: ${{ coalesce(parameters.artifacts.download.pattern, '**') }} - - - ${{ each step in parameters.steps }}: - - ${{ step }} - - - ${{ if eq(parameters.enableRichCodeNavigation, true) }}: - - task: RichCodeNavIndexer@0 - displayName: RichCodeNav Upload - inputs: - languages: ${{ coalesce(parameters.richCodeNavigationLanguage, 'csharp') }} - environment: ${{ coalesce(parameters.richCodeNavigationEnvironment, 'production') }} - richNavLogOutputDirectory: $(Build.SourcesDirectory)/artifacts/bin - uploadRichNavArtifacts: ${{ coalesce(parameters.richCodeNavigationUploadArtifacts, false) }} - continueOnError: true - - - template: /eng/common/templates-official/steps/component-governance.yml - parameters: - ${{ if eq(parameters.disableComponentGovernance, '') }}: - ${{ if and(ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest'), eq(parameters.runAsPublic, 'false'), or(startsWith(variables['Build.SourceBranch'], 'refs/heads/release/'), startsWith(variables['Build.SourceBranch'], 'refs/heads/dotnet/'), startsWith(variables['Build.SourceBranch'], 'refs/heads/microsoft/'), eq(variables['Build.SourceBranch'], 'refs/heads/main'))) }}: - disableComponentGovernance: false - ${{ else }}: - disableComponentGovernance: true - ${{ else }}: - disableComponentGovernance: ${{ parameters.disableComponentGovernance }} - componentGovernanceIgnoreDirectories: ${{ parameters.componentGovernanceIgnoreDirectories }} - - - ${{ if eq(parameters.enableMicrobuild, 'true') }}: - - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - - task: MicroBuildCleanup@1 - displayName: Execute Microbuild cleanup tasks - condition: and(always(), in(variables['_SignType'], 'real', 'test'), eq(variables['Agent.Os'], 'Windows_NT')) - continueOnError: ${{ parameters.continueOnError }} - env: - TeamName: $(_TeamName) - - - ${{ if ne(parameters.artifacts.publish, '') }}: - - ${{ if and(ne(parameters.artifacts.publish.artifacts, 'false'), ne(parameters.artifacts.publish.artifacts, '')) }}: - - task: CopyFiles@2 - displayName: Gather binaries for publish to artifacts - inputs: - SourceFolder: 'artifacts/bin' - Contents: '**' - TargetFolder: '$(Build.ArtifactStagingDirectory)/artifacts/bin' - - task: CopyFiles@2 - displayName: Gather packages for publish to artifacts - inputs: - SourceFolder: 'artifacts/packages' - Contents: '**' - TargetFolder: '$(Build.ArtifactStagingDirectory)/artifacts/packages' - - task: 1ES.PublishBuildArtifacts@1 - displayName: Publish pipeline artifacts - inputs: - PathtoPublish: '$(Build.ArtifactStagingDirectory)/artifacts' - PublishLocation: Container - ArtifactName: ${{ coalesce(parameters.artifacts.publish.artifacts.name , 'Artifacts_$(Agent.Os)_$(_BuildConfig)') }} - continueOnError: true - condition: always() - - ${{ if and(ne(parameters.artifacts.publish.logs, 'false'), ne(parameters.artifacts.publish.logs, '')) }}: - - task: 1ES.PublishPipelineArtifact@1 - inputs: - targetPath: 'artifacts/log' - artifactName: ${{ coalesce(parameters.artifacts.publish.logs.name, 'Logs_Build_$(Agent.Os)_$(_BuildConfig)') }} - displayName: 'Publish logs' - continueOnError: true - condition: always() - - - ${{ if ne(parameters.enablePublishBuildArtifacts, 'false') }}: - - task: 1ES.PublishBuildArtifacts@1 - displayName: Publish Logs - inputs: - PathtoPublish: '$(Build.SourcesDirectory)/artifacts/log/$(_BuildConfig)' - PublishLocation: Container - ArtifactName: ${{ coalesce(parameters.enablePublishBuildArtifacts.artifactName, '$(Agent.Os)_$(Agent.JobName)' ) }} - continueOnError: true - condition: always() - - - ${{ if or(and(eq(parameters.enablePublishTestResults, 'true'), eq(parameters.testResultsFormat, '')), eq(parameters.testResultsFormat, 'xunit')) }}: - - task: PublishTestResults@2 - displayName: Publish XUnit Test Results - inputs: - testResultsFormat: 'xUnit' - testResultsFiles: '*.xml' - searchFolder: '$(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig)' - testRunTitle: ${{ coalesce(parameters.testRunTitle, parameters.name, '$(System.JobName)') }}-xunit - mergeTestResults: ${{ parameters.mergeTestResults }} - continueOnError: true - condition: always() - - ${{ if or(and(eq(parameters.enablePublishTestResults, 'true'), eq(parameters.testResultsFormat, '')), eq(parameters.testResultsFormat, 'vstest')) }}: - - task: PublishTestResults@2 - displayName: Publish TRX Test Results - inputs: - testResultsFormat: 'VSTest' - testResultsFiles: '*.trx' - searchFolder: '$(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig)' - testRunTitle: ${{ coalesce(parameters.testRunTitle, parameters.name, '$(System.JobName)') }}-trx - mergeTestResults: ${{ parameters.mergeTestResults }} - continueOnError: true - condition: always() - - - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest'), eq(parameters.enableSbom, 'true')) }}: - - template: /eng/common/templates-official/steps/generate-sbom.yml - parameters: - PackageVersion: ${{ parameters.packageVersion}} - BuildDropPath: ${{ parameters.buildDropPath }} - IgnoreDirectories: ${{ parameters.componentGovernanceIgnoreDirectories }} - - - ${{ if eq(parameters.enableBuildRetry, 'true') }}: - - task: 1ES.PublishPipelineArtifact@1 - inputs: - targetPath: '$(Build.SourcesDirectory)\eng\common\BuildConfiguration' - artifactName: 'BuildConfiguration' - displayName: 'Publish build retry configuration' - continueOnError: true \ No newline at end of file +- template: /eng/common/core-templates/job/job.yml + parameters: + is1ESPipeline: true + + # publish artifacts + # for 1ES managed templates, use the templateContext.output to handle multiple outputs. + templateContext: + outputParentDirectory: $(Build.ArtifactStagingDirectory) + outputs: + - ${{ if ne(parameters.artifacts.publish, '') }}: + - ${{ if and(ne(parameters.artifacts.publish.artifacts, 'false'), ne(parameters.artifacts.publish.artifacts, '')) }}: + - output: buildArtifacts + displayName: Publish pipeline artifacts + PathtoPublish: '$(Build.ArtifactStagingDirectory)/artifacts' + ArtifactName: ${{ coalesce(parameters.artifacts.publish.artifacts.name , 'Artifacts_$(Agent.Os)_$(_BuildConfig)') }} + condition: always() + continueOnError: true + - ${{ if and(ne(parameters.artifacts.publish.logs, 'false'), ne(parameters.artifacts.publish.logs, '')) }}: + - output: pipelineArtifact + targetPath: '$(Build.ArtifactStagingDirectory)/artifacts/log' + artifactName: ${{ coalesce(parameters.artifacts.publish.logs.name, 'Logs_Build_$(Agent.Os)_$(_BuildConfig)_Attempt$(System.JobAttempt)') }} + displayName: 'Publish logs' + continueOnError: true + condition: always() + sbomEnabled: false # we don't need SBOM for logs + + - ${{ if eq(parameters.enablePublishBuildArtifacts, true) }}: + - output: buildArtifacts + displayName: Publish Logs + PathtoPublish: '$(Build.ArtifactStagingDirectory)/artifacts/log/$(_BuildConfig)' + publishLocation: Container + ArtifactName: ${{ coalesce(parameters.enablePublishBuildArtifacts.artifactName, '$(Agent.Os)_$(Agent.JobName)' ) }} + continueOnError: true + condition: always() + sbomEnabled: false # we don't need SBOM for logs + + - ${{ if eq(parameters.enableBuildRetry, 'true') }}: + - output: pipelineArtifact + targetPath: '$(Build.ArtifactStagingDirectory)/artifacts/eng/common/BuildConfiguration' + artifactName: 'BuildConfiguration' + displayName: 'Publish build retry configuration' + continueOnError: true + sbomEnabled: false # we don't need SBOM for BuildConfiguration + + - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest'), eq(parameters.enableSbom, 'true')) }}: + - output: pipelineArtifact + displayName: Publish SBOM manifest + continueOnError: true + targetPath: $(Build.ArtifactStagingDirectory)/sbom + artifactName: $(ARTIFACT_NAME) + + # add any outputs provided via root yaml + - ${{ if ne(parameters.templateContext.outputs, '') }}: + - ${{ each output in parameters.templateContext.outputs }}: + - ${{ output }} + + # add any remaining templateContext properties + ${{ each context in parameters.templateContext }}: + ${{ if and(ne(context.key, 'outputParentDirectory'), ne(context.key, 'outputs')) }}: + ${{ context.key }}: ${{ context.value }} + + ${{ each parameter in parameters }}: + ${{ if and(ne(parameter.key, 'templateContext'), ne(parameter.key, 'is1ESPipeline')) }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates-official/job/onelocbuild.yml b/eng/common/templates-official/job/onelocbuild.yml index 52b4d05d3f8..0f0c514b912 100644 --- a/eng/common/templates-official/job/onelocbuild.yml +++ b/eng/common/templates-official/job/onelocbuild.yml @@ -1,112 +1,7 @@ -parameters: - # Optional: dependencies of the job - dependsOn: '' - - # Optional: A defined YAML pool - https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=vsts&tabs=schema#pool - pool: '' - - CeapexPat: $(dn-bot-ceapex-package-r) # PAT for the loc AzDO instance https://dev.azure.com/ceapex - GithubPat: $(BotAccount-dotnet-bot-repo-PAT) - - SourcesDirectory: $(Build.SourcesDirectory) - CreatePr: true - AutoCompletePr: false - ReusePr: true - UseLfLineEndings: true - UseCheckedInLocProjectJson: false - SkipLocProjectJsonGeneration: false - LanguageSet: VS_Main_Languages - LclSource: lclFilesInRepo - LclPackageId: '' - RepoType: gitHub - GitHubOrg: dotnet - MirrorRepo: '' - MirrorBranch: main - condition: '' - JobNameSuffix: '' - jobs: -- job: OneLocBuild${{ parameters.JobNameSuffix }} - - dependsOn: ${{ parameters.dependsOn }} - - displayName: OneLocBuild${{ parameters.JobNameSuffix }} - - variables: - - group: OneLocBuildVariables # Contains the CeapexPat and GithubPat - - name: _GenerateLocProjectArguments - value: -SourcesDirectory ${{ parameters.SourcesDirectory }} - -LanguageSet "${{ parameters.LanguageSet }}" - -CreateNeutralXlfs - - ${{ if eq(parameters.UseCheckedInLocProjectJson, 'true') }}: - - name: _GenerateLocProjectArguments - value: ${{ variables._GenerateLocProjectArguments }} -UseCheckedInLocProjectJson - - template: /eng/common/templates-official/variables/pool-providers.yml - - ${{ if ne(parameters.pool, '') }}: - pool: ${{ parameters.pool }} - ${{ if eq(parameters.pool, '') }}: - pool: - # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) - ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: - name: AzurePipelines-EO - image: 1ESPT-Windows2022 - demands: Cmd - os: windows - # If it's not devdiv, it's dnceng - ${{ if ne(variables['System.TeamProject'], 'DevDiv') }}: - name: $(DncEngInternalBuildPool) - image: 1es-windows-2022 - os: windows - - steps: - - ${{ if ne(parameters.SkipLocProjectJsonGeneration, 'true') }}: - - task: Powershell@2 - inputs: - filePath: $(Build.SourcesDirectory)/eng/common/generate-locproject.ps1 - arguments: $(_GenerateLocProjectArguments) - displayName: Generate LocProject.json - condition: ${{ parameters.condition }} - - - task: OneLocBuild@2 - displayName: OneLocBuild - env: - SYSTEM_ACCESSTOKEN: $(System.AccessToken) - inputs: - locProj: eng/Localize/LocProject.json - outDir: $(Build.ArtifactStagingDirectory) - lclSource: ${{ parameters.LclSource }} - lclPackageId: ${{ parameters.LclPackageId }} - isCreatePrSelected: ${{ parameters.CreatePr }} - isAutoCompletePrSelected: ${{ parameters.AutoCompletePr }} - ${{ if eq(parameters.CreatePr, true) }}: - isUseLfLineEndingsSelected: ${{ parameters.UseLfLineEndings }} - ${{ if eq(parameters.RepoType, 'gitHub') }}: - isShouldReusePrSelected: ${{ parameters.ReusePr }} - packageSourceAuth: patAuth - patVariable: ${{ parameters.CeapexPat }} - ${{ if eq(parameters.RepoType, 'gitHub') }}: - repoType: ${{ parameters.RepoType }} - gitHubPatVariable: "${{ parameters.GithubPat }}" - ${{ if ne(parameters.MirrorRepo, '') }}: - isMirrorRepoSelected: true - gitHubOrganization: ${{ parameters.GitHubOrg }} - mirrorRepo: ${{ parameters.MirrorRepo }} - mirrorBranch: ${{ parameters.MirrorBranch }} - condition: ${{ parameters.condition }} - - - task: 1ES.PublishBuildArtifacts@1 - displayName: Publish Localization Files - inputs: - PathtoPublish: '$(Build.ArtifactStagingDirectory)/loc' - PublishLocation: Container - ArtifactName: Loc - condition: ${{ parameters.condition }} +- template: /eng/common/core-templates/job/onelocbuild.yml + parameters: + is1ESPipeline: true - - task: 1ES.PublishBuildArtifacts@1 - displayName: Publish LocProject.json - inputs: - PathtoPublish: '$(Build.SourcesDirectory)/eng/Localize/' - PublishLocation: Container - ArtifactName: Loc - condition: ${{ parameters.condition }} \ No newline at end of file + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates-official/job/publish-build-assets.yml b/eng/common/templates-official/job/publish-build-assets.yml index d01739c1285..d667a70e8de 100644 --- a/eng/common/templates-official/job/publish-build-assets.yml +++ b/eng/common/templates-official/job/publish-build-assets.yml @@ -1,157 +1,7 @@ -parameters: - configuration: 'Debug' - - # Optional: condition for the job to run - condition: '' - - # Optional: 'true' if future jobs should run even if this job fails - continueOnError: false - - # Optional: dependencies of the job - dependsOn: '' - - # Optional: Include PublishBuildArtifacts task - enablePublishBuildArtifacts: false - - # Optional: A defined YAML pool - https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=vsts&tabs=schema#pool - pool: {} - - # Optional: should run as a public build even in the internal project - # if 'true', the build won't run any of the internal only steps, even if it is running in non-public projects. - runAsPublic: false - - # Optional: whether the build's artifacts will be published using release pipelines or direct feed publishing - publishUsingPipelines: false - - # Optional: whether the build's artifacts will be published using release pipelines or direct feed publishing - publishAssetsImmediately: false - - artifactsPublishingAdditionalParameters: '' - - signingValidationAdditionalParameters: '' - jobs: -- job: Asset_Registry_Publish - - dependsOn: ${{ parameters.dependsOn }} - timeoutInMinutes: 150 - - ${{ if eq(parameters.publishAssetsImmediately, 'true') }}: - displayName: Publish Assets - ${{ else }}: - displayName: Publish to Build Asset Registry - - variables: - - template: /eng/common/templates-official/variables/pool-providers.yml - - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - - group: Publish-Build-Assets - - group: AzureDevOps-Artifact-Feeds-Pats - - name: runCodesignValidationInjection - value: false - - ${{ if eq(parameters.publishAssetsImmediately, 'true') }}: - - template: /eng/common/templates-official/post-build/common-variables.yml - - pool: - # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) - ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: - name: AzurePipelines-EO - image: 1ESPT-Windows2022 - demands: Cmd - os: windows - # If it's not devdiv, it's dnceng - ${{ if ne(variables['System.TeamProject'], 'DevDiv') }}: - name: NetCore1ESPool-Publishing-Internal - image: windows.vs2019.amd64 - os: windows - steps: - - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - - task: DownloadBuildArtifacts@0 - displayName: Download artifact - inputs: - artifactName: AssetManifests - downloadPath: '$(Build.StagingDirectory)/Download' - checkDownloadedFiles: true - condition: ${{ parameters.condition }} - continueOnError: ${{ parameters.continueOnError }} - - - task: NuGetAuthenticate@1 - - - task: AzureCLI@2 - displayName: Publish Build Assets - inputs: - azureSubscription: "Darc: Maestro Production" - scriptType: ps - scriptLocation: scriptPath - scriptPath: $(Build.SourcesDirectory)/eng/common/sdk-task.ps1 - arguments: > - -task PublishBuildAssets -restore -msbuildEngine dotnet - /p:ManifestsPath='$(Build.StagingDirectory)/Download/AssetManifests' - /p:MaestroApiEndpoint=https://maestro-prod.westus2.cloudapp.azure.com - /p:PublishUsingPipelines=${{ parameters.publishUsingPipelines }} - /p:OfficialBuildId=$(Build.BuildNumber) - condition: ${{ parameters.condition }} - continueOnError: ${{ parameters.continueOnError }} - - - task: powershell@2 - displayName: Create ReleaseConfigs Artifact - inputs: - targetType: inline - script: | - New-Item -Path "$(Build.StagingDirectory)/ReleaseConfigs" -ItemType Directory -Force - $filePath = "$(Build.StagingDirectory)/ReleaseConfigs/ReleaseConfigs.txt" - Add-Content -Path $filePath -Value $(BARBuildId) - Add-Content -Path $filePath -Value "$(DefaultChannels)" - Add-Content -Path $filePath -Value $(IsStableBuild) - - - task: 1ES.PublishBuildArtifacts@1 - displayName: Publish ReleaseConfigs Artifact - inputs: - PathtoPublish: '$(Build.StagingDirectory)/ReleaseConfigs' - PublishLocation: Container - ArtifactName: ReleaseConfigs - - - task: powershell@2 - displayName: Check if SymbolPublishingExclusionsFile.txt exists - inputs: - targetType: inline - script: | - $symbolExclusionfile = "$(Build.SourcesDirectory)/eng/SymbolPublishingExclusionsFile.txt" - if(Test-Path -Path $symbolExclusionfile) - { - Write-Host "SymbolExclusionFile exists" - Write-Host "##vso[task.setvariable variable=SymbolExclusionFile]true" - } - else{ - Write-Host "Symbols Exclusion file does not exists" - Write-Host "##vso[task.setvariable variable=SymbolExclusionFile]false" - } - - - task: 1ES.PublishBuildArtifacts@1 - displayName: Publish SymbolPublishingExclusionsFile Artifact - condition: eq(variables['SymbolExclusionFile'], 'true') - inputs: - PathtoPublish: '$(Build.SourcesDirectory)/eng/SymbolPublishingExclusionsFile.txt' - PublishLocation: Container - ArtifactName: ReleaseConfigs - - - ${{ if eq(parameters.publishAssetsImmediately, 'true') }}: - - template: /eng/common/templates-official/post-build/setup-maestro-vars.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - - - task: PowerShell@2 - displayName: Publish Using Darc - inputs: - filePath: $(Build.SourcesDirectory)/eng/common/post-build/publish-using-darc.ps1 - arguments: -BuildId $(BARBuildId) - -PublishingInfraVersion 3 - -AzdoToken '$(publishing-dnceng-devdiv-code-r-build-re)' - -WaitPublishingFinish true - -ArtifactsPublishingAdditionalParameters '${{ parameters.artifactsPublishingAdditionalParameters }}' - -SymbolPublishingAdditionalParameters '${{ parameters.symbolPublishingAdditionalParameters }}' +- template: /eng/common/core-templates/job/publish-build-assets.yml + parameters: + is1ESPipeline: true - - ${{ if eq(parameters.enablePublishBuildArtifacts, 'true') }}: - - template: /eng/common/templates-official/steps/publish-logs.yml - parameters: - JobLabel: 'Publish_Artifacts_Logs' + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates-official/job/source-build.yml b/eng/common/templates-official/job/source-build.yml index f983033bb02..1a480034b67 100644 --- a/eng/common/templates-official/job/source-build.yml +++ b/eng/common/templates-official/job/source-build.yml @@ -1,75 +1,7 @@ -parameters: - # This template adds arcade-powered source-build to CI. The template produces a server job with a - # default ID 'Source_Build_Complete' to put in a dependency list if necessary. - - # Specifies the prefix for source-build jobs added to pipeline. Use this if disambiguation needed. - jobNamePrefix: 'Source_Build' - - # Defines the platform on which to run the job. By default, a linux-x64 machine, suitable for - # managed-only repositories. This is an object with these properties: - # - # name: '' - # The name of the job. This is included in the job ID. - # targetRID: '' - # The name of the target RID to use, instead of the one auto-detected by Arcade. - # nonPortable: false - # Enables non-portable mode. This means a more specific RID (e.g. fedora.32-x64 rather than - # linux-x64), and compiling against distro-provided packages rather than portable ones. - # skipPublishValidation: false - # Disables publishing validation. By default, a check is performed to ensure no packages are - # published by source-build. - # container: '' - # A container to use. Runs in docker. - # pool: {} - # A pool to use. Runs directly on an agent. - # buildScript: '' - # Specifies the build script to invoke to perform the build in the repo. The default - # './build.sh' should work for typical Arcade repositories, but this is customizable for - # difficult situations. - # jobProperties: {} - # A list of job properties to inject at the top level, for potential extensibility beyond - # container and pool. - platform: {} - - # If set to true and running on a non-public project, - # Internal blob storage locations will be enabled. - # This is not enabled by default because many repositories do not need internal sources - # and do not need to have the required service connections approved in the pipeline. - enableInternalSources: false - jobs: -- job: ${{ parameters.jobNamePrefix }}_${{ parameters.platform.name }} - displayName: Source-Build (${{ parameters.platform.name }}) - - ${{ each property in parameters.platform.jobProperties }}: - ${{ property.key }}: ${{ property.value }} - - ${{ if ne(parameters.platform.container, '') }}: - container: ${{ parameters.platform.container }} - - ${{ if eq(parameters.platform.pool, '') }}: - # The default VM host AzDO pool. This should be capable of running Docker containers: almost all - # source-build builds run in Docker, including the default managed platform. - # /eng/common/templates-official/variables/pool-providers.yml can't be used here (some customers declare variables already), so duplicate its logic - pool: - ${{ if eq(variables['System.TeamProject'], 'public') }}: - name: $[replace(replace(eq(contains(coalesce(variables['System.PullRequest.TargetBranch'], variables['Build.SourceBranch'], 'refs/heads/main'), 'release'), 'true'), True, 'NetCore-Svc-Public' ), False, 'NetCore-Public')] - demands: ImageOverride -equals Build.Ubuntu.1804.Amd64.Open - - ${{ if eq(variables['System.TeamProject'], 'internal') }}: - name: $[replace(replace(eq(contains(coalesce(variables['System.PullRequest.TargetBranch'], variables['Build.SourceBranch'], 'refs/heads/main'), 'release'), 'true'), True, 'NetCore1ESPool-Svc-Internal'), False, 'NetCore1ESPool-Internal')] - image: 1es-mariner-2 - os: linux - - ${{ if ne(parameters.platform.pool, '') }}: - pool: ${{ parameters.platform.pool }} - - workspace: - clean: all +- template: /eng/common/core-templates/job/source-build.yml + parameters: + is1ESPipeline: true - steps: - - ${{ if eq(parameters.enableInternalSources, true) }}: - - template: /eng/common/templates-official/steps/enable-internal-runtimes.yml - - template: /eng/common/templates-official/steps/source-build.yml - parameters: - platform: ${{ parameters.platform }} + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates-official/job/source-index-stage1.yml b/eng/common/templates-official/job/source-index-stage1.yml index 60dfb6b2d1c..6d5ead316f9 100644 --- a/eng/common/templates-official/job/source-index-stage1.yml +++ b/eng/common/templates-official/job/source-index-stage1.yml @@ -1,83 +1,7 @@ -parameters: - runAsPublic: false - sourceIndexUploadPackageVersion: 2.0.0-20240502.12 - sourceIndexProcessBinlogPackageVersion: 1.0.1-20240129.2 - sourceIndexPackageSource: https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json - sourceIndexBuildCommand: powershell -NoLogo -NoProfile -ExecutionPolicy Bypass -Command "eng/common/build.ps1 -restore -build -binarylog -ci" - preSteps: [] - binlogPath: artifacts/log/Debug/Build.binlog - condition: '' - dependsOn: '' - pool: '' - jobs: -- job: SourceIndexStage1 - dependsOn: ${{ parameters.dependsOn }} - condition: ${{ parameters.condition }} - variables: - - name: SourceIndexUploadPackageVersion - value: ${{ parameters.sourceIndexUploadPackageVersion }} - - name: SourceIndexProcessBinlogPackageVersion - value: ${{ parameters.sourceIndexProcessBinlogPackageVersion }} - - name: SourceIndexPackageSource - value: ${{ parameters.sourceIndexPackageSource }} - - name: BinlogPath - value: ${{ parameters.binlogPath }} - - template: /eng/common/templates-official/variables/pool-providers.yml - - ${{ if ne(parameters.pool, '') }}: - pool: ${{ parameters.pool }} - ${{ if eq(parameters.pool, '') }}: - pool: - ${{ if eq(variables['System.TeamProject'], 'public') }}: - name: $(DncEngPublicBuildPool) - demands: ImageOverride -equals windows.vs2019.amd64.open - ${{ if eq(variables['System.TeamProject'], 'internal') }}: - name: $(DncEngInternalBuildPool) - image: windows.vs2022.amd64 - os: windows - - steps: - - ${{ each preStep in parameters.preSteps }}: - - ${{ preStep }} - - - task: UseDotNet@2 - displayName: Use .NET 8 SDK - inputs: - packageType: sdk - version: 8.0.x - installationPath: $(Agent.TempDirectory)/dotnet - workingDirectory: $(Agent.TempDirectory) - - - script: | - $(Agent.TempDirectory)/dotnet/dotnet tool install BinLogToSln --version $(sourceIndexProcessBinlogPackageVersion) --add-source $(SourceIndexPackageSource) --tool-path $(Agent.TempDirectory)/.source-index/tools - $(Agent.TempDirectory)/dotnet/dotnet tool install UploadIndexStage1 --version $(sourceIndexUploadPackageVersion) --add-source $(SourceIndexPackageSource) --tool-path $(Agent.TempDirectory)/.source-index/tools - displayName: Download Tools - # Set working directory to temp directory so 'dotnet' doesn't try to use global.json and use the repo's sdk. - workingDirectory: $(Agent.TempDirectory) - - - script: ${{ parameters.sourceIndexBuildCommand }} - displayName: Build Repository - - - script: $(Agent.TempDirectory)/.source-index/tools/BinLogToSln -i $(BinlogPath) -r $(Build.SourcesDirectory) -n $(Build.Repository.Name) -o .source-index/stage1output - displayName: Process Binlog into indexable sln - - - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - - task: AzureCLI@2 - displayName: Get stage 1 auth token - inputs: - azureSubscription: 'SourceDotNet Stage1 Publish' - addSpnToEnvironment: true - scriptType: 'ps' - scriptLocation: 'inlineScript' - inlineScript: | - echo "##vso[task.setvariable variable=ARM_CLIENT_ID;issecret=true]$env:servicePrincipalId" - echo "##vso[task.setvariable variable=ARM_ID_TOKEN;issecret=true]$env:idToken" - echo "##vso[task.setvariable variable=ARM_TENANT_ID;issecret=true]$env:tenantId" - - - script: | - az login --service-principal -u $(ARM_CLIENT_ID) --tenant $(ARM_TENANT_ID) --allow-no-subscriptions --federated-token $(ARM_ID_TOKEN) - displayName: "Login to Azure" +- template: /eng/common/core-templates/job/source-index-stage1.yml + parameters: + is1ESPipeline: true - - script: $(Agent.TempDirectory)/.source-index/tools/UploadIndexStage1 -i .source-index/stage1output -n $(Build.Repository.Name) -s netsourceindexstage1 -b stage1 - displayName: Upload stage1 artifacts to source index + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates-official/jobs/codeql-build.yml b/eng/common/templates-official/jobs/codeql-build.yml index b68d3c2f319..a726322ecfe 100644 --- a/eng/common/templates-official/jobs/codeql-build.yml +++ b/eng/common/templates-official/jobs/codeql-build.yml @@ -1,31 +1,7 @@ -parameters: - # See schema documentation in /Documentation/AzureDevOps/TemplateSchema.md - continueOnError: false - # Required: A collection of jobs to run - https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=vsts&tabs=schema#job - jobs: [] - # Optional: if specified, restore and use this version of Guardian instead of the default. - overrideGuardianVersion: '' - jobs: -- template: /eng/common/templates-official/jobs/jobs.yml +- template: /eng/common/core-templates/jobs/codeql-build.yml parameters: - enableMicrobuild: false - enablePublishBuildArtifacts: false - enablePublishTestResults: false - enablePublishBuildAssets: false - enablePublishUsingPipelines: false - enableTelemetry: true + is1ESPipeline: true - variables: - - group: Publish-Build-Assets - # The Guardian version specified in 'eng/common/sdl/packages.config'. This value must be kept in - # sync with the packages.config file. - - name: DefaultGuardianVersion - value: 0.109.0 - - name: GuardianPackagesConfigFile - value: $(Build.SourcesDirectory)\eng\common\sdl\packages.config - - name: GuardianVersion - value: ${{ coalesce(parameters.overrideGuardianVersion, '$(DefaultGuardianVersion)') }} - - jobs: ${{ parameters.jobs }} - + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates-official/jobs/jobs.yml b/eng/common/templates-official/jobs/jobs.yml index 857a0f8ba43..007deddaea0 100644 --- a/eng/common/templates-official/jobs/jobs.yml +++ b/eng/common/templates-official/jobs/jobs.yml @@ -1,97 +1,7 @@ -parameters: - # See schema documentation in /Documentation/AzureDevOps/TemplateSchema.md - continueOnError: false - - # Optional: Include PublishBuildArtifacts task - enablePublishBuildArtifacts: false - - # Optional: Enable publishing using release pipelines - enablePublishUsingPipelines: false - - # Optional: Enable running the source-build jobs to build repo from source - enableSourceBuild: false - - # Optional: Parameters for source-build template. - # See /eng/common/templates-official/jobs/source-build.yml for options - sourceBuildParameters: [] - - graphFileGeneration: - # Optional: Enable generating the graph files at the end of the build - enabled: false - # Optional: Include toolset dependencies in the generated graph files - includeToolset: false - - # Required: A collection of jobs to run - https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=vsts&tabs=schema#job - jobs: [] - - # Optional: Override automatically derived dependsOn value for "publish build assets" job - publishBuildAssetsDependsOn: '' - - # Optional: Publish the assets as soon as the publish to BAR stage is complete, rather doing so in a separate stage. - publishAssetsImmediately: false - - # Optional: If using publishAssetsImmediately and additional parameters are needed, can be used to send along additional parameters (normally sent to post-build.yml) - artifactsPublishingAdditionalParameters: '' - signingValidationAdditionalParameters: '' - - # Optional: should run as a public build even in the internal project - # if 'true', the build won't run any of the internal only steps, even if it is running in non-public projects. - runAsPublic: false - - enableSourceIndex: false - sourceIndexParams: {} - -# Internal resources (telemetry, microbuild) can only be accessed from non-public projects, -# and some (Microbuild) should only be applied to non-PR cases for internal builds. - jobs: -- ${{ each job in parameters.jobs }}: - - template: ../job/job.yml - parameters: - # pass along parameters - ${{ each parameter in parameters }}: - ${{ if ne(parameter.key, 'jobs') }}: - ${{ parameter.key }}: ${{ parameter.value }} - - # pass along job properties - ${{ each property in job }}: - ${{ if ne(property.key, 'job') }}: - ${{ property.key }}: ${{ property.value }} - - name: ${{ job.job }} - -- ${{ if eq(parameters.enableSourceBuild, true) }}: - - template: /eng/common/templates-official/jobs/source-build.yml - parameters: - allCompletedJobId: Source_Build_Complete - ${{ each parameter in parameters.sourceBuildParameters }}: - ${{ parameter.key }}: ${{ parameter.value }} - -- ${{ if eq(parameters.enableSourceIndex, 'true') }}: - - template: ../job/source-index-stage1.yml - parameters: - runAsPublic: ${{ parameters.runAsPublic }} - ${{ each parameter in parameters.sourceIndexParams }}: - ${{ parameter.key }}: ${{ parameter.value }} - -- ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - - ${{ if or(eq(parameters.enablePublishBuildAssets, true), eq(parameters.artifacts.publish.manifests, 'true'), ne(parameters.artifacts.publish.manifests, '')) }}: - - template: ../job/publish-build-assets.yml - parameters: - continueOnError: ${{ parameters.continueOnError }} - dependsOn: - - ${{ if ne(parameters.publishBuildAssetsDependsOn, '') }}: - - ${{ each job in parameters.publishBuildAssetsDependsOn }}: - - ${{ job.job }} - - ${{ if eq(parameters.publishBuildAssetsDependsOn, '') }}: - - ${{ each job in parameters.jobs }}: - - ${{ job.job }} - - ${{ if eq(parameters.enableSourceBuild, true) }}: - - Source_Build_Complete +- template: /eng/common/core-templates/jobs/jobs.yml + parameters: + is1ESPipeline: true - runAsPublic: ${{ parameters.runAsPublic }} - publishUsingPipelines: ${{ parameters.enablePublishUsingPipelines }} - publishAssetsImmediately: ${{ parameters.publishAssetsImmediately }} - enablePublishBuildArtifacts: ${{ parameters.enablePublishBuildArtifacts }} - artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} - signingValidationAdditionalParameters: ${{ parameters.signingValidationAdditionalParameters }} + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates-official/jobs/source-build.yml b/eng/common/templates-official/jobs/source-build.yml index 5cf6a269c0b..483e7b611f3 100644 --- a/eng/common/templates-official/jobs/source-build.yml +++ b/eng/common/templates-official/jobs/source-build.yml @@ -1,54 +1,7 @@ -parameters: - # This template adds arcade-powered source-build to CI. A job is created for each platform, as - # well as an optional server job that completes when all platform jobs complete. - - # The name of the "join" job for all source-build platforms. If set to empty string, the job is - # not included. Existing repo pipelines can use this job depend on all source-build jobs - # completing without maintaining a separate list of every single job ID: just depend on this one - # server job. By default, not included. Recommended name if used: 'Source_Build_Complete'. - allCompletedJobId: '' - - # See /eng/common/templates-official/job/source-build.yml - jobNamePrefix: 'Source_Build' - - # This is the default platform provided by Arcade, intended for use by a managed-only repo. - defaultManagedPlatform: - name: 'Managed' - container: 'mcr.microsoft.com/dotnet-buildtools/prereqs:centos-stream8' - - # Defines the platforms on which to run build jobs. One job is created for each platform, and the - # object in this array is sent to the job template as 'platform'. If no platforms are specified, - # one job runs on 'defaultManagedPlatform'. - platforms: [] - - # If set to true and running on a non-public project, - # Internal nuget and blob storage locations will be enabled. - # This is not enabled by default because many repositories do not need internal sources - # and do not need to have the required service connections approved in the pipeline. - enableInternalSources: false - jobs: +- template: /eng/common/core-templates/jobs/source-build.yml + parameters: + is1ESPipeline: true -- ${{ if ne(parameters.allCompletedJobId, '') }}: - - job: ${{ parameters.allCompletedJobId }} - displayName: Source-Build Complete - pool: server - dependsOn: - - ${{ each platform in parameters.platforms }}: - - ${{ parameters.jobNamePrefix }}_${{ platform.name }} - - ${{ if eq(length(parameters.platforms), 0) }}: - - ${{ parameters.jobNamePrefix }}_${{ parameters.defaultManagedPlatform.name }} - -- ${{ each platform in parameters.platforms }}: - - template: /eng/common/templates-official/job/source-build.yml - parameters: - jobNamePrefix: ${{ parameters.jobNamePrefix }} - platform: ${{ platform }} - enableInternalSources: ${{ parameters.enableInternalSources }} - -- ${{ if eq(length(parameters.platforms), 0) }}: - - template: /eng/common/templates-official/job/source-build.yml - parameters: - jobNamePrefix: ${{ parameters.jobNamePrefix }} - platform: ${{ parameters.defaultManagedPlatform }} - enableInternalSources: ${{ parameters.enableInternalSources }} + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} \ No newline at end of file diff --git a/eng/common/templates-official/post-build/common-variables.yml b/eng/common/templates-official/post-build/common-variables.yml index c24193acfc9..c32fc49233f 100644 --- a/eng/common/templates-official/post-build/common-variables.yml +++ b/eng/common/templates-official/post-build/common-variables.yml @@ -1,22 +1,8 @@ variables: - - group: Publish-Build-Assets +- template: /eng/common/core-templates/post-build/common-variables.yml + parameters: + # Specifies whether to use 1ES + is1ESPipeline: true - # Whether the build is internal or not - - name: IsInternalBuild - value: ${{ and(ne(variables['System.TeamProject'], 'public'), contains(variables['Build.SourceBranch'], 'internal')) }} - - # Default Maestro++ API Endpoint and API Version - - name: MaestroApiEndPoint - value: "https://maestro-prod.westus2.cloudapp.azure.com" - - name: MaestroApiAccessToken - value: $(MaestroAccessToken) - - name: MaestroApiVersion - value: "2020-02-20" - - - name: SourceLinkCLIVersion - value: 3.0.0 - - name: SymbolToolVersion - value: 1.0.1 - - - name: runCodesignValidationInjection - value: false + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} \ No newline at end of file diff --git a/eng/common/templates-official/post-build/post-build.yml b/eng/common/templates-official/post-build/post-build.yml index 0dfa387e7b7..2364c0fd4a5 100644 --- a/eng/common/templates-official/post-build/post-build.yml +++ b/eng/common/templates-official/post-build/post-build.yml @@ -1,287 +1,8 @@ -parameters: - # Which publishing infra should be used. THIS SHOULD MATCH THE VERSION ON THE BUILD MANIFEST. - # Publishing V1 is no longer supported - # Publishing V2 is no longer supported - # Publishing V3 is the default - - name: publishingInfraVersion - displayName: Which version of publishing should be used to promote the build definition? - type: number - default: 3 - values: - - 3 - - - name: BARBuildId - displayName: BAR Build Id - type: number - default: 0 - - - name: PromoteToChannelIds - displayName: Channel to promote BARBuildId to - type: string - default: '' - - - name: enableSourceLinkValidation - displayName: Enable SourceLink validation - type: boolean - default: false - - - name: enableSigningValidation - displayName: Enable signing validation - type: boolean - default: true - - - name: enableSymbolValidation - displayName: Enable symbol validation - type: boolean - default: false - - - name: enableNugetValidation - displayName: Enable NuGet validation - type: boolean - default: true - - - name: publishInstallersAndChecksums - displayName: Publish installers and checksums - type: boolean - default: true - - - name: SDLValidationParameters - type: object - default: - enable: false - publishGdn: false - continueOnError: false - params: '' - artifactNames: '' - downloadArtifacts: true - - # These parameters let the user customize the call to sdk-task.ps1 for publishing - # symbols & general artifacts as well as for signing validation - - name: symbolPublishingAdditionalParameters - displayName: Symbol publishing additional parameters - type: string - default: '' - - - name: artifactsPublishingAdditionalParameters - displayName: Artifact publishing additional parameters - type: string - default: '' - - - name: signingValidationAdditionalParameters - displayName: Signing validation additional parameters - type: string - default: '' - - # Which stages should finish execution before post-build stages start - - name: validateDependsOn - type: object - default: - - build - - - name: publishDependsOn - type: object - default: - - Validate - - # Optional: Call asset publishing rather than running in a separate stage - - name: publishAssetsImmediately - type: boolean - default: false - stages: -- ${{ if or(eq( parameters.enableNugetValidation, 'true'), eq(parameters.enableSigningValidation, 'true'), eq(parameters.enableSourceLinkValidation, 'true'), eq(parameters.SDLValidationParameters.enable, 'true')) }}: - - stage: Validate - dependsOn: ${{ parameters.validateDependsOn }} - displayName: Validate Build Assets - variables: - - template: common-variables.yml - - template: /eng/common/templates-official/variables/pool-providers.yml - jobs: - - job: - displayName: NuGet Validation - condition: and(succeededOrFailed(), eq( ${{ parameters.enableNugetValidation }}, 'true')) - pool: - # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) - ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: - name: AzurePipelines-EO - image: 1ESPT-Windows2022 - demands: Cmd - os: windows - # If it's not devdiv, it's dnceng - ${{ else }}: - name: $(DncEngInternalBuildPool) - image: 1es-windows-2022 - os: windows - - steps: - - template: setup-maestro-vars.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - - - task: DownloadBuildArtifacts@0 - displayName: Download Package Artifacts - inputs: - buildType: specific - buildVersionToDownload: specific - project: $(AzDOProjectName) - pipeline: $(AzDOPipelineId) - buildId: $(AzDOBuildId) - artifactName: PackageArtifacts - checkDownloadedFiles: true - - - task: PowerShell@2 - displayName: Validate - inputs: - filePath: $(Build.SourcesDirectory)/eng/common/post-build/nuget-validation.ps1 - arguments: -PackagesPath $(Build.ArtifactStagingDirectory)/PackageArtifacts/ - -ToolDestinationPath $(Agent.BuildDirectory)/Extract/ - - - job: - displayName: Signing Validation - condition: and( eq( ${{ parameters.enableSigningValidation }}, 'true'), ne( variables['PostBuildSign'], 'true')) - pool: - # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) - ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: - name: AzurePipelines-EO - image: 1ESPT-Windows2022 - demands: Cmd - os: windows - # If it's not devdiv, it's dnceng - ${{ else }}: - name: $(DncEngInternalBuildPool) - image: 1es-windows-2022 - os: windows - steps: - - template: setup-maestro-vars.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - - - task: DownloadBuildArtifacts@0 - displayName: Download Package Artifacts - inputs: - buildType: specific - buildVersionToDownload: specific - project: $(AzDOProjectName) - pipeline: $(AzDOPipelineId) - buildId: $(AzDOBuildId) - artifactName: PackageArtifacts - checkDownloadedFiles: true - itemPattern: | - ** - !**/Microsoft.SourceBuild.Intermediate.*.nupkg - - # This is necessary whenever we want to publish/restore to an AzDO private feed - # Since sdk-task.ps1 tries to restore packages we need to do this authentication here - # otherwise it'll complain about accessing a private feed. - - task: NuGetAuthenticate@1 - displayName: 'Authenticate to AzDO Feeds' - - # Signing validation will optionally work with the buildmanifest file which is downloaded from - # Azure DevOps above. - - task: PowerShell@2 - displayName: Validate - inputs: - filePath: eng\common\sdk-task.ps1 - arguments: -task SigningValidation -restore -msbuildEngine vs - /p:PackageBasePath='$(Build.ArtifactStagingDirectory)/PackageArtifacts' - /p:SignCheckExclusionsFile='$(Build.SourcesDirectory)/eng/SignCheckExclusionsFile.txt' - ${{ parameters.signingValidationAdditionalParameters }} - - - template: ../steps/publish-logs.yml - parameters: - StageLabel: 'Validation' - JobLabel: 'Signing' - BinlogToolVersion: $(BinlogToolVersion) - - - job: - displayName: SourceLink Validation - condition: eq( ${{ parameters.enableSourceLinkValidation }}, 'true') - pool: - # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) - ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: - name: AzurePipelines-EO - image: 1ESPT-Windows2022 - demands: Cmd - os: windows - # If it's not devdiv, it's dnceng - ${{ else }}: - name: $(DncEngInternalBuildPool) - image: 1es-windows-2022 - os: windows - steps: - - template: setup-maestro-vars.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - - - task: DownloadBuildArtifacts@0 - displayName: Download Blob Artifacts - inputs: - buildType: specific - buildVersionToDownload: specific - project: $(AzDOProjectName) - pipeline: $(AzDOPipelineId) - buildId: $(AzDOBuildId) - artifactName: BlobArtifacts - checkDownloadedFiles: true - - - task: PowerShell@2 - displayName: Validate - inputs: - filePath: $(Build.SourcesDirectory)/eng/common/post-build/sourcelink-validation.ps1 - arguments: -InputPath $(Build.ArtifactStagingDirectory)/BlobArtifacts/ - -ExtractPath $(Agent.BuildDirectory)/Extract/ - -GHRepoName $(Build.Repository.Name) - -GHCommit $(Build.SourceVersion) - -SourcelinkCliVersion $(SourceLinkCLIVersion) - continueOnError: true - -- ${{ if ne(parameters.publishAssetsImmediately, 'true') }}: - - stage: publish_using_darc - ${{ if or(eq(parameters.enableNugetValidation, 'true'), eq(parameters.enableSigningValidation, 'true'), eq(parameters.enableSourceLinkValidation, 'true'), eq(parameters.SDLValidationParameters.enable, 'true')) }}: - dependsOn: ${{ parameters.publishDependsOn }} - ${{ else }}: - dependsOn: ${{ parameters.validateDependsOn }} - displayName: Publish using Darc - variables: - - template: common-variables.yml - - template: /eng/common/templates-official/variables/pool-providers.yml - jobs: - - job: - displayName: Publish Using Darc - timeoutInMinutes: 120 - pool: - # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) - ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: - name: AzurePipelines-EO - image: 1ESPT-Windows2022 - demands: Cmd - os: windows - # If it's not devdiv, it's dnceng - ${{ else }}: - name: NetCore1ESPool-Publishing-Internal - image: windows.vs2019.amd64 - os: windows - steps: - - template: setup-maestro-vars.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - - - task: NuGetAuthenticate@1 +- template: /eng/common/core-templates/post-build/post-build.yml + parameters: + # Specifies whether to use 1ES + is1ESPipeline: true - - task: AzureCLI@2 - displayName: Publish Using Darc - inputs: - azureSubscription: "Darc: Maestro Production" - scriptType: ps - scriptLocation: scriptPath - scriptPath: $(Build.SourcesDirectory)/eng/common/post-build/publish-using-darc.ps1 - arguments: -BuildId $(BARBuildId) - -PublishingInfraVersion ${{ parameters.publishingInfraVersion }} - -AzdoToken '$(publishing-dnceng-devdiv-code-r-build-re)' - -WaitPublishingFinish true - -ArtifactsPublishingAdditionalParameters '${{ parameters.artifactsPublishingAdditionalParameters }}' - -SymbolPublishingAdditionalParameters '${{ parameters.symbolPublishingAdditionalParameters }}' + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates-official/post-build/setup-maestro-vars.yml b/eng/common/templates-official/post-build/setup-maestro-vars.yml index 0c87f149a4a..024397d8786 100644 --- a/eng/common/templates-official/post-build/setup-maestro-vars.yml +++ b/eng/common/templates-official/post-build/setup-maestro-vars.yml @@ -1,70 +1,8 @@ -parameters: - BARBuildId: '' - PromoteToChannelIds: '' - steps: - - ${{ if eq(coalesce(parameters.PromoteToChannelIds, 0), 0) }}: - - task: DownloadBuildArtifacts@0 - displayName: Download Release Configs - inputs: - buildType: current - artifactName: ReleaseConfigs - checkDownloadedFiles: true - - - task: PowerShell@2 - name: setReleaseVars - displayName: Set Release Configs Vars - inputs: - targetType: inline - pwsh: true - script: | - try { - if (!$Env:PromoteToMaestroChannels -or $Env:PromoteToMaestroChannels.Trim() -eq '') { - $Content = Get-Content $(Build.StagingDirectory)/ReleaseConfigs/ReleaseConfigs.txt - - $BarId = $Content | Select -Index 0 - $Channels = $Content | Select -Index 1 - $IsStableBuild = $Content | Select -Index 2 - - $AzureDevOpsProject = $Env:System_TeamProject - $AzureDevOpsBuildDefinitionId = $Env:System_DefinitionId - $AzureDevOpsBuildId = $Env:Build_BuildId - } - else { - $buildApiEndpoint = "${Env:MaestroApiEndPoint}/api/builds/${Env:BARBuildId}?api-version=${Env:MaestroApiVersion}" - - $apiHeaders = New-Object 'System.Collections.Generic.Dictionary[[String],[String]]' - $apiHeaders.Add('Accept', 'application/json') - $apiHeaders.Add('Authorization',"Bearer ${Env:MAESTRO_API_TOKEN}") - - $buildInfo = try { Invoke-WebRequest -Method Get -Uri $buildApiEndpoint -Headers $apiHeaders | ConvertFrom-Json } catch { Write-Host "Error: $_" } - - $BarId = $Env:BARBuildId - $Channels = $Env:PromoteToMaestroChannels -split "," - $Channels = $Channels -join "][" - $Channels = "[$Channels]" - - $IsStableBuild = $buildInfo.stable - $AzureDevOpsProject = $buildInfo.azureDevOpsProject - $AzureDevOpsBuildDefinitionId = $buildInfo.azureDevOpsBuildDefinitionId - $AzureDevOpsBuildId = $buildInfo.azureDevOpsBuildId - } - - Write-Host "##vso[task.setvariable variable=BARBuildId]$BarId" - Write-Host "##vso[task.setvariable variable=TargetChannels]$Channels" - Write-Host "##vso[task.setvariable variable=IsStableBuild]$IsStableBuild" +- template: /eng/common/core-templates/post-build/setup-maestro-vars.yml + parameters: + # Specifies whether to use 1ES + is1ESPipeline: true - Write-Host "##vso[task.setvariable variable=AzDOProjectName]$AzureDevOpsProject" - Write-Host "##vso[task.setvariable variable=AzDOPipelineId]$AzureDevOpsBuildDefinitionId" - Write-Host "##vso[task.setvariable variable=AzDOBuildId]$AzureDevOpsBuildId" - } - catch { - Write-Host $_ - Write-Host $_.Exception - Write-Host $_.ScriptStackTrace - exit 1 - } - env: - MAESTRO_API_TOKEN: $(MaestroApiAccessToken) - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToMaestroChannels: ${{ parameters.PromoteToChannelIds }} + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} \ No newline at end of file diff --git a/eng/common/templates-official/post-build/trigger-subscription.yml b/eng/common/templates-official/post-build/trigger-subscription.yml deleted file mode 100644 index da669030daf..00000000000 --- a/eng/common/templates-official/post-build/trigger-subscription.yml +++ /dev/null @@ -1,13 +0,0 @@ -parameters: - ChannelId: 0 - -steps: -- task: PowerShell@2 - displayName: Triggering subscriptions - inputs: - filePath: $(Build.SourcesDirectory)/eng/common/post-build/trigger-subscriptions.ps1 - arguments: -SourceRepo $(Build.Repository.Uri) - -ChannelId ${{ parameters.ChannelId }} - -MaestroApiAccessToken $(MaestroAccessToken) - -MaestroApiEndPoint $(MaestroApiEndPoint) - -MaestroApiVersion $(MaestroApiVersion) diff --git a/eng/common/templates-official/steps/add-build-to-channel.yml b/eng/common/templates-official/steps/add-build-to-channel.yml deleted file mode 100644 index f67a210d62f..00000000000 --- a/eng/common/templates-official/steps/add-build-to-channel.yml +++ /dev/null @@ -1,13 +0,0 @@ -parameters: - ChannelId: 0 - -steps: -- task: PowerShell@2 - displayName: Add Build to Channel - inputs: - filePath: $(Build.SourcesDirectory)/eng/common/post-build/add-build-to-channel.ps1 - arguments: -BuildId $(BARBuildId) - -ChannelId ${{ parameters.ChannelId }} - -MaestroApiAccessToken $(MaestroApiAccessToken) - -MaestroApiEndPoint $(MaestroApiEndPoint) - -MaestroApiVersion $(MaestroApiVersion) diff --git a/eng/common/templates-official/steps/build-reason.yml b/eng/common/templates-official/steps/build-reason.yml deleted file mode 100644 index eba58109b52..00000000000 --- a/eng/common/templates-official/steps/build-reason.yml +++ /dev/null @@ -1,12 +0,0 @@ -# build-reason.yml -# Description: runs steps if build.reason condition is valid. conditions is a string of valid build reasons -# to include steps (',' separated). -parameters: - conditions: '' - steps: [] - -steps: - - ${{ if and( not(startsWith(parameters.conditions, 'not')), contains(parameters.conditions, variables['build.reason'])) }}: - - ${{ parameters.steps }} - - ${{ if and( startsWith(parameters.conditions, 'not'), not(contains(parameters.conditions, variables['build.reason']))) }}: - - ${{ parameters.steps }} diff --git a/eng/common/templates-official/steps/component-governance.yml b/eng/common/templates-official/steps/component-governance.yml index cbba0596709..30bb3985ca2 100644 --- a/eng/common/templates-official/steps/component-governance.yml +++ b/eng/common/templates-official/steps/component-governance.yml @@ -1,13 +1,7 @@ -parameters: - disableComponentGovernance: false - componentGovernanceIgnoreDirectories: '' - steps: -- ${{ if eq(parameters.disableComponentGovernance, 'true') }}: - - script: echo "##vso[task.setvariable variable=skipComponentGovernanceDetection]true" - displayName: Set skipComponentGovernanceDetection variable -- ${{ if ne(parameters.disableComponentGovernance, 'true') }}: - - task: ComponentGovernanceComponentDetection@0 - continueOnError: true - inputs: - ignoreDirectories: ${{ parameters.componentGovernanceIgnoreDirectories }} \ No newline at end of file +- template: /eng/common/core-templates/steps/component-governance.yml + parameters: + is1ESPipeline: true + + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates-official/steps/enable-internal-runtimes.yml b/eng/common/templates-official/steps/enable-internal-runtimes.yml index 93a8394a666..f9dd238c6cd 100644 --- a/eng/common/templates-official/steps/enable-internal-runtimes.yml +++ b/eng/common/templates-official/steps/enable-internal-runtimes.yml @@ -1,28 +1,9 @@ # Obtains internal runtime download credentials and populates the 'dotnetbuilds-internal-container-read-token-base64' # variable with the base64-encoded SAS token, by default - -parameters: -- name: federatedServiceConnection - type: string - default: 'dotnetbuilds-internal-read' -- name: outputVariableName - type: string - default: 'dotnetbuilds-internal-container-read-token-base64' -- name: expiryInHours - type: number - default: 1 -- name: base64Encode - type: boolean - default: true - steps: -- ${{ if ne(variables['System.TeamProject'], 'public') }}: - - template: /eng/common/templates-official/steps/get-delegation-sas.yml - parameters: - federatedServiceConnection: ${{ parameters.federatedServiceConnection }} - outputVariableName: ${{ parameters.outputVariableName }} - expiryInHours: ${{ parameters.expiryInHours }} - base64Encode: ${{ parameters.base64Encode }} - storageAccount: dotnetbuilds - container: internal - permissions: rl +- template: /eng/common/core-templates/steps/enable-internal-runtimes.yml + parameters: + is1ESPipeline: true + + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates-official/steps/enable-internal-sources.yml b/eng/common/templates-official/steps/enable-internal-sources.yml new file mode 100644 index 00000000000..e6d57182284 --- /dev/null +++ b/eng/common/templates-official/steps/enable-internal-sources.yml @@ -0,0 +1,7 @@ +steps: +- template: /eng/common/core-templates/steps/enable-internal-sources.yml + parameters: + is1ESPipeline: true + + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} \ No newline at end of file diff --git a/eng/common/templates-official/steps/execute-codeql.yml b/eng/common/templates-official/steps/execute-codeql.yml deleted file mode 100644 index 9b4a5ffa30a..00000000000 --- a/eng/common/templates-official/steps/execute-codeql.yml +++ /dev/null @@ -1,32 +0,0 @@ -parameters: - # Language that should be analyzed. Defaults to csharp - language: csharp - # Build Commands - buildCommands: '' - overrideParameters: '' # Optional: to override values for parameters. - additionalParameters: '' # Optional: parameters that need user specific values eg: '-SourceToolsList @("abc","def") -ArtifactToolsList @("ghi","jkl")' - # Optional: if specified, restore and use this version of Guardian instead of the default. - overrideGuardianVersion: '' - # Optional: if true, publish the '.gdn' folder as a pipeline artifact. This can help with in-depth - # diagnosis of problems with specific tool configurations. - publishGuardianDirectoryToPipeline: false - # The script to run to execute all SDL tools. Use this if you want to use a script to define SDL - # parameters rather than relying on YAML. It may be better to use a local script, because you can - # reproduce results locally without piecing together a command based on the YAML. - executeAllSdlToolsScript: 'eng/common/sdl/execute-all-sdl-tools.ps1' - # There is some sort of bug (has been reported) in Azure DevOps where if this parameter is named - # 'continueOnError', the parameter value is not correctly picked up. - # This can also be remedied by the caller (post-build.yml) if it does not use a nested parameter - # optional: determines whether to continue the build if the step errors; - sdlContinueOnError: false - -steps: -- template: /eng/common/templates-official/steps/execute-sdl.yml - parameters: - overrideGuardianVersion: ${{ parameters.overrideGuardianVersion }} - executeAllSdlToolsScript: ${{ parameters.executeAllSdlToolsScript }} - overrideParameters: ${{ parameters.overrideParameters }} - additionalParameters: '${{ parameters.additionalParameters }} - -CodeQLAdditionalRunConfigParams @("BuildCommands < ${{ parameters.buildCommands }}", "Language < ${{ parameters.language }}")' - publishGuardianDirectoryToPipeline: ${{ parameters.publishGuardianDirectoryToPipeline }} - sdlContinueOnError: ${{ parameters.sdlContinueOnError }} \ No newline at end of file diff --git a/eng/common/templates-official/steps/execute-sdl.yml b/eng/common/templates-official/steps/execute-sdl.yml deleted file mode 100644 index 07426fde05d..00000000000 --- a/eng/common/templates-official/steps/execute-sdl.yml +++ /dev/null @@ -1,88 +0,0 @@ -parameters: - overrideGuardianVersion: '' - executeAllSdlToolsScript: '' - overrideParameters: '' - additionalParameters: '' - publishGuardianDirectoryToPipeline: false - sdlContinueOnError: false - condition: '' - -steps: -- task: NuGetAuthenticate@1 - inputs: - nuGetServiceConnections: GuardianConnect - -- task: NuGetToolInstaller@1 - displayName: 'Install NuGet.exe' - -- ${{ if ne(parameters.overrideGuardianVersion, '') }}: - - pwsh: | - Set-Location -Path $(Build.SourcesDirectory)\eng\common\sdl - . .\sdl.ps1 - $guardianCliLocation = Install-Gdn -Path $(Build.SourcesDirectory)\.artifacts -Version ${{ parameters.overrideGuardianVersion }} - Write-Host "##vso[task.setvariable variable=GuardianCliLocation]$guardianCliLocation" - displayName: Install Guardian (Overridden) - -- ${{ if eq(parameters.overrideGuardianVersion, '') }}: - - pwsh: | - Set-Location -Path $(Build.SourcesDirectory)\eng\common\sdl - . .\sdl.ps1 - $guardianCliLocation = Install-Gdn -Path $(Build.SourcesDirectory)\.artifacts - Write-Host "##vso[task.setvariable variable=GuardianCliLocation]$guardianCliLocation" - displayName: Install Guardian - -- ${{ if ne(parameters.overrideParameters, '') }}: - - powershell: ${{ parameters.executeAllSdlToolsScript }} ${{ parameters.overrideParameters }} - displayName: Execute SDL (Overridden) - continueOnError: ${{ parameters.sdlContinueOnError }} - condition: ${{ parameters.condition }} - -- ${{ if eq(parameters.overrideParameters, '') }}: - - powershell: ${{ parameters.executeAllSdlToolsScript }} - -GuardianCliLocation $(GuardianCliLocation) - -NugetPackageDirectory $(Build.SourcesDirectory)\.packages - -AzureDevOpsAccessToken $(dn-bot-dotnet-build-rw-code-rw) - ${{ parameters.additionalParameters }} - displayName: Execute SDL - continueOnError: ${{ parameters.sdlContinueOnError }} - condition: ${{ parameters.condition }} - -- ${{ if ne(parameters.publishGuardianDirectoryToPipeline, 'false') }}: - # We want to publish the Guardian results and configuration for easy diagnosis. However, the - # '.gdn' dir is a mix of configuration, results, extracted dependencies, and Guardian default - # tooling files. Some of these files are large and aren't useful during an investigation, so - # exclude them by simply deleting them before publishing. (As of writing, there is no documented - # way to selectively exclude a dir from the pipeline artifact publish task.) - - task: DeleteFiles@1 - displayName: Delete Guardian dependencies to avoid uploading - inputs: - SourceFolder: $(Agent.BuildDirectory)/.gdn - Contents: | - c - i - condition: succeededOrFailed() - - - publish: $(Agent.BuildDirectory)/.gdn - artifact: GuardianConfiguration - displayName: Publish GuardianConfiguration - condition: succeededOrFailed() - - # Publish the SARIF files in a container named CodeAnalysisLogs to enable integration - # with the "SARIF SAST Scans Tab" Azure DevOps extension - - task: CopyFiles@2 - displayName: Copy SARIF files - inputs: - flattenFolders: true - sourceFolder: $(Agent.BuildDirectory)/.gdn/rc/ - contents: '**/*.sarif' - targetFolder: $(Build.SourcesDirectory)/CodeAnalysisLogs - condition: succeededOrFailed() - - # Use PublishBuildArtifacts because the SARIF extension only checks this case - # see microsoft/sarif-azuredevops-extension#4 - - task: PublishBuildArtifacts@1 - displayName: Publish SARIF files to CodeAnalysisLogs container - inputs: - pathToPublish: $(Build.SourcesDirectory)/CodeAnalysisLogs - artifactName: CodeAnalysisLogs - condition: succeededOrFailed() \ No newline at end of file diff --git a/eng/common/templates-official/steps/generate-sbom.yml b/eng/common/templates-official/steps/generate-sbom.yml index 1bf43bf807a..9a89a4706d9 100644 --- a/eng/common/templates-official/steps/generate-sbom.yml +++ b/eng/common/templates-official/steps/generate-sbom.yml @@ -1,48 +1,7 @@ -# BuildDropPath - The root folder of the drop directory for which the manifest file will be generated. -# PackageName - The name of the package this SBOM represents. -# PackageVersion - The version of the package this SBOM represents. -# ManifestDirPath - The path of the directory where the generated manifest files will be placed -# IgnoreDirectories - Directories to ignore for SBOM generation. This will be passed through to the CG component detector. - -parameters: - PackageVersion: 8.0.0 - BuildDropPath: '$(Build.SourcesDirectory)/artifacts' - PackageName: '.NET' - ManifestDirPath: $(Build.ArtifactStagingDirectory)/sbom - IgnoreDirectories: '' - sbomContinueOnError: true - steps: -- task: PowerShell@2 - displayName: Prep for SBOM generation in (Non-linux) - condition: or(eq(variables['Agent.Os'], 'Windows_NT'), eq(variables['Agent.Os'], 'Darwin')) - inputs: - filePath: ./eng/common/generate-sbom-prep.ps1 - arguments: ${{parameters.manifestDirPath}} - -# Chmodding is a workaround for https://github.com/dotnet/arcade/issues/8461 -- script: | - chmod +x ./eng/common/generate-sbom-prep.sh - ./eng/common/generate-sbom-prep.sh ${{parameters.manifestDirPath}} - displayName: Prep for SBOM generation in (Linux) - condition: eq(variables['Agent.Os'], 'Linux') - continueOnError: ${{ parameters.sbomContinueOnError }} - -- task: AzureArtifacts.manifest-generator-task.manifest-generator-task.ManifestGeneratorTask@0 - displayName: 'Generate SBOM manifest' - continueOnError: ${{ parameters.sbomContinueOnError }} - inputs: - PackageName: ${{ parameters.packageName }} - BuildDropPath: ${{ parameters.buildDropPath }} - PackageVersion: ${{ parameters.packageVersion }} - ManifestDirPath: ${{ parameters.manifestDirPath }} - ${{ if ne(parameters.IgnoreDirectories, '') }}: - AdditionalComponentDetectorArgs: '--IgnoreDirectories ${{ parameters.IgnoreDirectories }}' - -- task: 1ES.PublishPipelineArtifact@1 - displayName: Publish SBOM manifest - continueOnError: ${{parameters.sbomContinueOnError}} - inputs: - targetPath: '${{parameters.manifestDirPath}}' - artifactName: $(ARTIFACT_NAME) +- template: /eng/common/core-templates/steps/generate-sbom.yml + parameters: + is1ESPipeline: true + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates-official/steps/get-delegation-sas.yml b/eng/common/templates-official/steps/get-delegation-sas.yml index c0e8f91317f..c5a9c1f8275 100644 --- a/eng/common/templates-official/steps/get-delegation-sas.yml +++ b/eng/common/templates-official/steps/get-delegation-sas.yml @@ -1,43 +1,7 @@ -parameters: -- name: federatedServiceConnection - type: string -- name: outputVariableName - type: string -- name: expiryInHours - type: number - default: 1 -- name: base64Encode - type: boolean - default: false -- name: storageAccount - type: string -- name: container - type: string -- name: permissions - type: string - default: 'rl' - steps: -- task: AzureCLI@2 - displayName: 'Generate delegation SAS Token for ${{ parameters.storageAccount }}/${{ parameters.container }}' - inputs: - azureSubscription: ${{ parameters.federatedServiceConnection }} - scriptType: 'pscore' - scriptLocation: 'inlineScript' - inlineScript: | - # Calculate the expiration of the SAS token and convert to UTC - $expiry = (Get-Date).AddHours(${{ parameters.expiryInHours }}).ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ") - - $sas = az storage container generate-sas --account-name ${{ parameters.storageAccount }} --name ${{ parameters.container }} --permissions ${{ parameters.permissions }} --expiry $expiry --auth-mode login --as-user -o tsv - - if ($LASTEXITCODE -ne 0) { - Write-Error "Failed to generate SAS token." - exit 1 - } - - if ('${{ parameters.base64Encode }}' -eq 'true') { - $sas = [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($sas)) - } +- template: /eng/common/core-templates/steps/get-delegation-sas.yml + parameters: + is1ESPipeline: true - Write-Host "Setting '${{ parameters.outputVariableName }}' with the access token value" - Write-Host "##vso[task.setvariable variable=${{ parameters.outputVariableName }};issecret=true]$sas" + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates-official/steps/get-federated-access-token.yml b/eng/common/templates-official/steps/get-federated-access-token.yml index e3786cef6df..c8dcf6b8139 100644 --- a/eng/common/templates-official/steps/get-federated-access-token.yml +++ b/eng/common/templates-official/steps/get-federated-access-token.yml @@ -1,28 +1,7 @@ -parameters: -- name: federatedServiceConnection - type: string -- name: outputVariableName - type: string -# Resource to get a token for. Common values include: -# - '499b84ac-1321-427f-aa17-267ca6975798' for Azure DevOps -# - 'https://storage.azure.com/' for storage -# Defaults to Azure DevOps -- name: resource - type: string - default: '499b84ac-1321-427f-aa17-267ca6975798' - steps: -- task: AzureCLI@2 - displayName: 'Getting federated access token for feeds' - inputs: - azureSubscription: ${{ parameters.federatedServiceConnection }} - scriptType: 'pscore' - scriptLocation: 'inlineScript' - inlineScript: | - $accessToken = az account get-access-token --query accessToken --resource ${{ parameters.resource }} --output tsv - if ($LASTEXITCODE -ne 0) { - Write-Error "Failed to get access token for resource '${{ parameters.resource }}'" - exit 1 - } - Write-Host "Setting '${{ parameters.outputVariableName }}' with the access token value" - Write-Host "##vso[task.setvariable variable=${{ parameters.outputVariableName }};issecret=true]$accessToken" +- template: /eng/common/core-templates/steps/get-federated-access-token.yml + parameters: + is1ESPipeline: true + + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} \ No newline at end of file diff --git a/eng/common/templates-official/steps/publish-build-artifacts.yml b/eng/common/templates-official/steps/publish-build-artifacts.yml new file mode 100644 index 00000000000..100a3fc9849 --- /dev/null +++ b/eng/common/templates-official/steps/publish-build-artifacts.yml @@ -0,0 +1,41 @@ +parameters: +- name: displayName + type: string + default: 'Publish to Build Artifact' + +- name: condition + type: string + default: succeeded() + +- name: artifactName + type: string + +- name: pathToPublish + type: string + +- name: continueOnError + type: boolean + default: false + +- name: publishLocation + type: string + default: 'Container' + +- name: is1ESPipeline + type: boolean + default: true + +steps: +- ${{ if ne(parameters.is1ESPipeline, true) }}: + - 'eng/common/templates-official cannot be referenced from a non-1ES managed template': error +- task: 1ES.PublishBuildArtifacts@1 + displayName: ${{ parameters.displayName }} + condition: ${{ parameters.condition }} + ${{ if parameters.continueOnError }}: + continueOnError: ${{ parameters.continueOnError }} + inputs: + PublishLocation: ${{ parameters.publishLocation }} + PathtoPublish: ${{ parameters.pathToPublish }} + ${{ if parameters.artifactName }}: + ArtifactName: ${{ parameters.artifactName }} + diff --git a/eng/common/templates-official/steps/publish-logs.yml b/eng/common/templates-official/steps/publish-logs.yml index 04012fed182..579fd531e94 100644 --- a/eng/common/templates-official/steps/publish-logs.yml +++ b/eng/common/templates-official/steps/publish-logs.yml @@ -1,23 +1,7 @@ -parameters: - StageLabel: '' - JobLabel: '' - steps: -- task: Powershell@2 - displayName: Prepare Binlogs to Upload - inputs: - targetType: inline - script: | - New-Item -ItemType Directory $(Build.SourcesDirectory)/PostBuildLogs/${{parameters.StageLabel}}/${{parameters.JobLabel}}/ - Move-Item -Path $(Build.SourcesDirectory)/artifacts/log/Debug/* $(Build.SourcesDirectory)/PostBuildLogs/${{parameters.StageLabel}}/${{parameters.JobLabel}}/ - continueOnError: true - condition: always() +- template: /eng/common/core-templates/steps/publish-logs.yml + parameters: + is1ESPipeline: true -- task: 1ES.PublishBuildArtifacts@1 - displayName: Publish Logs - inputs: - PathtoPublish: '$(Build.SourcesDirectory)/PostBuildLogs' - PublishLocation: Container - ArtifactName: PostBuildLogs - continueOnError: true - condition: always() + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates-official/steps/publish-pipeline-artifacts.yml b/eng/common/templates-official/steps/publish-pipeline-artifacts.yml new file mode 100644 index 00000000000..172f9f0fdc9 --- /dev/null +++ b/eng/common/templates-official/steps/publish-pipeline-artifacts.yml @@ -0,0 +1,28 @@ +parameters: +- name: is1ESPipeline + type: boolean + default: true + +- name: args + type: object + default: {} + +steps: +- ${{ if ne(parameters.is1ESPipeline, true) }}: + - 'eng/common/templates-official cannot be referenced from a non-1ES managed template': error +- task: 1ES.PublishPipelineArtifact@1 + displayName: ${{ coalesce(parameters.args.displayName, 'Publish to Build Artifact') }} + ${{ if parameters.args.condition }}: + condition: ${{ parameters.args.condition }} + ${{ else }}: + condition: succeeded() + ${{ if parameters.args.continueOnError }}: + continueOnError: ${{ parameters.args.continueOnError }} + inputs: + targetPath: ${{ parameters.args.targetPath }} + ${{ if parameters.args.artifactName }}: + artifactName: ${{ parameters.args.artifactName }} + ${{ if parameters.args.properties }}: + properties: ${{ parameters.args.properties }} + ${{ if parameters.args.sbomEnabled }}: + sbomEnabled: ${{ parameters.args.sbomEnabled }} diff --git a/eng/common/templates-official/steps/retain-build.yml b/eng/common/templates-official/steps/retain-build.yml index 83d97a26a01..5594551508a 100644 --- a/eng/common/templates-official/steps/retain-build.yml +++ b/eng/common/templates-official/steps/retain-build.yml @@ -1,28 +1,7 @@ -parameters: - # Optional azure devops PAT with build execute permissions for the build's organization, - # only needed if the build that should be retained ran on a different organization than - # the pipeline where this template is executing from - Token: '' - # Optional BuildId to retain, defaults to the current running build - BuildId: '' - # Azure devops Organization URI for the build in the https://dev.azure.com/ format. - # Defaults to the organization the current pipeline is running on - AzdoOrgUri: '$(System.CollectionUri)' - # Azure devops project for the build. Defaults to the project the current pipeline is running on - AzdoProject: '$(System.TeamProject)' - steps: - - task: powershell@2 - inputs: - targetType: 'filePath' - filePath: eng/common/retain-build.ps1 - pwsh: true - arguments: > - -AzdoOrgUri: ${{parameters.AzdoOrgUri}} - -AzdoProject ${{parameters.AzdoProject}} - -Token ${{coalesce(parameters.Token, '$env:SYSTEM_ACCESSTOKEN') }} - -BuildId ${{coalesce(parameters.BuildId, '$env:BUILD_ID')}} - displayName: Enable permanent build retention - env: - SYSTEM_ACCESSTOKEN: $(System.AccessToken) - BUILD_ID: $(Build.BuildId) \ No newline at end of file +- template: /eng/common/core-templates/steps/retain-build.yml + parameters: + is1ESPipeline: true + + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates-official/steps/send-to-helix.yml b/eng/common/templates-official/steps/send-to-helix.yml index 3eb7e2d5f84..6500f21bf84 100644 --- a/eng/common/templates-official/steps/send-to-helix.yml +++ b/eng/common/templates-official/steps/send-to-helix.yml @@ -1,91 +1,7 @@ -# Please remember to update the documentation if you make changes to these parameters! -parameters: - HelixSource: 'pr/default' # required -- sources must start with pr/, official/, prodcon/, or agent/ - HelixType: 'tests/default/' # required -- Helix telemetry which identifies what type of data this is; should include "test" for clarity and must end in '/' - HelixBuild: $(Build.BuildNumber) # required -- the build number Helix will use to identify this -- automatically set to the AzDO build number - HelixTargetQueues: '' # required -- semicolon-delimited list of Helix queues to test on; see https://helix.dot.net/ for a list of queues - HelixAccessToken: '' # required -- access token to make Helix API requests; should be provided by the appropriate variable group - HelixConfiguration: '' # optional -- additional property attached to a job - HelixPreCommands: '' # optional -- commands to run before Helix work item execution - HelixPostCommands: '' # optional -- commands to run after Helix work item execution - WorkItemDirectory: '' # optional -- a payload directory to zip up and send to Helix; requires WorkItemCommand; incompatible with XUnitProjects - WorkItemCommand: '' # optional -- a command to execute on the payload; requires WorkItemDirectory; incompatible with XUnitProjects - WorkItemTimeout: '' # optional -- a timeout in TimeSpan.Parse-ready value (e.g. 00:02:00) for the work item command; requires WorkItemDirectory; incompatible with XUnitProjects - CorrelationPayloadDirectory: '' # optional -- a directory to zip up and send to Helix as a correlation payload - XUnitProjects: '' # optional -- semicolon-delimited list of XUnitProjects to parse and send to Helix; requires XUnitRuntimeTargetFramework, XUnitPublishTargetFramework, XUnitRunnerVersion, and IncludeDotNetCli=true - XUnitWorkItemTimeout: '' # optional -- the workitem timeout in seconds for all workitems created from the xUnit projects specified by XUnitProjects - XUnitPublishTargetFramework: '' # optional -- framework to use to publish your xUnit projects - XUnitRuntimeTargetFramework: '' # optional -- framework to use for the xUnit console runner - XUnitRunnerVersion: '' # optional -- version of the xUnit nuget package you wish to use on Helix; required for XUnitProjects - IncludeDotNetCli: false # optional -- true will download a version of the .NET CLI onto the Helix machine as a correlation payload; requires DotNetCliPackageType and DotNetCliVersion - DotNetCliPackageType: '' # optional -- either 'sdk', 'runtime' or 'aspnetcore-runtime'; determines whether the sdk or runtime will be sent to Helix; see https://raw.githubusercontent.com/dotnet/core/main/release-notes/releases-index.json - DotNetCliVersion: '' # optional -- version of the CLI to send to Helix; based on this: https://raw.githubusercontent.com/dotnet/core/main/release-notes/releases-index.json - WaitForWorkItemCompletion: true # optional -- true will make the task wait until work items have been completed and fail the build if work items fail. False is "fire and forget." - IsExternal: false # [DEPRECATED] -- doesn't do anything, jobs are external if HelixAccessToken is empty and Creator is set - HelixBaseUri: 'https://helix.dot.net/' # optional -- sets the Helix API base URI (allows targeting https://helix.int-dot.net ) - Creator: '' # optional -- if the build is external, use this to specify who is sending the job - DisplayNamePrefix: 'Run Tests' # optional -- rename the beginning of the displayName of the steps in AzDO - condition: succeeded() # optional -- condition for step to execute; defaults to succeeded() - continueOnError: false # optional -- determines whether to continue the build if the step errors; defaults to false - steps: - - powershell: 'powershell "$env:BUILD_SOURCESDIRECTORY\eng\common\msbuild.ps1 $env:BUILD_SOURCESDIRECTORY\eng\common\helixpublish.proj /restore /p:TreatWarningsAsErrors=false /t:Test /bl:$env:BUILD_SOURCESDIRECTORY\artifacts\log\$env:BuildConfig\SendToHelix.binlog"' - displayName: ${{ parameters.DisplayNamePrefix }} (Windows) - env: - BuildConfig: $(_BuildConfig) - HelixSource: ${{ parameters.HelixSource }} - HelixType: ${{ parameters.HelixType }} - HelixBuild: ${{ parameters.HelixBuild }} - HelixConfiguration: ${{ parameters.HelixConfiguration }} - HelixTargetQueues: ${{ parameters.HelixTargetQueues }} - HelixAccessToken: ${{ parameters.HelixAccessToken }} - HelixPreCommands: ${{ parameters.HelixPreCommands }} - HelixPostCommands: ${{ parameters.HelixPostCommands }} - WorkItemDirectory: ${{ parameters.WorkItemDirectory }} - WorkItemCommand: ${{ parameters.WorkItemCommand }} - WorkItemTimeout: ${{ parameters.WorkItemTimeout }} - CorrelationPayloadDirectory: ${{ parameters.CorrelationPayloadDirectory }} - XUnitProjects: ${{ parameters.XUnitProjects }} - XUnitWorkItemTimeout: ${{ parameters.XUnitWorkItemTimeout }} - XUnitPublishTargetFramework: ${{ parameters.XUnitPublishTargetFramework }} - XUnitRuntimeTargetFramework: ${{ parameters.XUnitRuntimeTargetFramework }} - XUnitRunnerVersion: ${{ parameters.XUnitRunnerVersion }} - IncludeDotNetCli: ${{ parameters.IncludeDotNetCli }} - DotNetCliPackageType: ${{ parameters.DotNetCliPackageType }} - DotNetCliVersion: ${{ parameters.DotNetCliVersion }} - WaitForWorkItemCompletion: ${{ parameters.WaitForWorkItemCompletion }} - HelixBaseUri: ${{ parameters.HelixBaseUri }} - Creator: ${{ parameters.Creator }} - SYSTEM_ACCESSTOKEN: $(System.AccessToken) - condition: and(${{ parameters.condition }}, eq(variables['Agent.Os'], 'Windows_NT')) - continueOnError: ${{ parameters.continueOnError }} - - script: $BUILD_SOURCESDIRECTORY/eng/common/msbuild.sh $BUILD_SOURCESDIRECTORY/eng/common/helixpublish.proj /restore /p:TreatWarningsAsErrors=false /t:Test /bl:$BUILD_SOURCESDIRECTORY/artifacts/log/$BuildConfig/SendToHelix.binlog - displayName: ${{ parameters.DisplayNamePrefix }} (Unix) - env: - BuildConfig: $(_BuildConfig) - HelixSource: ${{ parameters.HelixSource }} - HelixType: ${{ parameters.HelixType }} - HelixBuild: ${{ parameters.HelixBuild }} - HelixConfiguration: ${{ parameters.HelixConfiguration }} - HelixTargetQueues: ${{ parameters.HelixTargetQueues }} - HelixAccessToken: ${{ parameters.HelixAccessToken }} - HelixPreCommands: ${{ parameters.HelixPreCommands }} - HelixPostCommands: ${{ parameters.HelixPostCommands }} - WorkItemDirectory: ${{ parameters.WorkItemDirectory }} - WorkItemCommand: ${{ parameters.WorkItemCommand }} - WorkItemTimeout: ${{ parameters.WorkItemTimeout }} - CorrelationPayloadDirectory: ${{ parameters.CorrelationPayloadDirectory }} - XUnitProjects: ${{ parameters.XUnitProjects }} - XUnitWorkItemTimeout: ${{ parameters.XUnitWorkItemTimeout }} - XUnitPublishTargetFramework: ${{ parameters.XUnitPublishTargetFramework }} - XUnitRuntimeTargetFramework: ${{ parameters.XUnitRuntimeTargetFramework }} - XUnitRunnerVersion: ${{ parameters.XUnitRunnerVersion }} - IncludeDotNetCli: ${{ parameters.IncludeDotNetCli }} - DotNetCliPackageType: ${{ parameters.DotNetCliPackageType }} - DotNetCliVersion: ${{ parameters.DotNetCliVersion }} - WaitForWorkItemCompletion: ${{ parameters.WaitForWorkItemCompletion }} - HelixBaseUri: ${{ parameters.HelixBaseUri }} - Creator: ${{ parameters.Creator }} - SYSTEM_ACCESSTOKEN: $(System.AccessToken) - condition: and(${{ parameters.condition }}, ne(variables['Agent.Os'], 'Windows_NT')) - continueOnError: ${{ parameters.continueOnError }} +- template: /eng/common/core-templates/steps/send-to-helix.yml + parameters: + is1ESPipeline: true + + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates-official/steps/source-build.yml b/eng/common/templates-official/steps/source-build.yml index 829f17c34d1..8f92c49e7b0 100644 --- a/eng/common/templates-official/steps/source-build.yml +++ b/eng/common/templates-official/steps/source-build.yml @@ -1,129 +1,7 @@ -parameters: - # This template adds arcade-powered source-build to CI. - - # This is a 'steps' template, and is intended for advanced scenarios where the existing build - # infra has a careful build methodology that must be followed. For example, a repo - # (dotnet/runtime) might choose to clone the GitHub repo only once and store it as a pipeline - # artifact for all subsequent jobs to use, to reduce dependence on a strong network connection to - # GitHub. Using this steps template leaves room for that infra to be included. - - # Defines the platform on which to run the steps. See 'eng/common/templates-official/job/source-build.yml' - # for details. The entire object is described in the 'job' template for simplicity, even though - # the usage of the properties on this object is split between the 'job' and 'steps' templates. - platform: {} - steps: -# Build. Keep it self-contained for simple reusability. (No source-build-specific job variables.) -- script: | - set -x - df -h - - # If building on the internal project, the artifact feeds variable may be available (usually only if needed) - # In that case, call the feed setup script to add internal feeds corresponding to public ones. - # In addition, add an msbuild argument to copy the WIP from the repo to the target build location. - # This is because SetupNuGetSources.sh will alter the current NuGet.config file, and we need to preserve those - # changes. - internalRestoreArgs= - if [ '$(dn-bot-dnceng-artifact-feeds-rw)' != '$''(dn-bot-dnceng-artifact-feeds-rw)' ]; then - # Temporarily work around https://github.com/dotnet/arcade/issues/7709 - chmod +x $(Build.SourcesDirectory)/eng/common/SetupNugetSources.sh - $(Build.SourcesDirectory)/eng/common/SetupNugetSources.sh $(Build.SourcesDirectory)/NuGet.config $(dn-bot-dnceng-artifact-feeds-rw) - internalRestoreArgs='/p:CopyWipIntoInnerSourceBuildRepo=true' - - # The 'Copy WIP' feature of source build uses git stash to apply changes from the original repo. - # This only works if there is a username/email configured, which won't be the case in most CI runs. - git config --get user.email - if [ $? -ne 0 ]; then - git config user.email dn-bot@microsoft.com - git config user.name dn-bot - fi - fi - - # If building on the internal project, the internal storage variable may be available (usually only if needed) - # In that case, add variables to allow the download of internal runtimes if the specified versions are not found - # in the default public locations. - internalRuntimeDownloadArgs= - if [ '$(dotnetbuilds-internal-container-read-token-base64)' != '$''(dotnetbuilds-internal-container-read-token-base64)' ]; then - internalRuntimeDownloadArgs='/p:DotNetRuntimeSourceFeed=https://dotnetbuilds.blob.core.windows.net/internal /p:DotNetRuntimeSourceFeedKey=$(dotnetbuilds-internal-container-read-token-base64) --runtimesourcefeed https://dotnetbuilds.blob.core.windows.net/internal --runtimesourcefeedkey $(dotnetbuilds-internal-container-read-token-base64)' - fi - - buildConfig=Release - # Check if AzDO substitutes in a build config from a variable, and use it if so. - if [ '$(_BuildConfig)' != '$''(_BuildConfig)' ]; then - buildConfig='$(_BuildConfig)' - fi - - officialBuildArgs= - if [ '${{ and(ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}' = 'True' ]; then - officialBuildArgs='/p:DotNetPublishUsingPipelines=true /p:OfficialBuildId=$(BUILD.BUILDNUMBER)' - fi - - targetRidArgs= - if [ '${{ parameters.platform.targetRID }}' != '' ]; then - targetRidArgs='/p:TargetRid=${{ parameters.platform.targetRID }}' - fi - - runtimeOsArgs= - if [ '${{ parameters.platform.runtimeOS }}' != '' ]; then - runtimeOsArgs='/p:RuntimeOS=${{ parameters.platform.runtimeOS }}' - fi - - baseOsArgs= - if [ '${{ parameters.platform.baseOS }}' != '' ]; then - baseOsArgs='/p:BaseOS=${{ parameters.platform.baseOS }}' - fi - - publishArgs= - if [ '${{ parameters.platform.skipPublishValidation }}' != 'true' ]; then - publishArgs='--publish' - fi - - assetManifestFileName=SourceBuild_RidSpecific.xml - if [ '${{ parameters.platform.name }}' != '' ]; then - assetManifestFileName=SourceBuild_${{ parameters.platform.name }}.xml - fi - - ${{ coalesce(parameters.platform.buildScript, './build.sh') }} --ci \ - --configuration $buildConfig \ - --restore --build --pack $publishArgs -bl \ - $officialBuildArgs \ - $internalRuntimeDownloadArgs \ - $internalRestoreArgs \ - $targetRidArgs \ - $runtimeOsArgs \ - $baseOsArgs \ - /p:SourceBuildNonPortable=${{ parameters.platform.nonPortable }} \ - /p:ArcadeBuildFromSource=true \ - /p:AssetManifestFileName=$assetManifestFileName - displayName: Build - -# Upload build logs for diagnosis. -- task: CopyFiles@2 - displayName: Prepare BuildLogs staging directory - inputs: - SourceFolder: '$(Build.SourcesDirectory)' - Contents: | - **/*.log - **/*.binlog - artifacts/source-build/self/prebuilt-report/** - TargetFolder: '$(Build.StagingDirectory)/BuildLogs' - CleanTargetFolder: true - continueOnError: true - condition: succeededOrFailed() - -- task: 1ES.PublishPipelineArtifact@1 - displayName: Publish BuildLogs - inputs: - targetPath: '$(Build.StagingDirectory)/BuildLogs' - artifactName: BuildLogs_SourceBuild_${{ parameters.platform.name }}_Attempt$(System.JobAttempt) - continueOnError: true - condition: succeededOrFailed() +- template: /eng/common/core-templates/steps/source-build.yml + parameters: + is1ESPipeline: true -# Manually inject component detection so that we can ignore the source build upstream cache, which contains -# a nupkg cache of input packages (a local feed). -# This path must match the upstream cache path in property 'CurrentRepoSourceBuiltNupkgCacheDir' -# in src\Microsoft.DotNet.Arcade.Sdk\tools\SourceBuild\SourceBuildArcade.targets -- task: ComponentGovernanceComponentDetection@0 - displayName: Component Detection (Exclude upstream cache) - inputs: - ignoreDirectories: '$(Build.SourcesDirectory)/artifacts/source-build/self/src/artifacts/obj/source-built-upstream-cache' + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates/job/execute-sdl.yml b/eng/common/templates/job/execute-sdl.yml deleted file mode 100644 index 7870f93bc17..00000000000 --- a/eng/common/templates/job/execute-sdl.yml +++ /dev/null @@ -1,139 +0,0 @@ -parameters: - enable: 'false' # Whether the SDL validation job should execute or not - overrideParameters: '' # Optional: to override values for parameters. - additionalParameters: '' # Optional: parameters that need user specific values eg: '-SourceToolsList @("abc","def") -ArtifactToolsList @("ghi","jkl")' - # Optional: if specified, restore and use this version of Guardian instead of the default. - overrideGuardianVersion: '' - # Optional: if true, publish the '.gdn' folder as a pipeline artifact. This can help with in-depth - # diagnosis of problems with specific tool configurations. - publishGuardianDirectoryToPipeline: false - # The script to run to execute all SDL tools. Use this if you want to use a script to define SDL - # parameters rather than relying on YAML. It may be better to use a local script, because you can - # reproduce results locally without piecing together a command based on the YAML. - executeAllSdlToolsScript: 'eng/common/sdl/execute-all-sdl-tools.ps1' - # There is some sort of bug (has been reported) in Azure DevOps where if this parameter is named - # 'continueOnError', the parameter value is not correctly picked up. - # This can also be remedied by the caller (post-build.yml) if it does not use a nested parameter - sdlContinueOnError: false # optional: determines whether to continue the build if the step errors; - # optional: determines if build artifacts should be downloaded. - downloadArtifacts: true - # optional: determines if this job should search the directory of downloaded artifacts for - # 'tar.gz' and 'zip' archive files and extract them before running SDL validation tasks. - extractArchiveArtifacts: false - dependsOn: '' # Optional: dependencies of the job - artifactNames: '' # Optional: patterns supplied to DownloadBuildArtifacts - # Usage: - # artifactNames: - # - 'BlobArtifacts' - # - 'Artifacts_Windows_NT_Release' - # Optional: download a list of pipeline artifacts. 'downloadArtifacts' controls build artifacts, - # not pipeline artifacts, so doesn't affect the use of this parameter. - pipelineArtifactNames: [] - -jobs: -- job: Run_SDL - dependsOn: ${{ parameters.dependsOn }} - displayName: Run SDL tool - condition: and(succeededOrFailed(), eq( ${{ parameters.enable }}, 'true')) - variables: - - group: DotNet-VSTS-Bot - - name: AzDOProjectName - value: ${{ parameters.AzDOProjectName }} - - name: AzDOPipelineId - value: ${{ parameters.AzDOPipelineId }} - - name: AzDOBuildId - value: ${{ parameters.AzDOBuildId }} - - template: /eng/common/templates/variables/sdl-variables.yml - - name: GuardianVersion - value: ${{ coalesce(parameters.overrideGuardianVersion, '$(DefaultGuardianVersion)') }} - - template: /eng/common/templates/variables/pool-providers.yml - pool: - # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) - ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: - name: VSEngSS-MicroBuild2022-1ES - demands: Cmd - # If it's not devdiv, it's dnceng - ${{ if ne(variables['System.TeamProject'], 'DevDiv') }}: - name: $(DncEngInternalBuildPool) - demands: ImageOverride -equals windows.vs2019.amd64 - steps: - - checkout: self - clean: true - - # If the template caller didn't provide an AzDO parameter, set them all up as Maestro vars. - - ${{ if not(and(parameters.AzDOProjectName, parameters.AzDOPipelineId, parameters.AzDOBuildId)) }}: - - template: /eng/common/templates/post-build/setup-maestro-vars.yml - - - ${{ if ne(parameters.downloadArtifacts, 'false')}}: - - ${{ if ne(parameters.artifactNames, '') }}: - - ${{ each artifactName in parameters.artifactNames }}: - - task: DownloadBuildArtifacts@0 - displayName: Download Build Artifacts - inputs: - buildType: specific - buildVersionToDownload: specific - project: $(AzDOProjectName) - pipeline: $(AzDOPipelineId) - buildId: $(AzDOBuildId) - artifactName: ${{ artifactName }} - downloadPath: $(Build.ArtifactStagingDirectory)\artifacts - checkDownloadedFiles: true - - ${{ if eq(parameters.artifactNames, '') }}: - - task: DownloadBuildArtifacts@0 - displayName: Download Build Artifacts - inputs: - buildType: specific - buildVersionToDownload: specific - project: $(AzDOProjectName) - pipeline: $(AzDOPipelineId) - buildId: $(AzDOBuildId) - downloadType: specific files - itemPattern: "**" - downloadPath: $(Build.ArtifactStagingDirectory)\artifacts - checkDownloadedFiles: true - - - ${{ each artifactName in parameters.pipelineArtifactNames }}: - - task: DownloadPipelineArtifact@2 - displayName: Download Pipeline Artifacts - inputs: - buildType: specific - buildVersionToDownload: specific - project: $(AzDOProjectName) - pipeline: $(AzDOPipelineId) - buildId: $(AzDOBuildId) - artifactName: ${{ artifactName }} - downloadPath: $(Build.ArtifactStagingDirectory)\artifacts - checkDownloadedFiles: true - - - powershell: eng/common/sdl/trim-assets-version.ps1 - -InputPath $(Build.ArtifactStagingDirectory)\artifacts - displayName: Trim the version from the NuGet packages - continueOnError: ${{ parameters.sdlContinueOnError }} - - - powershell: eng/common/sdl/extract-artifact-packages.ps1 - -InputPath $(Build.ArtifactStagingDirectory)\artifacts\BlobArtifacts - -ExtractPath $(Build.ArtifactStagingDirectory)\artifacts\BlobArtifacts - displayName: Extract Blob Artifacts - continueOnError: ${{ parameters.sdlContinueOnError }} - - - powershell: eng/common/sdl/extract-artifact-packages.ps1 - -InputPath $(Build.ArtifactStagingDirectory)\artifacts\PackageArtifacts - -ExtractPath $(Build.ArtifactStagingDirectory)\artifacts\PackageArtifacts - displayName: Extract Package Artifacts - continueOnError: ${{ parameters.sdlContinueOnError }} - - - ${{ if ne(parameters.extractArchiveArtifacts, 'false') }}: - - powershell: eng/common/sdl/extract-artifact-archives.ps1 - -InputPath $(Build.ArtifactStagingDirectory)\artifacts - -ExtractPath $(Build.ArtifactStagingDirectory)\artifacts - displayName: Extract Archive Artifacts - continueOnError: ${{ parameters.sdlContinueOnError }} - - - template: /eng/common/templates/steps/execute-sdl.yml - parameters: - overrideGuardianVersion: ${{ parameters.overrideGuardianVersion }} - executeAllSdlToolsScript: ${{ parameters.executeAllSdlToolsScript }} - overrideParameters: ${{ parameters.overrideParameters }} - additionalParameters: ${{ parameters.additionalParameters }} - publishGuardianDirectoryToPipeline: ${{ parameters.publishGuardianDirectoryToPipeline }} - sdlContinueOnError: ${{ parameters.sdlContinueOnError }} diff --git a/eng/common/templates/job/job.yml b/eng/common/templates/job/job.yml index 8ec5c4f2d9f..8da477dd69f 100644 --- a/eng/common/templates/job/job.yml +++ b/eng/common/templates/job/job.yml @@ -1,259 +1,89 @@ -# Internal resources (telemetry, microbuild) can only be accessed from non-public projects, -# and some (Microbuild) should only be applied to non-PR cases for internal builds. - -parameters: -# Job schema parameters - https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=vsts&tabs=schema#job - cancelTimeoutInMinutes: '' - condition: '' - container: '' - continueOnError: false - dependsOn: '' - displayName: '' - pool: '' - steps: [] - strategy: '' - timeoutInMinutes: '' - variables: [] - workspace: '' - templateContext: '' - -# Job base template specific parameters - # See schema documentation - https://github.com/dotnet/arcade/blob/master/Documentation/AzureDevOps/TemplateSchema.md - artifacts: '' - enableMicrobuild: false +parameters: enablePublishBuildArtifacts: false - enablePublishBuildAssets: false - enablePublishTestResults: false - enablePublishUsingPipelines: false - enableBuildRetry: false disableComponentGovernance: '' componentGovernanceIgnoreDirectories: '' - mergeTestResults: false - testRunTitle: '' - testResultsFormat: '' - name: '' - preSteps: [] - runAsPublic: false # Sbom related params enableSbom: true - PackageVersion: 7.0.0 + PackageVersion: 9.0.0 BuildDropPath: '$(Build.SourcesDirectory)/artifacts' jobs: -- job: ${{ parameters.name }} - - ${{ if ne(parameters.cancelTimeoutInMinutes, '') }}: - cancelTimeoutInMinutes: ${{ parameters.cancelTimeoutInMinutes }} - - ${{ if ne(parameters.condition, '') }}: - condition: ${{ parameters.condition }} - - ${{ if ne(parameters.container, '') }}: - container: ${{ parameters.container }} - - ${{ if ne(parameters.continueOnError, '') }}: - continueOnError: ${{ parameters.continueOnError }} - - ${{ if ne(parameters.dependsOn, '') }}: - dependsOn: ${{ parameters.dependsOn }} - - ${{ if ne(parameters.displayName, '') }}: - displayName: ${{ parameters.displayName }} - - ${{ if ne(parameters.pool, '') }}: - pool: ${{ parameters.pool }} - - ${{ if ne(parameters.strategy, '') }}: - strategy: ${{ parameters.strategy }} - - ${{ if ne(parameters.timeoutInMinutes, '') }}: - timeoutInMinutes: ${{ parameters.timeoutInMinutes }} - - ${{ if ne(parameters.templateContext, '') }}: - templateContext: ${{ parameters.templateContext }} - - variables: - - ${{ if ne(parameters.enableTelemetry, 'false') }}: - - name: DOTNET_CLI_TELEMETRY_PROFILE - value: '$(Build.Repository.Uri)' - - ${{ if eq(parameters.enableRichCodeNavigation, 'true') }}: - - name: EnableRichCodeNavigation - value: 'true' - # Retry signature validation up to three times, waiting 2 seconds between attempts. - # See https://learn.microsoft.com/en-us/nuget/reference/errors-and-warnings/nu3028#retry-untrusted-root-failures - - name: NUGET_EXPERIMENTAL_CHAIN_BUILD_RETRY_POLICY - value: 3,2000 - - ${{ each variable in parameters.variables }}: - # handle name-value variable syntax - # example: - # - name: [key] - # value: [value] - - ${{ if ne(variable.name, '') }}: - - name: ${{ variable.name }} - value: ${{ variable.value }} - - # handle variable groups - - ${{ if ne(variable.group, '') }}: - - group: ${{ variable.group }} - - # handle template variable syntax - # example: - # - template: path/to/template.yml - # parameters: - # [key]: [value] - - ${{ if ne(variable.template, '') }}: - - template: ${{ variable.template }} - ${{ if ne(variable.parameters, '') }}: - parameters: ${{ variable.parameters }} - - # handle key-value variable syntax. - # example: - # - [key]: [value] - - ${{ if and(eq(variable.name, ''), eq(variable.group, ''), eq(variable.template, '')) }}: - - ${{ each pair in variable }}: - - name: ${{ pair.key }} - value: ${{ pair.value }} - - # DotNet-HelixApi-Access provides 'HelixApiAccessToken' for internal builds - - ${{ if and(eq(parameters.enableTelemetry, 'true'), eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - - group: DotNet-HelixApi-Access - - ${{ if ne(parameters.workspace, '') }}: - workspace: ${{ parameters.workspace }} - - steps: - - ${{ if ne(parameters.preSteps, '') }}: - - ${{ each preStep in parameters.preSteps }}: - - ${{ preStep }} - - - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - - ${{ if eq(parameters.enableMicrobuild, 'true') }}: - - task: MicroBuildSigningPlugin@3 - displayName: Install MicroBuild plugin - inputs: - signType: $(_SignType) - zipSources: false - feedSource: https://dnceng.pkgs.visualstudio.com/_packaging/MicroBuildToolset/nuget/v3/index.json - env: - TeamName: $(_TeamName) - continueOnError: ${{ parameters.continueOnError }} - condition: and(succeeded(), in(variables['_SignType'], 'real', 'test'), eq(variables['Agent.Os'], 'Windows_NT')) - - - ${{ if and(eq(parameters.runAsPublic, 'false'), eq(variables['System.TeamProject'], 'internal')) }}: - - task: NuGetAuthenticate@1 - - - ${{ if and(ne(parameters.artifacts.download, 'false'), ne(parameters.artifacts.download, '')) }}: - - task: DownloadPipelineArtifact@2 - inputs: - buildType: current - artifactName: ${{ coalesce(parameters.artifacts.download.name, 'Artifacts_$(Agent.OS)_$(_BuildConfig)') }} - targetPath: ${{ coalesce(parameters.artifacts.download.path, 'artifacts') }} - itemPattern: ${{ coalesce(parameters.artifacts.download.pattern, '**') }} - - - ${{ each step in parameters.steps }}: - - ${{ step }} - - - ${{ if eq(parameters.enableRichCodeNavigation, true) }}: - - task: RichCodeNavIndexer@0 - displayName: RichCodeNav Upload - inputs: - languages: ${{ coalesce(parameters.richCodeNavigationLanguage, 'csharp') }} - environment: ${{ coalesce(parameters.richCodeNavigationEnvironment, 'production') }} - richNavLogOutputDirectory: $(Build.SourcesDirectory)/artifacts/bin - uploadRichNavArtifacts: ${{ coalesce(parameters.richCodeNavigationUploadArtifacts, false) }} - continueOnError: true - - - template: /eng/common/templates/steps/component-governance.yml - parameters: - ${{ if eq(parameters.disableComponentGovernance, '') }}: - ${{ if and(ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest'), eq(parameters.runAsPublic, 'false'), or(startsWith(variables['Build.SourceBranch'], 'refs/heads/release/'), startsWith(variables['Build.SourceBranch'], 'refs/heads/dotnet/'), startsWith(variables['Build.SourceBranch'], 'refs/heads/microsoft/'), eq(variables['Build.SourceBranch'], 'refs/heads/main'))) }}: - disableComponentGovernance: false - ${{ else }}: - disableComponentGovernance: true - ${{ else }}: - disableComponentGovernance: ${{ parameters.disableComponentGovernance }} - componentGovernanceIgnoreDirectories: ${{ parameters.componentGovernanceIgnoreDirectories }} - - - ${{ if eq(parameters.enableMicrobuild, 'true') }}: - - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - - task: MicroBuildCleanup@1 - displayName: Execute Microbuild cleanup tasks - condition: and(always(), in(variables['_SignType'], 'real', 'test'), eq(variables['Agent.Os'], 'Windows_NT')) - continueOnError: ${{ parameters.continueOnError }} - env: - TeamName: $(_TeamName) - - - ${{ if ne(parameters.artifacts.publish, '') }}: - - ${{ if and(ne(parameters.artifacts.publish.artifacts, 'false'), ne(parameters.artifacts.publish.artifacts, '')) }}: - - task: CopyFiles@2 - displayName: Gather binaries for publish to artifacts - inputs: - SourceFolder: 'artifacts/bin' - Contents: '**' - TargetFolder: '$(Build.ArtifactStagingDirectory)/artifacts/bin' - - task: CopyFiles@2 - displayName: Gather packages for publish to artifacts - inputs: - SourceFolder: 'artifacts/packages' - Contents: '**' - TargetFolder: '$(Build.ArtifactStagingDirectory)/artifacts/packages' - - task: PublishBuildArtifacts@1 - displayName: Publish pipeline artifacts - inputs: - PathtoPublish: '$(Build.ArtifactStagingDirectory)/artifacts' - PublishLocation: Container - ArtifactName: ${{ coalesce(parameters.artifacts.publish.artifacts.name , 'Artifacts_$(Agent.Os)_$(_BuildConfig)') }} - continueOnError: true - condition: always() - - ${{ if and(ne(parameters.artifacts.publish.logs, 'false'), ne(parameters.artifacts.publish.logs, '')) }}: - - publish: artifacts/log - artifact: ${{ coalesce(parameters.artifacts.publish.logs.name, 'Logs_Build_$(Agent.Os)_$(_BuildConfig)') }} - displayName: Publish logs - continueOnError: true - condition: always() - - - ${{ if ne(parameters.enablePublishBuildArtifacts, 'false') }}: - - task: PublishBuildArtifacts@1 - displayName: Publish Logs - inputs: - PathtoPublish: '$(Build.SourcesDirectory)/artifacts/log/$(_BuildConfig)' - PublishLocation: Container - ArtifactName: ${{ coalesce(parameters.enablePublishBuildArtifacts.artifactName, '$(Agent.Os)_$(Agent.JobName)' ) }} - continueOnError: true - condition: always() - - - ${{ if or(and(eq(parameters.enablePublishTestResults, 'true'), eq(parameters.testResultsFormat, '')), eq(parameters.testResultsFormat, 'xunit')) }}: - - task: PublishTestResults@2 - displayName: Publish XUnit Test Results - inputs: - testResultsFormat: 'xUnit' - testResultsFiles: '*.xml' - searchFolder: '$(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig)' - testRunTitle: ${{ coalesce(parameters.testRunTitle, parameters.name, '$(System.JobName)') }}-xunit - mergeTestResults: ${{ parameters.mergeTestResults }} - continueOnError: true - condition: always() - - ${{ if or(and(eq(parameters.enablePublishTestResults, 'true'), eq(parameters.testResultsFormat, '')), eq(parameters.testResultsFormat, 'vstest')) }}: - - task: PublishTestResults@2 - displayName: Publish TRX Test Results - inputs: - testResultsFormat: 'VSTest' - testResultsFiles: '*.trx' - searchFolder: '$(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig)' - testRunTitle: ${{ coalesce(parameters.testRunTitle, parameters.name, '$(System.JobName)') }}-trx - mergeTestResults: ${{ parameters.mergeTestResults }} - continueOnError: true - condition: always() - - - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest'), eq(parameters.enableSbom, 'true')) }}: - - template: /eng/common/templates/steps/generate-sbom.yml - parameters: - PackageVersion: ${{ parameters.packageVersion}} - BuildDropPath: ${{ parameters.buildDropPath }} - IgnoreDirectories: ${{ parameters.componentGovernanceIgnoreDirectories }} - - - ${{ if eq(parameters.enableBuildRetry, 'true') }}: - - publish: $(Build.SourcesDirectory)\eng\common\BuildConfiguration - artifact: BuildConfiguration - displayName: Publish build retry configuration - continueOnError: true +- template: /eng/common/core-templates/job/job.yml + parameters: + is1ESPipeline: false + + ${{ each parameter in parameters }}: + ${{ if and(ne(parameter.key, 'steps'), ne(parameter.key, 'is1ESPipeline')) }}: + ${{ parameter.key }}: ${{ parameter.value }} + + steps: + - ${{ each step in parameters.steps }}: + - ${{ step }} + + componentGovernanceSteps: + - template: /eng/common/templates/steps/component-governance.yml + parameters: + ${{ if eq(parameters.disableComponentGovernance, '') }}: + ${{ if and(ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest'), eq(parameters.runAsPublic, 'false'), or(startsWith(variables['Build.SourceBranch'], 'refs/heads/release/'), startsWith(variables['Build.SourceBranch'], 'refs/heads/dotnet/'), startsWith(variables['Build.SourceBranch'], 'refs/heads/microsoft/'), eq(variables['Build.SourceBranch'], 'refs/heads/main'))) }}: + disableComponentGovernance: false + ${{ else }}: + disableComponentGovernance: true + ${{ else }}: + disableComponentGovernance: ${{ parameters.disableComponentGovernance }} + componentGovernanceIgnoreDirectories: ${{ parameters.componentGovernanceIgnoreDirectories }} + + - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest'), eq(parameters.enableSbom, 'true')) }}: + - template: /eng/common/templates/steps/generate-sbom.yml + parameters: + PackageVersion: ${{ parameters.packageVersion }} + BuildDropPath: ${{ parameters.buildDropPath }} + publishArtifacts: false + + + artifactPublishSteps: + - ${{ if ne(parameters.artifacts.publish, '') }}: + - ${{ if and(ne(parameters.artifacts.publish.artifacts, 'false'), ne(parameters.artifacts.publish.artifacts, '')) }}: + - template: /eng/common/core-templates/steps/publish-build-artifacts.yml + parameters: + is1ESPipeline: false + args: + displayName: Publish pipeline artifacts + pathToPublish: '$(Build.ArtifactStagingDirectory)/artifacts' + publishLocation: Container + artifactName: ${{ coalesce(parameters.artifacts.publish.artifacts.name , 'Artifacts_$(Agent.Os)_$(_BuildConfig)') }} + continueOnError: true + condition: always() + - ${{ if and(ne(parameters.artifacts.publish.logs, 'false'), ne(parameters.artifacts.publish.logs, '')) }}: + - template: /eng/common/core-templates/steps/publish-pipeline-artifacts.yml + parameters: + is1ESPipeline: false + args: + targetPath: '$(Build.ArtifactStagingDirectory)/artifacts/log' + artifactName: ${{ coalesce(parameters.artifacts.publish.logs.name, 'Logs_Build_$(Agent.Os)_$(_BuildConfig)') }} + displayName: 'Publish logs' + continueOnError: true + condition: always() + sbomEnabled: false # we don't need SBOM for logs + + - ${{ if ne(parameters.enablePublishBuildArtifacts, 'false') }}: + - template: /eng/common/core-templates/steps/publish-build-artifacts.yml + parameters: + is1ESPipeline: false + args: + displayName: Publish Logs + pathToPublish: '$(Build.ArtifactStagingDirectory)/artifacts/log/$(_BuildConfig)' + publishLocation: Container + artifactName: ${{ coalesce(parameters.enablePublishBuildArtifacts.artifactName, '$(Agent.Os)_$(Agent.JobName)' ) }} + continueOnError: true + condition: always() + + - ${{ if eq(parameters.enableBuildRetry, 'true') }}: + - template: /eng/common/core-templates/steps/publish-pipeline-artifacts.yml + parameters: + is1ESPipeline: false + args: + targetPath: '$(Build.SourcesDirectory)\eng\common\BuildConfiguration' + artifactName: 'BuildConfiguration' + displayName: 'Publish build retry configuration' + continueOnError: true + sbomEnabled: false # we don't need SBOM for BuildConfiguration diff --git a/eng/common/templates/job/onelocbuild.yml b/eng/common/templates/job/onelocbuild.yml index 60ab00c4de3..ff829dc4c70 100644 --- a/eng/common/templates/job/onelocbuild.yml +++ b/eng/common/templates/job/onelocbuild.yml @@ -1,109 +1,7 @@ -parameters: - # Optional: dependencies of the job - dependsOn: '' - - # Optional: A defined YAML pool - https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=vsts&tabs=schema#pool - pool: '' - - CeapexPat: $(dn-bot-ceapex-package-r) # PAT for the loc AzDO instance https://dev.azure.com/ceapex - GithubPat: $(BotAccount-dotnet-bot-repo-PAT) - - SourcesDirectory: $(Build.SourcesDirectory) - CreatePr: true - AutoCompletePr: false - ReusePr: true - UseLfLineEndings: true - UseCheckedInLocProjectJson: false - SkipLocProjectJsonGeneration: false - LanguageSet: VS_Main_Languages - LclSource: lclFilesInRepo - LclPackageId: '' - RepoType: gitHub - GitHubOrg: dotnet - MirrorRepo: '' - MirrorBranch: main - condition: '' - JobNameSuffix: '' - jobs: -- job: OneLocBuild${{ parameters.JobNameSuffix }} - - dependsOn: ${{ parameters.dependsOn }} - - displayName: OneLocBuild${{ parameters.JobNameSuffix }} - - variables: - - group: OneLocBuildVariables # Contains the CeapexPat and GithubPat - - name: _GenerateLocProjectArguments - value: -SourcesDirectory ${{ parameters.SourcesDirectory }} - -LanguageSet "${{ parameters.LanguageSet }}" - -CreateNeutralXlfs - - ${{ if eq(parameters.UseCheckedInLocProjectJson, 'true') }}: - - name: _GenerateLocProjectArguments - value: ${{ variables._GenerateLocProjectArguments }} -UseCheckedInLocProjectJson - - template: /eng/common/templates/variables/pool-providers.yml - - ${{ if ne(parameters.pool, '') }}: - pool: ${{ parameters.pool }} - ${{ if eq(parameters.pool, '') }}: - pool: - # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) - ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: - name: VSEngSS-MicroBuild2022-1ES - demands: Cmd - # If it's not devdiv, it's dnceng - ${{ if ne(variables['System.TeamProject'], 'DevDiv') }}: - name: $(DncEngInternalBuildPool) - demands: ImageOverride -equals windows.vs2019.amd64 - - steps: - - ${{ if ne(parameters.SkipLocProjectJsonGeneration, 'true') }}: - - task: Powershell@2 - inputs: - filePath: $(Build.SourcesDirectory)/eng/common/generate-locproject.ps1 - arguments: $(_GenerateLocProjectArguments) - displayName: Generate LocProject.json - condition: ${{ parameters.condition }} - - - task: OneLocBuild@2 - displayName: OneLocBuild - env: - SYSTEM_ACCESSTOKEN: $(System.AccessToken) - inputs: - locProj: eng/Localize/LocProject.json - outDir: $(Build.ArtifactStagingDirectory) - lclSource: ${{ parameters.LclSource }} - lclPackageId: ${{ parameters.LclPackageId }} - isCreatePrSelected: ${{ parameters.CreatePr }} - isAutoCompletePrSelected: ${{ parameters.AutoCompletePr }} - ${{ if eq(parameters.CreatePr, true) }}: - isUseLfLineEndingsSelected: ${{ parameters.UseLfLineEndings }} - ${{ if eq(parameters.RepoType, 'gitHub') }}: - isShouldReusePrSelected: ${{ parameters.ReusePr }} - packageSourceAuth: patAuth - patVariable: ${{ parameters.CeapexPat }} - ${{ if eq(parameters.RepoType, 'gitHub') }}: - repoType: ${{ parameters.RepoType }} - gitHubPatVariable: "${{ parameters.GithubPat }}" - ${{ if ne(parameters.MirrorRepo, '') }}: - isMirrorRepoSelected: true - gitHubOrganization: ${{ parameters.GitHubOrg }} - mirrorRepo: ${{ parameters.MirrorRepo }} - mirrorBranch: ${{ parameters.MirrorBranch }} - condition: ${{ parameters.condition }} - - - task: PublishBuildArtifacts@1 - displayName: Publish Localization Files - inputs: - PathtoPublish: '$(Build.ArtifactStagingDirectory)/loc' - PublishLocation: Container - ArtifactName: Loc - condition: ${{ parameters.condition }} +- template: /eng/common/core-templates/job/onelocbuild.yml + parameters: + is1ESPipeline: false - - task: PublishBuildArtifacts@1 - displayName: Publish LocProject.json - inputs: - PathtoPublish: '$(Build.SourcesDirectory)/eng/Localize/' - PublishLocation: Container - ArtifactName: Loc - condition: ${{ parameters.condition }} \ No newline at end of file + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates/job/publish-build-assets.yml b/eng/common/templates/job/publish-build-assets.yml index 9fd69fa7c9b..ab2edec2adb 100644 --- a/eng/common/templates/job/publish-build-assets.yml +++ b/eng/common/templates/job/publish-build-assets.yml @@ -1,153 +1,7 @@ -parameters: - configuration: 'Debug' - - # Optional: condition for the job to run - condition: '' - - # Optional: 'true' if future jobs should run even if this job fails - continueOnError: false - - # Optional: dependencies of the job - dependsOn: '' - - # Optional: Include PublishBuildArtifacts task - enablePublishBuildArtifacts: false - - # Optional: A defined YAML pool - https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=vsts&tabs=schema#pool - pool: {} - - # Optional: should run as a public build even in the internal project - # if 'true', the build won't run any of the internal only steps, even if it is running in non-public projects. - runAsPublic: false - - # Optional: whether the build's artifacts will be published using release pipelines or direct feed publishing - publishUsingPipelines: false - - # Optional: whether the build's artifacts will be published using release pipelines or direct feed publishing - publishAssetsImmediately: false - - artifactsPublishingAdditionalParameters: '' - - signingValidationAdditionalParameters: '' - jobs: -- job: Asset_Registry_Publish - - dependsOn: ${{ parameters.dependsOn }} - timeoutInMinutes: 150 - - ${{ if eq(parameters.publishAssetsImmediately, 'true') }}: - displayName: Publish Assets - ${{ else }}: - displayName: Publish to Build Asset Registry - - variables: - - template: /eng/common/templates/variables/pool-providers.yml - - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - - group: Publish-Build-Assets - - group: AzureDevOps-Artifact-Feeds-Pats - - name: runCodesignValidationInjection - value: false - - ${{ if eq(parameters.publishAssetsImmediately, 'true') }}: - - template: /eng/common/templates/post-build/common-variables.yml - - pool: - # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) - ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: - name: VSEngSS-MicroBuild2022-1ES - demands: Cmd - # If it's not devdiv, it's dnceng - ${{ if ne(variables['System.TeamProject'], 'DevDiv') }}: - name: NetCore1ESPool-Publishing-Internal - demands: ImageOverride -equals windows.vs2019.amd64 - - steps: - - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - - task: DownloadBuildArtifacts@0 - displayName: Download artifact - inputs: - artifactName: AssetManifests - downloadPath: '$(Build.StagingDirectory)/Download' - checkDownloadedFiles: true - condition: ${{ parameters.condition }} - continueOnError: ${{ parameters.continueOnError }} - - - task: NuGetAuthenticate@1 - - - task: AzureCLI@2 - displayName: Publish Build Assets - inputs: - azureSubscription: "Darc: Maestro Production" - scriptType: ps - scriptLocation: scriptPath - scriptPath: $(Build.SourcesDirectory)/eng/common/sdk-task.ps1 - arguments: > - -task PublishBuildAssets -restore -msbuildEngine dotnet - /p:ManifestsPath='$(Build.StagingDirectory)/Download/AssetManifests' - /p:MaestroApiEndpoint=https://maestro.dot.net - /p:PublishUsingPipelines=${{ parameters.publishUsingPipelines }} - /p:OfficialBuildId=$(Build.BuildNumber) - condition: ${{ parameters.condition }} - continueOnError: ${{ parameters.continueOnError }} - - - task: powershell@2 - displayName: Create ReleaseConfigs Artifact - inputs: - targetType: inline - script: | - Add-Content -Path "$(Build.StagingDirectory)/ReleaseConfigs.txt" -Value $(BARBuildId) - Add-Content -Path "$(Build.StagingDirectory)/ReleaseConfigs.txt" -Value "$(DefaultChannels)" - Add-Content -Path "$(Build.StagingDirectory)/ReleaseConfigs.txt" -Value $(IsStableBuild) - - - task: PublishBuildArtifacts@1 - displayName: Publish ReleaseConfigs Artifact - inputs: - PathtoPublish: '$(Build.StagingDirectory)/ReleaseConfigs.txt' - PublishLocation: Container - ArtifactName: ReleaseConfigs - - - task: powershell@2 - displayName: Check if SymbolPublishingExclusionsFile.txt exists - inputs: - targetType: inline - script: | - $symbolExclusionfile = "$(Build.SourcesDirectory)/eng/SymbolPublishingExclusionsFile.txt" - if(Test-Path -Path $symbolExclusionfile) - { - Write-Host "SymbolExclusionFile exists" - Write-Host "##vso[task.setvariable variable=SymbolExclusionFile]true" - } - else{ - Write-Host "Symbols Exclusion file does not exists" - Write-Host "##vso[task.setvariable variable=SymbolExclusionFile]false" - } - - - task: PublishBuildArtifacts@1 - displayName: Publish SymbolPublishingExclusionsFile Artifact - condition: eq(variables['SymbolExclusionFile'], 'true') - inputs: - PathtoPublish: '$(Build.SourcesDirectory)/eng/SymbolPublishingExclusionsFile.txt' - PublishLocation: Container - ArtifactName: ReleaseConfigs - - - ${{ if eq(parameters.publishAssetsImmediately, 'true') }}: - - template: /eng/common/templates/post-build/setup-maestro-vars.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - - - task: PowerShell@2 - displayName: Publish Using Darc - inputs: - filePath: $(Build.SourcesDirectory)/eng/common/post-build/publish-using-darc.ps1 - arguments: -BuildId $(BARBuildId) - -PublishingInfraVersion 3 - -AzdoToken '$(publishing-dnceng-devdiv-code-r-build-re)' - -WaitPublishingFinish true - -ArtifactsPublishingAdditionalParameters '${{ parameters.artifactsPublishingAdditionalParameters }}' - -SymbolPublishingAdditionalParameters '${{ parameters.symbolPublishingAdditionalParameters }}' +- template: /eng/common/core-templates/job/publish-build-assets.yml + parameters: + is1ESPipeline: false - - ${{ if eq(parameters.enablePublishBuildArtifacts, 'true') }}: - - template: /eng/common/templates/steps/publish-logs.yml - parameters: - JobLabel: 'Publish_Artifacts_Logs' + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates/job/source-build.yml b/eng/common/templates/job/source-build.yml index c0ff472b697..e44d47b1d76 100644 --- a/eng/common/templates/job/source-build.yml +++ b/eng/common/templates/job/source-build.yml @@ -1,74 +1,7 @@ -parameters: - # This template adds arcade-powered source-build to CI. The template produces a server job with a - # default ID 'Source_Build_Complete' to put in a dependency list if necessary. - - # Specifies the prefix for source-build jobs added to pipeline. Use this if disambiguation needed. - jobNamePrefix: 'Source_Build' - - # Defines the platform on which to run the job. By default, a linux-x64 machine, suitable for - # managed-only repositories. This is an object with these properties: - # - # name: '' - # The name of the job. This is included in the job ID. - # targetRID: '' - # The name of the target RID to use, instead of the one auto-detected by Arcade. - # nonPortable: false - # Enables non-portable mode. This means a more specific RID (e.g. fedora.32-x64 rather than - # linux-x64), and compiling against distro-provided packages rather than portable ones. - # skipPublishValidation: false - # Disables publishing validation. By default, a check is performed to ensure no packages are - # published by source-build. - # container: '' - # A container to use. Runs in docker. - # pool: {} - # A pool to use. Runs directly on an agent. - # buildScript: '' - # Specifies the build script to invoke to perform the build in the repo. The default - # './build.sh' should work for typical Arcade repositories, but this is customizable for - # difficult situations. - # jobProperties: {} - # A list of job properties to inject at the top level, for potential extensibility beyond - # container and pool. - platform: {} - - # If set to true and running on a non-public project, - # Internal blob storage locations will be enabled. - # This is not enabled by default because many repositories do not need internal sources - # and do not need to have the required service connections approved in the pipeline. - enableInternalSources: false - jobs: -- job: ${{ parameters.jobNamePrefix }}_${{ parameters.platform.name }} - displayName: Source-Build (${{ parameters.platform.name }}) - - ${{ each property in parameters.platform.jobProperties }}: - ${{ property.key }}: ${{ property.value }} - - ${{ if ne(parameters.platform.container, '') }}: - container: ${{ parameters.platform.container }} - - ${{ if eq(parameters.platform.pool, '') }}: - # The default VM host AzDO pool. This should be capable of running Docker containers: almost all - # source-build builds run in Docker, including the default managed platform. - # /eng/common/templates/variables/pool-providers.yml can't be used here (some customers declare variables already), so duplicate its logic - pool: - ${{ if eq(variables['System.TeamProject'], 'public') }}: - name: $[replace(replace(eq(contains(coalesce(variables['System.PullRequest.TargetBranch'], variables['Build.SourceBranch'], 'refs/heads/main'), 'release'), 'true'), True, 'NetCore-Svc-Public' ), False, 'NetCore-Public')] - demands: ImageOverride -equals Build.Ubuntu.1804.Amd64.Open - - ${{ if eq(variables['System.TeamProject'], 'internal') }}: - name: $[replace(replace(eq(contains(coalesce(variables['System.PullRequest.TargetBranch'], variables['Build.SourceBranch'], 'refs/heads/main'), 'release'), 'true'), True, 'NetCore1ESPool-Svc-Internal'), False, 'NetCore1ESPool-Internal')] - demands: ImageOverride -equals Build.Ubuntu.1804.Amd64 - - ${{ if ne(parameters.platform.pool, '') }}: - pool: ${{ parameters.platform.pool }} - - workspace: - clean: all +- template: /eng/common/core-templates/job/source-build.yml + parameters: + is1ESPipeline: false - steps: - - ${{ if eq(parameters.enableInternalSources, true) }}: - - template: /eng/common/templates/steps/enable-internal-runtimes.yml - - template: /eng/common/templates/steps/source-build.yml - parameters: - platform: ${{ parameters.platform }} + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates/job/source-index-stage1.yml b/eng/common/templates/job/source-index-stage1.yml index 0b6bb89dc78..89f3291593c 100644 --- a/eng/common/templates/job/source-index-stage1.yml +++ b/eng/common/templates/job/source-index-stage1.yml @@ -1,82 +1,7 @@ -parameters: - runAsPublic: false - sourceIndexUploadPackageVersion: 2.0.0-20240502.12 - sourceIndexProcessBinlogPackageVersion: 1.0.1-20240129.2 - sourceIndexPackageSource: https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json - sourceIndexBuildCommand: powershell -NoLogo -NoProfile -ExecutionPolicy Bypass -Command "eng/common/build.ps1 -restore -build -binarylog -ci" - preSteps: [] - binlogPath: artifacts/log/Debug/Build.binlog - condition: '' - dependsOn: '' - pool: '' - jobs: -- job: SourceIndexStage1 - dependsOn: ${{ parameters.dependsOn }} - condition: ${{ parameters.condition }} - variables: - - name: SourceIndexUploadPackageVersion - value: ${{ parameters.sourceIndexUploadPackageVersion }} - - name: SourceIndexProcessBinlogPackageVersion - value: ${{ parameters.sourceIndexProcessBinlogPackageVersion }} - - name: SourceIndexPackageSource - value: ${{ parameters.sourceIndexPackageSource }} - - name: BinlogPath - value: ${{ parameters.binlogPath }} - - template: /eng/common/templates/variables/pool-providers.yml - - ${{ if ne(parameters.pool, '') }}: - pool: ${{ parameters.pool }} - ${{ if eq(parameters.pool, '') }}: - pool: - ${{ if eq(variables['System.TeamProject'], 'public') }}: - name: $(DncEngPublicBuildPool) - demands: ImageOverride -equals windows.vs2019.amd64.open - ${{ if eq(variables['System.TeamProject'], 'internal') }}: - name: $(DncEngInternalBuildPool) - demands: ImageOverride -equals windows.vs2019.amd64 - - steps: - - ${{ each preStep in parameters.preSteps }}: - - ${{ preStep }} - - - task: UseDotNet@2 - displayName: Use .NET 8 SDK - inputs: - packageType: sdk - version: 8.0.x - installationPath: $(Agent.TempDirectory)/dotnet - workingDirectory: $(Agent.TempDirectory) - - - script: | - $(Agent.TempDirectory)/dotnet/dotnet tool install BinLogToSln --version $(sourceIndexProcessBinlogPackageVersion) --add-source $(SourceIndexPackageSource) --tool-path $(Agent.TempDirectory)/.source-index/tools - $(Agent.TempDirectory)/dotnet/dotnet tool install UploadIndexStage1 --version $(sourceIndexUploadPackageVersion) --add-source $(SourceIndexPackageSource) --tool-path $(Agent.TempDirectory)/.source-index/tools - displayName: Download Tools - # Set working directory to temp directory so 'dotnet' doesn't try to use global.json and use the repo's sdk. - workingDirectory: $(Agent.TempDirectory) - - - script: ${{ parameters.sourceIndexBuildCommand }} - displayName: Build Repository - - - script: $(Agent.TempDirectory)/.source-index/tools/BinLogToSln -i $(BinlogPath) -r $(Build.SourcesDirectory) -n $(Build.Repository.Name) -o .source-index/stage1output - displayName: Process Binlog into indexable sln - - - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - - task: AzureCLI@2 - displayName: Get stage 1 auth token - inputs: - azureSubscription: 'SourceDotNet Stage1 Publish' - addSpnToEnvironment: true - scriptType: 'ps' - scriptLocation: 'inlineScript' - inlineScript: | - echo "##vso[task.setvariable variable=ARM_CLIENT_ID;issecret=true]$env:servicePrincipalId" - echo "##vso[task.setvariable variable=ARM_ID_TOKEN;issecret=true]$env:idToken" - echo "##vso[task.setvariable variable=ARM_TENANT_ID;issecret=true]$env:tenantId" - - - script: | - az login --service-principal -u $(ARM_CLIENT_ID) --tenant $(ARM_TENANT_ID) --allow-no-subscriptions --federated-token $(ARM_ID_TOKEN) - displayName: "Login to Azure" +- template: /eng/common/core-templates/job/source-index-stage1.yml + parameters: + is1ESPipeline: false - - script: $(Agent.TempDirectory)/.source-index/tools/UploadIndexStage1 -i .source-index/stage1output -n $(Build.Repository.Name) -s netsourceindexstage1 -b stage1 - displayName: Upload stage1 artifacts to source index + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates/jobs/codeql-build.yml b/eng/common/templates/jobs/codeql-build.yml index f7dc5ea4aaa..517f24d6a52 100644 --- a/eng/common/templates/jobs/codeql-build.yml +++ b/eng/common/templates/jobs/codeql-build.yml @@ -1,31 +1,7 @@ -parameters: - # See schema documentation in /Documentation/AzureDevOps/TemplateSchema.md - continueOnError: false - # Required: A collection of jobs to run - https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=vsts&tabs=schema#job - jobs: [] - # Optional: if specified, restore and use this version of Guardian instead of the default. - overrideGuardianVersion: '' - jobs: -- template: /eng/common/templates/jobs/jobs.yml +- template: /eng/common/core-templates/jobs/codeql-build.yml parameters: - enableMicrobuild: false - enablePublishBuildArtifacts: false - enablePublishTestResults: false - enablePublishBuildAssets: false - enablePublishUsingPipelines: false - enableTelemetry: true + is1ESPipeline: false - variables: - - group: Publish-Build-Assets - # The Guardian version specified in 'eng/common/sdl/packages.config'. This value must be kept in - # sync with the packages.config file. - - name: DefaultGuardianVersion - value: 0.109.0 - - name: GuardianPackagesConfigFile - value: $(Build.SourcesDirectory)\eng\common\sdl\packages.config - - name: GuardianVersion - value: ${{ coalesce(parameters.overrideGuardianVersion, '$(DefaultGuardianVersion)') }} - - jobs: ${{ parameters.jobs }} - + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates/jobs/jobs.yml b/eng/common/templates/jobs/jobs.yml index 289bb2396ce..388e9037b3e 100644 --- a/eng/common/templates/jobs/jobs.yml +++ b/eng/common/templates/jobs/jobs.yml @@ -1,97 +1,7 @@ -parameters: - # See schema documentation in /Documentation/AzureDevOps/TemplateSchema.md - continueOnError: false - - # Optional: Include PublishBuildArtifacts task - enablePublishBuildArtifacts: false - - # Optional: Enable publishing using release pipelines - enablePublishUsingPipelines: false - - # Optional: Enable running the source-build jobs to build repo from source - enableSourceBuild: false - - # Optional: Parameters for source-build template. - # See /eng/common/templates/jobs/source-build.yml for options - sourceBuildParameters: [] - - graphFileGeneration: - # Optional: Enable generating the graph files at the end of the build - enabled: false - # Optional: Include toolset dependencies in the generated graph files - includeToolset: false - - # Required: A collection of jobs to run - https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=vsts&tabs=schema#job - jobs: [] - - # Optional: Override automatically derived dependsOn value for "publish build assets" job - publishBuildAssetsDependsOn: '' - - # Optional: Publish the assets as soon as the publish to BAR stage is complete, rather doing so in a separate stage. - publishAssetsImmediately: false - - # Optional: If using publishAssetsImmediately and additional parameters are needed, can be used to send along additional parameters (normally sent to post-build.yml) - artifactsPublishingAdditionalParameters: '' - signingValidationAdditionalParameters: '' - - # Optional: should run as a public build even in the internal project - # if 'true', the build won't run any of the internal only steps, even if it is running in non-public projects. - runAsPublic: false - - enableSourceIndex: false - sourceIndexParams: {} - -# Internal resources (telemetry, microbuild) can only be accessed from non-public projects, -# and some (Microbuild) should only be applied to non-PR cases for internal builds. - jobs: -- ${{ each job in parameters.jobs }}: - - template: ../job/job.yml - parameters: - # pass along parameters - ${{ each parameter in parameters }}: - ${{ if ne(parameter.key, 'jobs') }}: - ${{ parameter.key }}: ${{ parameter.value }} - - # pass along job properties - ${{ each property in job }}: - ${{ if ne(property.key, 'job') }}: - ${{ property.key }}: ${{ property.value }} - - name: ${{ job.job }} - -- ${{ if eq(parameters.enableSourceBuild, true) }}: - - template: /eng/common/templates/jobs/source-build.yml - parameters: - allCompletedJobId: Source_Build_Complete - ${{ each parameter in parameters.sourceBuildParameters }}: - ${{ parameter.key }}: ${{ parameter.value }} - -- ${{ if eq(parameters.enableSourceIndex, 'true') }}: - - template: ../job/source-index-stage1.yml - parameters: - runAsPublic: ${{ parameters.runAsPublic }} - ${{ each parameter in parameters.sourceIndexParams }}: - ${{ parameter.key }}: ${{ parameter.value }} - -- ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - - ${{ if or(eq(parameters.enablePublishBuildAssets, true), eq(parameters.artifacts.publish.manifests, 'true'), ne(parameters.artifacts.publish.manifests, '')) }}: - - template: ../job/publish-build-assets.yml - parameters: - continueOnError: ${{ parameters.continueOnError }} - dependsOn: - - ${{ if ne(parameters.publishBuildAssetsDependsOn, '') }}: - - ${{ each job in parameters.publishBuildAssetsDependsOn }}: - - ${{ job.job }} - - ${{ if eq(parameters.publishBuildAssetsDependsOn, '') }}: - - ${{ each job in parameters.jobs }}: - - ${{ job.job }} - - ${{ if eq(parameters.enableSourceBuild, true) }}: - - Source_Build_Complete +- template: /eng/common/core-templates/jobs/jobs.yml + parameters: + is1ESPipeline: false - runAsPublic: ${{ parameters.runAsPublic }} - publishUsingPipelines: ${{ parameters.enablePublishUsingPipelines }} - publishAssetsImmediately: ${{ parameters.publishAssetsImmediately }} - enablePublishBuildArtifacts: ${{ parameters.enablePublishBuildArtifacts }} - artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} - signingValidationAdditionalParameters: ${{ parameters.signingValidationAdditionalParameters }} + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates/jobs/source-build.yml b/eng/common/templates/jobs/source-build.yml index 5f46bfa895c..818d4c326db 100644 --- a/eng/common/templates/jobs/source-build.yml +++ b/eng/common/templates/jobs/source-build.yml @@ -1,54 +1,7 @@ -parameters: - # This template adds arcade-powered source-build to CI. A job is created for each platform, as - # well as an optional server job that completes when all platform jobs complete. - - # The name of the "join" job for all source-build platforms. If set to empty string, the job is - # not included. Existing repo pipelines can use this job depend on all source-build jobs - # completing without maintaining a separate list of every single job ID: just depend on this one - # server job. By default, not included. Recommended name if used: 'Source_Build_Complete'. - allCompletedJobId: '' - - # See /eng/common/templates/job/source-build.yml - jobNamePrefix: 'Source_Build' - - # This is the default platform provided by Arcade, intended for use by a managed-only repo. - defaultManagedPlatform: - name: 'Managed' - container: 'mcr.microsoft.com/dotnet-buildtools/prereqs:centos-stream8' - - # Defines the platforms on which to run build jobs. One job is created for each platform, and the - # object in this array is sent to the job template as 'platform'. If no platforms are specified, - # one job runs on 'defaultManagedPlatform'. - platforms: [] - - # If set to true and running on a non-public project, - # Internal nuget and blob storage locations will be enabled. - # This is not enabled by default because many repositories do not need internal sources - # and do not need to have the required service connections approved in the pipeline. - enableInternalSources: false - jobs: +- template: /eng/common/core-templates/jobs/source-build.yml + parameters: + is1ESPipeline: false -- ${{ if ne(parameters.allCompletedJobId, '') }}: - - job: ${{ parameters.allCompletedJobId }} - displayName: Source-Build Complete - pool: server - dependsOn: - - ${{ each platform in parameters.platforms }}: - - ${{ parameters.jobNamePrefix }}_${{ platform.name }} - - ${{ if eq(length(parameters.platforms), 0) }}: - - ${{ parameters.jobNamePrefix }}_${{ parameters.defaultManagedPlatform.name }} - -- ${{ each platform in parameters.platforms }}: - - template: /eng/common/templates/job/source-build.yml - parameters: - jobNamePrefix: ${{ parameters.jobNamePrefix }} - platform: ${{ platform }} - enableInternalSources: ${{ parameters.enableInternalSources }} - -- ${{ if eq(length(parameters.platforms), 0) }}: - - template: /eng/common/templates/job/source-build.yml - parameters: - jobNamePrefix: ${{ parameters.jobNamePrefix }} - platform: ${{ parameters.defaultManagedPlatform }} - enableInternalSources: ${{ parameters.enableInternalSources }} + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} \ No newline at end of file diff --git a/eng/common/templates/post-build/common-variables.yml b/eng/common/templates/post-build/common-variables.yml index 173914f2364..7fa10587559 100644 --- a/eng/common/templates/post-build/common-variables.yml +++ b/eng/common/templates/post-build/common-variables.yml @@ -1,22 +1,8 @@ variables: - - group: Publish-Build-Assets +- template: /eng/common/core-templates/post-build/common-variables.yml + parameters: + # Specifies whether to use 1ES + is1ESPipeline: false - # Whether the build is internal or not - - name: IsInternalBuild - value: ${{ and(ne(variables['System.TeamProject'], 'public'), contains(variables['Build.SourceBranch'], 'internal')) }} - - # Default Maestro++ API Endpoint and API Version - - name: MaestroApiEndPoint - value: "https://maestro.dot.net" - - name: MaestroApiAccessToken - value: $(MaestroAccessToken) - - name: MaestroApiVersion - value: "2020-02-20" - - - name: SourceLinkCLIVersion - value: 3.0.0 - - name: SymbolToolVersion - value: 1.0.1 - - - name: runCodesignValidationInjection - value: false + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} \ No newline at end of file diff --git a/eng/common/templates/post-build/post-build.yml b/eng/common/templates/post-build/post-build.yml index 2db4933468f..53ede714bdd 100644 --- a/eng/common/templates/post-build/post-build.yml +++ b/eng/common/templates/post-build/post-build.yml @@ -1,283 +1,8 @@ -parameters: - # Which publishing infra should be used. THIS SHOULD MATCH THE VERSION ON THE BUILD MANIFEST. - # Publishing V1 is no longer supported - # Publishing V2 is no longer supported - # Publishing V3 is the default - - name: publishingInfraVersion - displayName: Which version of publishing should be used to promote the build definition? - type: number - default: 3 - values: - - 3 - - - name: BARBuildId - displayName: BAR Build Id - type: number - default: 0 - - - name: PromoteToChannelIds - displayName: Channel to promote BARBuildId to - type: string - default: '' - - - name: enableSourceLinkValidation - displayName: Enable SourceLink validation - type: boolean - default: false - - - name: enableSigningValidation - displayName: Enable signing validation - type: boolean - default: true - - - name: enableSymbolValidation - displayName: Enable symbol validation - type: boolean - default: false - - - name: enableNugetValidation - displayName: Enable NuGet validation - type: boolean - default: true - - - name: publishInstallersAndChecksums - displayName: Publish installers and checksums - type: boolean - default: true - - - name: SDLValidationParameters - type: object - default: - enable: false - publishGdn: false - continueOnError: false - params: '' - artifactNames: '' - downloadArtifacts: true - - # These parameters let the user customize the call to sdk-task.ps1 for publishing - # symbols & general artifacts as well as for signing validation - - name: symbolPublishingAdditionalParameters - displayName: Symbol publishing additional parameters - type: string - default: '' - - - name: artifactsPublishingAdditionalParameters - displayName: Artifact publishing additional parameters - type: string - default: '' - - - name: signingValidationAdditionalParameters - displayName: Signing validation additional parameters - type: string - default: '' - - # Which stages should finish execution before post-build stages start - - name: validateDependsOn - type: object - default: - - build - - - name: publishDependsOn - type: object - default: - - Validate - - # Optional: Call asset publishing rather than running in a separate stage - - name: publishAssetsImmediately - type: boolean - default: false - stages: -- ${{ if or(eq( parameters.enableNugetValidation, 'true'), eq(parameters.enableSigningValidation, 'true'), eq(parameters.enableSourceLinkValidation, 'true'), eq(parameters.SDLValidationParameters.enable, 'true')) }}: - - stage: Validate - dependsOn: ${{ parameters.validateDependsOn }} - displayName: Validate Build Assets - variables: - - template: common-variables.yml - - template: /eng/common/templates/variables/pool-providers.yml - jobs: - - job: - displayName: NuGet Validation - condition: and(succeededOrFailed(), eq( ${{ parameters.enableNugetValidation }}, 'true')) - pool: - # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) - ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: - name: VSEngSS-MicroBuild2022-1ES - demands: Cmd - # If it's not devdiv, it's dnceng - ${{ else }}: - name: $(DncEngInternalBuildPool) - demands: ImageOverride -equals windows.vs2019.amd64 - - steps: - - template: setup-maestro-vars.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - - - task: DownloadBuildArtifacts@0 - displayName: Download Package Artifacts - inputs: - buildType: specific - buildVersionToDownload: specific - project: $(AzDOProjectName) - pipeline: $(AzDOPipelineId) - buildId: $(AzDOBuildId) - artifactName: PackageArtifacts - checkDownloadedFiles: true - - - task: PowerShell@2 - displayName: Validate - inputs: - filePath: $(Build.SourcesDirectory)/eng/common/post-build/nuget-validation.ps1 - arguments: -PackagesPath $(Build.ArtifactStagingDirectory)/PackageArtifacts/ - -ToolDestinationPath $(Agent.BuildDirectory)/Extract/ - - - job: - displayName: Signing Validation - condition: and( eq( ${{ parameters.enableSigningValidation }}, 'true'), ne( variables['PostBuildSign'], 'true')) - pool: - # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) - ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: - name: VSEngSS-MicroBuild2022-1ES - demands: Cmd - # If it's not devdiv, it's dnceng - ${{ else }}: - name: $(DncEngInternalBuildPool) - demands: ImageOverride -equals windows.vs2019.amd64 - steps: - - template: setup-maestro-vars.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - - - task: DownloadBuildArtifacts@0 - displayName: Download Package Artifacts - inputs: - buildType: specific - buildVersionToDownload: specific - project: $(AzDOProjectName) - pipeline: $(AzDOPipelineId) - buildId: $(AzDOBuildId) - artifactName: PackageArtifacts - checkDownloadedFiles: true - itemPattern: | - ** - !**/Microsoft.SourceBuild.Intermediate.*.nupkg - - # This is necessary whenever we want to publish/restore to an AzDO private feed - # Since sdk-task.ps1 tries to restore packages we need to do this authentication here - # otherwise it'll complain about accessing a private feed. - - task: NuGetAuthenticate@1 - displayName: 'Authenticate to AzDO Feeds' - - # Signing validation will optionally work with the buildmanifest file which is downloaded from - # Azure DevOps above. - - task: PowerShell@2 - displayName: Validate - inputs: - filePath: eng\common\sdk-task.ps1 - arguments: -task SigningValidation -restore -msbuildEngine vs - /p:PackageBasePath='$(Build.ArtifactStagingDirectory)/PackageArtifacts' - /p:SignCheckExclusionsFile='$(Build.SourcesDirectory)/eng/SignCheckExclusionsFile.txt' - ${{ parameters.signingValidationAdditionalParameters }} - - - template: ../steps/publish-logs.yml - parameters: - StageLabel: 'Validation' - JobLabel: 'Signing' - - - job: - displayName: SourceLink Validation - condition: eq( ${{ parameters.enableSourceLinkValidation }}, 'true') - pool: - # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) - ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: - name: VSEngSS-MicroBuild2022-1ES - demands: Cmd - # If it's not devdiv, it's dnceng - ${{ else }}: - name: $(DncEngInternalBuildPool) - demands: ImageOverride -equals windows.vs2019.amd64 - steps: - - template: setup-maestro-vars.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - - - task: DownloadBuildArtifacts@0 - displayName: Download Blob Artifacts - inputs: - buildType: specific - buildVersionToDownload: specific - project: $(AzDOProjectName) - pipeline: $(AzDOPipelineId) - buildId: $(AzDOBuildId) - artifactName: BlobArtifacts - checkDownloadedFiles: true - - - task: PowerShell@2 - displayName: Validate - inputs: - filePath: $(Build.SourcesDirectory)/eng/common/post-build/sourcelink-validation.ps1 - arguments: -InputPath $(Build.ArtifactStagingDirectory)/BlobArtifacts/ - -ExtractPath $(Agent.BuildDirectory)/Extract/ - -GHRepoName $(Build.Repository.Name) - -GHCommit $(Build.SourceVersion) - -SourcelinkCliVersion $(SourceLinkCLIVersion) - continueOnError: true - - - template: /eng/common/templates/job/execute-sdl.yml - parameters: - enable: ${{ parameters.SDLValidationParameters.enable }} - publishGuardianDirectoryToPipeline: ${{ parameters.SDLValidationParameters.publishGdn }} - additionalParameters: ${{ parameters.SDLValidationParameters.params }} - continueOnError: ${{ parameters.SDLValidationParameters.continueOnError }} - artifactNames: ${{ parameters.SDLValidationParameters.artifactNames }} - downloadArtifacts: ${{ parameters.SDLValidationParameters.downloadArtifacts }} - -- ${{ if ne(parameters.publishAssetsImmediately, 'true') }}: - - stage: publish_using_darc - ${{ if or(eq(parameters.enableNugetValidation, 'true'), eq(parameters.enableSigningValidation, 'true'), eq(parameters.enableSourceLinkValidation, 'true'), eq(parameters.SDLValidationParameters.enable, 'true')) }}: - dependsOn: ${{ parameters.publishDependsOn }} - ${{ else }}: - dependsOn: ${{ parameters.validateDependsOn }} - displayName: Publish using Darc - variables: - - template: common-variables.yml - - template: /eng/common/templates/variables/pool-providers.yml - jobs: - - job: - displayName: Publish Using Darc - timeoutInMinutes: 120 - pool: - # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) - ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: - name: VSEngSS-MicroBuild2022-1ES - demands: Cmd - # If it's not devdiv, it's dnceng - ${{ else }}: - name: NetCore1ESPool-Publishing-Internal - demands: ImageOverride -equals windows.vs2019.amd64 - steps: - - template: setup-maestro-vars.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - - - task: NuGetAuthenticate@1 +- template: /eng/common/core-templates/post-build/post-build.yml + parameters: + # Specifies whether to use 1ES + is1ESPipeline: false - - task: AzureCLI@2 - displayName: Publish Using Darc - inputs: - azureSubscription: "Darc: Maestro Production" - scriptType: ps - scriptLocation: scriptPath - scriptPath: $(Build.SourcesDirectory)/eng/common/post-build/publish-using-darc.ps1 - arguments: -BuildId $(BARBuildId) - -PublishingInfraVersion ${{ parameters.publishingInfraVersion }} - -AzdoToken '$(publishing-dnceng-devdiv-code-r-build-re)' - -WaitPublishingFinish true - -ArtifactsPublishingAdditionalParameters '${{ parameters.artifactsPublishingAdditionalParameters }}' - -SymbolPublishingAdditionalParameters '${{ parameters.symbolPublishingAdditionalParameters }}' + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} \ No newline at end of file diff --git a/eng/common/templates/post-build/setup-maestro-vars.yml b/eng/common/templates/post-build/setup-maestro-vars.yml index 64b9abc6850..a79fab5b441 100644 --- a/eng/common/templates/post-build/setup-maestro-vars.yml +++ b/eng/common/templates/post-build/setup-maestro-vars.yml @@ -1,70 +1,8 @@ -parameters: - BARBuildId: '' - PromoteToChannelIds: '' - steps: - - ${{ if eq(coalesce(parameters.PromoteToChannelIds, 0), 0) }}: - - task: DownloadBuildArtifacts@0 - displayName: Download Release Configs - inputs: - buildType: current - artifactName: ReleaseConfigs - checkDownloadedFiles: true - - - task: AzureCLI@2 - name: setReleaseVars - displayName: Set Release Configs Vars - inputs: - azureSubscription: "Darc: Maestro Production" - scriptType: pscore - scriptLocation: inlineScript - inlineScript: | - try { - if (!$Env:PromoteToMaestroChannels -or $Env:PromoteToMaestroChannels.Trim() -eq '') { - $Content = Get-Content $(Build.StagingDirectory)/ReleaseConfigs/ReleaseConfigs.txt - - $BarId = $Content | Select -Index 0 - $Channels = $Content | Select -Index 1 - $IsStableBuild = $Content | Select -Index 2 - - $AzureDevOpsProject = $Env:System_TeamProject - $AzureDevOpsBuildDefinitionId = $Env:System_DefinitionId - $AzureDevOpsBuildId = $Env:Build_BuildId - } - else { - . $(Build.SourcesDirectory)\eng\common\tools.ps1 - $darc = Get-Darc - $buildInfo = & $darc get-build ` - --id ${{ parameters.BARBuildId }} ` - --extended ` - --output-format json ` - --ci ` - | convertFrom-Json - - $BarId = ${{ parameters.BARBuildId }} - $Channels = $Env:PromoteToMaestroChannels -split "," - $Channels = $Channels -join "][" - $Channels = "[$Channels]" - - $IsStableBuild = $buildInfo.stable - $AzureDevOpsProject = $buildInfo.azureDevOpsProject - $AzureDevOpsBuildDefinitionId = $buildInfo.azureDevOpsBuildDefinitionId - $AzureDevOpsBuildId = $buildInfo.azureDevOpsBuildId - } - - Write-Host "##vso[task.setvariable variable=BARBuildId]$BarId" - Write-Host "##vso[task.setvariable variable=TargetChannels]$Channels" - Write-Host "##vso[task.setvariable variable=IsStableBuild]$IsStableBuild" +- template: /eng/common/core-templates/post-build/setup-maestro-vars.yml + parameters: + # Specifies whether to use 1ES + is1ESPipeline: false - Write-Host "##vso[task.setvariable variable=AzDOProjectName]$AzureDevOpsProject" - Write-Host "##vso[task.setvariable variable=AzDOPipelineId]$AzureDevOpsBuildDefinitionId" - Write-Host "##vso[task.setvariable variable=AzDOBuildId]$AzureDevOpsBuildId" - } - catch { - Write-Host $_ - Write-Host $_.Exception - Write-Host $_.ScriptStackTrace - exit 1 - } - env: - PromoteToMaestroChannels: ${{ parameters.PromoteToChannelIds }} + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} \ No newline at end of file diff --git a/eng/common/templates/post-build/trigger-subscription.yml b/eng/common/templates/post-build/trigger-subscription.yml deleted file mode 100644 index da669030daf..00000000000 --- a/eng/common/templates/post-build/trigger-subscription.yml +++ /dev/null @@ -1,13 +0,0 @@ -parameters: - ChannelId: 0 - -steps: -- task: PowerShell@2 - displayName: Triggering subscriptions - inputs: - filePath: $(Build.SourcesDirectory)/eng/common/post-build/trigger-subscriptions.ps1 - arguments: -SourceRepo $(Build.Repository.Uri) - -ChannelId ${{ parameters.ChannelId }} - -MaestroApiAccessToken $(MaestroAccessToken) - -MaestroApiEndPoint $(MaestroApiEndPoint) - -MaestroApiVersion $(MaestroApiVersion) diff --git a/eng/common/templates/steps/add-build-to-channel.yml b/eng/common/templates/steps/add-build-to-channel.yml deleted file mode 100644 index f67a210d62f..00000000000 --- a/eng/common/templates/steps/add-build-to-channel.yml +++ /dev/null @@ -1,13 +0,0 @@ -parameters: - ChannelId: 0 - -steps: -- task: PowerShell@2 - displayName: Add Build to Channel - inputs: - filePath: $(Build.SourcesDirectory)/eng/common/post-build/add-build-to-channel.ps1 - arguments: -BuildId $(BARBuildId) - -ChannelId ${{ parameters.ChannelId }} - -MaestroApiAccessToken $(MaestroApiAccessToken) - -MaestroApiEndPoint $(MaestroApiEndPoint) - -MaestroApiVersion $(MaestroApiVersion) diff --git a/eng/common/templates/steps/build-reason.yml b/eng/common/templates/steps/build-reason.yml deleted file mode 100644 index eba58109b52..00000000000 --- a/eng/common/templates/steps/build-reason.yml +++ /dev/null @@ -1,12 +0,0 @@ -# build-reason.yml -# Description: runs steps if build.reason condition is valid. conditions is a string of valid build reasons -# to include steps (',' separated). -parameters: - conditions: '' - steps: [] - -steps: - - ${{ if and( not(startsWith(parameters.conditions, 'not')), contains(parameters.conditions, variables['build.reason'])) }}: - - ${{ parameters.steps }} - - ${{ if and( startsWith(parameters.conditions, 'not'), not(contains(parameters.conditions, variables['build.reason']))) }}: - - ${{ parameters.steps }} diff --git a/eng/common/templates/steps/component-governance.yml b/eng/common/templates/steps/component-governance.yml index cbba0596709..c12a5f8d21d 100644 --- a/eng/common/templates/steps/component-governance.yml +++ b/eng/common/templates/steps/component-governance.yml @@ -1,13 +1,7 @@ -parameters: - disableComponentGovernance: false - componentGovernanceIgnoreDirectories: '' - steps: -- ${{ if eq(parameters.disableComponentGovernance, 'true') }}: - - script: echo "##vso[task.setvariable variable=skipComponentGovernanceDetection]true" - displayName: Set skipComponentGovernanceDetection variable -- ${{ if ne(parameters.disableComponentGovernance, 'true') }}: - - task: ComponentGovernanceComponentDetection@0 - continueOnError: true - inputs: - ignoreDirectories: ${{ parameters.componentGovernanceIgnoreDirectories }} \ No newline at end of file +- template: /eng/common/core-templates/steps/component-governance.yml + parameters: + is1ESPipeline: false + + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates/steps/enable-internal-runtimes.yml b/eng/common/templates/steps/enable-internal-runtimes.yml index 54dc9416c51..b21a8038cc1 100644 --- a/eng/common/templates/steps/enable-internal-runtimes.yml +++ b/eng/common/templates/steps/enable-internal-runtimes.yml @@ -1,28 +1,10 @@ # Obtains internal runtime download credentials and populates the 'dotnetbuilds-internal-container-read-token-base64' # variable with the base64-encoded SAS token, by default -parameters: -- name: federatedServiceConnection - type: string - default: 'dotnetbuilds-internal-read' -- name: outputVariableName - type: string - default: 'dotnetbuilds-internal-container-read-token-base64' -- name: expiryInHours - type: number - default: 1 -- name: base64Encode - type: boolean - default: true - steps: -- ${{ if ne(variables['System.TeamProject'], 'public') }}: - - template: /eng/common/templates/steps/get-delegation-sas.yml - parameters: - federatedServiceConnection: ${{ parameters.federatedServiceConnection }} - outputVariableName: ${{ parameters.outputVariableName }} - expiryInHours: ${{ parameters.expiryInHours }} - base64Encode: ${{ parameters.base64Encode }} - storageAccount: dotnetbuilds - container: internal - permissions: rl +- template: /eng/common/core-templates/steps/enable-internal-runtimes.yml + parameters: + is1ESPipeline: false + + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates/steps/enable-internal-sources.yml b/eng/common/templates/steps/enable-internal-sources.yml new file mode 100644 index 00000000000..5f87e9abb8a --- /dev/null +++ b/eng/common/templates/steps/enable-internal-sources.yml @@ -0,0 +1,7 @@ +steps: +- template: /eng/common/core-templates/steps/enable-internal-sources.yml + parameters: + is1ESPipeline: false + + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} \ No newline at end of file diff --git a/eng/common/templates/steps/execute-codeql.yml b/eng/common/templates/steps/execute-codeql.yml deleted file mode 100644 index 3930b163021..00000000000 --- a/eng/common/templates/steps/execute-codeql.yml +++ /dev/null @@ -1,32 +0,0 @@ -parameters: - # Language that should be analyzed. Defaults to csharp - language: csharp - # Build Commands - buildCommands: '' - overrideParameters: '' # Optional: to override values for parameters. - additionalParameters: '' # Optional: parameters that need user specific values eg: '-SourceToolsList @("abc","def") -ArtifactToolsList @("ghi","jkl")' - # Optional: if specified, restore and use this version of Guardian instead of the default. - overrideGuardianVersion: '' - # Optional: if true, publish the '.gdn' folder as a pipeline artifact. This can help with in-depth - # diagnosis of problems with specific tool configurations. - publishGuardianDirectoryToPipeline: false - # The script to run to execute all SDL tools. Use this if you want to use a script to define SDL - # parameters rather than relying on YAML. It may be better to use a local script, because you can - # reproduce results locally without piecing together a command based on the YAML. - executeAllSdlToolsScript: 'eng/common/sdl/execute-all-sdl-tools.ps1' - # There is some sort of bug (has been reported) in Azure DevOps where if this parameter is named - # 'continueOnError', the parameter value is not correctly picked up. - # This can also be remedied by the caller (post-build.yml) if it does not use a nested parameter - # optional: determines whether to continue the build if the step errors; - sdlContinueOnError: false - -steps: -- template: /eng/common/templates/steps/execute-sdl.yml - parameters: - overrideGuardianVersion: ${{ parameters.overrideGuardianVersion }} - executeAllSdlToolsScript: ${{ parameters.executeAllSdlToolsScript }} - overrideParameters: ${{ parameters.overrideParameters }} - additionalParameters: '${{ parameters.additionalParameters }} - -CodeQLAdditionalRunConfigParams @("BuildCommands < ${{ parameters.buildCommands }}", "Language < ${{ parameters.language }}")' - publishGuardianDirectoryToPipeline: ${{ parameters.publishGuardianDirectoryToPipeline }} - sdlContinueOnError: ${{ parameters.sdlContinueOnError }} \ No newline at end of file diff --git a/eng/common/templates/steps/execute-sdl.yml b/eng/common/templates/steps/execute-sdl.yml deleted file mode 100644 index 07426fde05d..00000000000 --- a/eng/common/templates/steps/execute-sdl.yml +++ /dev/null @@ -1,88 +0,0 @@ -parameters: - overrideGuardianVersion: '' - executeAllSdlToolsScript: '' - overrideParameters: '' - additionalParameters: '' - publishGuardianDirectoryToPipeline: false - sdlContinueOnError: false - condition: '' - -steps: -- task: NuGetAuthenticate@1 - inputs: - nuGetServiceConnections: GuardianConnect - -- task: NuGetToolInstaller@1 - displayName: 'Install NuGet.exe' - -- ${{ if ne(parameters.overrideGuardianVersion, '') }}: - - pwsh: | - Set-Location -Path $(Build.SourcesDirectory)\eng\common\sdl - . .\sdl.ps1 - $guardianCliLocation = Install-Gdn -Path $(Build.SourcesDirectory)\.artifacts -Version ${{ parameters.overrideGuardianVersion }} - Write-Host "##vso[task.setvariable variable=GuardianCliLocation]$guardianCliLocation" - displayName: Install Guardian (Overridden) - -- ${{ if eq(parameters.overrideGuardianVersion, '') }}: - - pwsh: | - Set-Location -Path $(Build.SourcesDirectory)\eng\common\sdl - . .\sdl.ps1 - $guardianCliLocation = Install-Gdn -Path $(Build.SourcesDirectory)\.artifacts - Write-Host "##vso[task.setvariable variable=GuardianCliLocation]$guardianCliLocation" - displayName: Install Guardian - -- ${{ if ne(parameters.overrideParameters, '') }}: - - powershell: ${{ parameters.executeAllSdlToolsScript }} ${{ parameters.overrideParameters }} - displayName: Execute SDL (Overridden) - continueOnError: ${{ parameters.sdlContinueOnError }} - condition: ${{ parameters.condition }} - -- ${{ if eq(parameters.overrideParameters, '') }}: - - powershell: ${{ parameters.executeAllSdlToolsScript }} - -GuardianCliLocation $(GuardianCliLocation) - -NugetPackageDirectory $(Build.SourcesDirectory)\.packages - -AzureDevOpsAccessToken $(dn-bot-dotnet-build-rw-code-rw) - ${{ parameters.additionalParameters }} - displayName: Execute SDL - continueOnError: ${{ parameters.sdlContinueOnError }} - condition: ${{ parameters.condition }} - -- ${{ if ne(parameters.publishGuardianDirectoryToPipeline, 'false') }}: - # We want to publish the Guardian results and configuration for easy diagnosis. However, the - # '.gdn' dir is a mix of configuration, results, extracted dependencies, and Guardian default - # tooling files. Some of these files are large and aren't useful during an investigation, so - # exclude them by simply deleting them before publishing. (As of writing, there is no documented - # way to selectively exclude a dir from the pipeline artifact publish task.) - - task: DeleteFiles@1 - displayName: Delete Guardian dependencies to avoid uploading - inputs: - SourceFolder: $(Agent.BuildDirectory)/.gdn - Contents: | - c - i - condition: succeededOrFailed() - - - publish: $(Agent.BuildDirectory)/.gdn - artifact: GuardianConfiguration - displayName: Publish GuardianConfiguration - condition: succeededOrFailed() - - # Publish the SARIF files in a container named CodeAnalysisLogs to enable integration - # with the "SARIF SAST Scans Tab" Azure DevOps extension - - task: CopyFiles@2 - displayName: Copy SARIF files - inputs: - flattenFolders: true - sourceFolder: $(Agent.BuildDirectory)/.gdn/rc/ - contents: '**/*.sarif' - targetFolder: $(Build.SourcesDirectory)/CodeAnalysisLogs - condition: succeededOrFailed() - - # Use PublishBuildArtifacts because the SARIF extension only checks this case - # see microsoft/sarif-azuredevops-extension#4 - - task: PublishBuildArtifacts@1 - displayName: Publish SARIF files to CodeAnalysisLogs container - inputs: - pathToPublish: $(Build.SourcesDirectory)/CodeAnalysisLogs - artifactName: CodeAnalysisLogs - condition: succeededOrFailed() \ No newline at end of file diff --git a/eng/common/templates/steps/generate-sbom.yml b/eng/common/templates/steps/generate-sbom.yml index 2b21eae4273..26dc00a2e0f 100644 --- a/eng/common/templates/steps/generate-sbom.yml +++ b/eng/common/templates/steps/generate-sbom.yml @@ -1,48 +1,7 @@ -# BuildDropPath - The root folder of the drop directory for which the manifest file will be generated. -# PackageName - The name of the package this SBOM represents. -# PackageVersion - The version of the package this SBOM represents. -# ManifestDirPath - The path of the directory where the generated manifest files will be placed -# IgnoreDirectories - Directories to ignore for SBOM generation. This will be passed through to the CG component detector. - -parameters: - PackageVersion: 8.0.0 - BuildDropPath: '$(Build.SourcesDirectory)/artifacts' - PackageName: '.NET' - ManifestDirPath: $(Build.ArtifactStagingDirectory)/sbom - IgnoreDirectories: '' - sbomContinueOnError: true - steps: -- task: PowerShell@2 - displayName: Prep for SBOM generation in (Non-linux) - condition: or(eq(variables['Agent.Os'], 'Windows_NT'), eq(variables['Agent.Os'], 'Darwin')) - inputs: - filePath: ./eng/common/generate-sbom-prep.ps1 - arguments: ${{parameters.manifestDirPath}} - -# Chmodding is a workaround for https://github.com/dotnet/arcade/issues/8461 -- script: | - chmod +x ./eng/common/generate-sbom-prep.sh - ./eng/common/generate-sbom-prep.sh ${{parameters.manifestDirPath}} - displayName: Prep for SBOM generation in (Linux) - condition: eq(variables['Agent.Os'], 'Linux') - continueOnError: ${{ parameters.sbomContinueOnError }} - -- task: AzureArtifacts.manifest-generator-task.manifest-generator-task.ManifestGeneratorTask@0 - displayName: 'Generate SBOM manifest' - continueOnError: ${{ parameters.sbomContinueOnError }} - inputs: - PackageName: ${{ parameters.packageName }} - BuildDropPath: ${{ parameters.buildDropPath }} - PackageVersion: ${{ parameters.packageVersion }} - ManifestDirPath: ${{ parameters.manifestDirPath }} - ${{ if ne(parameters.IgnoreDirectories, '') }}: - AdditionalComponentDetectorArgs: '--IgnoreDirectories ${{ parameters.IgnoreDirectories }}' - -- task: PublishPipelineArtifact@1 - displayName: Publish SBOM manifest - continueOnError: ${{parameters.sbomContinueOnError}} - inputs: - targetPath: '${{parameters.manifestDirPath}}' - artifactName: $(ARTIFACT_NAME) +- template: /eng/common/core-templates/steps/generate-sbom.yml + parameters: + is1ESPipeline: false + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates/steps/get-delegation-sas.yml b/eng/common/templates/steps/get-delegation-sas.yml index c0e8f91317f..83760c9798e 100644 --- a/eng/common/templates/steps/get-delegation-sas.yml +++ b/eng/common/templates/steps/get-delegation-sas.yml @@ -1,43 +1,7 @@ -parameters: -- name: federatedServiceConnection - type: string -- name: outputVariableName - type: string -- name: expiryInHours - type: number - default: 1 -- name: base64Encode - type: boolean - default: false -- name: storageAccount - type: string -- name: container - type: string -- name: permissions - type: string - default: 'rl' - steps: -- task: AzureCLI@2 - displayName: 'Generate delegation SAS Token for ${{ parameters.storageAccount }}/${{ parameters.container }}' - inputs: - azureSubscription: ${{ parameters.federatedServiceConnection }} - scriptType: 'pscore' - scriptLocation: 'inlineScript' - inlineScript: | - # Calculate the expiration of the SAS token and convert to UTC - $expiry = (Get-Date).AddHours(${{ parameters.expiryInHours }}).ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ") - - $sas = az storage container generate-sas --account-name ${{ parameters.storageAccount }} --name ${{ parameters.container }} --permissions ${{ parameters.permissions }} --expiry $expiry --auth-mode login --as-user -o tsv - - if ($LASTEXITCODE -ne 0) { - Write-Error "Failed to generate SAS token." - exit 1 - } - - if ('${{ parameters.base64Encode }}' -eq 'true') { - $sas = [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($sas)) - } +- template: /eng/common/core-templates/steps/get-delegation-sas.yml + parameters: + is1ESPipeline: false - Write-Host "Setting '${{ parameters.outputVariableName }}' with the access token value" - Write-Host "##vso[task.setvariable variable=${{ parameters.outputVariableName }};issecret=true]$sas" + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates/steps/get-federated-access-token.yml b/eng/common/templates/steps/get-federated-access-token.yml index c8c49cc0e8f..31e151d9d9e 100644 --- a/eng/common/templates/steps/get-federated-access-token.yml +++ b/eng/common/templates/steps/get-federated-access-token.yml @@ -1,28 +1,7 @@ -parameters: -- name: federatedServiceConnection - type: string -- name: outputVariableName - type: string -# Resource to get a token for. Common values include: -# - '499b84ac-1321-427f-aa17-267ca6975798' for Azure DevOps -# - 'https://storage.azure.com/' for storage -# Defaults to Azure DevOps -- name: resource - type: string - default: '499b84ac-1321-427f-aa17-267ca6975798' - steps: -- task: AzureCLI@2 - displayName: 'Getting federated access token for feeds' - inputs: - azureSubscription: ${{ parameters.federatedServiceConnection }} - scriptType: 'pscore' - scriptLocation: 'inlineScript' - inlineScript: | - $accessToken = az account get-access-token --query accessToken --resource ${{ parameters.resource }} --output tsv - if ($LASTEXITCODE -ne 0) { - Write-Error "Failed to get access token for resource '${{ parameters.resource }}'" - exit 1 - } - Write-Host "Setting '${{ parameters.outputVariableName }}' with the access token value" - Write-Host "##vso[task.setvariable variable=${{ parameters.outputVariableName }};issecret=true]$accessToken" \ No newline at end of file +- template: /eng/common/core-templates/steps/get-federated-access-token.yml + parameters: + is1ESPipeline: false + + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} \ No newline at end of file diff --git a/eng/common/templates/steps/publish-build-artifacts.yml b/eng/common/templates/steps/publish-build-artifacts.yml new file mode 100644 index 00000000000..6428a98dfef --- /dev/null +++ b/eng/common/templates/steps/publish-build-artifacts.yml @@ -0,0 +1,40 @@ +parameters: +- name: is1ESPipeline + type: boolean + default: false + +- name: displayName + type: string + default: 'Publish to Build Artifact' + +- name: condition + type: string + default: succeeded() + +- name: artifactName + type: string + +- name: pathToPublish + type: string + +- name: continueOnError + type: boolean + default: false + +- name: publishLocation + type: string + default: 'Container' + +steps: +- ${{ if eq(parameters.is1ESPipeline, true) }}: + - 'eng/common/templates cannot be referenced from a 1ES managed template': error +- task: PublishBuildArtifacts@1 + displayName: ${{ parameters.displayName }} + condition: ${{ parameters.condition }} + ${{ if parameters.continueOnError }}: + continueOnError: ${{ parameters.continueOnError }} + inputs: + PublishLocation: ${{ parameters.publishLocation }} + PathtoPublish: ${{ parameters.pathToPublish }} + ${{ if parameters.artifactName }}: + ArtifactName: ${{ parameters.artifactName }} \ No newline at end of file diff --git a/eng/common/templates/steps/publish-logs.yml b/eng/common/templates/steps/publish-logs.yml index 88f238f36bf..4ea86bd8823 100644 --- a/eng/common/templates/steps/publish-logs.yml +++ b/eng/common/templates/steps/publish-logs.yml @@ -1,23 +1,7 @@ -parameters: - StageLabel: '' - JobLabel: '' - steps: -- task: Powershell@2 - displayName: Prepare Binlogs to Upload - inputs: - targetType: inline - script: | - New-Item -ItemType Directory $(Build.SourcesDirectory)/PostBuildLogs/${{parameters.StageLabel}}/${{parameters.JobLabel}}/ - Move-Item -Path $(Build.SourcesDirectory)/artifacts/log/Debug/* $(Build.SourcesDirectory)/PostBuildLogs/${{parameters.StageLabel}}/${{parameters.JobLabel}}/ - continueOnError: true - condition: always() +- template: /eng/common/core-templates/steps/publish-logs.yml + parameters: + is1ESPipeline: false -- task: PublishBuildArtifacts@1 - displayName: Publish Logs - inputs: - PathtoPublish: '$(Build.SourcesDirectory)/PostBuildLogs' - PublishLocation: Container - ArtifactName: PostBuildLogs - continueOnError: true - condition: always() + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates/steps/publish-pipeline-artifacts.yml b/eng/common/templates/steps/publish-pipeline-artifacts.yml new file mode 100644 index 00000000000..5dd698b212f --- /dev/null +++ b/eng/common/templates/steps/publish-pipeline-artifacts.yml @@ -0,0 +1,34 @@ +parameters: +- name: is1ESPipeline + type: boolean + default: false + +- name: args + type: object + default: {} + +steps: +- ${{ if eq(parameters.is1ESPipeline, true) }}: + - 'eng/common/templates cannot be referenced from a 1ES managed template': error +- task: PublishPipelineArtifact@1 + displayName: ${{ coalesce(parameters.args.displayName, 'Publish to Build Artifact') }} + ${{ if parameters.args.condition }}: + condition: ${{ parameters.args.condition }} + ${{ else }}: + condition: succeeded() + ${{ if parameters.args.continueOnError }}: + continueOnError: ${{ parameters.args.continueOnError }} + inputs: + targetPath: ${{ parameters.args.targetPath }} + ${{ if parameters.args.artifactName }}: + artifactName: ${{ parameters.args.artifactName }} + ${{ if parameters.args.publishLocation }}: + publishLocation: ${{ parameters.args.publishLocation }} + ${{ if parameters.args.fileSharePath }}: + fileSharePath: ${{ parameters.args.fileSharePath }} + ${{ if parameters.args.Parallel }}: + parallel: ${{ parameters.args.Parallel }} + ${{ if parameters.args.parallelCount }}: + parallelCount: ${{ parameters.args.parallelCount }} + ${{ if parameters.args.properties }}: + properties: ${{ parameters.args.properties }} \ No newline at end of file diff --git a/eng/common/templates/steps/retain-build.yml b/eng/common/templates/steps/retain-build.yml index 83d97a26a01..8e841ace3d2 100644 --- a/eng/common/templates/steps/retain-build.yml +++ b/eng/common/templates/steps/retain-build.yml @@ -1,28 +1,7 @@ -parameters: - # Optional azure devops PAT with build execute permissions for the build's organization, - # only needed if the build that should be retained ran on a different organization than - # the pipeline where this template is executing from - Token: '' - # Optional BuildId to retain, defaults to the current running build - BuildId: '' - # Azure devops Organization URI for the build in the https://dev.azure.com/ format. - # Defaults to the organization the current pipeline is running on - AzdoOrgUri: '$(System.CollectionUri)' - # Azure devops project for the build. Defaults to the project the current pipeline is running on - AzdoProject: '$(System.TeamProject)' - steps: - - task: powershell@2 - inputs: - targetType: 'filePath' - filePath: eng/common/retain-build.ps1 - pwsh: true - arguments: > - -AzdoOrgUri: ${{parameters.AzdoOrgUri}} - -AzdoProject ${{parameters.AzdoProject}} - -Token ${{coalesce(parameters.Token, '$env:SYSTEM_ACCESSTOKEN') }} - -BuildId ${{coalesce(parameters.BuildId, '$env:BUILD_ID')}} - displayName: Enable permanent build retention - env: - SYSTEM_ACCESSTOKEN: $(System.AccessToken) - BUILD_ID: $(Build.BuildId) \ No newline at end of file +- template: /eng/common/core-templates/steps/retain-build.yml + parameters: + is1ESPipeline: false + + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates/steps/run-on-unix.yml b/eng/common/templates/steps/run-on-unix.yml deleted file mode 100644 index e1733814f65..00000000000 --- a/eng/common/templates/steps/run-on-unix.yml +++ /dev/null @@ -1,7 +0,0 @@ -parameters: - agentOs: '' - steps: [] - -steps: -- ${{ if ne(parameters.agentOs, 'Windows_NT') }}: - - ${{ parameters.steps }} diff --git a/eng/common/templates/steps/run-on-windows.yml b/eng/common/templates/steps/run-on-windows.yml deleted file mode 100644 index 73e7e9c275a..00000000000 --- a/eng/common/templates/steps/run-on-windows.yml +++ /dev/null @@ -1,7 +0,0 @@ -parameters: - agentOs: '' - steps: [] - -steps: -- ${{ if eq(parameters.agentOs, 'Windows_NT') }}: - - ${{ parameters.steps }} diff --git a/eng/common/templates/steps/run-script-ifequalelse.yml b/eng/common/templates/steps/run-script-ifequalelse.yml deleted file mode 100644 index 3d1242f5587..00000000000 --- a/eng/common/templates/steps/run-script-ifequalelse.yml +++ /dev/null @@ -1,33 +0,0 @@ -parameters: - # if parameter1 equals parameter 2, run 'ifScript' command, else run 'elsescript' command - parameter1: '' - parameter2: '' - ifScript: '' - elseScript: '' - - # name of script step - name: Script - - # display name of script step - displayName: If-Equal-Else Script - - # environment - env: {} - - # conditional expression for step execution - condition: '' - -steps: -- ${{ if and(ne(parameters.ifScript, ''), eq(parameters.parameter1, parameters.parameter2)) }}: - - script: ${{ parameters.ifScript }} - name: ${{ parameters.name }} - displayName: ${{ parameters.displayName }} - env: ${{ parameters.env }} - condition: ${{ parameters.condition }} - -- ${{ if and(ne(parameters.elseScript, ''), ne(parameters.parameter1, parameters.parameter2)) }}: - - script: ${{ parameters.elseScript }} - name: ${{ parameters.name }} - displayName: ${{ parameters.displayName }} - env: ${{ parameters.env }} - condition: ${{ parameters.condition }} \ No newline at end of file diff --git a/eng/common/templates/steps/send-to-helix.yml b/eng/common/templates/steps/send-to-helix.yml index 3eb7e2d5f84..39f99fc2762 100644 --- a/eng/common/templates/steps/send-to-helix.yml +++ b/eng/common/templates/steps/send-to-helix.yml @@ -1,91 +1,7 @@ -# Please remember to update the documentation if you make changes to these parameters! -parameters: - HelixSource: 'pr/default' # required -- sources must start with pr/, official/, prodcon/, or agent/ - HelixType: 'tests/default/' # required -- Helix telemetry which identifies what type of data this is; should include "test" for clarity and must end in '/' - HelixBuild: $(Build.BuildNumber) # required -- the build number Helix will use to identify this -- automatically set to the AzDO build number - HelixTargetQueues: '' # required -- semicolon-delimited list of Helix queues to test on; see https://helix.dot.net/ for a list of queues - HelixAccessToken: '' # required -- access token to make Helix API requests; should be provided by the appropriate variable group - HelixConfiguration: '' # optional -- additional property attached to a job - HelixPreCommands: '' # optional -- commands to run before Helix work item execution - HelixPostCommands: '' # optional -- commands to run after Helix work item execution - WorkItemDirectory: '' # optional -- a payload directory to zip up and send to Helix; requires WorkItemCommand; incompatible with XUnitProjects - WorkItemCommand: '' # optional -- a command to execute on the payload; requires WorkItemDirectory; incompatible with XUnitProjects - WorkItemTimeout: '' # optional -- a timeout in TimeSpan.Parse-ready value (e.g. 00:02:00) for the work item command; requires WorkItemDirectory; incompatible with XUnitProjects - CorrelationPayloadDirectory: '' # optional -- a directory to zip up and send to Helix as a correlation payload - XUnitProjects: '' # optional -- semicolon-delimited list of XUnitProjects to parse and send to Helix; requires XUnitRuntimeTargetFramework, XUnitPublishTargetFramework, XUnitRunnerVersion, and IncludeDotNetCli=true - XUnitWorkItemTimeout: '' # optional -- the workitem timeout in seconds for all workitems created from the xUnit projects specified by XUnitProjects - XUnitPublishTargetFramework: '' # optional -- framework to use to publish your xUnit projects - XUnitRuntimeTargetFramework: '' # optional -- framework to use for the xUnit console runner - XUnitRunnerVersion: '' # optional -- version of the xUnit nuget package you wish to use on Helix; required for XUnitProjects - IncludeDotNetCli: false # optional -- true will download a version of the .NET CLI onto the Helix machine as a correlation payload; requires DotNetCliPackageType and DotNetCliVersion - DotNetCliPackageType: '' # optional -- either 'sdk', 'runtime' or 'aspnetcore-runtime'; determines whether the sdk or runtime will be sent to Helix; see https://raw.githubusercontent.com/dotnet/core/main/release-notes/releases-index.json - DotNetCliVersion: '' # optional -- version of the CLI to send to Helix; based on this: https://raw.githubusercontent.com/dotnet/core/main/release-notes/releases-index.json - WaitForWorkItemCompletion: true # optional -- true will make the task wait until work items have been completed and fail the build if work items fail. False is "fire and forget." - IsExternal: false # [DEPRECATED] -- doesn't do anything, jobs are external if HelixAccessToken is empty and Creator is set - HelixBaseUri: 'https://helix.dot.net/' # optional -- sets the Helix API base URI (allows targeting https://helix.int-dot.net ) - Creator: '' # optional -- if the build is external, use this to specify who is sending the job - DisplayNamePrefix: 'Run Tests' # optional -- rename the beginning of the displayName of the steps in AzDO - condition: succeeded() # optional -- condition for step to execute; defaults to succeeded() - continueOnError: false # optional -- determines whether to continue the build if the step errors; defaults to false - steps: - - powershell: 'powershell "$env:BUILD_SOURCESDIRECTORY\eng\common\msbuild.ps1 $env:BUILD_SOURCESDIRECTORY\eng\common\helixpublish.proj /restore /p:TreatWarningsAsErrors=false /t:Test /bl:$env:BUILD_SOURCESDIRECTORY\artifacts\log\$env:BuildConfig\SendToHelix.binlog"' - displayName: ${{ parameters.DisplayNamePrefix }} (Windows) - env: - BuildConfig: $(_BuildConfig) - HelixSource: ${{ parameters.HelixSource }} - HelixType: ${{ parameters.HelixType }} - HelixBuild: ${{ parameters.HelixBuild }} - HelixConfiguration: ${{ parameters.HelixConfiguration }} - HelixTargetQueues: ${{ parameters.HelixTargetQueues }} - HelixAccessToken: ${{ parameters.HelixAccessToken }} - HelixPreCommands: ${{ parameters.HelixPreCommands }} - HelixPostCommands: ${{ parameters.HelixPostCommands }} - WorkItemDirectory: ${{ parameters.WorkItemDirectory }} - WorkItemCommand: ${{ parameters.WorkItemCommand }} - WorkItemTimeout: ${{ parameters.WorkItemTimeout }} - CorrelationPayloadDirectory: ${{ parameters.CorrelationPayloadDirectory }} - XUnitProjects: ${{ parameters.XUnitProjects }} - XUnitWorkItemTimeout: ${{ parameters.XUnitWorkItemTimeout }} - XUnitPublishTargetFramework: ${{ parameters.XUnitPublishTargetFramework }} - XUnitRuntimeTargetFramework: ${{ parameters.XUnitRuntimeTargetFramework }} - XUnitRunnerVersion: ${{ parameters.XUnitRunnerVersion }} - IncludeDotNetCli: ${{ parameters.IncludeDotNetCli }} - DotNetCliPackageType: ${{ parameters.DotNetCliPackageType }} - DotNetCliVersion: ${{ parameters.DotNetCliVersion }} - WaitForWorkItemCompletion: ${{ parameters.WaitForWorkItemCompletion }} - HelixBaseUri: ${{ parameters.HelixBaseUri }} - Creator: ${{ parameters.Creator }} - SYSTEM_ACCESSTOKEN: $(System.AccessToken) - condition: and(${{ parameters.condition }}, eq(variables['Agent.Os'], 'Windows_NT')) - continueOnError: ${{ parameters.continueOnError }} - - script: $BUILD_SOURCESDIRECTORY/eng/common/msbuild.sh $BUILD_SOURCESDIRECTORY/eng/common/helixpublish.proj /restore /p:TreatWarningsAsErrors=false /t:Test /bl:$BUILD_SOURCESDIRECTORY/artifacts/log/$BuildConfig/SendToHelix.binlog - displayName: ${{ parameters.DisplayNamePrefix }} (Unix) - env: - BuildConfig: $(_BuildConfig) - HelixSource: ${{ parameters.HelixSource }} - HelixType: ${{ parameters.HelixType }} - HelixBuild: ${{ parameters.HelixBuild }} - HelixConfiguration: ${{ parameters.HelixConfiguration }} - HelixTargetQueues: ${{ parameters.HelixTargetQueues }} - HelixAccessToken: ${{ parameters.HelixAccessToken }} - HelixPreCommands: ${{ parameters.HelixPreCommands }} - HelixPostCommands: ${{ parameters.HelixPostCommands }} - WorkItemDirectory: ${{ parameters.WorkItemDirectory }} - WorkItemCommand: ${{ parameters.WorkItemCommand }} - WorkItemTimeout: ${{ parameters.WorkItemTimeout }} - CorrelationPayloadDirectory: ${{ parameters.CorrelationPayloadDirectory }} - XUnitProjects: ${{ parameters.XUnitProjects }} - XUnitWorkItemTimeout: ${{ parameters.XUnitWorkItemTimeout }} - XUnitPublishTargetFramework: ${{ parameters.XUnitPublishTargetFramework }} - XUnitRuntimeTargetFramework: ${{ parameters.XUnitRuntimeTargetFramework }} - XUnitRunnerVersion: ${{ parameters.XUnitRunnerVersion }} - IncludeDotNetCli: ${{ parameters.IncludeDotNetCli }} - DotNetCliPackageType: ${{ parameters.DotNetCliPackageType }} - DotNetCliVersion: ${{ parameters.DotNetCliVersion }} - WaitForWorkItemCompletion: ${{ parameters.WaitForWorkItemCompletion }} - HelixBaseUri: ${{ parameters.HelixBaseUri }} - Creator: ${{ parameters.Creator }} - SYSTEM_ACCESSTOKEN: $(System.AccessToken) - condition: and(${{ parameters.condition }}, ne(variables['Agent.Os'], 'Windows_NT')) - continueOnError: ${{ parameters.continueOnError }} +- template: /eng/common/core-templates/steps/send-to-helix.yml + parameters: + is1ESPipeline: false + + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates/steps/source-build.yml b/eng/common/templates/steps/source-build.yml index 41bbb915736..23c1d6f4e9f 100644 --- a/eng/common/templates/steps/source-build.yml +++ b/eng/common/templates/steps/source-build.yml @@ -1,129 +1,7 @@ -parameters: - # This template adds arcade-powered source-build to CI. - - # This is a 'steps' template, and is intended for advanced scenarios where the existing build - # infra has a careful build methodology that must be followed. For example, a repo - # (dotnet/runtime) might choose to clone the GitHub repo only once and store it as a pipeline - # artifact for all subsequent jobs to use, to reduce dependence on a strong network connection to - # GitHub. Using this steps template leaves room for that infra to be included. - - # Defines the platform on which to run the steps. See 'eng/common/templates/job/source-build.yml' - # for details. The entire object is described in the 'job' template for simplicity, even though - # the usage of the properties on this object is split between the 'job' and 'steps' templates. - platform: {} - steps: -# Build. Keep it self-contained for simple reusability. (No source-build-specific job variables.) -- script: | - set -x - df -h - - # If building on the internal project, the artifact feeds variable may be available (usually only if needed) - # In that case, call the feed setup script to add internal feeds corresponding to public ones. - # In addition, add an msbuild argument to copy the WIP from the repo to the target build location. - # This is because SetupNuGetSources.sh will alter the current NuGet.config file, and we need to preserve those - # changes. - internalRestoreArgs= - if [ '$(dn-bot-dnceng-artifact-feeds-rw)' != '$''(dn-bot-dnceng-artifact-feeds-rw)' ]; then - # Temporarily work around https://github.com/dotnet/arcade/issues/7709 - chmod +x $(Build.SourcesDirectory)/eng/common/SetupNugetSources.sh - $(Build.SourcesDirectory)/eng/common/SetupNugetSources.sh $(Build.SourcesDirectory)/NuGet.config $(dn-bot-dnceng-artifact-feeds-rw) - internalRestoreArgs='/p:CopyWipIntoInnerSourceBuildRepo=true' - - # The 'Copy WIP' feature of source build uses git stash to apply changes from the original repo. - # This only works if there is a username/email configured, which won't be the case in most CI runs. - git config --get user.email - if [ $? -ne 0 ]; then - git config user.email dn-bot@microsoft.com - git config user.name dn-bot - fi - fi - - # If building on the internal project, the internal storage variable may be available (usually only if needed) - # In that case, add variables to allow the download of internal runtimes if the specified versions are not found - # in the default public locations. - internalRuntimeDownloadArgs= - if [ '$(dotnetbuilds-internal-container-read-token-base64)' != '$''(dotnetbuilds-internal-container-read-token-base64)' ]; then - internalRuntimeDownloadArgs='/p:DotNetRuntimeSourceFeed=https://dotnetbuilds.blob.core.windows.net/internal /p:DotNetRuntimeSourceFeedKey=$(dotnetbuilds-internal-container-read-token-base64) --runtimesourcefeed https://dotnetbuilds.blob.core.windows.net/internal --runtimesourcefeedkey $(dotnetbuilds-internal-container-read-token-base64)' - fi - - buildConfig=Release - # Check if AzDO substitutes in a build config from a variable, and use it if so. - if [ '$(_BuildConfig)' != '$''(_BuildConfig)' ]; then - buildConfig='$(_BuildConfig)' - fi - - officialBuildArgs= - if [ '${{ and(ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}' = 'True' ]; then - officialBuildArgs='/p:DotNetPublishUsingPipelines=true /p:OfficialBuildId=$(BUILD.BUILDNUMBER)' - fi - - targetRidArgs= - if [ '${{ parameters.platform.targetRID }}' != '' ]; then - targetRidArgs='/p:TargetRid=${{ parameters.platform.targetRID }}' - fi - - runtimeOsArgs= - if [ '${{ parameters.platform.runtimeOS }}' != '' ]; then - runtimeOsArgs='/p:RuntimeOS=${{ parameters.platform.runtimeOS }}' - fi - - baseOsArgs= - if [ '${{ parameters.platform.baseOS }}' != '' ]; then - baseOsArgs='/p:BaseOS=${{ parameters.platform.baseOS }}' - fi - - publishArgs= - if [ '${{ parameters.platform.skipPublishValidation }}' != 'true' ]; then - publishArgs='--publish' - fi - - assetManifestFileName=SourceBuild_RidSpecific.xml - if [ '${{ parameters.platform.name }}' != '' ]; then - assetManifestFileName=SourceBuild_${{ parameters.platform.name }}.xml - fi - - ${{ coalesce(parameters.platform.buildScript, './build.sh') }} --ci \ - --configuration $buildConfig \ - --restore --build --pack $publishArgs -bl \ - $officialBuildArgs \ - $internalRuntimeDownloadArgs \ - $internalRestoreArgs \ - $targetRidArgs \ - $runtimeOsArgs \ - $baseOsArgs \ - /p:SourceBuildNonPortable=${{ parameters.platform.nonPortable }} \ - /p:ArcadeBuildFromSource=true \ - /p:AssetManifestFileName=$assetManifestFileName - displayName: Build - -# Upload build logs for diagnosis. -- task: CopyFiles@2 - displayName: Prepare BuildLogs staging directory - inputs: - SourceFolder: '$(Build.SourcesDirectory)' - Contents: | - **/*.log - **/*.binlog - artifacts/source-build/self/prebuilt-report/** - TargetFolder: '$(Build.StagingDirectory)/BuildLogs' - CleanTargetFolder: true - continueOnError: true - condition: succeededOrFailed() - -- task: PublishPipelineArtifact@1 - displayName: Publish BuildLogs - inputs: - targetPath: '$(Build.StagingDirectory)/BuildLogs' - artifactName: BuildLogs_SourceBuild_${{ parameters.platform.name }}_Attempt$(System.JobAttempt) - continueOnError: true - condition: succeededOrFailed() +- template: /eng/common/core-templates/steps/source-build.yml + parameters: + is1ESPipeline: false -# Manually inject component detection so that we can ignore the source build upstream cache, which contains -# a nupkg cache of input packages (a local feed). -# This path must match the upstream cache path in property 'CurrentRepoSourceBuiltNupkgCacheDir' -# in src\Microsoft.DotNet.Arcade.Sdk\tools\SourceBuild\SourceBuildArcade.targets -- task: ComponentGovernanceComponentDetection@0 - displayName: Component Detection (Exclude upstream cache) - inputs: - ignoreDirectories: '$(Build.SourcesDirectory)/artifacts/source-build/self/src/artifacts/obj/source-built-upstream-cache' + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates/steps/telemetry-end.yml b/eng/common/templates/steps/telemetry-end.yml deleted file mode 100644 index fadc04ca1b9..00000000000 --- a/eng/common/templates/steps/telemetry-end.yml +++ /dev/null @@ -1,102 +0,0 @@ -parameters: - maxRetries: 5 - retryDelay: 10 # in seconds - -steps: -- bash: | - if [ "$AGENT_JOBSTATUS" = "Succeeded" ] || [ "$AGENT_JOBSTATUS" = "PartiallySucceeded" ]; then - errorCount=0 - else - errorCount=1 - fi - warningCount=0 - - curlStatus=1 - retryCount=0 - # retry loop to harden against spotty telemetry connections - # we don't retry successes and 4xx client errors - until [[ $curlStatus -eq 0 || ( $curlStatus -ge 400 && $curlStatus -le 499 ) || $retryCount -ge $MaxRetries ]] - do - if [ $retryCount -gt 0 ]; then - echo "Failed to send telemetry to Helix; waiting $RetryDelay seconds before retrying..." - sleep $RetryDelay - fi - - # create a temporary file for curl output - res=`mktemp` - - curlResult=` - curl --verbose --output $res --write-out "%{http_code}"\ - -H 'Content-Type: application/json' \ - -H "X-Helix-Job-Token: $Helix_JobToken" \ - -H 'Content-Length: 0' \ - -X POST -G "https://helix.dot.net/api/2018-03-14/telemetry/job/build/$Helix_WorkItemId/finish" \ - --data-urlencode "errorCount=$errorCount" \ - --data-urlencode "warningCount=$warningCount"` - curlStatus=$? - - if [ $curlStatus -eq 0 ]; then - if [ $curlResult -gt 299 ] || [ $curlResult -lt 200 ]; then - curlStatus=$curlResult - fi - fi - - let retryCount++ - done - - if [ $curlStatus -ne 0 ]; then - echo "Failed to Send Build Finish information after $retryCount retries" - vstsLogOutput="vso[task.logissue type=error;sourcepath=templates/steps/telemetry-end.yml;code=1;]Failed to Send Build Finish information: $curlStatus" - echo "##$vstsLogOutput" - exit 1 - fi - displayName: Send Unix Build End Telemetry - env: - # defined via VSTS variables in start-job.sh - Helix_JobToken: $(Helix_JobToken) - Helix_WorkItemId: $(Helix_WorkItemId) - MaxRetries: ${{ parameters.maxRetries }} - RetryDelay: ${{ parameters.retryDelay }} - condition: and(always(), ne(variables['Agent.Os'], 'Windows_NT')) -- powershell: | - if (($env:Agent_JobStatus -eq 'Succeeded') -or ($env:Agent_JobStatus -eq 'PartiallySucceeded')) { - $ErrorCount = 0 - } else { - $ErrorCount = 1 - } - $WarningCount = 0 - - # Basic retry loop to harden against server flakiness - $retryCount = 0 - while ($retryCount -lt $env:MaxRetries) { - try { - Invoke-RestMethod -Uri "https://helix.dot.net/api/2018-03-14/telemetry/job/build/$env:Helix_WorkItemId/finish?errorCount=$ErrorCount&warningCount=$WarningCount" -Method Post -ContentType "application/json" -Body "" ` - -Headers @{ 'X-Helix-Job-Token'=$env:Helix_JobToken } - break - } - catch { - $statusCode = $_.Exception.Response.StatusCode.value__ - if ($statusCode -ge 400 -and $statusCode -le 499) { - Write-Host "##vso[task.logissue]error Failed to send telemetry to Helix (status code $statusCode); not retrying (4xx client error)" - Write-Host "##vso[task.logissue]error ", $_.Exception.GetType().FullName, $_.Exception.Message - exit 1 - } - Write-Host "Failed to send telemetry to Helix (status code $statusCode); waiting $env:RetryDelay seconds before retrying..." - $retryCount++ - sleep $env:RetryDelay - continue - } - } - - if ($retryCount -ge $env:MaxRetries) { - Write-Host "##vso[task.logissue]error Failed to send telemetry to Helix after $retryCount retries." - exit 1 - } - displayName: Send Windows Build End Telemetry - env: - # defined via VSTS variables in start-job.ps1 - Helix_JobToken: $(Helix_JobToken) - Helix_WorkItemId: $(Helix_WorkItemId) - MaxRetries: ${{ parameters.maxRetries }} - RetryDelay: ${{ parameters.retryDelay }} - condition: and(always(),eq(variables['Agent.Os'], 'Windows_NT')) diff --git a/eng/common/templates/steps/telemetry-start.yml b/eng/common/templates/steps/telemetry-start.yml deleted file mode 100644 index 32c01ef0b55..00000000000 --- a/eng/common/templates/steps/telemetry-start.yml +++ /dev/null @@ -1,241 +0,0 @@ -parameters: - helixSource: 'undefined_defaulted_in_telemetry.yml' - helixType: 'undefined_defaulted_in_telemetry.yml' - buildConfig: '' - runAsPublic: false - maxRetries: 5 - retryDelay: 10 # in seconds - -steps: -- ${{ if and(eq(parameters.runAsPublic, 'false'), not(eq(variables['System.TeamProject'], 'public'))) }}: - - task: AzureKeyVault@1 - inputs: - azureSubscription: 'HelixProd_KeyVault' - KeyVaultName: HelixProdKV - SecretsFilter: 'HelixApiAccessToken' - condition: always() -- bash: | - # create a temporary file - jobInfo=`mktemp` - - # write job info content to temporary file - cat > $jobInfo < /dev/null; then echo "Curl failed; dumping some information about dotnet.microsoft.com for later investigation" - echo | openssl s_client -showcerts -servername dotnet.microsoft.com -connect dotnet.microsoft.com:443 + echo | openssl s_client -showcerts -servername dotnet.microsoft.com -connect dotnet.microsoft.com:443 || true fi echo "Will now retry the same URL with verbose logging." with_retries curl "$install_script_url" -sSL --verbose --retry 10 --create-dirs -o "$install_script" || { @@ -343,20 +341,20 @@ function InitializeBuildTool { _InitializeBuildToolCommand="msbuild" # use override if it exists - commonly set by source-build if [[ "${_OverrideArcadeInitializeBuildToolFramework:-x}" == "x" ]]; then - _InitializeBuildToolFramework="net8.0" + _InitializeBuildToolFramework="net9.0" else _InitializeBuildToolFramework="${_OverrideArcadeInitializeBuildToolFramework}" fi } -# Set RestoreNoCache as a workaround for https://github.com/NuGet/Home/issues/3116 +# Set RestoreNoHttpCache as a workaround for https://github.com/NuGet/Home/issues/3116 function GetNuGetPackageCachePath { if [[ -z ${NUGET_PACKAGES:-} ]]; then if [[ "$use_global_nuget_cache" == true ]]; then - export NUGET_PACKAGES="$HOME/.nuget/packages" + export NUGET_PACKAGES="$HOME/.nuget/packages/" else - export NUGET_PACKAGES="$repo_root/.packages" - export RESTORENOCACHE=true + export NUGET_PACKAGES="$repo_root/.packages/" + export RESTORENOHTTPCACHE=true fi fi @@ -440,7 +438,7 @@ function StopProcesses { } function MSBuild { - local args=$@ + local args=( "$@" ) if [[ "$pipelines_log" == true ]]; then InitializeBuildTool InitializeToolset @@ -458,12 +456,10 @@ function MSBuild { local possiblePaths=() possiblePaths+=( "$toolset_dir/$_InitializeBuildToolFramework/Microsoft.DotNet.ArcadeLogging.dll" ) possiblePaths+=( "$toolset_dir/$_InitializeBuildToolFramework/Microsoft.DotNet.Arcade.Sdk.dll" ) - possiblePaths+=( "$toolset_dir/netcoreapp2.1/Microsoft.DotNet.ArcadeLogging.dll" ) - possiblePaths+=( "$toolset_dir/netcoreapp2.1/Microsoft.DotNet.Arcade.Sdk.dll" ) - possiblePaths+=( "$toolset_dir/netcoreapp3.1/Microsoft.DotNet.ArcadeLogging.dll" ) - possiblePaths+=( "$toolset_dir/netcoreapp3.1/Microsoft.DotNet.Arcade.Sdk.dll" ) possiblePaths+=( "$toolset_dir/net7.0/Microsoft.DotNet.ArcadeLogging.dll" ) possiblePaths+=( "$toolset_dir/net7.0/Microsoft.DotNet.Arcade.Sdk.dll" ) + possiblePaths+=( "$toolset_dir/net8.0/Microsoft.DotNet.ArcadeLogging.dll" ) + possiblePaths+=( "$toolset_dir/net8.0/Microsoft.DotNet.Arcade.Sdk.dll" ) for path in "${possiblePaths[@]}"; do if [[ -f $path ]]; then selectedPath=$path @@ -477,7 +473,7 @@ function MSBuild { args+=( "-logger:$selectedPath" ) fi - MSBuild-Core ${args[@]} + MSBuild-Core "${args[@]}" } function MSBuild-Core { @@ -510,7 +506,8 @@ function MSBuild-Core { echo "Build failed with exit code $exit_code. Check errors above." # When running on Azure Pipelines, override the returned exit code to avoid double logging. - if [[ "$ci" == "true" && -n ${SYSTEM_TEAMPROJECT:-} ]]; then + # Skip this when the build is a child of the VMR orchestrator build. + if [[ "$ci" == true && -n ${SYSTEM_TEAMPROJECT:-} && "$product_build" != true && "$properties" != *"DotNetBuildRepo=true"* ]]; then Write-PipelineSetResult -result "Failed" -message "msbuild execution failed." # Exiting with an exit code causes the azure pipelines task to log yet another "noise" error # The above Write-PipelineSetResult will cause the task to be marked as failure without adding yet another error diff --git a/global.json b/global.json index 84da89a24e8..9af5736134a 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "tools": { - "dotnet": "8.0.101", + "dotnet": "9.0.100-preview.5.24307.3", "runtimes": { "dotnet": [ "2.1.30", @@ -16,12 +16,12 @@ } }, "sdk": { - "version": "8.0.101", + "version": "9.0.100-preview.5.24307.3", "allowPrerelease": false, "rollForward": "latestPatch" }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "8.0.0-beta.24352.1", + "Microsoft.DotNet.Arcade.Sdk": "9.0.0-beta.24352.2", "Microsoft.Build.NoTargets": "3.7.0" } } From e957bb2f8193b8f2c09df0072807880e5a0723bd Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Tue, 9 Jul 2024 08:58:49 -0700 Subject: [PATCH 025/176] Nullable-enable `DefaultRazorTagHelperContextDiscoveryPhase` --- ...aultRazorTagHelperContextDiscoveryPhase.cs | 45 ++++++++++--------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/DefaultRazorTagHelperContextDiscoveryPhase.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/DefaultRazorTagHelperContextDiscoveryPhase.cs index 7957b1a66dc..998c4375d38 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/DefaultRazorTagHelperContextDiscoveryPhase.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/DefaultRazorTagHelperContextDiscoveryPhase.cs @@ -1,12 +1,10 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -#nullable disable - using System; using System.Collections.Generic; -using System.Collections.Immutable; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using Microsoft.AspNetCore.Razor.Language.Components; using Microsoft.AspNetCore.Razor.Language.Legacy; using Microsoft.AspNetCore.Razor.Language.Syntax; @@ -24,13 +22,13 @@ protected override void ExecuteCore(RazorCodeDocument codeDocument) var descriptors = codeDocument.GetTagHelpers(); if (descriptors == null) { - if (!Engine.TryGetFeature(out ITagHelperFeature feature)) + if (!Engine.TryGetFeature(out ITagHelperFeature? tagHelperFeature)) { // No feature, nothing to do. return; } - descriptors = feature.GetDescriptors(); + descriptors = tagHelperFeature.GetDescriptors(); } var parserOptions = codeDocument.GetParserOptions(); @@ -46,7 +44,8 @@ protected override void ExecuteCore(RazorCodeDocument codeDocument) (parserOptions == null || parserOptions.FeatureFlags.AllowComponentFileKind)) { codeDocument.TryComputeNamespace(fallbackToRootNamespace: true, out var currentNamespace); - visitor = new ComponentDirectiveVisitor(codeDocument.Source.FilePath, descriptors, currentNamespace, matches); + var filePath = codeDocument.Source.FilePath.AssumeNotNull(); + visitor = new ComponentDirectiveVisitor(filePath, descriptors, currentNamespace, matches); } else { @@ -68,7 +67,7 @@ protected override void ExecuteCore(RazorCodeDocument codeDocument) // This will always be null for a component document. var tagHelperPrefix = visitor.TagHelperPrefix; - var context = TagHelperDocumentContext.Create(tagHelperPrefix, matches.ToImmutableArray()); + var context = TagHelperDocumentContext.Create(tagHelperPrefix, [.. matches]); codeDocument.SetTagHelperContext(context); codeDocument.SetPreTagHelperSyntaxTree(syntaxTree); } @@ -113,7 +112,7 @@ internal abstract class DirectiveVisitor(HashSet matches) : { protected readonly HashSet Matches = matches; - public abstract string TagHelperPrefix { get; } + public abstract string? TagHelperPrefix { get; } public abstract void Visit(RazorSyntaxTree tree); @@ -122,8 +121,8 @@ internal abstract class DirectiveVisitor(HashSet matches) : internal sealed class TagHelperDirectiveVisitor : DirectiveVisitor { - private List _tagHelpers; - private string _tagHelperPrefix; + private List? _tagHelpers; + private string? _tagHelperPrefix; public TagHelperDirectiveVisitor(IReadOnlyList tagHelpers, HashSet matches) : base(matches) @@ -141,7 +140,7 @@ public TagHelperDirectiveVisitor(IReadOnlyList tagHelpers, } } - public override string TagHelperPrefix => _tagHelperPrefix; + public override string? TagHelperPrefix => _tagHelperPrefix; public override void Visit(RazorSyntaxTree tree) { @@ -193,7 +192,6 @@ public override void VisitRazorDirective(RazorDirectiveSyntax node) continue; } - if (!AssemblyContainsTagHelpers(removeTagHelper.AssemblyName, _tagHelpers)) { // No tag helpers in the assembly. @@ -222,8 +220,13 @@ public override void VisitRazorDirective(RazorDirectiveSyntax node) } } - private static bool AssemblyContainsTagHelpers(string assemblyName, List tagHelpers) + private static bool AssemblyContainsTagHelpers(string assemblyName, [NotNullWhen(true)] List? tagHelpers) { + if (tagHelpers is null) + { + return false; + } + foreach (var tagHelper in tagHelpers) { if (tagHelper.AssemblyName == assemblyName) @@ -247,9 +250,9 @@ public override void Dispose() internal sealed class ComponentDirectiveVisitor : DirectiveVisitor { - private List _notFullyQualifiedComponents; + private List? _notFullyQualifiedComponents; private readonly string _filePath; - private RazorSourceDocument _source; + private RazorSourceDocument? _source; public ComponentDirectiveVisitor(string filePath, IReadOnlyList tagHelpers, string currentNamespace, HashSet matches) : base(matches) @@ -299,7 +302,7 @@ public ComponentDirectiveVisitor(string filePath, IReadOnlyList null; + public override string? TagHelperPrefix => null; public override void Visit(RazorSyntaxTree tree) { @@ -324,7 +327,7 @@ public override void VisitRazorDirective(RazorDirectiveSyntax node) continue; case AddTagHelperChunkGenerator addTagHelper: // Make sure this node exists in the file we're parsing and not in its imports. - if (_filePath.Equals(_source.FilePath, StringComparison.Ordinal)) + if (_filePath.Equals(_source.AssumeNotNull().FilePath, StringComparison.Ordinal)) { addTagHelper.Diagnostics.Add( ComponentDiagnosticFactory.Create_UnsupportedTagHelperDirective(node.GetSourceSpan(_source))); @@ -332,7 +335,7 @@ public override void VisitRazorDirective(RazorDirectiveSyntax node) break; case RemoveTagHelperChunkGenerator removeTagHelper: // Make sure this node exists in the file we're parsing and not in its imports. - if (_filePath.Equals(_source.FilePath, StringComparison.Ordinal)) + if (_filePath.Equals(_source.AssumeNotNull().FilePath, StringComparison.Ordinal)) { removeTagHelper.Diagnostics.Add( ComponentDiagnosticFactory.Create_UnsupportedTagHelperDirective(node.GetSourceSpan(_source))); @@ -340,7 +343,7 @@ public override void VisitRazorDirective(RazorDirectiveSyntax node) break; case TagHelperPrefixDirectiveChunkGenerator tagHelperPrefix: // Make sure this node exists in the file we're parsing and not in its imports. - if (_filePath.Equals(_source.FilePath, StringComparison.Ordinal)) + if (_filePath.Equals(_source.AssumeNotNull().FilePath, StringComparison.Ordinal)) { tagHelperPrefix.Diagnostics.Add( ComponentDiagnosticFactory.Create_UnsupportedTagHelperDirective(node.GetSourceSpan(_source))); @@ -349,13 +352,13 @@ public override void VisitRazorDirective(RazorDirectiveSyntax node) case AddImportChunkGenerator { IsStatic: false } usingStatement: // Get the namespace from the using statement. var @namespace = usingStatement.ParsedNamespace; - if (@namespace.IndexOf('=') != -1) + if (@namespace.Contains('=')) { // We don't support usings with alias. continue; } - foreach (var tagHelper in _notFullyQualifiedComponents) + foreach (var tagHelper in _notFullyQualifiedComponents.AssumeNotNull()) { Debug.Assert(!tagHelper.IsComponentFullyQualifiedNameMatch, "We've already processed these."); From b24cd9cb1408ab05343922442e11c480286be871 Mon Sep 17 00:00:00 2001 From: Chris Sienkiewicz Date: Tue, 9 Jul 2024 11:16:22 -0700 Subject: [PATCH 026/176] Improve perf in generator cache cases (#10577) * Manually validate if additional files and metadata references have actually changed * Short circuit metadata ref comparer * Add tests --- .../RazorSourceGenerator.Helpers.cs | 1 - .../SourceGenerators/RazorSourceGenerator.cs | 34 ++++++- .../SourceGeneratorProjectItem.cs | 17 +++- .../RazorSourceGeneratorTests.cs | 88 +++++++++++++++++++ 4 files changed, 137 insertions(+), 3 deletions(-) diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/SourceGenerators/RazorSourceGenerator.Helpers.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/SourceGenerators/RazorSourceGenerator.Helpers.cs index b4bbcf595cd..bc0e302982d 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/SourceGenerators/RazorSourceGenerator.Helpers.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/SourceGenerators/RazorSourceGenerator.Helpers.cs @@ -74,7 +74,6 @@ private static StaticCompilationTagHelperFeature GetStaticTagHelperFeature(Compi // the tagHelperFeature will have its Engine property set as part of adding it to the engine, which is used later when doing the actual discovery var discoveryProjectEngine = RazorProjectEngine.Create(RazorConfiguration.Default, new VirtualRazorProjectFileSystem(), b => { - b.Features.Add(new DefaultMetadataReferenceFeature { References = compilation.References.ToImmutableArray() }); b.Features.Add(tagHelperFeature); b.Features.Add(new DefaultTagHelperDescriptorProvider()); diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/SourceGenerators/RazorSourceGenerator.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/SourceGenerators/RazorSourceGenerator.cs index 90f2a42312a..2d30561712b 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/SourceGenerators/RazorSourceGenerator.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/SourceGenerators/RazorSourceGenerator.cs @@ -145,7 +145,39 @@ public void Initialize(IncrementalGeneratorInitializationContext context) var ((compilationA, razorSourceGeneratorOptionsA), hasRazorFilesA) = a; var ((compilationB, razorSourceGeneratorOptionsB), hasRazorFilesB) = b; - if (!compilationA.References.SequenceEqual(compilationB.References)) + // When using the generator cache in the compiler it's possible to encounter metadata references that are different instances + // but ultimately represent the same underlying assembly. We compare the module version ids to determine if the references are the same + if (!compilationA.References.SequenceEqual(compilationB.References, new LambdaComparer((old, @new) => + { + if (ReferenceEquals(old, @new)) + { + return true; + } + + if (old is null || @new is null) + { + return false; + } + + var oldSymbol = compilationA.GetAssemblyOrModuleSymbol(old); + var newSymbol = compilationB.GetAssemblyOrModuleSymbol(@new); + + if (SymbolEqualityComparer.Default.Equals(oldSymbol, newSymbol)) + { + return true; + } + + if (oldSymbol is IAssemblySymbol oldAssembly && newSymbol is IAssemblySymbol newAssembly) + { + var oldModuleMVIDs = oldAssembly.Modules.Select(GetMVID); + var newModuleMVIDs = newAssembly.Modules.Select(GetMVID); + return oldModuleMVIDs.SequenceEqual(newModuleMVIDs); + + static Guid GetMVID(IModuleSymbol m) => m.GetMetadata()?.GetModuleVersionId() ?? Guid.Empty; + } + + return false; + }))) { return false; } diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/SourceGenerators/SourceGeneratorProjectItem.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/SourceGenerators/SourceGeneratorProjectItem.cs index 55950c564ce..73592d47f6b 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/SourceGenerators/SourceGeneratorProjectItem.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/SourceGenerators/SourceGeneratorProjectItem.cs @@ -3,6 +3,7 @@ using System; using System.IO; +using System.Linq; using Microsoft.AspNetCore.Razor.Language; using Microsoft.CodeAnalysis; @@ -47,7 +48,21 @@ public override Stream Read() => throw new NotSupportedException("This API should not be invoked. We should instead be relying on " + "the RazorSourceDocument associated with this item instead."); - public bool Equals(SourceGeneratorProjectItem? other) => other is not null && AdditionalText == other.AdditionalText; + public bool Equals(SourceGeneratorProjectItem? other) + { + if (ReferenceEquals(AdditionalText, other?.AdditionalText)) + { + return true; + } + + // In the compiler server when the generator driver cache is enabled the + // additional files are always different instances even if their content is the same. + // It's technically possible for these hashes to collide, but other things would + // also break in those cases, so for now we're okay with this. + var thisHash = AdditionalText.GetText()?.GetContentHash() ?? []; + var otherHash = other?.AdditionalText.GetText()?.GetContentHash() ?? []; + return thisHash.SequenceEqual(otherHash); + } public override int GetHashCode() => AdditionalText.GetHashCode(); diff --git a/src/Compiler/test/Microsoft.NET.Sdk.Razor.SourceGenerators.Tests/RazorSourceGeneratorTests.cs b/src/Compiler/test/Microsoft.NET.Sdk.Razor.SourceGenerators.Tests/RazorSourceGeneratorTests.cs index f85188fc36a..9d5de9e89e6 100644 --- a/src/Compiler/test/Microsoft.NET.Sdk.Razor.SourceGenerators.Tests/RazorSourceGeneratorTests.cs +++ b/src/Compiler/test/Microsoft.NET.Sdk.Razor.SourceGenerators.Tests/RazorSourceGeneratorTests.cs @@ -3175,5 +3175,93 @@ public class LambdaGenerator(Action a { public void Initialize(IncrementalGeneratorInitializationContext context) => action(context); } + + [Fact] + public async Task IncrementalCompilation_NothingRuns_When_AdditionalFiles_HaveSameContent() + { + // Arrange + using var eventListener = new RazorEventListener(); + var project = CreateTestProject(new() + { + ["Pages/Index.razor"] = "

Hello world

", + ["Pages/Counter.razor"] = "

Counter

", + }); + var compilation = await project.GetCompilationAsync(); + var (driver, additionalTexts) = await GetDriverWithAdditionalTextAsync(project); + + var result = RunGenerator(compilation!, ref driver); + Assert.Empty(result.Diagnostics); + Assert.Equal(2, result.GeneratedSources.Length); + + eventListener.Events.Clear(); + + result = RunGenerator(compilation!, ref driver) + .VerifyOutputsMatch(result); + + Assert.Empty(result.Diagnostics); + Assert.Equal(2, result.GeneratedSources.Length); + Assert.Empty(eventListener.Events); + + project = project.RemoveAdditionalDocument(project.AdditionalDocumentIds[1]) + .AddAdditionalDocument("Counter.razor", SourceText.From("

Counter

", Encoding.UTF8)) + .Project; + + compilation = await project.GetCompilationAsync(); + + result = RunGenerator(compilation!, ref driver) + .VerifyOutputsMatch(result); + + Assert.Empty(result.Diagnostics); + Assert.Equal(2, result.GeneratedSources.Length); + + Assert.Empty(eventListener.Events); + } + + [Fact] + public async Task IncrementalCompilation_OnlyCompilationRuns_When_MetadataReferences_SameAssembly() + { + // Arrange + using var eventListener = new RazorEventListener(); + var project = CreateTestProject(new() + { + ["Pages/Index.razor"] = "

Hello world

", + ["Pages/Counter.razor"] = "

Counter

", + }); + var compilation = await project.GetCompilationAsync(); + var (driver, additionalTexts) = await GetDriverWithAdditionalTextAsync(project); + + var result = RunGenerator(compilation!, ref driver); + + Assert.Empty(result.Diagnostics); + Assert.Equal(2, result.GeneratedSources.Length); + + eventListener.Events.Clear(); + + result = RunGenerator(compilation!, ref driver) + .VerifyOutputsMatch(result); + + Assert.Empty(result.Diagnostics); + Assert.Equal(2, result.GeneratedSources.Length); + Assert.Empty(eventListener.Events); + + var reference = (PortableExecutableReference) project.MetadataReferences[^1]; + + project = project.RemoveMetadataReference(reference) + .AddMetadataReference(MetadataReference.CreateFromFile(reference.FilePath!)); + + compilation = await project.GetCompilationAsync(); + + result = RunGenerator(compilation!, ref driver) + .VerifyOutputsMatch(result); + + Assert.Empty(result.Diagnostics); + Assert.Equal(2, result.GeneratedSources.Length); + + // reference causes the compilation to change so we re-run tag helper discovery there + // but we didn't re-check the actual reference itself + Assert.Collection(eventListener.Events, + e => Assert.Equal("DiscoverTagHelpersFromCompilationStart", e.EventName), + e => Assert.Equal("DiscoverTagHelpersFromCompilationStop", e.EventName)); + } } } From 7d38fdf1082a324a58ad82c78ea5e323e8282e70 Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Tue, 9 Jul 2024 10:16:42 -0700 Subject: [PATCH 027/176] Add pooling for DirectiveVisitors --- .../DefaultRazorTagHelperBinderPhaseTest.cs | 108 ++++++------ ...aultRazorTagHelperContextDiscoveryPhase.cs | 166 +++++++++--------- ...rTagHelperContextDiscoveryPhase_Pooling.cs | 78 ++++++++ .../RazorTagHelperParsingBenchmark.cs | 4 +- 4 files changed, 225 insertions(+), 131 deletions(-) create mode 100644 src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/DefaultRazorTagHelperContextDiscoveryPhase_Pooling.cs diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/DefaultRazorTagHelperBinderPhaseTest.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/DefaultRazorTagHelperBinderPhaseTest.cs index 68b3fdfcd88..567dfe62ff6 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/DefaultRazorTagHelperBinderPhaseTest.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/DefaultRazorTagHelperBinderPhaseTest.cs @@ -724,8 +724,8 @@ public void DirectiveVisitor_ExtractsPrefixFromSyntaxTree( var sourceDocument = TestRazorSourceDocument.Create(source, filePath: "TestFile"); var parser = new RazorParser(); var syntaxTree = parser.Parse(sourceDocument); - var matches = new HashSet(); - var visitor = new DefaultRazorTagHelperContextDiscoveryPhase.TagHelperDirectiveVisitor(tagHelpers: [], matches); + var visitor = new DefaultRazorTagHelperContextDiscoveryPhase.TagHelperDirectiveVisitor(); + visitor.Initialize(tagHelpers: []); // Act visitor.Visit(syntaxTree.Root); @@ -883,26 +883,26 @@ public static TheoryData ProcessTagHelperMatchesData [MemberData(nameof(ProcessTagHelperMatchesData))] public void DirectiveVisitor_FiltersTagHelpersByDirectives( string source, - object tagHelpers, - object expectedDescriptors) + TagHelperDescriptor[] tagHelpers, + TagHelperDescriptor[] expectedTagHelpers) { // Arrange - var expected = (TagHelperDescriptor[])expectedDescriptors; var sourceDocument = TestRazorSourceDocument.Create(source, filePath: "TestFile"); var parser = new RazorParser(); var syntaxTree = parser.Parse(sourceDocument); - var matches = new HashSet(); - var visitor = new DefaultRazorTagHelperContextDiscoveryPhase.TagHelperDirectiveVisitor((TagHelperDescriptor[])tagHelpers, matches); + var visitor = new DefaultRazorTagHelperContextDiscoveryPhase.TagHelperDirectiveVisitor(); + visitor.Initialize(tagHelpers); // Act visitor.Visit(syntaxTree.Root); + var results = visitor.GetResults(); // Assert - Assert.Equal(expected.Length, matches.Count); + Assert.Equal(expectedTagHelpers.Length, results.Length); - foreach (var expectedDescriptor in expected) + foreach (var expectedTagHelper in expectedTagHelpers) { - Assert.Contains(expectedDescriptor, matches); + Assert.Contains(expectedTagHelper, results); } } @@ -1030,20 +1030,21 @@ public static TheoryData ProcessTagHelperMatches_EmptyResultData [MemberData(nameof(ProcessTagHelperMatches_EmptyResultData))] public void ProcessDirectives_CanReturnEmptyDescriptorsBasedOnDirectiveDescriptors( string source, - object tagHelpers) + TagHelperDescriptor[] tagHelpers) { // Arrange var sourceDocument = TestRazorSourceDocument.Create(source, filePath: "TestFile"); var parser = new RazorParser(); var syntaxTree = parser.Parse(sourceDocument); - var matches = new HashSet(); - var visitor = new DefaultRazorTagHelperContextDiscoveryPhase.TagHelperDirectiveVisitor((TagHelperDescriptor[])tagHelpers, matches); + var visitor = new DefaultRazorTagHelperContextDiscoveryPhase.TagHelperDirectiveVisitor(); + visitor.Initialize(tagHelpers); // Act visitor.Visit(syntaxTree.Root); + var results = visitor.GetResults(); // Assert - Assert.Empty(matches); + Assert.Empty(results); } [Fact] @@ -1052,22 +1053,24 @@ public void TagHelperDirectiveVisitor_DoesNotMatch_Components() // Arrange var componentDescriptor = CreateComponentDescriptor("counter", "SomeProject.Counter", AssemblyA); var legacyDescriptor = Valid_PlainTagHelperDescriptor; - var descriptors = new[] + var tagHelpers = new[] { legacyDescriptor, componentDescriptor, }; - var matches = new HashSet(); - var visitor = new DefaultRazorTagHelperContextDiscoveryPhase.TagHelperDirectiveVisitor(descriptors, matches); + + var visitor = new DefaultRazorTagHelperContextDiscoveryPhase.TagHelperDirectiveVisitor(); + visitor.Initialize(tagHelpers); var sourceDocument = CreateTestSourceDocument(); var tree = RazorSyntaxTree.Parse(sourceDocument); // Act visitor.Visit(tree); + var results = visitor.GetResults(); // Assert - var match = Assert.Single(matches); - Assert.Same(legacyDescriptor, match); + var result = Assert.Single(results); + Assert.Same(legacyDescriptor, result); } private static RazorSourceDocument CreateTestSourceDocument() @@ -1110,16 +1113,16 @@ public void ComponentDirectiveVisitor_DoesNotMatch_LegacyTagHelpers() }; var sourceDocument = CreateComponentTestSourceDocument(@"", "C:\\SomeFolder\\SomeProject\\Counter.cshtml"); var tree = RazorSyntaxTree.Parse(sourceDocument); - var matches = new HashSet(); - var visitor = new DefaultRazorTagHelperContextDiscoveryPhase.ComponentDirectiveVisitor(sourceDocument.FilePath, descriptors, currentNamespace, matches); + var visitor = new DefaultRazorTagHelperContextDiscoveryPhase.ComponentDirectiveVisitor(); + visitor.Initialize(sourceDocument.FilePath, descriptors, currentNamespace); // Act visitor.Visit(tree); // Assert Assert.Null(visitor.TagHelperPrefix); - var match = Assert.Single(matches); - Assert.Same(componentDescriptor, match); + var result = Assert.Single(visitor.GetResults()); + Assert.Same(componentDescriptor, result); } [Fact] @@ -1142,16 +1145,17 @@ public void ComponentDirectiveVisitor_AddsErrorOnLegacyTagHelperDirectives() "; var sourceDocument = CreateComponentTestSourceDocument(content, filePath); var tree = RazorSyntaxTree.Parse(sourceDocument); - var matches = new HashSet(); - var visitor = new DefaultRazorTagHelperContextDiscoveryPhase.ComponentDirectiveVisitor(sourceDocument.FilePath, descriptors, currentNamespace, matches); + var visitor = new DefaultRazorTagHelperContextDiscoveryPhase.ComponentDirectiveVisitor(); + visitor.Initialize(sourceDocument.FilePath, descriptors, currentNamespace); // Act visitor.Visit(tree); + var results = visitor.GetResults(); // Assert Assert.Null(visitor.TagHelperPrefix); - var match = Assert.Single(matches); - Assert.Same(componentDescriptor, match); + var result = Assert.Single(results); + Assert.Same(componentDescriptor, result); var directiveChunkGenerator = (TagHelperPrefixDirectiveChunkGenerator)tree.Root.DescendantNodes().First(n => n is CSharpStatementLiteralSyntax).GetChunkGenerator(); var diagnostic = Assert.Single(directiveChunkGenerator.Diagnostics); Assert.Equal("RZ9978", diagnostic.Id); @@ -1176,15 +1180,16 @@ public void ComponentDirectiveVisitor_MatchesFullyQualifiedComponents() "; var sourceDocument = CreateComponentTestSourceDocument(content, filePath); var tree = RazorSyntaxTree.Parse(sourceDocument); - var matches = new HashSet(); - var visitor = new DefaultRazorTagHelperContextDiscoveryPhase.ComponentDirectiveVisitor(sourceDocument.FilePath, descriptors, currentNamespace, matches); + var visitor = new DefaultRazorTagHelperContextDiscoveryPhase.ComponentDirectiveVisitor(); + visitor.Initialize(sourceDocument.FilePath, descriptors, currentNamespace); // Act visitor.Visit(tree); + var results = visitor.GetResults(); // Assert - var match = Assert.Single(matches); - Assert.Same(componentDescriptor, match); + var result = Assert.Single(results); + Assert.Same(componentDescriptor, result); } [Fact] @@ -1213,14 +1218,15 @@ public void ComponentDirectiveVisitor_ComponentInScope_MatchesChildContent() "; var sourceDocument = CreateComponentTestSourceDocument(content, filePath); var tree = RazorSyntaxTree.Parse(sourceDocument); - var matches = new HashSet(); - var visitor = new DefaultRazorTagHelperContextDiscoveryPhase.ComponentDirectiveVisitor(sourceDocument.FilePath, descriptors, currentNamespace, matches); + var visitor = new DefaultRazorTagHelperContextDiscoveryPhase.ComponentDirectiveVisitor(); + visitor.Initialize(sourceDocument.FilePath, descriptors, currentNamespace); // Act visitor.Visit(tree); + var results = visitor.GetResults(); // Assert - Assert.Equal(2, matches.Count); + Assert.Equal(2, results.Length); } [Fact] @@ -1247,15 +1253,16 @@ public void ComponentDirectiveVisitor_NullCurrentNamespace_MatchesOnlyFullyQuali "; var sourceDocument = CreateComponentTestSourceDocument(content, filePath); var tree = RazorSyntaxTree.Parse(sourceDocument); - var matches = new HashSet(); - var visitor = new DefaultRazorTagHelperContextDiscoveryPhase.ComponentDirectiveVisitor(sourceDocument.FilePath, descriptors, currentNamespace, matches); + var visitor = new DefaultRazorTagHelperContextDiscoveryPhase.ComponentDirectiveVisitor(); + visitor.Initialize(sourceDocument.FilePath, descriptors, currentNamespace); // Act visitor.Visit(tree); + var results = visitor.GetResults(); // Assert - var match = Assert.Single(matches); - Assert.Same(fullyQualifiedComponent, match); + var result = Assert.Single(results); + Assert.Same(fullyQualifiedComponent, result); } [Fact] @@ -1282,14 +1289,15 @@ @using SomeProject.SomeOtherFolder "; var sourceDocument = CreateComponentTestSourceDocument(content, filePath); var tree = RazorSyntaxTree.Parse(sourceDocument); - var matches = new HashSet(); - var visitor = new DefaultRazorTagHelperContextDiscoveryPhase.ComponentDirectiveVisitor(sourceDocument.FilePath, descriptors, currentNamespace, matches); + var visitor = new DefaultRazorTagHelperContextDiscoveryPhase.ComponentDirectiveVisitor(); + visitor.Initialize(sourceDocument.FilePath, descriptors, currentNamespace); // Act visitor.Visit(tree); + var results = visitor.GetResults(); // Assert - Assert.Equal(2, matches.Count); + Assert.Equal(2, results.Length); } [Fact] @@ -1311,15 +1319,16 @@ public void ComponentDirectiveVisitor_MatchesIfNamespaceInUsing_GlobalPrefix() """; var sourceDocument = CreateComponentTestSourceDocument(content, filePath); var tree = RazorSyntaxTree.Parse(sourceDocument); - var matches = new HashSet(); - var visitor = new DefaultRazorTagHelperContextDiscoveryPhase.ComponentDirectiveVisitor(sourceDocument.FilePath, descriptors, currentNamespace, matches); + var visitor = new DefaultRazorTagHelperContextDiscoveryPhase.ComponentDirectiveVisitor(); + visitor.Initialize(sourceDocument.FilePath, descriptors, currentNamespace); // Act visitor.Visit(tree); + var results = visitor.GetResults(); // Assert - var match = Assert.Single(matches); - Assert.Same(componentDescriptor, match); + var result = Assert.Single(results); + Assert.Same(componentDescriptor, result); } [Fact] @@ -1347,15 +1356,16 @@ @using static SomeProject.SomeOtherFolder.Foo "; var sourceDocument = CreateComponentTestSourceDocument(content, filePath); var tree = RazorSyntaxTree.Parse(sourceDocument); - var matches = new HashSet(); - var visitor = new DefaultRazorTagHelperContextDiscoveryPhase.ComponentDirectiveVisitor(sourceDocument.FilePath, descriptors, currentNamespace, matches); + var visitor = new DefaultRazorTagHelperContextDiscoveryPhase.ComponentDirectiveVisitor(); + visitor.Initialize(sourceDocument.FilePath, descriptors, currentNamespace); // Act visitor.Visit(tree); + var results = visitor.GetResults(); // Assert - var match = Assert.Single(matches); - Assert.Same(componentDescriptor, match); + var result = Assert.Single(results); + Assert.Same(componentDescriptor, result); } [Theory] diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/DefaultRazorTagHelperContextDiscoveryPhase.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/DefaultRazorTagHelperContextDiscoveryPhase.cs index 998c4375d38..d3663a1eb96 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/DefaultRazorTagHelperContextDiscoveryPhase.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/DefaultRazorTagHelperContextDiscoveryPhase.cs @@ -3,24 +3,24 @@ using System; using System.Collections.Generic; +using System.Collections.Immutable; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using Microsoft.AspNetCore.Razor.Language.Components; using Microsoft.AspNetCore.Razor.Language.Legacy; using Microsoft.AspNetCore.Razor.Language.Syntax; -using Microsoft.AspNetCore.Razor.PooledObjects; namespace Microsoft.AspNetCore.Razor.Language; -internal sealed class DefaultRazorTagHelperContextDiscoveryPhase : RazorEnginePhaseBase +internal sealed partial class DefaultRazorTagHelperContextDiscoveryPhase : RazorEnginePhaseBase { protected override void ExecuteCore(RazorCodeDocument codeDocument) { var syntaxTree = codeDocument.GetPreTagHelperSyntaxTree() ?? codeDocument.GetSyntaxTree(); ThrowForMissingDocumentDependency(syntaxTree); - var descriptors = codeDocument.GetTagHelpers(); - if (descriptors == null) + var tagHelpers = codeDocument.GetTagHelpers(); + if (tagHelpers == null) { if (!Engine.TryGetFeature(out ITagHelperFeature? tagHelperFeature)) { @@ -28,49 +28,32 @@ protected override void ExecuteCore(RazorCodeDocument codeDocument) return; } - descriptors = tagHelperFeature.GetDescriptors(); + tagHelpers = tagHelperFeature.GetDescriptors(); } - var parserOptions = codeDocument.GetParserOptions(); - - using var _ = HashSetPool.GetPooledObject(out var matches); + using var _ = GetPooledVisitor(codeDocument, tagHelpers, out var visitor); // We need to find directives in all of the *imports* as well as in the main razor file // // The imports come logically before the main razor file and are in the order they // should be processed. - DirectiveVisitor visitor; - if (FileKinds.IsComponent(codeDocument.GetFileKind()) && - (parserOptions == null || parserOptions.FeatureFlags.AllowComponentFileKind)) - { - codeDocument.TryComputeNamespace(fallbackToRootNamespace: true, out var currentNamespace); - var filePath = codeDocument.Source.FilePath.AssumeNotNull(); - visitor = new ComponentDirectiveVisitor(filePath, descriptors, currentNamespace, matches); - } - else - { - visitor = new TagHelperDirectiveVisitor(descriptors, matches); - } - using (visitor) + if (codeDocument.GetImportSyntaxTrees() is { IsDefault: false } imports) { - if (codeDocument.GetImportSyntaxTrees() is { IsDefault: false } imports) + foreach (var import in imports) { - foreach (var import in imports) - { - visitor.Visit(import); - } + visitor.Visit(import); } + } - visitor.Visit(syntaxTree); + visitor.Visit(syntaxTree); - // This will always be null for a component document. - var tagHelperPrefix = visitor.TagHelperPrefix; + // This will always be null for a component document. + var tagHelperPrefix = visitor.TagHelperPrefix; - var context = TagHelperDocumentContext.Create(tagHelperPrefix, [.. matches]); - codeDocument.SetTagHelperContext(context); - codeDocument.SetPreTagHelperSyntaxTree(syntaxTree); - } + var context = TagHelperDocumentContext.Create(tagHelperPrefix, visitor.GetResults()); + codeDocument.SetTagHelperContext(context); + codeDocument.SetPreTagHelperSyntaxTree(syntaxTree); } private static bool MatchesDirective(TagHelperDescriptor descriptor, string typePattern, string assemblyName) @@ -108,28 +91,53 @@ private static ReadOnlySpan RemoveGlobalPrefix(in ReadOnlySpan span) return span; } - internal abstract class DirectiveVisitor(HashSet matches) : SyntaxWalker, IDisposable + internal abstract class DirectiveVisitor : SyntaxWalker { - protected readonly HashSet Matches = matches; + private bool _isInitialized; + private readonly HashSet _matches = []; - public abstract string? TagHelperPrefix { get; } + protected bool IsInitialized => _isInitialized; + + public virtual string? TagHelperPrefix => null; public abstract void Visit(RazorSyntaxTree tree); - public abstract void Dispose(); + public ImmutableArray GetResults() => [.. _matches]; + + protected void Initialize() + { + _isInitialized = true; + } + + public virtual void Reset() + { + _matches.Clear(); + _isInitialized = false; + } + + public void AddMatch(TagHelperDescriptor tagHelper) + { + _matches.Add(tagHelper); + } + + public void RemoveMatch(TagHelperDescriptor tagHelper) + { + _matches.Remove(tagHelper); + } } internal sealed class TagHelperDirectiveVisitor : DirectiveVisitor { - private List? _tagHelpers; + private readonly List _tagHelpers = []; private string? _tagHelperPrefix; - public TagHelperDirectiveVisitor(IReadOnlyList tagHelpers, HashSet matches) - : base(matches) + public override string? TagHelperPrefix => _tagHelperPrefix; + + public void Initialize(IReadOnlyList tagHelpers) { - // We don't want to consider components in a view document. - _tagHelpers = ListPool.Default.Get(); + Debug.Assert(!IsInitialized); + // We don't want to consider components in a view document. for (var i = 0; i < tagHelpers.Count; i++) { var tagHelper = tagHelpers[i]; @@ -138,9 +146,17 @@ public TagHelperDirectiveVisitor(IReadOnlyList tagHelpers, _tagHelpers.Add(tagHelper); } } + + base.Initialize(); } - public override string? TagHelperPrefix => _tagHelperPrefix; + public override void Reset() + { + _tagHelpers.Clear(); + _tagHelperPrefix = null; + + base.Reset(); + } public override void Visit(RazorSyntaxTree tree) { @@ -179,7 +195,7 @@ public override void VisitRazorDirective(RazorDirectiveSyntax node) { if (MatchesDirective(tagHelper, addTagHelper.TypePattern, addTagHelper.AssemblyName)) { - Matches.Add(tagHelper); + AddMatch(tagHelper); } } @@ -202,14 +218,14 @@ public override void VisitRazorDirective(RazorDirectiveSyntax node) { if (MatchesDirective(tagHelper, removeTagHelper.TypePattern, removeTagHelper.AssemblyName)) { - Matches.Remove(tagHelper); + RemoveMatch(tagHelper); } } break; case TagHelperPrefixDirectiveChunkGenerator tagHelperPrefix: - if (!string.IsNullOrEmpty(tagHelperPrefix.DirectiveText)) + if (!tagHelperPrefix.DirectiveText.IsNullOrEmpty()) { // We only expect to see a single one of these per file, but that's enforced at another level. _tagHelperPrefix = tagHelperPrefix.DirectiveText; @@ -237,29 +253,19 @@ private static bool AssemblyContainsTagHelpers(string assemblyName, [NotNullWhen return false; } - - public override void Dispose() - { - if (_tagHelpers != null) - { - ListPool.Default.Return(_tagHelpers); - _tagHelpers = null; - } - } } internal sealed class ComponentDirectiveVisitor : DirectiveVisitor { - private List? _notFullyQualifiedComponents; - private readonly string _filePath; + private readonly List _notFullyQualifiedComponents = []; + private string? _filePath; private RazorSourceDocument? _source; - public ComponentDirectiveVisitor(string filePath, IReadOnlyList tagHelpers, string currentNamespace, HashSet matches) - : base(matches) + public void Initialize(string filePath, IReadOnlyList tagHelpers, string currentNamespace) { - _filePath = filePath; + Debug.Assert(!IsInitialized); - _notFullyQualifiedComponents = ListPool.Default.Get(); + _filePath = filePath; for (var i = 0; i < tagHelpers.Count; i++) { @@ -273,7 +279,7 @@ public ComponentDirectiveVisitor(string filePath, IReadOnlyList null; + public override void Reset() + { + _notFullyQualifiedComponents.Clear(); + _filePath = null; + _source = null; + + base.Reset(); + } public override void Visit(RazorSyntaxTree tree) { + // Set _source based on the current tree, since this visitor is called for the document and its imports. _source = tree.Source; Visit(tree.Root); } @@ -327,7 +342,7 @@ public override void VisitRazorDirective(RazorDirectiveSyntax node) continue; case AddTagHelperChunkGenerator addTagHelper: // Make sure this node exists in the file we're parsing and not in its imports. - if (_filePath.Equals(_source.AssumeNotNull().FilePath, StringComparison.Ordinal)) + if (_filePath.AssumeNotNull().Equals(_source.AssumeNotNull().FilePath, StringComparison.Ordinal)) { addTagHelper.Diagnostics.Add( ComponentDiagnosticFactory.Create_UnsupportedTagHelperDirective(node.GetSourceSpan(_source))); @@ -335,7 +350,7 @@ public override void VisitRazorDirective(RazorDirectiveSyntax node) break; case RemoveTagHelperChunkGenerator removeTagHelper: // Make sure this node exists in the file we're parsing and not in its imports. - if (_filePath.Equals(_source.AssumeNotNull().FilePath, StringComparison.Ordinal)) + if (_filePath.AssumeNotNull().Equals(_source.AssumeNotNull().FilePath, StringComparison.Ordinal)) { removeTagHelper.Diagnostics.Add( ComponentDiagnosticFactory.Create_UnsupportedTagHelperDirective(node.GetSourceSpan(_source))); @@ -343,7 +358,7 @@ public override void VisitRazorDirective(RazorDirectiveSyntax node) break; case TagHelperPrefixDirectiveChunkGenerator tagHelperPrefix: // Make sure this node exists in the file we're parsing and not in its imports. - if (_filePath.Equals(_source.AssumeNotNull().FilePath, StringComparison.Ordinal)) + if (_filePath.AssumeNotNull().Equals(_source.AssumeNotNull().FilePath, StringComparison.Ordinal)) { tagHelperPrefix.Diagnostics.Add( ComponentDiagnosticFactory.Create_UnsupportedTagHelperDirective(node.GetSourceSpan(_source))); @@ -368,13 +383,13 @@ public override void VisitRazorDirective(RazorDirectiveSyntax node) // E.g, if the type name is `Test.MyComponent.ChildContent`, we want to add it if `Test.MyComponent` is in this namespace. if (IsTypeInNamespace(tagHelper, @namespace)) { - Matches.Add(tagHelper); + AddMatch(tagHelper); } } else if (IsTypeInNamespace(tagHelper, @namespace)) { // If the type is at the top-level or if the type's namespace matches the using's namespace, add it. - Matches.Add(tagHelper); + AddMatch(tagHelper); } } break; @@ -442,14 +457,5 @@ internal static bool IsTagHelperFromMangledClass(TagHelperDescriptor tagHelper) { return ComponentMetadata.IsMangledClass(tagHelper.GetTypeNameIdentifier()); } - - public override void Dispose() - { - if (_notFullyQualifiedComponents != null) - { - ListPool.Default.Return(_notFullyQualifiedComponents); - _notFullyQualifiedComponents = null; - } - } } } diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/DefaultRazorTagHelperContextDiscoveryPhase_Pooling.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/DefaultRazorTagHelperContextDiscoveryPhase_Pooling.cs new file mode 100644 index 00000000000..a96fc6f49ca --- /dev/null +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/DefaultRazorTagHelperContextDiscoveryPhase_Pooling.cs @@ -0,0 +1,78 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Generic; +using Microsoft.AspNetCore.Razor.PooledObjects; +using Microsoft.Extensions.ObjectPool; + +namespace Microsoft.AspNetCore.Razor.Language; + +internal partial class DefaultRazorTagHelperContextDiscoveryPhase +{ + private static readonly ObjectPool s_tagHelperDirectiveVisitorPool = DefaultPool.Create(DirectiveVisitorPolicy.Instance); + private static readonly ObjectPool s_componentDirectiveVisitorPool = DefaultPool.Create(DirectiveVisitorPolicy.Instance); + + private sealed class DirectiveVisitorPolicy : IPooledObjectPolicy + where T : DirectiveVisitor, new() + { + public static readonly DirectiveVisitorPolicy Instance = new(); + + private DirectiveVisitorPolicy() + { + } + + public T Create() => new(); + + public bool Return(T visitor) + { + visitor.Reset(); + + return true; + } + } + + internal readonly ref struct PooledDirectiveVisitor(DirectiveVisitor visitor, bool isComponentDirectiveVisitor) + { + public void Dispose() + { + if (isComponentDirectiveVisitor) + { + s_componentDirectiveVisitorPool.Return((ComponentDirectiveVisitor)visitor); + } + else + { + s_tagHelperDirectiveVisitorPool.Return((TagHelperDirectiveVisitor)visitor); + } + } + } + + internal static PooledDirectiveVisitor GetPooledVisitor( + RazorCodeDocument codeDocument, + IReadOnlyList tagHelpers, + out DirectiveVisitor visitor) + { + var useComponentDirectiveVisitor = FileKinds.IsComponent(codeDocument.GetFileKind()) && + (codeDocument.GetParserOptions() is null or { FeatureFlags.AllowComponentFileKind: true }); + + if (useComponentDirectiveVisitor) + { + var componentDirectiveVisitor = s_componentDirectiveVisitorPool.Get(); + + codeDocument.TryComputeNamespace(fallbackToRootNamespace: true, out var currentNamespace); + var filePath = codeDocument.Source.FilePath.AssumeNotNull(); + componentDirectiveVisitor.Initialize(filePath, tagHelpers, currentNamespace); + + visitor = componentDirectiveVisitor; + } + else + { + var tagHelperDirectiveVisitor = s_tagHelperDirectiveVisitorPool.Get(); + + tagHelperDirectiveVisitor.Initialize(tagHelpers); + + visitor = tagHelperDirectiveVisitor; + } + + return new(visitor, useComponentDirectiveVisitor); + } +} diff --git a/src/Compiler/perf/Microbenchmarks/RazorTagHelperParsingBenchmark.cs b/src/Compiler/perf/Microbenchmarks/RazorTagHelperParsingBenchmark.cs index aa0456c3207..48b2a0eb413 100644 --- a/src/Compiler/perf/Microbenchmarks/RazorTagHelperParsingBenchmark.cs +++ b/src/Compiler/perf/Microbenchmarks/RazorTagHelperParsingBenchmark.cs @@ -41,8 +41,8 @@ public RazorTagHelperParsingBenchmark() }); BlazorServerTagHelpersDemoFile = fileSystem.GetItem(Path.Combine(blazorServerTagHelpersFilePath), FileKinds.Component); - var matches = new HashSet(); - ComponentDirectiveVisitor = new ComponentDirectiveVisitor(blazorServerTagHelpersFilePath, tagHelpers, currentNamespace: null, matches); + ComponentDirectiveVisitor = new ComponentDirectiveVisitor(); + ComponentDirectiveVisitor.Initialize(blazorServerTagHelpersFilePath, tagHelpers, currentNamespace: null); var codeDocument = ProjectEngine.ProcessDesignTime(BlazorServerTagHelpersDemoFile); SyntaxTree = codeDocument.GetSyntaxTree(); } From 918e316c5adc9594da05a5218c575b276235a0ff Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Tue, 9 Jul 2024 12:31:23 -0700 Subject: [PATCH 028/176] Don't compute list of non-component tag helpers until necessary --- ...aultRazorTagHelperContextDiscoveryPhase.cs | 50 +++++++++++++------ 1 file changed, 36 insertions(+), 14 deletions(-) diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/DefaultRazorTagHelperContextDiscoveryPhase.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/DefaultRazorTagHelperContextDiscoveryPhase.cs index d3663a1eb96..81c5164f3b6 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/DefaultRazorTagHelperContextDiscoveryPhase.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/DefaultRazorTagHelperContextDiscoveryPhase.cs @@ -128,31 +128,53 @@ public void RemoveMatch(TagHelperDescriptor tagHelper) internal sealed class TagHelperDirectiveVisitor : DirectiveVisitor { - private readonly List _tagHelpers = []; + private readonly List _nonComponentTagHelpers = []; + + private IReadOnlyList? _tagHelpers; + private bool _nonComponentTagHelpersComputed; private string? _tagHelperPrefix; public override string? TagHelperPrefix => _tagHelperPrefix; - public void Initialize(IReadOnlyList tagHelpers) + private List NonComponentTagHelpers { - Debug.Assert(!IsInitialized); - - // We don't want to consider components in a view document. - for (var i = 0; i < tagHelpers.Count; i++) + get { - var tagHelper = tagHelpers[i]; - if (!tagHelper.IsAnyComponentDocumentTagHelper()) + if (!_nonComponentTagHelpersComputed) { - _tagHelpers.Add(tagHelper); + var tagHelpers = _tagHelpers.AssumeNotNull(); + + // We don't want to consider components in a view document. + for (var i = 0; i < tagHelpers.Count; i++) + { + var tagHelper = tagHelpers[i]; + if (!tagHelper.IsAnyComponentDocumentTagHelper()) + { + _nonComponentTagHelpers.Add(tagHelper); + } + } + + _nonComponentTagHelpersComputed = true; } + + return _nonComponentTagHelpers; } + } + + public void Initialize(IReadOnlyList tagHelpers) + { + Debug.Assert(!IsInitialized); + + _tagHelpers = tagHelpers; base.Initialize(); } public override void Reset() { - _tagHelpers.Clear(); + _nonComponentTagHelpers.Clear(); + _nonComponentTagHelpersComputed = false; + _tagHelpers = null; _tagHelperPrefix = null; base.Reset(); @@ -185,13 +207,13 @@ public override void VisitRazorDirective(RazorDirectiveSyntax node) continue; } - if (!AssemblyContainsTagHelpers(addTagHelper.AssemblyName, _tagHelpers)) + if (!AssemblyContainsTagHelpers(addTagHelper.AssemblyName, NonComponentTagHelpers)) { // No tag helpers in the assembly. continue; } - foreach (var tagHelper in _tagHelpers) + foreach (var tagHelper in NonComponentTagHelpers) { if (MatchesDirective(tagHelper, addTagHelper.TypePattern, addTagHelper.AssemblyName)) { @@ -208,13 +230,13 @@ public override void VisitRazorDirective(RazorDirectiveSyntax node) continue; } - if (!AssemblyContainsTagHelpers(removeTagHelper.AssemblyName, _tagHelpers)) + if (!AssemblyContainsTagHelpers(removeTagHelper.AssemblyName, NonComponentTagHelpers)) { // No tag helpers in the assembly. continue; } - foreach (var tagHelper in _tagHelpers) + foreach (var tagHelper in NonComponentTagHelpers) { if (MatchesDirective(tagHelper, removeTagHelper.TypePattern, removeTagHelper.AssemblyName)) { From 27feb667fc420168047ae993b627021d2d00d70d Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Tue, 9 Jul 2024 12:35:22 -0700 Subject: [PATCH 029/176] Prefer list pattern --- ...DefaultRazorTagHelperContextDiscoveryPhase.cs | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/DefaultRazorTagHelperContextDiscoveryPhase.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/DefaultRazorTagHelperContextDiscoveryPhase.cs index 81c5164f3b6..ea11fa46781 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/DefaultRazorTagHelperContextDiscoveryPhase.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/DefaultRazorTagHelperContextDiscoveryPhase.cs @@ -65,18 +65,12 @@ private static bool MatchesDirective(TagHelperDescriptor descriptor, string type var typePatternSpan = RemoveGlobalPrefix(typePattern.AsSpan()); - if (typePatternSpan[^1] == '*') + return typePatternSpan switch { - if (typePatternSpan.Length == 1) - { - // TypePattern is "*". - return true; - } - - return descriptor.Name.AsSpan().StartsWith(typePatternSpan[..^1], StringComparison.Ordinal); - } - - return descriptor.Name.AsSpan().Equals(typePatternSpan, StringComparison.Ordinal); + ['*'] => true, + [.. var pattern, '*'] => descriptor.Name.AsSpan().StartsWith(pattern, StringComparison.Ordinal), + var pattern => descriptor.Name.AsSpan().Equals(pattern, StringComparison.Ordinal) + }; } private static ReadOnlySpan RemoveGlobalPrefix(in ReadOnlySpan span) From 848286c5337e3f915fd4e254c24f1bce632aacb8 Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Tue, 9 Jul 2024 15:27:02 -0700 Subject: [PATCH 030/176] Track tag helpers by assembly in TagHelperDirectiveVisitor We can avoid sifting through all tag helpers and performing string comparisons by storing tag helpers them in a dictionary keyed by assembly name. --- ...aultRazorTagHelperContextDiscoveryPhase.cs | 220 +++++++++++------- .../PooledObjects/ListPool`1.cs | 3 + .../ReadOnlyListExtensions.cs | 43 ++++ 3 files changed, 186 insertions(+), 80 deletions(-) diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/DefaultRazorTagHelperContextDiscoveryPhase.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/DefaultRazorTagHelperContextDiscoveryPhase.cs index ea11fa46781..82b73f113ce 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/DefaultRazorTagHelperContextDiscoveryPhase.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/DefaultRazorTagHelperContextDiscoveryPhase.cs @@ -5,10 +5,11 @@ using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; using Microsoft.AspNetCore.Razor.Language.Components; using Microsoft.AspNetCore.Razor.Language.Legacy; using Microsoft.AspNetCore.Razor.Language.Syntax; +using Microsoft.AspNetCore.Razor.PooledObjects; +using Microsoft.Extensions.ObjectPool; namespace Microsoft.AspNetCore.Razor.Language; @@ -56,27 +57,12 @@ protected override void ExecuteCore(RazorCodeDocument codeDocument) codeDocument.SetPreTagHelperSyntaxTree(syntaxTree); } - private static bool MatchesDirective(TagHelperDescriptor descriptor, string typePattern, string assemblyName) - { - if (!string.Equals(descriptor.AssemblyName, assemblyName, StringComparison.Ordinal)) - { - return false; - } - - var typePatternSpan = RemoveGlobalPrefix(typePattern.AsSpan()); - - return typePatternSpan switch - { - ['*'] => true, - [.. var pattern, '*'] => descriptor.Name.AsSpan().StartsWith(pattern, StringComparison.Ordinal), - var pattern => descriptor.Name.AsSpan().Equals(pattern, StringComparison.Ordinal) - }; - } - - private static ReadOnlySpan RemoveGlobalPrefix(in ReadOnlySpan span) + private static ReadOnlySpan GetSpanWithoutGlobalPrefix(string s) { const string globalPrefix = "global::"; + var span = s.AsSpan(); + if (span.StartsWith(globalPrefix.AsSpan(), StringComparison.Ordinal)) { return span[globalPrefix.Length..]; @@ -114,44 +100,88 @@ public void AddMatch(TagHelperDescriptor tagHelper) _matches.Add(tagHelper); } + public void AddMatches(List tagHelpers) + { + foreach (var tagHelper in tagHelpers) + { + _matches.Add(tagHelper); + } + } + public void RemoveMatch(TagHelperDescriptor tagHelper) { _matches.Remove(tagHelper); } + + public void RemoveMatches(List tagHelpers) + { + foreach (var tagHelper in tagHelpers) + { + _matches.Remove(tagHelper); + } + } } internal sealed class TagHelperDirectiveVisitor : DirectiveVisitor { - private readonly List _nonComponentTagHelpers = []; + /// + /// A larger pool of lists to handle scenarios where tag helpers + /// originate from a large number of assemblies. + /// + private static readonly ObjectPool> s_pool = ListPool.Create(100); + + /// + /// A map from assembly name to list of . Lists are allocated from and returned to + /// . + /// + private readonly Dictionary> _nonComponentTagHelperMap = new(StringComparer.Ordinal); private IReadOnlyList? _tagHelpers; - private bool _nonComponentTagHelpersComputed; + private bool _nonComponentTagHelperMapComputed; private string? _tagHelperPrefix; public override string? TagHelperPrefix => _tagHelperPrefix; - private List NonComponentTagHelpers + private Dictionary> NonComponentTagHelperMap { get { - if (!_nonComponentTagHelpersComputed) + if (!_nonComponentTagHelperMapComputed) + { + ComputeNonComponentTagHelpersMap(); + + _nonComponentTagHelperMapComputed = true; + } + + return _nonComponentTagHelperMap; + + void ComputeNonComponentTagHelpersMap() { var tagHelpers = _tagHelpers.AssumeNotNull(); + string? currentAssemblyName = null; + List? currentTagHelpers = null; + // We don't want to consider components in a view document. - for (var i = 0; i < tagHelpers.Count; i++) + foreach (var tagHelper in tagHelpers.AsEnumerable()) { - var tagHelper = tagHelpers[i]; if (!tagHelper.IsAnyComponentDocumentTagHelper()) { - _nonComponentTagHelpers.Add(tagHelper); + if (tagHelper.AssemblyName != currentAssemblyName) + { + currentAssemblyName = tagHelper.AssemblyName; + + if (!_nonComponentTagHelperMap.TryGetValue(currentAssemblyName, out currentTagHelpers)) + { + currentTagHelpers = s_pool.Get(); + _nonComponentTagHelperMap.Add(tagHelper.AssemblyName, currentTagHelpers); + } + } + + currentTagHelpers!.Add(tagHelper); } } - - _nonComponentTagHelpersComputed = true; } - - return _nonComponentTagHelpers; } } @@ -166,8 +196,13 @@ public void Initialize(IReadOnlyList tagHelpers) public override void Reset() { - _nonComponentTagHelpers.Clear(); - _nonComponentTagHelpersComputed = false; + foreach (var (_, tagHelpers) in _nonComponentTagHelperMap) + { + s_pool.Return(tagHelpers); + } + + _nonComponentTagHelperMap.Clear(); + _nonComponentTagHelperMapComputed = false; _tagHelpers = null; _tagHelperPrefix = null; @@ -191,50 +226,93 @@ public override void VisitRazorDirective(RazorDirectiveSyntax node) switch (literal.ChunkGenerator) { - case null: - continue; - case AddTagHelperChunkGenerator addTagHelper: - if (addTagHelper.AssemblyName == null) { - // Skip this one, it's an error - continue; - } + if (addTagHelper.AssemblyName == null) + { + // Skip this one, it's an error + continue; + } - if (!AssemblyContainsTagHelpers(addTagHelper.AssemblyName, NonComponentTagHelpers)) - { - // No tag helpers in the assembly. - continue; - } + if (!NonComponentTagHelperMap.TryGetValue(addTagHelper.AssemblyName, out var nonComponentTagHelpers)) + { + // No tag helpers in the assembly. + continue; + } - foreach (var tagHelper in NonComponentTagHelpers) - { - if (MatchesDirective(tagHelper, addTagHelper.TypePattern, addTagHelper.AssemblyName)) + switch (GetSpanWithoutGlobalPrefix(addTagHelper.TypePattern)) { - AddMatch(tagHelper); + case ['*']: + AddMatches(nonComponentTagHelpers); + break; + + case [.. var pattern, '*']: + foreach (var tagHelper in nonComponentTagHelpers) + { + if (tagHelper.Name.AsSpan().StartsWith(pattern, StringComparison.Ordinal)) + { + AddMatch(tagHelper); + } + } + + break; + + case var pattern: + foreach (var tagHelper in nonComponentTagHelpers) + { + if (tagHelper.Name.AsSpan().Equals(pattern, StringComparison.Ordinal)) + { + AddMatch(tagHelper); + } + } + + break; } } break; case RemoveTagHelperChunkGenerator removeTagHelper: - if (removeTagHelper.AssemblyName == null) { - // Skip this one, it's an error - continue; - } + if (removeTagHelper.AssemblyName == null) + { + // Skip this one, it's an error + continue; + } - if (!AssemblyContainsTagHelpers(removeTagHelper.AssemblyName, NonComponentTagHelpers)) - { - // No tag helpers in the assembly. - continue; - } + if (!NonComponentTagHelperMap.TryGetValue(removeTagHelper.AssemblyName, out var nonComponentTagHelpers)) + { + // No tag helpers in the assembly. + continue; + } - foreach (var tagHelper in NonComponentTagHelpers) - { - if (MatchesDirective(tagHelper, removeTagHelper.TypePattern, removeTagHelper.AssemblyName)) + switch (GetSpanWithoutGlobalPrefix(removeTagHelper.TypePattern)) { - RemoveMatch(tagHelper); + case ['*']: + RemoveMatches(nonComponentTagHelpers); + break; + + case [.. var pattern, '*']: + foreach (var tagHelper in nonComponentTagHelpers) + { + if (tagHelper.Name.AsSpan().StartsWith(pattern, StringComparison.Ordinal)) + { + RemoveMatch(tagHelper); + } + } + + break; + + case var pattern: + foreach (var tagHelper in nonComponentTagHelpers) + { + if (tagHelper.Name.AsSpan().Equals(pattern, StringComparison.Ordinal)) + { + RemoveMatch(tagHelper); + } + } + + break; } } @@ -251,24 +329,6 @@ public override void VisitRazorDirective(RazorDirectiveSyntax node) } } } - - private static bool AssemblyContainsTagHelpers(string assemblyName, [NotNullWhen(true)] List? tagHelpers) - { - if (tagHelpers is null) - { - return false; - } - - foreach (var tagHelper in tagHelpers) - { - if (tagHelper.AssemblyName == assemblyName) - { - return true; - } - } - - return false; - } } internal sealed class ComponentDirectiveVisitor : DirectiveVisitor @@ -426,7 +486,7 @@ static bool IsTypeInNamespace(string typeNamespace, string @namespace) } // Remove global:: prefix from namespace. - var normalizedNamespace = RemoveGlobalPrefix(@namespace.AsSpan()); + var normalizedNamespace = GetSpanWithoutGlobalPrefix(@namespace); return normalizedNamespace.Equals(typeNamespace.AsSpan(), StringComparison.Ordinal); } diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/PooledObjects/ListPool`1.cs b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/PooledObjects/ListPool`1.cs index 7f9cc9d0618..98532ec7d80 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/PooledObjects/ListPool`1.cs +++ b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/PooledObjects/ListPool`1.cs @@ -18,6 +18,9 @@ internal static partial class ListPool { public static readonly ObjectPool> Default = DefaultPool.Create(Policy.Instance); + public static ObjectPool> Create(int size = 20) + => DefaultPool.Create(Policy.Instance, size); + public static PooledObject> GetPooledObject() => Default.GetPooledObject(); diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/ReadOnlyListExtensions.cs b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/ReadOnlyListExtensions.cs index 3cc2211eb70..d5cc1e4c64c 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/ReadOnlyListExtensions.cs +++ b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/ReadOnlyListExtensions.cs @@ -32,4 +32,47 @@ static ImmutableArray BuildResult(IReadOnlyList items, Func AsEnumerable(this IReadOnlyList source) => new(source); + + public readonly struct Enumerable(IReadOnlyList source) : IEnumerable + { + public Enumerator GetEnumerator() => new(source); + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + } + + public struct Enumerator(IReadOnlyList source) : IEnumerator + { + private int _index; + private T _current; + + public readonly T Current => _current!; + + readonly object IEnumerator.Current => _current!; + + public readonly void Dispose() + { + } + + public bool MoveNext() + { + if (_index < source.Count) + { + _current = source[_index]; + _index++; + return true; + } + + return false; + } + + public void Reset() + { + _index = 0; + _current = default!; + } + } } From cec0f4ef65ad3cc0cc6b4b4eccf4bfb81336d716 Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Tue, 9 Jul 2024 15:51:33 -0700 Subject: [PATCH 031/176] Clean up ComponentDirectiveVisitor a bit --- ...aultRazorTagHelperContextDiscoveryPhase.cs | 72 +++++++++---------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/DefaultRazorTagHelperContextDiscoveryPhase.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/DefaultRazorTagHelperContextDiscoveryPhase.cs index 82b73f113ce..a059ae0a44c 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/DefaultRazorTagHelperContextDiscoveryPhase.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/DefaultRazorTagHelperContextDiscoveryPhase.cs @@ -333,19 +333,22 @@ public override void VisitRazorDirective(RazorDirectiveSyntax node) internal sealed class ComponentDirectiveVisitor : DirectiveVisitor { - private readonly List _notFullyQualifiedComponents = []; + private readonly List _nonFullyQualifiedComponents = []; + private string? _filePath; private RazorSourceDocument? _source; - public void Initialize(string filePath, IReadOnlyList tagHelpers, string currentNamespace) + private string FilePath => _filePath.AssumeNotNull(); + private RazorSourceDocument Source => _source.AssumeNotNull(); + + public void Initialize(string filePath, IReadOnlyList tagHelpers, string? currentNamespace) { Debug.Assert(!IsInitialized); _filePath = filePath; - for (var i = 0; i < tagHelpers.Count; i++) + foreach (var tagHelper in tagHelpers.AsEnumerable()) { - var tagHelper = tagHelpers[i]; // We don't want to consider non-component tag helpers in a component document. if (!tagHelper.IsAnyComponentDocumentTagHelper() || IsTagHelperFromMangledClass(tagHelper)) { @@ -359,7 +362,7 @@ public void Initialize(string filePath, IReadOnlyList tagHe continue; } - _notFullyQualifiedComponents.Add(tagHelper); + _nonFullyQualifiedComponents.Add(tagHelper); if (currentNamespace is null) { @@ -387,7 +390,7 @@ public void Initialize(string filePath, IReadOnlyList tagHe public override void Reset() { - _notFullyQualifiedComponents.Clear(); + _nonFullyQualifiedComponents.Clear(); _filePath = null; _source = null; @@ -413,33 +416,35 @@ public override void VisitRazorDirective(RazorDirectiveSyntax node) switch (literal.ChunkGenerator) { - case null: - // We can't find a chunk generator. - continue; case AddTagHelperChunkGenerator addTagHelper: - // Make sure this node exists in the file we're parsing and not in its imports. - if (_filePath.AssumeNotNull().Equals(_source.AssumeNotNull().FilePath, StringComparison.Ordinal)) + if (FilePath == Source.FilePath) { addTagHelper.Diagnostics.Add( - ComponentDiagnosticFactory.Create_UnsupportedTagHelperDirective(node.GetSourceSpan(_source))); + ComponentDiagnosticFactory.Create_UnsupportedTagHelperDirective(node.GetSourceSpan(Source))); } + break; + case RemoveTagHelperChunkGenerator removeTagHelper: // Make sure this node exists in the file we're parsing and not in its imports. - if (_filePath.AssumeNotNull().Equals(_source.AssumeNotNull().FilePath, StringComparison.Ordinal)) + if (FilePath == Source.FilePath) { removeTagHelper.Diagnostics.Add( - ComponentDiagnosticFactory.Create_UnsupportedTagHelperDirective(node.GetSourceSpan(_source))); + ComponentDiagnosticFactory.Create_UnsupportedTagHelperDirective(node.GetSourceSpan(Source))); } + break; + case TagHelperPrefixDirectiveChunkGenerator tagHelperPrefix: // Make sure this node exists in the file we're parsing and not in its imports. - if (_filePath.AssumeNotNull().Equals(_source.AssumeNotNull().FilePath, StringComparison.Ordinal)) + if (FilePath == Source.FilePath) { tagHelperPrefix.Diagnostics.Add( - ComponentDiagnosticFactory.Create_UnsupportedTagHelperDirective(node.GetSourceSpan(_source))); + ComponentDiagnosticFactory.Create_UnsupportedTagHelperDirective(node.GetSourceSpan(Source))); } + break; + case AddImportChunkGenerator { IsStatic: false } usingStatement: // Get the namespace from the using statement. var @namespace = usingStatement.ParsedNamespace; @@ -449,7 +454,7 @@ public override void VisitRazorDirective(RazorDirectiveSyntax node) continue; } - foreach (var tagHelper in _notFullyQualifiedComponents.AssumeNotNull()) + foreach (var tagHelper in _nonFullyQualifiedComponents) { Debug.Assert(!tagHelper.IsComponentFullyQualifiedNameMatch, "We've already processed these."); @@ -468,6 +473,7 @@ public override void VisitRazorDirective(RazorDirectiveSyntax node) AddMatch(tagHelper); } } + break; } } @@ -475,21 +481,18 @@ public override void VisitRazorDirective(RazorDirectiveSyntax node) internal static bool IsTypeInNamespace(TagHelperDescriptor tagHelper, string @namespace) { - return IsTypeInNamespace(tagHelper.GetTypeNamespace(), @namespace); + var typeNamespace = tagHelper.GetTypeNamespace(); - static bool IsTypeInNamespace(string typeNamespace, string @namespace) + if (typeNamespace.IsNullOrEmpty()) { - if (string.IsNullOrEmpty(typeNamespace)) - { - // Either the typeName is not the full type name or this type is at the top level. - return true; - } + // Either the typeName is not the full type name or this type is at the top level. + return true; + } - // Remove global:: prefix from namespace. - var normalizedNamespace = GetSpanWithoutGlobalPrefix(@namespace); + // Remove global:: prefix from namespace. + var normalizedNamespaceSpan = GetSpanWithoutGlobalPrefix(@namespace); - return normalizedNamespace.Equals(typeNamespace.AsSpan(), StringComparison.Ordinal); - } + return normalizedNamespaceSpan.Equals(typeNamespace.AsSpan(), StringComparison.Ordinal); } // Check if the given type is already in scope given the namespace of the current document. @@ -497,27 +500,24 @@ static bool IsTypeInNamespace(string typeNamespace, string @namespace) // If the namespace of the document is `MyComponents.Components.Shared`, // then the types `MyComponents.FooComponent`, `MyComponents.Components.BarComponent`, `MyComponents.Components.Shared.BazComponent` are all in scope. // Whereas `MyComponents.SomethingElse.OtherComponent` is not in scope. - internal static bool IsTypeInScope(TagHelperDescriptor descriptor, string currentNamespace) + internal static bool IsTypeInScope(TagHelperDescriptor tagHelper, string @namespace) { - return IsTypeInScopeCore(currentNamespace, descriptor.GetTypeNamespace()); - } + var typeNamespace = tagHelper.GetTypeNamespace(); - private static bool IsTypeInScopeCore(string currentNamespace, string typeNamespace) - { - if (string.IsNullOrEmpty(typeNamespace)) + if (typeNamespace.IsNullOrEmpty()) { // Either the typeName is not the full type name or this type is at the top level. return true; } - if (!currentNamespace.StartsWith(typeNamespace, StringComparison.Ordinal)) + if (!@namespace.StartsWith(typeNamespace, StringComparison.Ordinal)) { // typeName: MyComponents.Shared.SomeCoolNamespace // currentNamespace: MyComponents.Shared return false; } - if (typeNamespace.Length > currentNamespace.Length && typeNamespace[currentNamespace.Length] != '.') + if (typeNamespace.Length > @namespace.Length && typeNamespace[@namespace.Length] != '.') { // typeName: MyComponents.SharedFoo // currentNamespace: MyComponent.Shared From 36fea34f77a9d61c7016e19bfc48c7a78de646a9 Mon Sep 17 00:00:00 2001 From: Amadeusz Wieczorek Date: Tue, 9 Jul 2024 16:51:36 -0700 Subject: [PATCH 032/176] assert UI thread --- .../RazorLSPTextViewConnectionListener.cs | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/RazorLSPTextViewConnectionListener.cs b/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/RazorLSPTextViewConnectionListener.cs index aef5ffe3a49..13e993f8e8f 100644 --- a/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/RazorLSPTextViewConnectionListener.cs +++ b/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/RazorLSPTextViewConnectionListener.cs @@ -14,6 +14,7 @@ using Microsoft.VisualStudio.Text; using Microsoft.VisualStudio.Text.Editor; using Microsoft.VisualStudio.TextManager.Interop; +using Microsoft.VisualStudio.Threading; using Microsoft.VisualStudio.Utilities; using IServiceProvider = System.IServiceProvider; @@ -42,6 +43,7 @@ internal class RazorLSPTextViewConnectionListener : ITextViewConnectionListener private readonly ILspEditorFeatureDetector _editorFeatureDetector; private readonly IEditorOptionsFactoryService _editorOptionsFactory; private readonly IClientSettingsManager _editorSettingsManager; + private readonly JoinableTaskContext _joinableTaskContext; private IVsTextManager4? _textManager; /// @@ -62,19 +64,28 @@ public RazorLSPTextViewConnectionListener( IVsEditorAdaptersFactoryService editorAdaptersFactory, ILspEditorFeatureDetector editorFeatureDetector, IEditorOptionsFactoryService editorOptionsFactory, - IClientSettingsManager editorSettingsManager) + IClientSettingsManager editorSettingsManager, + JoinableTaskContext joinableTaskContext) { _serviceProvider = serviceProvider; _editorAdaptersFactory = editorAdaptersFactory; _editorFeatureDetector = editorFeatureDetector; _editorOptionsFactory = editorOptionsFactory; _editorSettingsManager = editorSettingsManager; + _joinableTaskContext = joinableTaskContext; } /// /// Gets instance of . This accesses COM object and requires to be called on the UI thread. /// - private IVsTextManager4 TextManager => _textManager ??= (IVsTextManager4)_serviceProvider.GetService(typeof(SVsTextManager)); + private IVsTextManager4 TextManager + { + get + { + _joinableTaskContext.AssertUIThread(); + return _textManager ??= (IVsTextManager4)_serviceProvider.GetService(typeof(SVsTextManager)); + } + } public void SubjectBuffersConnected(ITextView textView, ConnectionReason reason, IReadOnlyCollection subjectBuffers) { From 82d6cf65090d3d3d2af42718bb3edc119b73c858 Mon Sep 17 00:00:00 2001 From: David Wengier Date: Wed, 10 Jul 2024 11:05:34 +1000 Subject: [PATCH 033/176] PR Feedback --- .../ToolingTestBase.cs | 7 +++++++ .../Cohost/CohostTestBase.cs | 9 +++------ .../Cohost/InterceptingServiceBroker.cs | 3 ++- .../ShortCircuitingRemoteServiceProvider.cs | 15 ++++++++++----- 4 files changed, 22 insertions(+), 12 deletions(-) diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/ToolingTestBase.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/ToolingTestBase.cs index 1cac6d4b4ff..8dad3a87185 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/ToolingTestBase.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/ToolingTestBase.cs @@ -70,6 +70,12 @@ static ToolingTestBase() /// internal ILoggerFactory LoggerFactory { get; } + /// + /// An that the currently running test can use to write + /// though using is probably preferred. + /// + internal ITestOutputHelper TestOutputHelper { get; } + private ILogger? _logger; /// @@ -86,6 +92,7 @@ protected ToolingTestBase(ITestOutputHelper testOutput) _disposalTokenSource = new(); DisposalToken = _disposalTokenSource.Token; + TestOutputHelper = testOutput; LoggerFactory = new TestOutputLoggerFactory(testOutput); // Give this thread a name, so it's easier to find in the VS Threads window. diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostTestBase.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostTestBase.cs index d4a7baff69a..1ee26c68cf4 100644 --- a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostTestBase.cs +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostTestBase.cs @@ -2,7 +2,6 @@ // Licensed under the MIT license. See License.txt in the project root for license information. using System.IO; -using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Razor; using Microsoft.AspNetCore.Razor.Test.Common; @@ -14,17 +13,15 @@ namespace Microsoft.VisualStudio.LanguageServices.Razor.Test.Cohost; -public class CohostTestBase(ITestOutputHelper testOutputHelper) : WorkspaceTestBase(testOutputHelper) +public abstract class CohostTestBase(ITestOutputHelper testOutputHelper) : WorkspaceTestBase(testOutputHelper) { - private readonly ITestOutputHelper _testOutputHelper = testOutputHelper; - private IRemoteServiceProvider? _remoteServiceProvider; - internal IRemoteServiceProvider RemoteServiceProvider => _remoteServiceProvider.AssumeNotNull(); + private protected IRemoteServiceProvider RemoteServiceProvider => _remoteServiceProvider.AssumeNotNull(); protected override Task InitializeAsync() { - _remoteServiceProvider = new ShortCircuitingRemoteServiceProvider(_testOutputHelper); + _remoteServiceProvider = new ShortCircuitingRemoteServiceProvider(TestOutputHelper); return base.InitializeAsync(); } diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/InterceptingServiceBroker.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/InterceptingServiceBroker.cs index 0cee8db4187..364f0effc00 100644 --- a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/InterceptingServiceBroker.cs +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/InterceptingServiceBroker.cs @@ -21,7 +21,8 @@ public event EventHandler? AvailabilityChanged throw new NotImplementedException(); } - public ValueTask GetProxyAsync(ServiceRpcDescriptor serviceDescriptor, ServiceActivationOptions options = default, CancellationToken cancellationToken = default) where T : class + public ValueTask GetProxyAsync(ServiceRpcDescriptor serviceDescriptor, ServiceActivationOptions options = default, CancellationToken cancellationToken = default) + where T : class { throw new NotImplementedException(); } diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/ShortCircuitingRemoteServiceProvider.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/ShortCircuitingRemoteServiceProvider.cs index 5c5f8dde01f..e49bb65bbed 100644 --- a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/ShortCircuitingRemoteServiceProvider.cs +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/ShortCircuitingRemoteServiceProvider.cs @@ -3,7 +3,6 @@ using System; using System.Collections.Generic; -using System.Diagnostics; using System.IO; using System.Linq; using System.Runtime.CompilerServices; @@ -25,7 +24,7 @@ namespace Microsoft.VisualStudio.LanguageServices.Razor.Test.Cohost; /// internal class ShortCircuitingRemoteServiceProvider(ITestOutputHelper testOutputHelper) : IRemoteServiceProvider { - private static Dictionary _factoryMap = BuildFactoryMap(); + private static readonly Dictionary s_factoryMap = BuildFactoryMap(); private readonly IServiceProvider _serviceProvider = new TestTraceSourceProvider(testOutputHelper); @@ -38,7 +37,7 @@ private static Dictionary BuildFactoryMap() if (!type.IsAbstract && typeof(IServiceHubServiceFactory).IsAssignableFrom(type)) { - Debug.Assert(type.BaseType.GetGenericTypeDefinition() == typeof(RazorServiceFactoryBase<>)); + Assert.Equal(typeof(RazorServiceFactoryBase<>), type.BaseType.GetGenericTypeDefinition()); var genericType = type.BaseType.GetGenericArguments().FirstOrDefault(); if (genericType != null) @@ -53,9 +52,15 @@ private static Dictionary BuildFactoryMap() return result; } - public async ValueTask TryInvokeAsync(Solution solution, Func> invocation, CancellationToken cancellationToken, [CallerFilePath] string? callerFilePath = null, [CallerMemberName] string? callerMemberName = null) where TService : class + public async ValueTask TryInvokeAsync( + Solution solution, + Func> invocation, + CancellationToken cancellationToken, + [CallerFilePath] string? callerFilePath = null, + [CallerMemberName] string? callerMemberName = null) + where TService : class { - Assert.True(_factoryMap.TryGetValue(typeof(TService), out var factory)); + Assert.True(s_factoryMap.TryGetValue(typeof(TService), out var factory)); var testServiceBroker = new InterceptingServiceBroker(solution); From b92a394c94789aa02b78e4f6beb588a00d0b3a46 Mon Sep 17 00:00:00 2001 From: David Wengier Date: Wed, 10 Jul 2024 11:05:42 +1000 Subject: [PATCH 034/176] Improve create document method --- .../Cohost/CohostTestBase.cs | 31 +++++++++---------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostTestBase.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostTestBase.cs index 1ee26c68cf4..cc0800edf62 100644 --- a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostTestBase.cs +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostTestBase.cs @@ -26,29 +26,28 @@ protected override Task InitializeAsync() return base.InitializeAsync(); } - protected TextDocument CreateRazorDocument(string input) + protected TextDocument CreateRazorDocument(string contents) { - var hostProject = TestProjectData.SomeProject; - var hostDocument = TestProjectData.SomeProjectComponentFile1; - - var sourceText = SourceText.From(input); + var projectFilePath = TestProjectData.SomeProject.FilePath; + var documentFilePath = TestProjectData.SomeProjectComponentFile1.FilePath; + var projectName = Path.GetFileNameWithoutExtension(projectFilePath); + var projectId = ProjectId.CreateNewId(debugName: projectName); + var documentId = DocumentId.CreateNewId(projectId, debugName: documentFilePath); var solution = Workspace.CurrentSolution.AddProject(ProjectInfo.Create( - ProjectId.CreateNewId(Path.GetFileNameWithoutExtension(hostProject.FilePath)), + projectId, VersionStamp.Create(), - Path.GetFileNameWithoutExtension(hostDocument.FilePath), - Path.GetFileNameWithoutExtension(hostDocument.FilePath), + name: projectName, + assemblyName: projectName, LanguageNames.CSharp, - hostDocument.FilePath)); + documentFilePath)); solution = solution.AddAdditionalDocument( - DocumentId.CreateNewId(solution.ProjectIds.Single(), hostDocument.FilePath), - hostDocument.FilePath, - sourceText, - filePath: hostDocument.FilePath); - - var document = solution.Projects.Single().AdditionalDocuments.Single(); + documentId, + documentFilePath, + SourceText.From(contents), + filePath: documentFilePath); - return document; + return solution.GetAdditionalDocument(documentId).AssumeNotNull(); } } From a1d07e0d89eefc33b7fc957a5215bce9becc08a1 Mon Sep 17 00:00:00 2001 From: David Wengier Date: Wed, 10 Jul 2024 11:17:15 +1000 Subject: [PATCH 035/176] Expand tests to match the existing ones --- .../Cohost/CohostLinkedEditingRangeTest.cs | 111 ++++++++++++++++-- 1 file changed, 103 insertions(+), 8 deletions(-) diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostLinkedEditingRangeTest.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostLinkedEditingRangeTest.cs index 0420d4d9b67..b84ad7a36ee 100644 --- a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostLinkedEditingRangeTest.cs +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostLinkedEditingRangeTest.cs @@ -17,13 +17,16 @@ namespace Microsoft.VisualStudio.LanguageServices.Razor.Test.Cohost; public class CohostLinkedEditingRangeTest(ITestOutputHelper testOutputHelper) : CohostTestBase(testOutputHelper) { - [Fact] - public async Task StartTag() + [Theory] + [InlineData("$$div")] + [InlineData("di$$v")] + [InlineData("div$$")] + public async Task Html_StartTag(string startTagAndCursorLocation) { - var input = """ + var input = $""" This is a Razor document. - <[|$$div|]> + <[|{startTagAndCursorLocation}|]> Here is some content. @@ -33,15 +36,101 @@ The end. await VerifyLinkedEditingRangeAsync(input); } - [Fact] - public async Task EndTag() + [Theory] + [InlineData("$$div")] + [InlineData("di$$v")] + [InlineData("div$$")] + public async Task Html_EndTag(string endTagAndCursorLocation) { - var input = """ + var input = $""" This is a Razor document. <[|div|]> Here is some content. - + + + The end. + """; + + await VerifyLinkedEditingRangeAsync(input); + } + + [Fact] + public async Task Html_EndTag_BeforeSlash() + { + var input = $""" + This is a Razor document. + +
+ Here is some content. + <$$/div> + + The end. + """; + + await VerifyLinkedEditingRangeAsync(input); + } + + [Fact] + public async Task Html_NotATag() + { + var input = $""" + This is a $$Razor document. + +
+ Here is some content. +
+ + The end. + """; + + await VerifyLinkedEditingRangeAsync(input); + } + + [Fact] + public async Task Html_NestedTags_Outer() + { + var input = $""" + This is a Razor document. + + <[|d$$iv|]> +
+ Here is some content. +
+ + + The end. + """; + + await VerifyLinkedEditingRangeAsync(input); + } + + [Fact] + public async Task Html_NestedTags_Inner() + { + var input = $""" + This is a Razor document. + +
+ <[|d$$iv|]> + Here is some content. + +
+ + The end. + """; + + await VerifyLinkedEditingRangeAsync(input); + } + + [Fact] + public async Task Html_SelfClosingTag() + { + var input = $""" + This is a Razor document. + + + Here is some content. The end. """; @@ -73,6 +162,12 @@ private async Task VerifyLinkedEditingRangeAsync(string input) var result = await endpoint.GetTestAccessor().HandleRequestAsync(request, document, DisposalToken); + if (spans.Length == 0) + { + Assert.Null(result); + return; + } + Assert.NotNull(result); Assert.Equal(LinkedEditingRangeHelper.WordPattern, result.WordPattern); Assert.Equal(spans[0], result.Ranges[0].ToTextSpan(sourceText)); From 28ff338a9a2a338e865298b4f89afc7aea95886a Mon Sep 17 00:00:00 2001 From: David Wengier Date: Wed, 10 Jul 2024 13:46:07 +1000 Subject: [PATCH 036/176] PR Feedback --- .../SignatureHelp/SignatureHelpEndpoint.cs | 5 +++-- .../LanguageClient/Cohost/CohostSignatureHelpEndpoint.cs | 6 ++++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/SignatureHelp/SignatureHelpEndpoint.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/SignatureHelp/SignatureHelpEndpoint.cs index 167ee99201a..790cd537f07 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/SignatureHelp/SignatureHelpEndpoint.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/SignatureHelp/SignatureHelpEndpoint.cs @@ -11,10 +11,11 @@ using Microsoft.CodeAnalysis.Razor.Protocol; using Microsoft.CodeAnalysis.Razor.Workspaces; using Microsoft.VisualStudio.LanguageServer.Protocol; -using LSP = Microsoft.VisualStudio.LanguageServer.Protocol; namespace Microsoft.AspNetCore.Razor.LanguageServer.SignatureHelp; +using SignatureHelp = VisualStudio.LanguageServer.Protocol.SignatureHelp; + [RazorLanguageServerEndpoint(Methods.TextDocumentSignatureHelpName)] internal sealed class SignatureHelpEndpoint( LanguageServerFeatureOptions languageServerFeatureOptions, @@ -22,7 +23,7 @@ internal sealed class SignatureHelpEndpoint( IClientConnection clientConnection, RazorLSPOptionsMonitor optionsMonitor, ILoggerFactory loggerProvider) - : AbstractRazorDelegatingEndpoint( + : AbstractRazorDelegatingEndpoint( languageServerFeatureOptions, documentMappingService, clientConnection, diff --git a/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/CohostSignatureHelpEndpoint.cs b/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/CohostSignatureHelpEndpoint.cs index 5e9164491d0..e2dc1f050d5 100644 --- a/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/CohostSignatureHelpEndpoint.cs +++ b/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/CohostSignatureHelpEndpoint.cs @@ -81,7 +81,8 @@ internal class CohostSignatureHelpEndpoint( var data = await _remoteServiceProvider.TryInvokeAsync( razorDocument.Project.Solution, (service, solutionInfo, cancellationToken) => service.GetSignatureHelpAsync(solutionInfo, razorDocument.Id, new RLSP.Position(request.Position.Line, request.Position.Character), cancellationToken), - cancellationToken).ConfigureAwait(false); + cancellationToken) + .ConfigureAwait(false); // If we got a response back, then either Razor or C# wants to do something with this, so we're good to go if (data is { } signatureHelp) @@ -103,7 +104,8 @@ internal class CohostSignatureHelpEndpoint( Methods.TextDocumentSignatureHelpName, RazorLSPConstants.HtmlLanguageServerName, request, - cancellationToken).ConfigureAwait(false); + cancellationToken) + .ConfigureAwait(false); return result?.Response; } From 6b6696a46884f372f46342f0cac1281085c3054b Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Wed, 10 Jul 2024 09:51:23 -0700 Subject: [PATCH 037/176] Use collection expressions --- .../PooledObjects/PooledArrayBuilder`1.cs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/PooledObjects/PooledArrayBuilder`1.cs b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/PooledObjects/PooledArrayBuilder`1.cs index c12caed3645..985ce5bb4d6 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/PooledObjects/PooledArrayBuilder`1.cs +++ b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/PooledObjects/PooledArrayBuilder`1.cs @@ -409,11 +409,11 @@ private readonly ImmutableArray InlineItemsToImmutableArray() return _inlineCount switch { - 0 => ImmutableArray.Empty, - 1 => ImmutableArray.Create(_element0), - 2 => ImmutableArray.Create(_element0, _element1), - 3 => ImmutableArray.Create(_element0, _element1, _element2), - _ => ImmutableArray.Create(_element0, _element1, _element2, _element3) + 0 => [], + 1 => [_element0], + 2 => [_element0, _element1], + 3 => [_element0, _element1, _element2], + _ => [_element0, _element1, _element2, _element3] }; } @@ -427,10 +427,10 @@ public readonly T[] ToArray() return _inlineCount switch { 0 => [], - 1 => new[] { _element0 }, - 2 => new[] { _element0, _element1 }, - 3 => new[] { _element0, _element1, _element2 }, - _ => new[] { _element0, _element1, _element2, _element3 } + 1 => [_element0], + 2 => [_element0, _element1], + 3 => [_element0, _element1, _element2], + _ => [_element0, _element1, _element2, _element3] }; } From 86e57e58b2132416a0144a0829b666f7934b4072 Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Wed, 10 Jul 2024 09:51:47 -0700 Subject: [PATCH 038/176] Mark method as readonly --- .../PooledObjects/PooledArrayBuilder`1.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/PooledObjects/PooledArrayBuilder`1.cs b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/PooledObjects/PooledArrayBuilder`1.cs index 985ce5bb4d6..8591e930b77 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/PooledObjects/PooledArrayBuilder`1.cs +++ b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/PooledObjects/PooledArrayBuilder`1.cs @@ -434,7 +434,7 @@ public readonly T[] ToArray() }; } - public bool Any() => Count > 0; + public readonly bool Any() => Count > 0; public void Push(T item) { From 171f21c599b73f51536c98e408fe9bf9e663fc3e Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Wed, 10 Jul 2024 09:56:39 -0700 Subject: [PATCH 039/176] Add First(), FirstOrDefault(), Last() and LastOrDefault() methods --- .../PooledObjects/PooledArrayBuilder`1.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/PooledObjects/PooledArrayBuilder`1.cs b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/PooledObjects/PooledArrayBuilder`1.cs index 8591e930b77..6ca89f7ca13 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/PooledObjects/PooledArrayBuilder`1.cs +++ b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/PooledObjects/PooledArrayBuilder`1.cs @@ -467,6 +467,11 @@ public bool TryPop([MaybeNullWhen(false)] out T item) return true; } + public readonly T First() => this[0]; + public readonly T? FirstOrDefault() => Count > 0 ? this[0] : default; + public readonly T Last() => this[^1]; + public readonly T? LastOrDefault() => Count > 0 ? this[^1] : default; + /// /// This is present to help the JIT inline methods that need to throw /// a . From 5e622586419f7cb98c76363b8fac3546e96b3997 Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Wed, 10 Jul 2024 10:06:03 -0700 Subject: [PATCH 040/176] Add Single() and SingleOrDefault() methods --- .../PooledObjects/PooledArrayBuilder`1.cs | 25 +++++++++++++++++++ .../Resources/SR.resx | 6 +++++ .../Resources/xlf/SR.cs.xlf | 10 ++++++++ .../Resources/xlf/SR.de.xlf | 10 ++++++++ .../Resources/xlf/SR.es.xlf | 10 ++++++++ .../Resources/xlf/SR.fr.xlf | 10 ++++++++ .../Resources/xlf/SR.it.xlf | 10 ++++++++ .../Resources/xlf/SR.ja.xlf | 10 ++++++++ .../Resources/xlf/SR.ko.xlf | 10 ++++++++ .../Resources/xlf/SR.pl.xlf | 10 ++++++++ .../Resources/xlf/SR.pt-BR.xlf | 10 ++++++++ .../Resources/xlf/SR.ru.xlf | 10 ++++++++ .../Resources/xlf/SR.tr.xlf | 10 ++++++++ .../Resources/xlf/SR.zh-Hans.xlf | 10 ++++++++ .../Resources/xlf/SR.zh-Hant.xlf | 10 ++++++++ 15 files changed, 161 insertions(+) diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/PooledObjects/PooledArrayBuilder`1.cs b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/PooledObjects/PooledArrayBuilder`1.cs index 6ca89f7ca13..1de01c94f5c 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/PooledObjects/PooledArrayBuilder`1.cs +++ b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/PooledObjects/PooledArrayBuilder`1.cs @@ -472,6 +472,23 @@ public bool TryPop([MaybeNullWhen(false)] out T item) public readonly T Last() => this[^1]; public readonly T? LastOrDefault() => Count > 0 ? this[^1] : default; + public readonly T Single() + { + if (Count == 0) + { + ThrowInvalidOperation(SR.Contains_no_elements); + } + else if (Count > 1) + { + ThrowInvalidOperation(SR.Contains_more_than_one_element); + } + + return this[0]; + } + + public readonly T? SingleOrDefault() + => Count == 1 ? this[0] : default; + /// /// This is present to help the JIT inline methods that need to throw /// a . @@ -480,6 +497,14 @@ public bool TryPop([MaybeNullWhen(false)] out T item) private static void ThrowIndexOutOfRangeException() => throw new IndexOutOfRangeException(); + /// + /// This is present to help the JIT inline methods that need to throw + /// a . + /// + [DoesNotReturn] + private static void ThrowInvalidOperation(string message) + => throw new InvalidOperationException(message); + [MemberNotNull(nameof(_builder))] private void MoveInlineItemsToBuilder() { diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/SR.resx b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/SR.resx index 5d1e6da3fd1..d3fc107d94a 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/SR.resx +++ b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/SR.resx @@ -177,4 +177,10 @@ Unsupported type: '{0}'. + + Contains no elements + + + Contains more than one element + \ No newline at end of file diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.cs.xlf b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.cs.xlf index b4799a7333a..c2a8d3c78b9 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.cs.xlf +++ b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.cs.xlf @@ -57,6 +57,16 @@ Nelze přidělit vyrovnávací paměť o velikosti {0}. + + Contains more than one element + Contains more than one element + + + + Contains no elements + Contains no elements + + Destination is too short. Cíl je příliš krátký. diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.de.xlf b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.de.xlf index 4e13650d4aa..4f1fb4d427d 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.de.xlf +++ b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.de.xlf @@ -57,6 +57,16 @@ Ein Puffer der Größe {0} kann nicht zugeordnet werden. + + Contains more than one element + Contains more than one element + + + + Contains no elements + Contains no elements + + Destination is too short. Das Ziel ist zu kurz. diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.es.xlf b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.es.xlf index 7fdaa54ea42..a7f25e00fcc 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.es.xlf +++ b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.es.xlf @@ -57,6 +57,16 @@ No se puede asignar un búfer de tamaño {0}. + + Contains more than one element + Contains more than one element + + + + Contains no elements + Contains no elements + + Destination is too short. El destino es demasiado corto. diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.fr.xlf b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.fr.xlf index 3aa16aa7b53..331945d58d5 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.fr.xlf +++ b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.fr.xlf @@ -57,6 +57,16 @@ Impossible d’allouer une mémoire tampon de taille {0}. + + Contains more than one element + Contains more than one element + + + + Contains no elements + Contains no elements + + Destination is too short. La destination est trop courte. diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.it.xlf b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.it.xlf index 9186f8e028d..65872f7bad0 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.it.xlf +++ b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.it.xlf @@ -57,6 +57,16 @@ Impossibile allocare un buffer di dimensioni {0}. + + Contains more than one element + Contains more than one element + + + + Contains no elements + Contains no elements + + Destination is too short. La destinazione è troppo breve. diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.ja.xlf b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.ja.xlf index 111a70c3ff5..30e48926c0d 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.ja.xlf +++ b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.ja.xlf @@ -57,6 +57,16 @@ サイズ {0} のバッファーを割り当てることができません。 + + Contains more than one element + Contains more than one element + + + + Contains no elements + Contains no elements + + Destination is too short. 宛先が短すぎます。 diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.ko.xlf b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.ko.xlf index ab17a911b1a..97425713380 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.ko.xlf +++ b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.ko.xlf @@ -57,6 +57,16 @@ {0} 크기의 버퍼를 할당할 수 없습니다. + + Contains more than one element + Contains more than one element + + + + Contains no elements + Contains no elements + + Destination is too short. 대상이 너무 짧습니다. diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.pl.xlf b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.pl.xlf index d95b962c479..a17ec158d99 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.pl.xlf +++ b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.pl.xlf @@ -57,6 +57,16 @@ Nie można przydzielić buforu o rozmiarze {0}. + + Contains more than one element + Contains more than one element + + + + Contains no elements + Contains no elements + + Destination is too short. Miejsce docelowe jest zbyt krótkie. diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.pt-BR.xlf b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.pt-BR.xlf index ef5d15dc904..c7e0f21de69 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.pt-BR.xlf +++ b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.pt-BR.xlf @@ -57,6 +57,16 @@ Não é possível alocar um buffer de tamanho {0}. + + Contains more than one element + Contains more than one element + + + + Contains no elements + Contains no elements + + Destination is too short. O destino é muito curto. diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.ru.xlf b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.ru.xlf index e3c55bc9764..775e4d87632 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.ru.xlf +++ b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.ru.xlf @@ -57,6 +57,16 @@ Невозможно выделить буфер размером {0}. + + Contains more than one element + Contains more than one element + + + + Contains no elements + Contains no elements + + Destination is too short. Имя назначения слишком короткое. diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.tr.xlf b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.tr.xlf index 7d9905d2b93..6d5ac22f06d 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.tr.xlf +++ b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.tr.xlf @@ -57,6 +57,16 @@ Boyutu {0} olan arabellek ayrılamıyor + + Contains more than one element + Contains more than one element + + + + Contains no elements + Contains no elements + + Destination is too short. Hedef çok kısa. diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.zh-Hans.xlf b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.zh-Hans.xlf index 0d91a0b555b..5ccfe77c4d2 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.zh-Hans.xlf +++ b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.zh-Hans.xlf @@ -57,6 +57,16 @@ 无法分配大小为 {0} 的缓冲区。 + + Contains more than one element + Contains more than one element + + + + Contains no elements + Contains no elements + + Destination is too short. 目标太短。 diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.zh-Hant.xlf b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.zh-Hant.xlf index 83eb07c4189..54651834c33 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.zh-Hant.xlf +++ b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.zh-Hant.xlf @@ -57,6 +57,16 @@ 無法配置大小為 {0} 的緩衝區。 + + Contains more than one element + Contains more than one element + + + + Contains no elements + Contains no elements + + Destination is too short. 目的地太短。 From 7a3e1e5f7d9a6c2f1a6e48bd3125af24bd78d316 Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Wed, 10 Jul 2024 10:07:55 -0700 Subject: [PATCH 041/176] Prefer TheoryData in tests --- .../PooledObjects/PooledArrayBuilderTests.cs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared.Test/PooledObjects/PooledArrayBuilderTests.cs b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared.Test/PooledObjects/PooledArrayBuilderTests.cs index 5c7e582abba..3a11821f474 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared.Test/PooledObjects/PooledArrayBuilderTests.cs +++ b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared.Test/PooledObjects/PooledArrayBuilderTests.cs @@ -1,7 +1,6 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT license. See License.txt in the project root for license information. -using System.Collections.Generic; using Microsoft.AspNetCore.Razor.PooledObjects; using Xunit; @@ -33,20 +32,24 @@ public void AddElements([CombinatorialRange(0, 8)] int count) } } - public static IEnumerable RemoveAtIndex_Data + public static TheoryData RemoveAtIndex_Data { get { + var data = new TheoryData(); + for (var count = 0; count < 8; count++) { for (var removeIndex = 0; removeIndex < 8; removeIndex++) { if (removeIndex < count) { - yield return new object[] { count, removeIndex }; + data.Add(count, removeIndex); } } } + + return data; } } From 6647eb0a509c27e27849e3b87e5890a06717f313 Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Wed, 10 Jul 2024 10:15:39 -0700 Subject: [PATCH 042/176] Add tests for new PooledArrayBuilder methods --- .../PooledObjects/PooledArrayBuilderTests.cs | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared.Test/PooledObjects/PooledArrayBuilderTests.cs b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared.Test/PooledObjects/PooledArrayBuilderTests.cs index 3a11821f474..ed9c5994328 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared.Test/PooledObjects/PooledArrayBuilderTests.cs +++ b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared.Test/PooledObjects/PooledArrayBuilderTests.cs @@ -1,8 +1,10 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT license. See License.txt in the project root for license information. +using System; using Microsoft.AspNetCore.Razor.PooledObjects; using Xunit; +using SR = Microsoft.AspNetCore.Razor.Utilities.Shared.Resources.SR; namespace Microsoft.AspNetCore.Razor.Utilities.Shared.Test.PooledObjects; @@ -83,4 +85,42 @@ public void RemoveAtIndex(int count, int removeIndex) } } } + + [Fact] + public void FirstAndLast() + { + using var builder = new PooledArrayBuilder(); + builder.Add(19); + builder.Add(23); + + Assert.Equal(19, builder.First()); + Assert.Equal(19, builder.FirstOrDefault()); + Assert.Equal(23, builder.Last()); + Assert.Equal(23, builder.LastOrDefault()); + + builder.Clear(); + Assert.Equal(default, builder.FirstOrDefault()); + Assert.Equal(default, builder.LastOrDefault()); + } + + [Fact] + public void Single() + { + using var builder = new PooledArrayBuilder(); + + var exception1 = Assert.Throws(() => builder.Single()); + Assert.Equal(SR.Contains_no_elements, exception1.Message); + Assert.Equal(default, builder.SingleOrDefault()); + + builder.Add(19); + + Assert.Equal(19, builder.Single()); + Assert.Equal(19, builder.SingleOrDefault()); + + builder.Add(23); + + var exception2 = Assert.Throws(() => builder.Single()); + Assert.Equal(SR.Contains_more_than_one_element, exception2.Message); + Assert.Equal(default, builder.SingleOrDefault()); + } } From 0abee9c6c9c5988cdb14845c0a8d377b302cd2fd Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Wed, 10 Jul 2024 10:17:11 -0700 Subject: [PATCH 043/176] Fix XML doc comment typo --- .../PooledObjects/PooledArrayBuilder`1.cs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/PooledObjects/PooledArrayBuilder`1.cs b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/PooledObjects/PooledArrayBuilder`1.cs index 1de01c94f5c..5b1a48dbf19 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/PooledObjects/PooledArrayBuilder`1.cs +++ b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/PooledObjects/PooledArrayBuilder`1.cs @@ -490,16 +490,14 @@ public readonly T Single() => Count == 1 ? this[0] : default; /// - /// This is present to help the JIT inline methods that need to throw - /// a . + /// This is present to help the JIT inline methods that need to throw an . /// [DoesNotReturn] private static void ThrowIndexOutOfRangeException() => throw new IndexOutOfRangeException(); /// - /// This is present to help the JIT inline methods that need to throw - /// a . + /// This is present to help the JIT inline methods that need to throw an . /// [DoesNotReturn] private static void ThrowInvalidOperation(string message) From 9f10648fd5590a376d7cae571cf3069c1f0ba71c Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Wed, 10 Jul 2024 12:04:31 -0700 Subject: [PATCH 044/176] Add predicate overloads, XML doc comments, and more tests --- .../PooledObjects/PooledArrayBuilderTests.cs | 138 +++++++- .../PooledObjects/PooledArrayBuilder`1.cs | 326 +++++++++++++++++- .../Resources/SR.resx | 6 + .../Resources/xlf/SR.cs.xlf | 10 + .../Resources/xlf/SR.de.xlf | 10 + .../Resources/xlf/SR.es.xlf | 10 + .../Resources/xlf/SR.fr.xlf | 10 + .../Resources/xlf/SR.it.xlf | 10 + .../Resources/xlf/SR.ja.xlf | 10 + .../Resources/xlf/SR.ko.xlf | 10 + .../Resources/xlf/SR.pl.xlf | 10 + .../Resources/xlf/SR.pt-BR.xlf | 10 + .../Resources/xlf/SR.ru.xlf | 10 + .../Resources/xlf/SR.tr.xlf | 10 + .../Resources/xlf/SR.zh-Hans.xlf | 10 + .../Resources/xlf/SR.zh-Hant.xlf | 10 + 16 files changed, 583 insertions(+), 17 deletions(-) diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared.Test/PooledObjects/PooledArrayBuilderTests.cs b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared.Test/PooledObjects/PooledArrayBuilderTests.cs index ed9c5994328..03129b86b02 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared.Test/PooledObjects/PooledArrayBuilderTests.cs +++ b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared.Test/PooledObjects/PooledArrayBuilderTests.cs @@ -86,21 +86,123 @@ public void RemoveAtIndex(int count, int removeIndex) } } + private static Func IsEven => x => x % 2 == 0; + private static Func IsOdd => x => x % 2 != 0; + + [Fact] + public void Any() + { + using var builder = new PooledArrayBuilder(); + + Assert.False(builder.Any()); + + builder.Add(19); + + Assert.True(builder.Any()); + + builder.Add(23); + + Assert.True(builder.Any(IsOdd)); + + // ... but no even numbers + Assert.False(builder.Any(IsEven)); + } + + [Fact] + public void All() + { + using var builder = new PooledArrayBuilder(); + + Assert.True(builder.All(IsEven)); + + builder.Add(19); + + Assert.False(builder.All(IsEven)); + + builder.Add(23); + + Assert.True(builder.All(IsOdd)); + + builder.Add(42); + + Assert.False(builder.All(IsOdd)); + } + [Fact] public void FirstAndLast() { using var builder = new PooledArrayBuilder(); + + var exception1 = Assert.Throws(() => builder.First()); + Assert.Equal(SR.Contains_no_elements, exception1.Message); + + Assert.Equal(default, builder.FirstOrDefault()); + + var exception2 = Assert.Throws(() => builder.Last()); + Assert.Equal(SR.Contains_no_elements, exception1.Message); + + Assert.Equal(default, builder.LastOrDefault()); + builder.Add(19); + + Assert.Equal(19, builder.First()); + Assert.Equal(19, builder.FirstOrDefault()); + Assert.Equal(19, builder.Last()); + Assert.Equal(19, builder.LastOrDefault()); + builder.Add(23); Assert.Equal(19, builder.First()); Assert.Equal(19, builder.FirstOrDefault()); Assert.Equal(23, builder.Last()); Assert.Equal(23, builder.LastOrDefault()); + } - builder.Clear(); - Assert.Equal(default, builder.FirstOrDefault()); - Assert.Equal(default, builder.LastOrDefault()); + [Fact] + public void FirstAndLastWithPredicate() + { + using var builder = new PooledArrayBuilder(); + + var exception1 = Assert.Throws(() => builder.First(IsOdd)); + Assert.Equal(SR.Contains_no_matching_elements, exception1.Message); + + Assert.Equal(default, builder.FirstOrDefault(IsOdd)); + + var exception2 = Assert.Throws(() => builder.Last(IsOdd)); + Assert.Equal(SR.Contains_no_matching_elements, exception2.Message); + + Assert.Equal(default, builder.LastOrDefault(IsOdd)); + + builder.Add(19); + + Assert.Equal(19, builder.First(IsOdd)); + Assert.Equal(19, builder.FirstOrDefault(IsOdd)); + Assert.Equal(19, builder.Last(IsOdd)); + Assert.Equal(19, builder.LastOrDefault(IsOdd)); + + builder.Add(23); + + Assert.Equal(19, builder.First(IsOdd)); + Assert.Equal(19, builder.FirstOrDefault(IsOdd)); + Assert.Equal(23, builder.Last(IsOdd)); + Assert.Equal(23, builder.LastOrDefault(IsOdd)); + + var exception3 = Assert.Throws(() => builder.First(IsEven)); + Assert.Equal(SR.Contains_no_matching_elements, exception3.Message); + + Assert.Equal(default, builder.FirstOrDefault(IsEven)); + + var exception4 = Assert.Throws(() => builder.Last(IsEven)); + Assert.Equal(SR.Contains_no_matching_elements, exception4.Message); + + Assert.Equal(default, builder.LastOrDefault(IsEven)); + + builder.Add(42); + + Assert.Equal(42, builder.First(IsEven)); + Assert.Equal(42, builder.FirstOrDefault(IsEven)); + Assert.Equal(42, builder.Last(IsEven)); + Assert.Equal(42, builder.LastOrDefault(IsEven)); } [Fact] @@ -121,6 +223,34 @@ public void Single() var exception2 = Assert.Throws(() => builder.Single()); Assert.Equal(SR.Contains_more_than_one_element, exception2.Message); - Assert.Equal(default, builder.SingleOrDefault()); + var exception3 = Assert.Throws(() => builder.SingleOrDefault()); + Assert.Equal(SR.Contains_more_than_one_element, exception2.Message); + } + + [Fact] + public void SingleWithPredicate() + { + using var builder = new PooledArrayBuilder(); + + var exception1 = Assert.Throws(() => builder.Single(IsOdd)); + Assert.Equal(SR.Contains_no_matching_elements, exception1.Message); + Assert.Equal(default, builder.SingleOrDefault(IsOdd)); + + builder.Add(19); + + Assert.Equal(19, builder.Single(IsOdd)); + Assert.Equal(19, builder.SingleOrDefault(IsOdd)); + + builder.Add(23); + + var exception2 = Assert.Throws(() => builder.Single(IsOdd)); + Assert.Equal(SR.Contains_more_than_one_matching_element, exception2.Message); + var exception3 = Assert.Throws(() => builder.SingleOrDefault(IsOdd)); + Assert.Equal(SR.Contains_more_than_one_matching_element, exception2.Message); + + builder.Add(42); + + Assert.Equal(42, builder.Single(IsEven)); + Assert.Equal(42, builder.SingleOrDefault(IsEven)); } } diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/PooledObjects/PooledArrayBuilder`1.cs b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/PooledObjects/PooledArrayBuilder`1.cs index 5b1a48dbf19..6e14fcbd52b 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/PooledObjects/PooledArrayBuilder`1.cs +++ b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/PooledObjects/PooledArrayBuilder`1.cs @@ -434,8 +434,6 @@ public readonly T[] ToArray() }; } - public readonly bool Any() => Count > 0; - public void Push(T item) { Add(item); @@ -467,27 +465,329 @@ public bool TryPop([MaybeNullWhen(false)] out T item) return true; } - public readonly T First() => this[0]; - public readonly T? FirstOrDefault() => Count > 0 ? this[0] : default; - public readonly T Last() => this[^1]; - public readonly T? LastOrDefault() => Count > 0 ? this[^1] : default; + /// + /// Determines whether this builder contains any elements. + /// + /// + /// if this builder contains any elements; otherwise, . + /// + public readonly bool Any() + => Count > 0; + /// + /// Determines whether any element in this builder satisfies a condition. + /// + /// + /// A function to test each element for a condition. + /// + /// + /// if this builder is not empty and at least one of its elements passes + /// the test in the specified predicate; otherwise, . + /// + public readonly bool Any(Func predicate) + { + foreach (var item in this) + { + if (predicate(item)) + { + return true; + } + } + + return false; + } + + /// + /// Determines whether all elements in this builder satisfy a condition. + /// + /// + /// A function to test each element for a condition. + /// + /// + /// if every element in this builder passes the test + /// in the specified predicate, or if the builder is empty; otherwise, + /// . + public readonly bool All(Func predicate) + { + foreach (var item in this) + { + if (!predicate(item)) + { + return false; + } + } + + return true; + } + + /// + /// Returns the first element in this builder. + /// + /// + /// The first element in this builder. + /// + /// + /// The builder is empty. + /// + public readonly T First() + => Count > 0 ? this[0] : ThrowInvalidOperation(SR.Contains_no_elements); + + /// + /// Returns the first element in this builder that satisfies a specified condition. + /// + /// + /// A function to test each element for a condition. + /// + /// + /// The first element in this builder that passes the test in the specified predicate function. + /// + /// + /// No element satisfies the condition in . + /// + public readonly T First(Func predicate) + { + foreach (var item in this) + { + if (predicate(item)) + { + return item; + } + } + + return ThrowInvalidOperation(SR.Contains_no_matching_elements); + } + + /// + /// Returns the first element in this builder, or a default value if the builder is empty. + /// + /// + /// () if this builder is empty; otherwise, + /// the first element in this builder. + /// + public readonly T? FirstOrDefault() + => Count > 0 ? this[0] : default; + + /// + /// Returns the first element in this builder that satisfies a condition, or a default value + /// if no such element is found. + /// + /// + /// A function to test each element for a condition. + /// + /// + /// () if this builder is empty or if no element + /// passes the test specified by ; otherwise, the first element in this + /// builder that passes the test specified by . + /// + public readonly T? FirstOrDefault(Func predicate) + { + foreach (var item in this) + { + if (predicate(item)) + { + return item; + } + } + + return default; + } + + /// + /// Returns the last element in this builder. + /// + /// + /// The value at the last position in this builder. + /// + /// + /// The builder is empty. + /// + public readonly T Last() + => Count > 0 ? this[^1] : ThrowInvalidOperation(SR.Contains_no_elements); + + /// + /// Returns the last element in this builder that satisfies a specified condition. + /// + /// + /// A function to test each element for a condition. + /// + /// + /// The last element in this builder that passes the test in the specified predicate function. + /// + /// + /// No element satisfies the condition in . + /// + public readonly T Last(Func predicate) + { + for (var i = Count - 1; i >= 0; i--) + { + var item = this[i]; + if (predicate(item)) + { + return item; + } + } + + return ThrowInvalidOperation(SR.Contains_no_matching_elements); + } + + /// + /// Returns the last element in this builder, or a default value if the builder is empty. + /// + /// + /// () if this builder is empty; otherwise, + /// the last element in this builder. + /// + public readonly T? LastOrDefault() + => Count > 0 ? this[^1] : default; + + /// + /// Returns the last element in this builder that satisfies a condition, or a default value + /// if no such element is found. + /// + /// + /// A function to test each element for a condition. + /// + /// + /// () if this builder is empty or if no element + /// passes the test specified by ; otherwise, the last element in this + /// builder that passes the test specified by . + /// + public readonly T? LastOrDefault(Func predicate) + { + for (var i = Count - 1; i >= 0; i--) + { + var item = this[i]; + if (predicate(item)) + { + return item; + } + } + + return default; + } + + /// + /// Returns the only element in this builder, and throws an exception if there is not exactly one element. + /// + /// + /// The single element in this builder. + /// + /// + /// The builder is empty. + /// + /// + /// The builder contains more than one element. + /// public readonly T Single() { - if (Count == 0) + return Count switch + { + 1 => this[0], + 0 => ThrowInvalidOperation(SR.Contains_no_elements), + _ => ThrowInvalidOperation(SR.Contains_more_than_one_element) + }; + } + + /// + /// Returns the only element in this builder that satisfies a specified condition, + /// and throws an exception if more than one such element exists. + /// + /// + /// A function to test an element for a condition. + /// + /// + /// The single element in this builder that satisfies a condition. + /// + /// + /// No element satisfies the condition in . + /// + /// + /// More than one element satisfies the condition in . + /// + public readonly T Single(Func predicate) + { + var firstSeen = false; + T? result = default; + + foreach (var item in this) { - ThrowInvalidOperation(SR.Contains_no_elements); + if (predicate(item)) + { + if (firstSeen) + { + return ThrowInvalidOperation(SR.Contains_more_than_one_matching_element); + } + + firstSeen = true; + result = item; + } } - else if (Count > 1) + + if (!firstSeen) { - ThrowInvalidOperation(SR.Contains_more_than_one_element); + return ThrowInvalidOperation(SR.Contains_no_matching_elements); } - return this[0]; + return result!; } + /// + /// Returns the only element in this builder, or a default value if the builder is empty; + /// this method throws an exception if there is more than one element in the builder. + /// + /// + /// The single element in this builder, or () + /// if this builder contains no elements. + /// + /// + /// The builder contains more than one element. + /// public readonly T? SingleOrDefault() - => Count == 1 ? this[0] : default; + { + return Count switch + { + 1 => this[0], + 0 => default, + _ => ThrowInvalidOperation(SR.Contains_more_than_one_element) + }; + } + + /// + /// Returns the only element in this builder that satisfies a specified condition or a default + /// value if no such element exists; this method throws an exception if more than one element + /// satisfies the condition. + /// + /// + /// A function to test an element for a condition. + /// + /// + /// The single element in this builder that satisfies the condition, or + /// () if no such element is found. + /// + /// + /// More than one element satisfies the condition in predicate. + /// + public readonly T? SingleOrDefault(Func predicate) + { + var firstSeen = false; + T? result = default; + + foreach (var item in this) + { + if (predicate(item)) + { + if (firstSeen) + { + return ThrowInvalidOperation(SR.Contains_more_than_one_matching_element); + } + + firstSeen = true; + result = item; + } + } + + return result; + } /// /// This is present to help the JIT inline methods that need to throw an . @@ -500,7 +800,7 @@ private static void ThrowIndexOutOfRangeException() /// This is present to help the JIT inline methods that need to throw an . /// [DoesNotReturn] - private static void ThrowInvalidOperation(string message) + private static T ThrowInvalidOperation(string message) => throw new InvalidOperationException(message); [MemberNotNull(nameof(_builder))] diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/SR.resx b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/SR.resx index d3fc107d94a..77a9d817c57 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/SR.resx +++ b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/SR.resx @@ -183,4 +183,10 @@ Contains more than one element + + Contains no matching elements + + + Contains more than one matching element + \ No newline at end of file diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.cs.xlf b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.cs.xlf index c2a8d3c78b9..6df92ebf321 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.cs.xlf +++ b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.cs.xlf @@ -62,11 +62,21 @@ Contains more than one element + + Contains more than one matching element + Contains more than one matching element + + Contains no elements Contains no elements + + Contains no matching elements + Contains no matching elements + + Destination is too short. Cíl je příliš krátký. diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.de.xlf b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.de.xlf index 4f1fb4d427d..039bcd0a986 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.de.xlf +++ b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.de.xlf @@ -62,11 +62,21 @@ Contains more than one element + + Contains more than one matching element + Contains more than one matching element + + Contains no elements Contains no elements + + Contains no matching elements + Contains no matching elements + + Destination is too short. Das Ziel ist zu kurz. diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.es.xlf b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.es.xlf index a7f25e00fcc..3baf8c2158e 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.es.xlf +++ b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.es.xlf @@ -62,11 +62,21 @@ Contains more than one element + + Contains more than one matching element + Contains more than one matching element + + Contains no elements Contains no elements + + Contains no matching elements + Contains no matching elements + + Destination is too short. El destino es demasiado corto. diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.fr.xlf b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.fr.xlf index 331945d58d5..82795630352 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.fr.xlf +++ b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.fr.xlf @@ -62,11 +62,21 @@ Contains more than one element + + Contains more than one matching element + Contains more than one matching element + + Contains no elements Contains no elements + + Contains no matching elements + Contains no matching elements + + Destination is too short. La destination est trop courte. diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.it.xlf b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.it.xlf index 65872f7bad0..c591e22d614 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.it.xlf +++ b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.it.xlf @@ -62,11 +62,21 @@ Contains more than one element + + Contains more than one matching element + Contains more than one matching element + + Contains no elements Contains no elements + + Contains no matching elements + Contains no matching elements + + Destination is too short. La destinazione è troppo breve. diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.ja.xlf b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.ja.xlf index 30e48926c0d..9e24555eb74 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.ja.xlf +++ b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.ja.xlf @@ -62,11 +62,21 @@ Contains more than one element + + Contains more than one matching element + Contains more than one matching element + + Contains no elements Contains no elements + + Contains no matching elements + Contains no matching elements + + Destination is too short. 宛先が短すぎます。 diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.ko.xlf b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.ko.xlf index 97425713380..8c49817f712 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.ko.xlf +++ b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.ko.xlf @@ -62,11 +62,21 @@ Contains more than one element + + Contains more than one matching element + Contains more than one matching element + + Contains no elements Contains no elements + + Contains no matching elements + Contains no matching elements + + Destination is too short. 대상이 너무 짧습니다. diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.pl.xlf b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.pl.xlf index a17ec158d99..593b96a3be1 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.pl.xlf +++ b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.pl.xlf @@ -62,11 +62,21 @@ Contains more than one element + + Contains more than one matching element + Contains more than one matching element + + Contains no elements Contains no elements + + Contains no matching elements + Contains no matching elements + + Destination is too short. Miejsce docelowe jest zbyt krótkie. diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.pt-BR.xlf b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.pt-BR.xlf index c7e0f21de69..eed8347b2e3 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.pt-BR.xlf +++ b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.pt-BR.xlf @@ -62,11 +62,21 @@ Contains more than one element + + Contains more than one matching element + Contains more than one matching element + + Contains no elements Contains no elements + + Contains no matching elements + Contains no matching elements + + Destination is too short. O destino é muito curto. diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.ru.xlf b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.ru.xlf index 775e4d87632..64c65fef075 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.ru.xlf +++ b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.ru.xlf @@ -62,11 +62,21 @@ Contains more than one element + + Contains more than one matching element + Contains more than one matching element + + Contains no elements Contains no elements + + Contains no matching elements + Contains no matching elements + + Destination is too short. Имя назначения слишком короткое. diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.tr.xlf b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.tr.xlf index 6d5ac22f06d..fc2a2125c5e 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.tr.xlf +++ b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.tr.xlf @@ -62,11 +62,21 @@ Contains more than one element + + Contains more than one matching element + Contains more than one matching element + + Contains no elements Contains no elements + + Contains no matching elements + Contains no matching elements + + Destination is too short. Hedef çok kısa. diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.zh-Hans.xlf b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.zh-Hans.xlf index 5ccfe77c4d2..6f7ef38cc83 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.zh-Hans.xlf +++ b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.zh-Hans.xlf @@ -62,11 +62,21 @@ Contains more than one element + + Contains more than one matching element + Contains more than one matching element + + Contains no elements Contains no elements + + Contains no matching elements + Contains no matching elements + + Destination is too short. 目标太短。 diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.zh-Hant.xlf b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.zh-Hant.xlf index 54651834c33..7a6c4405352 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.zh-Hant.xlf +++ b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Resources/xlf/SR.zh-Hant.xlf @@ -62,11 +62,21 @@ Contains more than one element + + Contains more than one matching element + Contains more than one matching element + + Contains no elements Contains no elements + + Contains no matching elements + Contains no matching elements + + Destination is too short. 目的地太短。 From fda387efb995f7885043ca4de1857793d41b2377 Mon Sep 17 00:00:00 2001 From: Andrew Hall Date: Wed, 10 Jul 2024 13:40:41 -0700 Subject: [PATCH 045/176] Fix razor/namedPipe params to use STJ. Also rename the endpoint (#10604) --- ...ipeConnectHandler.cs => RazorNamedPipeConnectEndpoint.cs} | 4 ++-- .../Protocol/RazorNamedPipeConnectParams.cs | 5 ++--- src/Razor/src/rzls/Program.cs | 2 +- .../RazorLanguageServerTest.cs | 2 +- 4 files changed, 6 insertions(+), 7 deletions(-) rename src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/ProjectSystem/{RazorNamedPipeConnectHandler.cs => RazorNamedPipeConnectEndpoint.cs} (85%) diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/ProjectSystem/RazorNamedPipeConnectHandler.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/ProjectSystem/RazorNamedPipeConnectEndpoint.cs similarity index 85% rename from src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/ProjectSystem/RazorNamedPipeConnectHandler.cs rename to src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/ProjectSystem/RazorNamedPipeConnectEndpoint.cs index 3c2264e577e..23c477cea72 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/ProjectSystem/RazorNamedPipeConnectHandler.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/ProjectSystem/RazorNamedPipeConnectEndpoint.cs @@ -12,10 +12,10 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer.Hosting; [RazorLanguageServerEndpoint(CustomMessageNames.RazorNamedPipeConnectEndpointName)] -internal sealed class RazorNamedPipeConnectHandler(IRazorProjectInfoDriver infoDriver, ILoggerFactory loggerFactory) : IRazorNotificationHandler +internal sealed class RazorNamedPipeConnectEndpoint(IRazorProjectInfoDriver infoDriver, ILoggerFactory loggerFactory) : IRazorNotificationHandler { private readonly IRazorProjectInfoDriver _infoDriver = infoDriver; - private readonly ILogger _logger = loggerFactory.GetOrCreateLogger(); + private readonly ILogger _logger = loggerFactory.GetOrCreateLogger(); public bool MutatesSolutionState => false; diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Protocol/RazorNamedPipeConnectParams.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Protocol/RazorNamedPipeConnectParams.cs index 0508648e96f..ee365fcaa33 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Protocol/RazorNamedPipeConnectParams.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Protocol/RazorNamedPipeConnectParams.cs @@ -1,13 +1,12 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT license. See License.txt in the project root for license information. -using System.Runtime.Serialization; +using System.Text.Json.Serialization; namespace Microsoft.CodeAnalysis.Razor.Protocol; -[DataContract] internal class RazorNamedPipeConnectParams { - [DataMember(Name = "pipeName")] + [JsonPropertyName("pipeName")] public required string PipeName { get; set; } } diff --git a/src/Razor/src/rzls/Program.cs b/src/Razor/src/rzls/Program.cs index 0b9efd80538..f84d5a1bbf3 100644 --- a/src/Razor/src/rzls/Program.cs +++ b/src/Razor/src/rzls/Program.cs @@ -92,7 +92,7 @@ public static async Task Main(string[] args) configureServices: static services => { services.AddSingleton(); - services.AddHandler(); + services.AddHandler(); }); // Now we have a server, and hence a connection, we have somewhere to log diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/RazorLanguageServerTest.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/RazorLanguageServerTest.cs index 1ab963b28e5..70477b6bb44 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/RazorLanguageServerTest.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/RazorLanguageServerTest.cs @@ -117,7 +117,7 @@ private RazorLanguageServerHost CreateLanguageServerHost(Stream input, Stream ou s.AddSingleton(); // VS Code only handler is added by rzls, but add here for testing purposes - s.AddHandler(); + s.AddHandler(); }); } From f8893e881eb4b7ad58a9aaa4acda542e994c79d9 Mon Sep 17 00:00:00 2001 From: Andrew Hall Date: Wed, 10 Jul 2024 14:59:31 -0700 Subject: [PATCH 046/176] Fix unified settings (#10607) While self-hosting I noticed unified settings were no longer available and were defaulting back to the classic experience. Looks like they updated how some of the registration works and added a fix for f5 debugging them. Worked locally on my machine but I will not claim any expertise here. --- .../Microsoft.VisualStudio.RazorExtension.Custom.pkgdef | 7 +++++++ .../Microsoft.VisualStudio.RazorExtension/RazorPackage.cs | 1 + 2 files changed, 8 insertions(+) diff --git a/src/Razor/src/Microsoft.VisualStudio.RazorExtension/Microsoft.VisualStudio.RazorExtension.Custom.pkgdef b/src/Razor/src/Microsoft.VisualStudio.RazorExtension/Microsoft.VisualStudio.RazorExtension.Custom.pkgdef index 98918c86fc2..f8a61eafbb7 100644 --- a/src/Razor/src/Microsoft.VisualStudio.RazorExtension/Microsoft.VisualStudio.RazorExtension.Custom.pkgdef +++ b/src/Razor/src/Microsoft.VisualStudio.RazorExtension/Microsoft.VisualStudio.RazorExtension.Custom.pkgdef @@ -74,3 +74,10 @@ "Value"=dword:00000000 "Title"="Force use of runtime code generation for Razor (requires restart)" "PreviewPaneChannels"="IntPreview,int.main" + +// CacheTag value should be changed when registration file changes +// See https://devdiv.visualstudio.com/DevDiv/_wiki/wikis/DevDiv.wiki/39345/Manifest-Build-Deployment-and-Setup-Authoring-In-Depth?anchor=example-pkgdef-key for more infomation +[$RootKey$\SettingsManifests\{13b72f58-279e-49e0-a56d-296be02f0805}] +@="Microsoft.VisualStudio.RazorExtension.RazorPackage" +"ManifestPath"="$PackageFolder$\UnifiedSettings\razor.registration.json" +"CacheTag"=qword:5DE8496A8900B809 diff --git a/src/Razor/src/Microsoft.VisualStudio.RazorExtension/RazorPackage.cs b/src/Razor/src/Microsoft.VisualStudio.RazorExtension/RazorPackage.cs index 81a89fb79fa..acb9099758a 100644 --- a/src/Razor/src/Microsoft.VisualStudio.RazorExtension/RazorPackage.cs +++ b/src/Razor/src/Microsoft.VisualStudio.RazorExtension/RazorPackage.cs @@ -34,6 +34,7 @@ namespace Microsoft.VisualStudio.RazorExtension; [ProvideMenuResource("SyntaxVisualizerMenu.ctmenu", 1)] [ProvideToolWindow(typeof(SyntaxVisualizerToolWindow))] [ProvideLanguageEditorOptionPage(typeof(AdvancedOptionPage), RazorConstants.RazorLSPContentTypeName, category: null, "Advanced", pageNameResourceId: "#1050", keywordListResourceId: 1060)] +[ProvideSettingsManifest(PackageRelativeManifestFile = @"UnifiedSettings\razor.registration.json")] [Guid(PackageGuidString)] // We activate cohosting when the first Razor file is opened. This matches the previous behavior where the // LSP client MEF export had the Razor content type metadata. From 3b2da7704436f24f0239b64984e04e4122cd09aa Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Wed, 10 Jul 2024 15:25:44 -0700 Subject: [PATCH 047/176] Add ImmutableArray extension methods for ordering This change introduces four sets of extension methods with overloads: - OrderAsArray(...) - OrderDescendingAsArray(...) - OrderByAsArray(...) - OrderByDescendingAsArray(...) Each of these operates on an `ImmutableArray` and returns an `ImmutableArray`. --- .../ImmutableArrayExtensionsTests.cs | 98 ++++++++++++++ .../ImmutableArrayExtensions.cs | 123 ++++++++++++++++++ 2 files changed, 221 insertions(+) diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared.Test/ImmutableArrayExtensionsTests.cs b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared.Test/ImmutableArrayExtensionsTests.cs index c8a436095c4..5dd1f43216a 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared.Test/ImmutableArrayExtensionsTests.cs +++ b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared.Test/ImmutableArrayExtensionsTests.cs @@ -36,4 +36,102 @@ public void GetMostRecentUniqueItems() }, s => Assert.Equal("WoRlD", s)); } + + public static TheoryData, ImmutableArray> OrderAsArrayData + { + get + { + return new() + { + { [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] }, + { [10, 9, 8, 7, 6, 5, 4, 3, 2, 1], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] }, + { [1, 3, 5, 7, 9, 2, 4, 6, 8, 10], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] }, + { [2, 5, 8, 1, 3, 9, 7, 4, 10, 6], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] }, + { [6, 10, 4, 7, 9, 3, 1, 8, 5, 2], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] }, + }; + } + } + + [Theory] + [MemberData(nameof(OrderAsArrayData))] + public void OrderAsArray(ImmutableArray data, ImmutableArray expected) + { + var sorted = data.OrderAsArray(); + Assert.Equal(expected, sorted); + } + + public static TheoryData, ImmutableArray> OrderDescendingAsArrayData + { + get + { + return new() + { + { [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [10, 9, 8, 7, 6, 5, 4, 3, 2, 1] }, + { [10, 9, 8, 7, 6, 5, 4, 3, 2, 1], [10, 9, 8, 7, 6, 5, 4, 3, 2, 1] }, + { [1, 3, 5, 7, 9, 2, 4, 6, 8, 10], [10, 9, 8, 7, 6, 5, 4, 3, 2, 1] }, + { [2, 5, 8, 1, 3, 9, 7, 4, 10, 6], [10, 9, 8, 7, 6, 5, 4, 3, 2, 1] }, + { [6, 10, 4, 7, 9, 3, 1, 8, 5, 2], [10, 9, 8, 7, 6, 5, 4, 3, 2, 1] }, + }; + } + } + + [Theory] + [MemberData(nameof(OrderAsArrayData))] + public void OrderDescendingAsArray(ImmutableArray data, ImmutableArray expected) + { + var sorted = data.OrderAsArray(); + Assert.Equal(expected, sorted); + } + + public readonly record struct ValueHolder(int Value) + { + public static implicit operator ValueHolder(int value) + => new(value); + } + + public static TheoryData, ImmutableArray> OrderByAsArrayData + { + get + { + return new() + { + { [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] }, + { [10, 9, 8, 7, 6, 5, 4, 3, 2, 1], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] }, + { [1, 3, 5, 7, 9, 2, 4, 6, 8, 10], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] }, + { [2, 5, 8, 1, 3, 9, 7, 4, 10, 6], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] }, + { [6, 10, 4, 7, 9, 3, 1, 8, 5, 2], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] }, + }; + } + } + + [Theory] + [MemberData(nameof(OrderByAsArrayData))] + public void OrderByAsArray(ImmutableArray data, ImmutableArray expected) + { + var sorted = data.OrderByAsArray(static x => x.Value); + Assert.Equal(expected, sorted); + } + + public static TheoryData, ImmutableArray> OrderByDescendingAsArrayData + { + get + { + return new() + { + { [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [10, 9, 8, 7, 6, 5, 4, 3, 2, 1] }, + { [10, 9, 8, 7, 6, 5, 4, 3, 2, 1], [10, 9, 8, 7, 6, 5, 4, 3, 2, 1] }, + { [1, 3, 5, 7, 9, 2, 4, 6, 8, 10], [10, 9, 8, 7, 6, 5, 4, 3, 2, 1] }, + { [2, 5, 8, 1, 3, 9, 7, 4, 10, 6], [10, 9, 8, 7, 6, 5, 4, 3, 2, 1] }, + { [6, 10, 4, 7, 9, 3, 1, 8, 5, 2], [10, 9, 8, 7, 6, 5, 4, 3, 2, 1] }, + }; + } + } + + [Theory] + [MemberData(nameof(OrderByDescendingAsArrayData))] + public void OrderByDescendingAsArray(ImmutableArray data, ImmutableArray expected) + { + var sorted = data.OrderByDescendingAsArray(static x => x.Value); + Assert.Equal(expected, sorted); + } } diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/ImmutableArrayExtensions.cs b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/ImmutableArrayExtensions.cs index 54ab5702f27..9bb9798a015 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/ImmutableArrayExtensions.cs +++ b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/ImmutableArrayExtensions.cs @@ -1,7 +1,11 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT license. See License.txt in the project root for license information. +using System.Buffers; using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Threading; +using Microsoft.AspNetCore.Razor; using Microsoft.AspNetCore.Razor.PooledObjects; namespace System.Collections.Immutable; @@ -205,4 +209,123 @@ public static int BinarySearchBy(this ImmutableArray array, TArg arg return ~min; } + + public static ImmutableArray OrderAsArray(this ImmutableArray array) + => array.OrderAsArrayCore(GetComparer(comparer: null, descending: false)); + + public static ImmutableArray OrderAsArray(this ImmutableArray array, IComparer comparer) + => array.OrderAsArrayCore(GetComparer(comparer, descending: false)); + + public static ImmutableArray OrderAsArray(this ImmutableArray array, Comparison comparison) + => array.OrderAsArrayCore(GetComparer(comparison, descending: false)); + + public static ImmutableArray OrderDescendingAsArray(this ImmutableArray array) + => array.OrderAsArrayCore(GetComparer(comparer: null, descending: true)); + + public static ImmutableArray OrderDescendingAsArray(this ImmutableArray array, IComparer comparer) + => array.OrderAsArrayCore(GetComparer(comparer, descending: true)); + + public static ImmutableArray OrderDescendingAsArray(this ImmutableArray array, Comparison comparison) + => array.OrderAsArrayCore(GetComparer(comparison, descending: true)); + + public static ImmutableArray OrderByAsArray( + this ImmutableArray array, Func keySelector) + => array.OrderByAsArrayCore(keySelector, GetComparer(comparer: null, descending: false)); + + public static ImmutableArray OrderByAsArray( + this ImmutableArray array, Func keySelector, IComparer comparer) + => array.OrderByAsArrayCore(keySelector, GetComparer(comparer, descending: false)); + + public static ImmutableArray OrderByAsArray( + this ImmutableArray array, Func keySelector, Comparison comparison) + => array.OrderByAsArrayCore(keySelector, GetComparer(comparison, descending: false)); + + public static ImmutableArray OrderByDescendingAsArray( + this ImmutableArray array, Func keySelector) + => array.OrderByAsArrayCore(keySelector, GetComparer(comparer: null, descending: true)); + + public static ImmutableArray OrderByDescendingAsArray( + this ImmutableArray array, Func keySelector, IComparer comparer) + => array.OrderByAsArrayCore(keySelector, GetComparer(comparer, descending: true)); + + public static ImmutableArray OrderByDescendingAsArray( + this ImmutableArray array, Func keySelector, Comparison comparison) + => array.OrderByAsArrayCore(keySelector, GetComparer(comparison, descending: true)); + + private static IComparer GetComparer(IComparer? comparer, bool descending) + { + if (comparer is null) + { + return descending + ? DescendingComparer.Default + : Comparer.Default; + } + + return descending + ? new DescendingComparer(comparer) + : comparer; + } + + private static IComparer GetComparer(Comparison comparison, bool descending) + { + var comparer = Comparer.Create(comparison); + + return descending + ? new DescendingComparer(comparer) + : comparer; + } + + private sealed class DescendingComparer(IComparer comparer) : IComparer + { + private static IComparer? s_default; + + public static IComparer Default => s_default ??= new DescendingComparer(Comparer.Default); + + public int Compare(T? x, T? y) + => comparer.Compare(y!, x!); + } + + private static ImmutableArray OrderAsArrayCore(this ImmutableArray array, IComparer comparer) + { + if (array.IsEmpty) + { + return array; + } + + var span = array.AsSpan(); + + var length = span.Length; + var items = new T[length]; + span.CopyTo(items); + + Array.Sort(items, comparer); + + return ImmutableCollectionsMarshal.AsImmutableArray(items); + } + + private static ImmutableArray OrderByAsArrayCore( + this ImmutableArray array, Func keySelector, IComparer comparer) + { + if (array.IsEmpty) + { + return array; + } + + var span = array.AsSpan(); + + var length = span.Length; + var items = new TElement[length]; + span.CopyTo(items); + + using var _ = ArrayPool.Shared.GetPooledArray(minimumLength: length, out var keys); + + for (var i = 0; i < length; i++) + { + keys[i] = keySelector(items[i]); + } + + Array.Sort(keys, items, 0, length, comparer); + + return ImmutableCollectionsMarshal.AsImmutableArray(items); + } } From 7b511df1710c54ab1a36ea5e422c7edd7bb29d20 Mon Sep 17 00:00:00 2001 From: Andrew Hall Date: Wed, 10 Jul 2024 17:45:12 -0700 Subject: [PATCH 048/176] Use pooled objects in more locations (#10598) Cleaning up some places that are newing up Lists intead of using the object pool. I also moved a few things to ImmutableArray instead of List since they weren't mutated after initial collection --- .../AutoInsert/OnAutoInsertEndpoint.cs | 2 +- .../AddUsingsCodeActionProviderHelper.cs | 5 +- .../CSharp/DefaultCSharpCodeActionProvider.cs | 12 +++-- .../TypeAccessibilityCodeActionProvider.cs | 34 +++++++------- .../CodeActions/CodeActionEndpoint.cs | 28 +++++------ .../CodeActions/CodeActionResolveEndpoint.cs | 15 +++--- .../Html/DefaultHtmlCodeActionProvider.cs | 11 +++-- .../CodeActions/ICodeActionProvider.cs | 3 +- .../Razor/AddUsingsCodeActionResolver.cs | 24 +++++----- ...omponentAccessibilityCodeActionProvider.cs | 33 ++++++------- .../CreateComponentCodeActionResolver.cs | 12 ++--- .../ExtractToCodeBehindCodeActionProvider.cs | 29 ++++++------ .../Razor/GenerateMethodCodeActionProvider.cs | 17 ++++--- .../Razor/IRazorCodeActionProvider.cs | 3 +- .../AggregateCompletionItemResolver.cs | 20 ++++---- .../Completion/CompletionListMerger.cs | 45 +++++++++--------- .../DelegatedCompletionItemResolver.cs | 2 +- .../VSInternalCompletionItemExtensions.cs | 13 +++--- ...actTextDocumentPresentationEndpointBase.cs | 33 ++++++------- .../FindAllReferencesEndpoint.cs | 3 +- .../Formatting/CSharpFormatter.cs | 6 ++- .../Formatting/CSharpFormattingPass.cs | 11 +++-- .../MapCode/MapCodeEndpoint.cs | 46 +++++++++---------- .../Refactoring/RenameEndpoint.cs | 2 +- .../Parsing/VisualStudioRazorParser.cs | 3 +- .../IntraTextAdornmentTagger.cs | 42 +++++++++-------- .../DefaultCSharpCodeActionProviderTest.cs | 38 ++++++--------- ...TypeAccessibilityCodeActionProviderTest.cs | 39 ++++++++-------- .../CodeActions/CodeActionEndpointTest.cs | 44 +++++++++--------- .../Html/DefaultHtmlCodeActionProviderTest.cs | 28 ++++++----- ...nentAccessibilityCodeActionProviderTest.cs | 14 ++---- ...tractToCodeBehindCodeActionProviderTest.cs | 17 +++---- .../PooledObjects/QueuePool.Policy.cs | 35 ++++++++++++++ .../PooledObjects/QueuePool.cs | 18 ++++++++ 34 files changed, 368 insertions(+), 319 deletions(-) create mode 100644 src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/PooledObjects/QueuePool.Policy.cs create mode 100644 src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/PooledObjects/QueuePool.cs diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/AutoInsert/OnAutoInsertEndpoint.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/AutoInsert/OnAutoInsertEndpoint.cs index 6a4e110a47a..ea7d46e8e45 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/AutoInsert/OnAutoInsertEndpoint.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/AutoInsert/OnAutoInsertEndpoint.cs @@ -83,7 +83,7 @@ public void ApplyCapabilities(VSInternalServerCapabilities serverCapabilities, V var character = request.Character; - using var _ = ListPool.GetPooledObject(out var applicableProviders); + using var applicableProviders = new PooledArrayBuilder(); foreach (var provider in _onAutoInsertProviders) { if (provider.TriggerCharacter == character) diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/AddUsingsCodeActionProviderHelper.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/AddUsingsCodeActionProviderHelper.cs index d60ea8bc994..a216287aea1 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/AddUsingsCodeActionProviderHelper.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/AddUsingsCodeActionProviderHelper.cs @@ -11,6 +11,7 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Razor.Language; using Microsoft.AspNetCore.Razor.LanguageServer.CodeActions.Models; +using Microsoft.AspNetCore.Razor.PooledObjects; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Text; @@ -38,7 +39,7 @@ public static async Task GetUsingStatementEditsAsync(RazorCodeDocume var oldUsings = await FindUsingDirectiveStringsAsync(originalCSharpText, cancellationToken).ConfigureAwait(false); var newUsings = await FindUsingDirectiveStringsAsync(changedCSharpText, cancellationToken).ConfigureAwait(false); - var edits = new List(); + using var edits = new PooledArrayBuilder(); foreach (var usingStatement in newUsings.Except(oldUsings)) { // This identifier will be eventually thrown away. @@ -48,7 +49,7 @@ public static async Task GetUsingStatementEditsAsync(RazorCodeDocume edits.AddRange(workspaceEdit.DocumentChanges!.Value.First.First().Edits); } - return [.. edits]; + return edits.ToArray(); } private static async Task> FindUsingDirectiveStringsAsync(SourceText originalCSharpText, CancellationToken cancellationToken) diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CSharp/DefaultCSharpCodeActionProvider.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CSharp/DefaultCSharpCodeActionProvider.cs index fb8dafb245f..429d8aff10d 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CSharp/DefaultCSharpCodeActionProvider.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CSharp/DefaultCSharpCodeActionProvider.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Collections.Immutable; using System.Linq; using System.Text.Json; using System.Threading; @@ -10,6 +11,7 @@ using Microsoft.AspNetCore.Razor.Language; using Microsoft.AspNetCore.Razor.Language.Syntax; using Microsoft.AspNetCore.Razor.LanguageServer.CodeActions.Models; +using Microsoft.AspNetCore.Razor.PooledObjects; using Microsoft.AspNetCore.Razor.Threading; using Microsoft.CodeAnalysis.ExternalAccess.Razor; using Microsoft.CodeAnalysis.Razor.Workspaces; @@ -52,16 +54,16 @@ internal sealed class DefaultCSharpCodeActionProvider(LanguageServerFeatureOptio private readonly LanguageServerFeatureOptions _languageServerFeatureOptions = languageServerFeatureOptions; - public Task?> ProvideAsync( + public Task> ProvideAsync( RazorCodeActionContext context, - IEnumerable codeActions, + ImmutableArray codeActions, CancellationToken cancellationToken) { // Used to identify if this is VSCode which doesn't support // code action resolve. if (!context.SupportsCodeActionResolve) { - return SpecializedTasks.AsNullable(SpecializedTasks.EmptyReadOnlyList()); + return SpecializedTasks.EmptyImmutableArray(); } var tree = context.CodeDocument.GetSyntaxTree(); @@ -72,7 +74,7 @@ internal sealed class DefaultCSharpCodeActionProvider(LanguageServerFeatureOptio ? SupportedImplicitExpressionCodeActionNames : SupportedDefaultCodeActionNames; - var results = new List(); + using var results = new PooledArrayBuilder(); foreach (var codeAction in codeActions) { @@ -94,7 +96,7 @@ internal sealed class DefaultCSharpCodeActionProvider(LanguageServerFeatureOptio } } - return Task.FromResult?>(results); + return Task.FromResult(results.ToImmutable()); static bool CanDeserializeTo(object? data) { diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CSharp/TypeAccessibilityCodeActionProvider.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CSharp/TypeAccessibilityCodeActionProvider.cs index 7763a850688..4e4263e54c9 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CSharp/TypeAccessibilityCodeActionProvider.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CSharp/TypeAccessibilityCodeActionProvider.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Collections.Immutable; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Linq; @@ -12,6 +13,7 @@ using Microsoft.AspNetCore.Razor.Language.Syntax; using Microsoft.AspNetCore.Razor.LanguageServer.CodeActions.Models; using Microsoft.AspNetCore.Razor.LanguageServer.CodeActions.Razor; +using Microsoft.AspNetCore.Razor.PooledObjects; using Microsoft.AspNetCore.Razor.Threading; using Microsoft.CodeAnalysis.ExternalAccess.Razor; using Microsoft.CodeAnalysis.Razor.Workspaces; @@ -36,32 +38,32 @@ internal sealed class TypeAccessibilityCodeActionProvider : ICSharpCodeActionPro "IDE1007" }; - public Task?> ProvideAsync( + public Task> ProvideAsync( RazorCodeActionContext context, - IEnumerable codeActions, + ImmutableArray codeActions, CancellationToken cancellationToken) { if (context.Request?.Context?.Diagnostics is null) { - return SpecializedTasks.AsNullable(SpecializedTasks.EmptyReadOnlyList()); + return SpecializedTasks.EmptyImmutableArray(); } - if (!codeActions.Any()) + if (codeActions.IsEmpty) { - return SpecializedTasks.AsNullable(SpecializedTasks.EmptyReadOnlyList()); + return SpecializedTasks.EmptyImmutableArray(); } var results = context.SupportsCodeActionResolve ? ProcessCodeActionsVS(context, codeActions) : ProcessCodeActionsVSCode(context, codeActions); - var orderedResults = results.OrderBy(codeAction => codeAction.Title).ToArray(); - return Task.FromResult?>(orderedResults); + var orderedResults = results.Sort(static (x, y) => StringComparer.CurrentCulture.Compare(x.Title, y.Title)); + return Task.FromResult(orderedResults); } - private static IEnumerable ProcessCodeActionsVSCode( + private static ImmutableArray ProcessCodeActionsVSCode( RazorCodeActionContext context, - IEnumerable codeActions) + ImmutableArray codeActions) { var diagnostics = context.Request.Context.Diagnostics.Where(diagnostic => diagnostic is { Severity: DiagnosticSeverity.Error, Code: { } code } && @@ -70,10 +72,10 @@ private static IEnumerable ProcessCodeActionsVSCode( if (diagnostics is null || !diagnostics.Any()) { - return Array.Empty(); + return []; } - var typeAccessibilityCodeActions = new List(); + using var typeAccessibilityCodeActions = new PooledArrayBuilder(); foreach (var diagnostic in diagnostics) { @@ -142,14 +144,14 @@ private static IEnumerable ProcessCodeActionsVSCode( } } - return typeAccessibilityCodeActions; + return typeAccessibilityCodeActions.ToImmutable(); } - private static IEnumerable ProcessCodeActionsVS( + private static ImmutableArray ProcessCodeActionsVS( RazorCodeActionContext context, - IEnumerable codeActions) + ImmutableArray codeActions) { - var typeAccessibilityCodeActions = new List(1); + using var typeAccessibilityCodeActions = new PooledArrayBuilder(); foreach (var codeAction in codeActions) { @@ -199,7 +201,7 @@ private static IEnumerable ProcessCodeActionsVS( } } - return typeAccessibilityCodeActions; + return typeAccessibilityCodeActions.ToImmutable(); static bool TryGetOwner(RazorCodeActionContext context, [NotNullWhen(true)] out SyntaxNode? owner) { diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CodeActionEndpoint.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CodeActionEndpoint.cs index 1872fb25a94..1acf449023b 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CodeActionEndpoint.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CodeActionEndpoint.cs @@ -82,7 +82,7 @@ internal sealed class CodeActionEndpoint( cancellationToken.ThrowIfCancellationRequested(); - using var _ = ArrayBuilderPool>.GetPooledObject(out var commandsOrCodeActions); + using var commandsOrCodeActions = new PooledArrayBuilder>(); // Grouping the code actions causes VS to sort them into groups, rather than just alphabetically sorting them // by title. The latter is bad for us because it can put "Remove
" at the top in some locales, and our fully @@ -201,12 +201,12 @@ private async Task> GetDelegatedCodeAc providers = _htmlCodeActionProviders; } - return await FilterCodeActionsAsync(context, codeActions, providers, cancellationToken).ConfigureAwait(false); + return await FilterCodeActionsAsync(context, codeActions.ToImmutableArray(), providers, cancellationToken).ConfigureAwait(false); } private RazorVSInternalCodeAction[] ExtractCSharpCodeActionNamesFromData(RazorVSInternalCodeAction[] codeActions) { - using var _ = ArrayBuilderPool.GetPooledObject(out var actions); + using var actions = new PooledArrayBuilder(); foreach (var codeAction in codeActions) { @@ -239,20 +239,19 @@ private RazorVSInternalCodeAction[] ExtractCSharpCodeActionNamesFromData(RazorVS private static async Task> FilterCodeActionsAsync( RazorCodeActionContext context, - RazorVSInternalCodeAction[] codeActions, + ImmutableArray codeActions, IEnumerable providers, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); - using var _ = ArrayBuilderPool?>>.GetPooledObject(out var tasks); - + using var tasks = new PooledArrayBuilder>>(); foreach (var provider in providers) { tasks.Add(provider.ProvideAsync(context, codeActions, cancellationToken)); } - return await ConsolidateCodeActionsFromProvidersAsync(tasks.ToImmutableArray(), cancellationToken).ConfigureAwait(false); + return await ConsolidateCodeActionsFromProvidersAsync(tasks.ToImmutable(), cancellationToken).ConfigureAwait(false); } // Internal for testing @@ -304,35 +303,32 @@ private async Task> GetRazorCodeAction { cancellationToken.ThrowIfCancellationRequested(); - using var _ = ArrayBuilderPool?>>.GetPooledObject(out var tasks); + using var tasks = new PooledArrayBuilder>>(); foreach (var provider in _razorCodeActionProviders) { tasks.Add(provider.ProvideAsync(context, cancellationToken)); } - return await ConsolidateCodeActionsFromProvidersAsync(tasks.ToImmutableArray(), cancellationToken).ConfigureAwait(false); + return await ConsolidateCodeActionsFromProvidersAsync(tasks.ToImmutable(), cancellationToken).ConfigureAwait(false); } private static async Task> ConsolidateCodeActionsFromProvidersAsync( - ImmutableArray?>> tasks, + ImmutableArray>> tasks, CancellationToken cancellationToken) { var results = await Task.WhenAll(tasks).ConfigureAwait(false); - using var _ = ArrayBuilderPool.GetPooledObject(out var codeActions); + using var codeActions = new PooledArrayBuilder(); cancellationToken.ThrowIfCancellationRequested(); foreach (var result in results) { - if (result is not null) - { - codeActions.AddRange(result); - } + codeActions.AddRange(result); } - return codeActions.ToImmutableArray(); + return codeActions.ToImmutable(); } private static ImmutableHashSet GetAllAvailableCodeActionNames() diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CodeActionResolveEndpoint.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CodeActionResolveEndpoint.cs index 1744a69d2a8..cdf0620fcab 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CodeActionResolveEndpoint.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CodeActionResolveEndpoint.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. See License.txt in the project root for license information. using System; +using System.Collections.Frozen; using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics; @@ -23,9 +24,9 @@ internal sealed class CodeActionResolveEndpoint( IEnumerable htmlCodeActionResolvers, ILoggerFactory loggerFactory) : IRazorDocumentlessRequestHandler { - private readonly ImmutableDictionary _razorCodeActionResolvers = CreateResolverMap(razorCodeActionResolvers); - private readonly ImmutableDictionary _csharpCodeActionResolvers = CreateResolverMap(csharpCodeActionResolvers); - private readonly ImmutableDictionary _htmlCodeActionResolvers = CreateResolverMap(htmlCodeActionResolvers); + private readonly FrozenDictionary _razorCodeActionResolvers = CreateResolverMap(razorCodeActionResolvers); + private readonly FrozenDictionary _csharpCodeActionResolvers = CreateResolverMap(csharpCodeActionResolvers); + private readonly FrozenDictionary _htmlCodeActionResolvers = CreateResolverMap(htmlCodeActionResolvers); private readonly ILogger _logger = loggerFactory.GetOrCreateLogger(); public bool MutatesSolutionState => false; @@ -111,7 +112,7 @@ internal Task ResolveCSharpCodeActionAsync(CodeAction codeAction, Ra internal Task ResolveHtmlCodeActionAsync(CodeAction codeAction, RazorCodeActionResolutionParams resolutionParams, CancellationToken cancellationToken) => ResolveDelegatedCodeActionAsync(_htmlCodeActionResolvers, codeAction, resolutionParams, cancellationToken); - private async Task ResolveDelegatedCodeActionAsync(ImmutableDictionary resolvers, CodeAction codeAction, RazorCodeActionResolutionParams resolutionParams, CancellationToken cancellationToken) + private async Task ResolveDelegatedCodeActionAsync(FrozenDictionary resolvers, CodeAction codeAction, RazorCodeActionResolutionParams resolutionParams, CancellationToken cancellationToken) { if (resolutionParams.Data is not JsonElement csharpParamsObj) { @@ -140,10 +141,10 @@ private async Task ResolveDelegatedCodeActionAsync(ImmutableDictiona return resolvedCodeAction; } - private static ImmutableDictionary CreateResolverMap(IEnumerable codeActionResolvers) + private static FrozenDictionary CreateResolverMap(IEnumerable codeActionResolvers) where T : ICodeActionResolver { - using var _ = DictionaryPool.GetPooledObject(out var resolverMap); + using var _ = StringDictionaryPool.GetPooledObject(out var resolverMap); foreach (var resolver in codeActionResolvers) { @@ -155,7 +156,7 @@ private static ImmutableDictionary CreateResolverMap(IEnumerable diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Html/DefaultHtmlCodeActionProvider.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Html/DefaultHtmlCodeActionProvider.cs index 6c441da4187..919bb61de8c 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Html/DefaultHtmlCodeActionProvider.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Html/DefaultHtmlCodeActionProvider.cs @@ -2,11 +2,13 @@ // Licensed under the MIT license. See License.txt in the project root for license information. using System.Collections.Generic; +using System.Collections.Immutable; using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.Razor.Language; using Microsoft.AspNetCore.Razor.LanguageServer.CodeActions.Models; using Microsoft.AspNetCore.Razor.LanguageServer.Formatting; +using Microsoft.AspNetCore.Razor.PooledObjects; using Microsoft.CodeAnalysis.Razor.DocumentMapping; using Microsoft.CodeAnalysis.Razor.Workspaces; using Microsoft.VisualStudio.LanguageServer.Protocol; @@ -17,13 +19,12 @@ internal sealed class DefaultHtmlCodeActionProvider(IRazorDocumentMappingService { private readonly IRazorDocumentMappingService _documentMappingService = documentMappingService; - public async Task?> ProvideAsync( + public async Task> ProvideAsync( RazorCodeActionContext context, - IEnumerable codeActions, + ImmutableArray codeActions, CancellationToken cancellationToken) { - var results = new List(); - + using var results = new PooledArrayBuilder(codeActions.Length); foreach (var codeAction in codeActions) { if (codeAction.Edit is not null) @@ -38,7 +39,7 @@ internal sealed class DefaultHtmlCodeActionProvider(IRazorDocumentMappingService } } - return results; + return results.ToImmutable(); } public static async Task RemapAndFixHtmlCodeActionEditAsync(IRazorDocumentMappingService documentMappingService, RazorCodeDocument codeDocument, CodeAction codeAction, CancellationToken cancellationToken) diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/ICodeActionProvider.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/ICodeActionProvider.cs index eea3a89166b..593b99b4a09 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/ICodeActionProvider.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/ICodeActionProvider.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. See License.txt in the project root for license information. using System.Collections.Generic; +using System.Collections.Immutable; using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.Razor.LanguageServer.CodeActions.Models; @@ -17,5 +18,5 @@ internal interface ICodeActionProvider /// The list of code actions returned from all providers will be combined together in a list. A null result and an empty /// result are effectively the same. /// - Task?> ProvideAsync(RazorCodeActionContext context, IEnumerable codeActions, CancellationToken cancellationToken); + Task> ProvideAsync(RazorCodeActionContext context, ImmutableArray codeActions, CancellationToken cancellationToken); } diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/AddUsingsCodeActionResolver.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/AddUsingsCodeActionResolver.cs index 20c49f36af1..51dbd90ebbe 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/AddUsingsCodeActionResolver.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/AddUsingsCodeActionResolver.cs @@ -3,6 +3,8 @@ using System; using System.Collections.Generic; +using System.Collections.Immutable; +using System.Diagnostics; using System.Linq; using System.Text.Json; using System.Threading; @@ -69,7 +71,7 @@ internal static WorkspaceEdit CreateAddUsingWorkspaceEdit(string @namespace, Tex * that now I can come up with a more sophisticated heuristic (something along the lines of checking if * there's already an ordering, etc.). */ - using var _ = ListPool.GetPooledObject(out var documentChanges); + using var documentChanges = new PooledArrayBuilder(); // Need to add the additional edit first, as the actual usings go at the top of the file, and would // change the ranges needed in the additional edit if they went in first @@ -78,11 +80,12 @@ internal static WorkspaceEdit CreateAddUsingWorkspaceEdit(string @namespace, Tex documentChanges.Add(additionalEdit); } - var usingDirectives = FindUsingDirectives(codeDocument); + using var usingDirectives = new PooledArrayBuilder(); + CollectUsingDirectives(codeDocument, ref usingDirectives.AsRef()); if (usingDirectives.Count > 0) { // Interpolate based on existing @using statements - var edits = GenerateSingleUsingEditsInterpolated(codeDocument, codeDocumentIdentifier, @namespace, usingDirectives); + var edits = GenerateSingleUsingEditsInterpolated(codeDocument, codeDocumentIdentifier, @namespace, in usingDirectives); documentChanges.Add(edits); } else @@ -102,9 +105,11 @@ private static TextDocumentEdit GenerateSingleUsingEditsInterpolated( RazorCodeDocument codeDocument, OptionalVersionedTextDocumentIdentifier codeDocumentIdentifier, string newUsingNamespace, - List existingUsingDirectives) + ref readonly PooledArrayBuilder existingUsingDirectives) { - var edits = new List(); + Debug.Assert(existingUsingDirectives.Count > 0); + + using var edits = new PooledArrayBuilder(); var newText = $"@using {newUsingNamespace}{Environment.NewLine}"; foreach (var usingDirective in existingUsingDirectives) @@ -129,7 +134,7 @@ private static TextDocumentEdit GenerateSingleUsingEditsInterpolated( // If we haven't actually found a place to insert the using directive, do so at the end if (edits.Count == 0) { - var endIndex = existingUsingDirectives.Last().Node.Span.End; + var endIndex = existingUsingDirectives[^1].Node.Span.End; var lineIndex = GetLineIndexOrEnd(codeDocument, endIndex - 1) + 1; var head = new Position(lineIndex, 0); var edit = new TextEdit() { Range = new Range { Start = head, End = head }, NewText = newText }; @@ -139,7 +144,7 @@ private static TextDocumentEdit GenerateSingleUsingEditsInterpolated( return new TextDocumentEdit() { TextDocument = codeDocumentIdentifier, - Edits = [.. edits] + Edits = edits.ToArray() }; } @@ -190,9 +195,8 @@ private static int GetLineIndexOrEnd(RazorCodeDocument codeDocument, int endInde } } - private static List FindUsingDirectives(RazorCodeDocument codeDocument) + private static void CollectUsingDirectives(RazorCodeDocument codeDocument, ref PooledArrayBuilder directives) { - var directives = new List(); var syntaxTreeRoot = codeDocument.GetSyntaxTree().Root; foreach (var node in syntaxTreeRoot.DescendantNodes()) { @@ -207,8 +211,6 @@ private static List FindUsingDirectives(RazorCodeDocument c } } } - - return directives; } private static bool IsNamespaceOrPageDirective(SyntaxNode node) diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/ComponentAccessibilityCodeActionProvider.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/ComponentAccessibilityCodeActionProvider.cs index 880a9123192..29fabbac9ae 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/ComponentAccessibilityCodeActionProvider.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/ComponentAccessibilityCodeActionProvider.cs @@ -24,15 +24,13 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer.CodeActions; internal sealed class ComponentAccessibilityCodeActionProvider : IRazorCodeActionProvider { - public async Task?> ProvideAsync(RazorCodeActionContext context, CancellationToken cancellationToken) + public async Task> ProvideAsync(RazorCodeActionContext context, CancellationToken cancellationToken) { - using var _ = ListPool.GetPooledObject(out var codeActions); - // Locate cursor var node = context.CodeDocument.GetSyntaxTree().Root.FindInnermostNode(context.Location.AbsoluteIndex); if (node is null) { - return null; + return []; } // Find start tag. We allow this code action to work from anywhere in the start tag, which includes @@ -43,7 +41,7 @@ internal sealed class ComponentAccessibilityCodeActionProvider : IRazorCodeActio var startTag = (IStartTagSyntaxNode?)node.FirstAncestorOrSelf(n => n is IStartTagSyntaxNode); if (startTag is null) { - return null; + return []; } if (context.Location.AbsoluteIndex < startTag.SpanStart) @@ -51,27 +49,30 @@ internal sealed class ComponentAccessibilityCodeActionProvider : IRazorCodeActio // Cursor is before the start tag, so we shouldn't show a light bulb. This can happen // in cases where the cursor is in whitespace at the beginning of the document // eg: $$ - return null; + return []; } // Ignore if start tag has dots, as we only handle short tags if (startTag.Name.Content.Contains(".")) { - return null; + return []; } if (!IsApplicableTag(startTag)) { - return null; + return []; } - if (IsTagUnknown(startTag, context)) + if (!IsTagUnknown(startTag, context)) { - await AddComponentAccessFromTagAsync(context, startTag, codeActions, cancellationToken).ConfigureAwait(false); - AddCreateComponentFromTag(context, startTag, codeActions); + return []; } - return codeActions.ToArray(); + using var _ = ListPool.GetPooledObject(out var codeActions); + await AddComponentAccessFromTagAsync(context, startTag, codeActions, cancellationToken).ConfigureAwait(false); + AddCreateComponentFromTag(context, startTag, codeActions); + + return [.. codeActions]; } private static bool IsApplicableTag(IStartTagSyntaxNode startTag) @@ -190,7 +191,7 @@ private static async Task AddComponentAccessFromTagAsync(RazorCodeActionContext } } - private static async Task> FindMatchingTagHelpersAsync(RazorCodeActionContext context, IStartTagSyntaxNode startTag, CancellationToken cancellationToken) + private static async Task> FindMatchingTagHelpersAsync(RazorCodeActionContext context, IStartTagSyntaxNode startTag, CancellationToken cancellationToken) { // Get all data necessary for matching var tagName = startTag.Name.Content; @@ -231,7 +232,7 @@ private static async Task> FindMatchingTagHelpersAsync(Razor } } - return new List(matching.Values); + return [.. matching.Values]; } private static bool SatisfiesRules(ImmutableArray tagMatchingRules, ReadOnlySpan tagNameWithoutPrefix, ReadOnlySpan parentTagNameWithoutPrefix, ImmutableArray> tagAttributes, out bool caseInsensitiveMatch) @@ -273,7 +274,7 @@ private static bool SatisfiesRules(ImmutableArray tag private static WorkspaceEdit CreateRenameTagEdit(RazorCodeActionContext context, IStartTagSyntaxNode startTag, string newTagName) { - using var _ = ListPool.GetPooledObject(out var textEdits); + using var textEdits = new PooledArrayBuilder(); var codeDocumentIdentifier = new OptionalVersionedTextDocumentIdentifier() { Uri = context.Request.TextDocument.Uri }; var startTagTextEdit = new TextEdit @@ -303,7 +304,7 @@ private static WorkspaceEdit CreateRenameTagEdit(RazorCodeActionContext context, new TextDocumentEdit() { TextDocument = codeDocumentIdentifier, - Edits = [.. textEdits] + Edits = textEdits.ToArray() } }, }; diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/CreateComponentCodeActionResolver.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/CreateComponentCodeActionResolver.cs index e3afbcfd3be..aa08bd57a5d 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/CreateComponentCodeActionResolver.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/CreateComponentCodeActionResolver.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Collections.Immutable; using System.Linq; using System.Text.Json; using System.Threading; @@ -11,6 +12,7 @@ using Microsoft.AspNetCore.Razor.Language.Extensions; using Microsoft.AspNetCore.Razor.Language.Syntax; using Microsoft.AspNetCore.Razor.LanguageServer.CodeActions.Models; +using Microsoft.AspNetCore.Razor.PooledObjects; using Microsoft.CodeAnalysis.Razor.ProjectSystem; using Microsoft.CodeAnalysis.Razor.Workspaces; using Microsoft.VisualStudio.LanguageServer.Protocol; @@ -59,12 +61,10 @@ internal sealed class CreateComponentCodeActionResolver(IDocumentContextFactory Host = string.Empty, }.Uri; - var documentChanges = new List> - { - new CreateFile() { Uri = newComponentUri }, - }; + using var documentChanges = new PooledArrayBuilder>(); + documentChanges.Add(new CreateFile() { Uri = newComponentUri }); - TryAddNamespaceDirective(codeDocument, newComponentUri, documentChanges); + TryAddNamespaceDirective(codeDocument, newComponentUri, ref documentChanges.AsRef()); return new WorkspaceEdit() { @@ -72,7 +72,7 @@ internal sealed class CreateComponentCodeActionResolver(IDocumentContextFactory }; } - private static void TryAddNamespaceDirective(RazorCodeDocument codeDocument, Uri newComponentUri, List> documentChanges) + private static void TryAddNamespaceDirective(RazorCodeDocument codeDocument, Uri newComponentUri, ref PooledArrayBuilder> documentChanges) { var syntaxTree = codeDocument.GetSyntaxTree(); var namespaceDirective = syntaxTree.Root.DescendantNodes() diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/ExtractToCodeBehindCodeActionProvider.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/ExtractToCodeBehindCodeActionProvider.cs index 6457b46c0d6..546b5f71d32 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/ExtractToCodeBehindCodeActionProvider.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/ExtractToCodeBehindCodeActionProvider.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Collections.Immutable; using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Threading; @@ -24,29 +25,29 @@ internal sealed class ExtractToCodeBehindCodeActionProvider(ILoggerFactory logge { private readonly ILogger _logger = loggerFactory.GetOrCreateLogger(); - public Task?> ProvideAsync(RazorCodeActionContext context, CancellationToken cancellationToken) + public Task> ProvideAsync(RazorCodeActionContext context, CancellationToken cancellationToken) { if (!context.SupportsFileCreation) { - return SpecializedTasks.Null>(); + return SpecializedTasks.EmptyImmutableArray(); } if (!FileKinds.IsComponent(context.CodeDocument.GetFileKind())) { - return SpecializedTasks.Null>(); + return SpecializedTasks.EmptyImmutableArray(); } var syntaxTree = context.CodeDocument.GetSyntaxTree(); if (syntaxTree?.Root is null) { - return SpecializedTasks.Null>(); + return SpecializedTasks.EmptyImmutableArray(); } var owner = syntaxTree.Root.FindInnermostNode(context.Location.AbsoluteIndex); if (owner is null) { _logger.LogWarning($"Owner should never be null."); - return SpecializedTasks.Null>(); + return SpecializedTasks.EmptyImmutableArray(); } var directiveNode = owner.Parent switch @@ -61,42 +62,42 @@ internal sealed class ExtractToCodeBehindCodeActionProvider(ILoggerFactory logge }; if (directiveNode is null) { - return SpecializedTasks.Null>(); + return SpecializedTasks.EmptyImmutableArray(); } // Make sure we've found a @code or @functions if (directiveNode.DirectiveDescriptor != ComponentCodeDirective.Directive && directiveNode.DirectiveDescriptor != FunctionsDirective.Directive) { - return SpecializedTasks.Null>(); + return SpecializedTasks.EmptyImmutableArray(); } // No code action if malformed if (directiveNode.GetDiagnostics().Any(d => d.Severity == RazorDiagnosticSeverity.Error)) { - return SpecializedTasks.Null>(); + return SpecializedTasks.EmptyImmutableArray(); } var csharpCodeBlockNode = (directiveNode.Body as RazorDirectiveBodySyntax)?.CSharpCode; if (csharpCodeBlockNode is null) { - return SpecializedTasks.Null>(); + return SpecializedTasks.EmptyImmutableArray(); } // Do not provide code action if the cursor is inside the code block if (context.Location.AbsoluteIndex > csharpCodeBlockNode.SpanStart) { - return SpecializedTasks.Null>(); + return SpecializedTasks.EmptyImmutableArray(); } if (HasUnsupportedChildren(csharpCodeBlockNode)) { - return SpecializedTasks.Null>(); + return SpecializedTasks.EmptyImmutableArray(); } if (!TryGetNamespace(context.CodeDocument, out var @namespace)) { - return SpecializedTasks.Null>(); + return SpecializedTasks.EmptyImmutableArray(); } var actionParams = new ExtractToCodeBehindCodeActionParams() @@ -117,9 +118,7 @@ internal sealed class ExtractToCodeBehindCodeActionProvider(ILoggerFactory logge }; var codeAction = RazorCodeActionFactory.CreateExtractToCodeBehind(resolutionParams); - var codeActions = new List { codeAction }; - - return Task.FromResult?>(codeActions); + return Task.FromResult>([codeAction]); } private static bool TryGetNamespace(RazorCodeDocument codeDocument, [NotNullWhen(returnValue: true)] out string? @namespace) diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/GenerateMethodCodeActionProvider.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/GenerateMethodCodeActionProvider.cs index 3399a4815de..366b544d783 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/GenerateMethodCodeActionProvider.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/GenerateMethodCodeActionProvider.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. See License.txt in the project root for license information. using System.Collections.Generic; +using System.Collections.Immutable; using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Threading; @@ -20,12 +21,12 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer.CodeActions.Razor; internal sealed class GenerateMethodCodeActionProvider : IRazorCodeActionProvider { - public Task?> ProvideAsync(RazorCodeActionContext context, CancellationToken cancellationToken) + public Task> ProvideAsync(RazorCodeActionContext context, CancellationToken cancellationToken) { var nameNotExistDiagnostics = context.Request.Context.Diagnostics.Any(d => d.Code == "CS0103"); if (!nameNotExistDiagnostics) { - return SpecializedTasks.Null>(); + return SpecializedTasks.EmptyImmutableArray(); } var syntaxTree = context.CodeDocument.GetSyntaxTree(); @@ -34,12 +35,14 @@ internal sealed class GenerateMethodCodeActionProvider : IRazorCodeActionProvide if (IsGenerateEventHandlerValid(owner, out var methodName, out var eventName)) { var uri = context.Request.TextDocument.Uri; - return Task.FromResult?>([ - RazorCodeActionFactory.CreateGenerateMethod(uri, methodName, eventName), - RazorCodeActionFactory.CreateAsyncGenerateMethod(uri, methodName, eventName)]); + return Task.FromResult>( + [ + RazorCodeActionFactory.CreateGenerateMethod(uri, methodName, eventName), + RazorCodeActionFactory.CreateAsyncGenerateMethod(uri, methodName, eventName) + ]); } - return SpecializedTasks.Null>(); + return SpecializedTasks.EmptyImmutableArray(); } private static bool IsGenerateEventHandlerValid( @@ -69,7 +72,7 @@ private static bool IsGenerateEventHandlerValid( return false; } - // MarkupTagHelperElement > MarkupTagHelperStartTag > MarkupTagHelperDirectiveAttribute + // MarkupTagHelperElement > MarkupTagHelperStartTag > MarkupTagHelperDirectiveAttribute if (commonParent.Parent.Parent is not MarkupTagHelperElementSyntax { TagHelperInfo.BindingResult: var binding }) { return false; diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/IRazorCodeActionProvider.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/IRazorCodeActionProvider.cs index 6df5bab58ff..76f118fa86a 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/IRazorCodeActionProvider.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/IRazorCodeActionProvider.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. See License.txt in the project root for license information. using System.Collections.Generic; +using System.Collections.Immutable; using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.Razor.LanguageServer.CodeActions.Models; @@ -10,7 +11,7 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer.CodeActions; internal interface IRazorCodeActionProvider { - Task?> ProvideAsync( + Task> ProvideAsync( RazorCodeActionContext context, CancellationToken cancellationToken); } diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Completion/AggregateCompletionItemResolver.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Completion/AggregateCompletionItemResolver.cs index 77ecb184217..21075cfacc1 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Completion/AggregateCompletionItemResolver.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Completion/AggregateCompletionItemResolver.cs @@ -2,10 +2,12 @@ // Licensed under the MIT license. See License.txt in the project root for license information. using System; +using System.Buffers; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; +using Microsoft.AspNetCore.Razor.PooledObjects; using Microsoft.CodeAnalysis.Razor.Logging; using Microsoft.VisualStudio.LanguageServer.Protocol; @@ -29,7 +31,7 @@ public AggregateCompletionItemResolver(IEnumerable compl VSInternalClientCapabilities? clientCapabilities, CancellationToken cancellationToken) { - var completionItemResolverTasks = new List>(_completionItemResolvers.Count); + using var completionItemResolverTasks = new PooledArrayBuilder>(_completionItemResolvers.Count); foreach (var completionItemResolver in _completionItemResolvers) { @@ -44,7 +46,9 @@ public AggregateCompletionItemResolver(IEnumerable compl } } - var resolvedCompletionItems = new Queue(); + // We don't currently handle merging completion items because it's very rare for more than one resolution to take place. + // Instead we'll prioritized the last completion item resolved. + VSInternalCompletionItem? lastResolved = null; foreach (var completionItemResolverTask in completionItemResolverTasks) { try @@ -52,7 +56,7 @@ public AggregateCompletionItemResolver(IEnumerable compl var resolvedCompletionItem = await completionItemResolverTask.ConfigureAwait(false); if (resolvedCompletionItem is not null) { - resolvedCompletionItems.Enqueue(resolvedCompletionItem); + lastResolved = resolvedCompletionItem; } cancellationToken.ThrowIfCancellationRequested(); @@ -63,14 +67,6 @@ public AggregateCompletionItemResolver(IEnumerable compl } } - if (resolvedCompletionItems.Count == 0) - { - return null; - } - - // We don't currently handle merging completion items because it's very rare for more than one resolution to take place. - // Instead we'll prioritized the last completion item resolved. - var finalCompletionItem = resolvedCompletionItems.Last(); - return finalCompletionItem; + return lastResolved; } } diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Completion/CompletionListMerger.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Completion/CompletionListMerger.cs index 5f4bb5ac7d9..cf1344a1936 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Completion/CompletionListMerger.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Completion/CompletionListMerger.cs @@ -2,12 +2,14 @@ // Licensed under the MIT license. See License.txt in the project root for license information. using System.Collections.Generic; +using System.Collections.Immutable; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Text.Json; using System.Text.Json.Nodes; using System.Text.Json.Serialization; +using Microsoft.AspNetCore.Razor.PooledObjects; using Microsoft.CodeAnalysis.Razor.Protocol; using Microsoft.VisualStudio.LanguageServer.Protocol; using Newtonsoft.Json.Linq; @@ -79,45 +81,45 @@ internal static class CompletionListMerger return new MergedCompletionListData(data1, data2); } - public static bool TrySplit(object? data, [NotNullWhen(true)] out IReadOnlyList? splitData) + public static bool TrySplit(object? data, out ImmutableArray splitData) { if (data is null) { - splitData = null; + splitData = default; return false; } - var collector = new List(); - Split(data, collector); + using var collector = new PooledArrayBuilder(); + Split(data, ref collector.AsRef()); if (collector.Count == 0) { - splitData = null; + splitData = default; return false; } - splitData = collector; + splitData = collector.ToImmutable(); return true; } - private static void Split(object data, List collector) + private static void Split(object data, ref PooledArrayBuilder collector) { if (data is MergedCompletionListData mergedData) { // Merged data adds an extra object wrapper around the original data, so remove // that to restore to the original form. - Split(mergedData.Data1, collector); - Split(mergedData.Data2, collector); + Split(mergedData.Data1, ref collector); + Split(mergedData.Data2, ref collector); return; } // We have to be agnostic to which serialization method the delegated servers use, including // the scenario where they use different ones, so we normalize the data to JObject. - TrySplitJsonElement(data, collector); - TrySplitJObject(data, collector); + TrySplitJsonElement(data, ref collector); + TrySplitJObject(data, ref collector); } - private static void TrySplitJsonElement(object data, List collector) + private static void TrySplitJsonElement(object data, ref PooledArrayBuilder collector) { if (data is not JsonElement jsonElement) { @@ -136,8 +138,8 @@ private static void TrySplitJsonElement(object data, List collector return; } - Split(mergedCompletionListData.Data1, collector); - Split(mergedCompletionListData.Data2, collector); + Split(mergedCompletionListData.Data1, ref collector); + Split(mergedCompletionListData.Data2, ref collector); } else { @@ -145,7 +147,7 @@ private static void TrySplitJsonElement(object data, List collector } } - private static void TrySplitJObject(object data, List collector) + private static void TrySplitJObject(object data, ref PooledArrayBuilder collector) { if (data is not JObject jObject) { @@ -164,8 +166,8 @@ private static void TrySplitJObject(object data, List collector) return; } - Split(mergedCompletionListData.Data1, collector); - Split(mergedCompletionListData.Data2, collector); + Split(mergedCompletionListData.Data1, ref collector); + Split(mergedCompletionListData.Data2, ref collector); } else { @@ -209,7 +211,7 @@ private static void EnsureMergeableCommitCharacters(VSInternalCompletionList com VSInternalCompletionList? completionListToStopInheriting; // Decide which completion list has more items that benefit from "inheriting" commit characters. - if (inheritableCommitCharacterCompletionsA.Count >= inheritableCommitCharacterCompletionsB.Count) + if (inheritableCommitCharacterCompletionsA.Length >= inheritableCommitCharacterCompletionsB.Length) { completionListToStopInheriting = completionListB; completionItemsToStopInheriting = inheritableCommitCharacterCompletionsB; @@ -241,10 +243,9 @@ private static void EnsureMergeableCommitCharacters(VSInternalCompletionList com } } - private static IReadOnlyList GetCompletionsThatDoNotSpecifyCommitCharacters(VSInternalCompletionList completionList) + private static ImmutableArray GetCompletionsThatDoNotSpecifyCommitCharacters(VSInternalCompletionList completionList) { - var inheritableCompletions = new List(); - + using var inheritableCompletions = new PooledArrayBuilder(); for (var i = 0; i < completionList.Items.Length; i++) { var completionItem = completionList.Items[i] as VSInternalCompletionItem; @@ -259,7 +260,7 @@ completionItem.CommitCharacters is not null || inheritableCompletions.Add(completionItem); } - return inheritableCompletions; + return inheritableCompletions.ToImmutable(); } private record MergedCompletionListData(object Data1, object Data2); diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Completion/Delegation/DelegatedCompletionItemResolver.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Completion/Delegation/DelegatedCompletionItemResolver.cs index bc422f283b0..7d58f7bfbd6 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Completion/Delegation/DelegatedCompletionItemResolver.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Completion/Delegation/DelegatedCompletionItemResolver.cs @@ -52,7 +52,7 @@ public DelegatedCompletionItemResolver( // If the data was merged to combine resultId with original data, undo that merge and set the data back // to what it originally was for the delegated request - if (CompletionListMerger.TrySplit(associatedDelegatedCompletion.Data, out var splitData) && splitData.Count == 2) + if (CompletionListMerger.TrySplit(associatedDelegatedCompletion.Data, out var splitData) && splitData.Length == 2) { item.Data = splitData[1]; } diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Completion/VSInternalCompletionItemExtensions.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Completion/VSInternalCompletionItemExtensions.cs index 540d01a3280..c52fe46804c 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Completion/VSInternalCompletionItemExtensions.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Completion/VSInternalCompletionItemExtensions.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Collections.Immutable; using System.Diagnostics.CodeAnalysis; using Microsoft.AspNetCore.Razor.PooledObjects; using Microsoft.CodeAnalysis.Razor.Completion; @@ -16,7 +17,7 @@ internal static class VSInternalCompletionItemExtensions private static readonly Dictionary s_commitCharacterCache = []; - public static bool TryGetCompletionListResultIds(this VSInternalCompletionItem completion, [NotNullWhen(true)] out IReadOnlyList? resultIds) + public static bool TryGetCompletionListResultIds(this VSInternalCompletionItem completion, out ImmutableArray resultIds) { if (completion is null) { @@ -25,12 +26,12 @@ public static bool TryGetCompletionListResultIds(this VSInternalCompletionItem c if (!CompletionListMerger.TrySplit(completion.Data, out var splitData)) { - resultIds = null; + resultIds = default; return false; } - var ids = new List(); - for (var i = 0; i < splitData.Count; i++) + using var ids = new PooledArrayBuilder(); + for (var i = 0; i < splitData.Length; i++) { var data = splitData[i]; if (data.TryGetProperty(ResultIdKey, out var resultIdElement) && @@ -42,11 +43,11 @@ public static bool TryGetCompletionListResultIds(this VSInternalCompletionItem c if (ids.Count > 0) { - resultIds = ids; + resultIds = ids.ToImmutable(); return true; } - resultIds = null; + resultIds = default; return false; } diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/DocumentPresentation/AbstractTextDocumentPresentationEndpointBase.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/DocumentPresentation/AbstractTextDocumentPresentationEndpointBase.cs index 4361c339beb..2a66dc32eab 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/DocumentPresentation/AbstractTextDocumentPresentationEndpointBase.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/DocumentPresentation/AbstractTextDocumentPresentationEndpointBase.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Collections.Immutable; using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Threading; @@ -10,6 +11,7 @@ using Microsoft.AspNetCore.Razor.Language; using Microsoft.AspNetCore.Razor.LanguageServer.EndpointContracts; using Microsoft.AspNetCore.Razor.LanguageServer.Hosting; +using Microsoft.AspNetCore.Razor.PooledObjects; using Microsoft.CodeAnalysis.Razor.DocumentMapping; using Microsoft.CodeAnalysis.Razor.Logging; using Microsoft.CodeAnalysis.Razor.ProjectSystem; @@ -128,26 +130,26 @@ protected AbstractTextDocumentPresentationEndpointBase( private static bool TryGetDocumentChanges(WorkspaceEdit workspaceEdit, [NotNullWhen(true)] out TextDocumentEdit[]? documentChanges) { - if (workspaceEdit.DocumentChanges?.Value is TextDocumentEdit[] documentEdits) + if (workspaceEdit.DocumentChanges?.Value is TextDocumentEdit[] documentEditArray) { - documentChanges = documentEdits; + documentChanges = documentEditArray; return true; } if (workspaceEdit.DocumentChanges?.Value is SumType[] sumTypeArray) { - var documentEditList = new List(); + using var documentEdits = new PooledArrayBuilder(); foreach (var sumType in sumTypeArray) { if (sumType.Value is TextDocumentEdit textDocumentEdit) { - documentEditList.Add(textDocumentEdit); + documentEdits.Add(textDocumentEdit); } } - if (documentEditList.Count > 0) + if (documentEdits.Count > 0) { - documentChanges = [.. documentEditList]; + documentChanges = documentEdits.ToArray(); return true; } } @@ -172,7 +174,7 @@ private Dictionary MapChanges(Dictionary } var remappedEdits = MapTextEdits(mapRanges, codeDocument, edits); - if (remappedEdits is null || remappedEdits.Length == 0) + if (remappedEdits.Length == 0) { // Nothing to do. continue; @@ -187,7 +189,7 @@ private Dictionary MapChanges(Dictionary private TextDocumentEdit[] MapDocumentChanges(TextDocumentEdit[] documentEdits, bool mapRanges, RazorCodeDocument codeDocument, int hostDocumentVersion) { - var remappedDocumentEdits = new List(); + using var remappedDocumentEdits = new PooledArrayBuilder(documentEdits.Length); foreach (var entry in documentEdits) { var uri = entry.TextDocument.Uri; @@ -195,7 +197,6 @@ private TextDocumentEdit[] MapDocumentChanges(TextDocumentEdit[] documentEdits, { // This location doesn't point to a background razor file. No need to remap. remappedDocumentEdits.Add(entry); - continue; } @@ -215,26 +216,26 @@ private TextDocumentEdit[] MapDocumentChanges(TextDocumentEdit[] documentEdits, Uri = razorDocumentUri, Version = hostDocumentVersion }, - Edits = remappedEdits + Edits = remappedEdits.ToArray() }); } - return [.. remappedDocumentEdits]; + return remappedDocumentEdits.ToArray(); } - private TextEdit[]? MapTextEdits(bool mapRanges, RazorCodeDocument codeDocument, IEnumerable edits) + private TextEdit[] MapTextEdits(bool mapRanges, RazorCodeDocument codeDocument, TextEdit[] edits) { if (!mapRanges) { - return edits.ToArray(); + return edits; } - var mappedEdits = new List(); + using var mappedEdits = new PooledArrayBuilder(); foreach (var edit in edits) { if (!_razorDocumentMappingService.TryMapToHostDocumentRange(codeDocument.GetCSharpDocument(), edit.Range, out var newRange)) { - return null; + return []; } var newEdit = new TextEdit() @@ -245,7 +246,7 @@ private TextDocumentEdit[] MapDocumentChanges(TextDocumentEdit[] documentEdits, mappedEdits.Add(newEdit); } - return [.. mappedEdits]; + return mappedEdits.ToArray(); } private WorkspaceEdit? MapWorkspaceEdit(WorkspaceEdit workspaceEdit, bool mapRanges, RazorCodeDocument codeDocument, int hostDocumentVersion) diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/FindAllReferences/FindAllReferencesEndpoint.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/FindAllReferences/FindAllReferencesEndpoint.cs index 1f5d4fd6c01..b3b9da23856 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/FindAllReferences/FindAllReferencesEndpoint.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/FindAllReferences/FindAllReferencesEndpoint.cs @@ -8,6 +8,7 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Razor.LanguageServer.EndpointContracts; using Microsoft.AspNetCore.Razor.LanguageServer.Hosting; +using Microsoft.AspNetCore.Razor.PooledObjects; using Microsoft.AspNetCore.Razor.Threading; using Microsoft.CodeAnalysis.Razor.DocumentMapping; using Microsoft.CodeAnalysis.Razor.Logging; @@ -73,7 +74,7 @@ public void ApplyCapabilities(VSInternalServerCapabilities serverCapabilities, V protected override async Task HandleDelegatedResponseAsync(VSInternalReferenceItem[] delegatedResponse, ReferenceParams originalRequest, RazorRequestContext requestContext, DocumentPositionInfo positionInfo, CancellationToken cancellationToken) { - var remappedLocations = new List(); + using var remappedLocations = new PooledArrayBuilder(); foreach (var referenceItem in delegatedResponse) { diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Formatting/CSharpFormatter.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Formatting/CSharpFormatter.cs index 924e0c5df57..0d7a4e01fa7 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Formatting/CSharpFormatter.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Formatting/CSharpFormatter.cs @@ -7,6 +7,7 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.Razor.Language; +using Microsoft.AspNetCore.Razor.PooledObjects; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; @@ -280,7 +281,8 @@ private static (Dictionary, SyntaxTree) InitializeInden var indentationMap = new Dictionary(); var marker = "/*__marker__*/"; var markerString = $"{context.NewLineString}{marker}{context.NewLineString}"; - var changes = new List(); + + using var changes = new PooledArrayBuilder(); var previousMarkerOffset = 0; foreach (var projectedDocumentIndex in projectedDocumentLocations) @@ -318,7 +320,7 @@ private static (Dictionary, SyntaxTree) InitializeInden } } - var changedText = context.CSharpSourceText.WithChanges(changes); + var changedText = context.CSharpSourceText.WithChanges(changes.ToImmutable()); var syntaxTree = CSharpSyntaxTree.ParseText(changedText, cancellationToken: cancellationToken); return (indentationMap, syntaxTree); } diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Formatting/CSharpFormattingPass.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Formatting/CSharpFormattingPass.cs index 3154fe0a963..81abf67078e 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Formatting/CSharpFormattingPass.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Formatting/CSharpFormattingPass.cs @@ -3,11 +3,13 @@ using System; using System.Collections.Generic; +using System.Collections.Immutable; using System.Linq; using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.Razor.Language; using Microsoft.AspNetCore.Razor.LanguageServer.Hosting; +using Microsoft.AspNetCore.Razor.PooledObjects; using Microsoft.CodeAnalysis.Razor.DocumentMapping; using Microsoft.CodeAnalysis.Razor.Logging; using Microsoft.CodeAnalysis.Razor.Protocol; @@ -50,7 +52,7 @@ public async override Task ExecuteAsync(FormattingContext cont // Apply original C# edits var csharpEdits = await FormatCSharpAsync(changedContext, cancellationToken).ConfigureAwait(false); - if (csharpEdits.Count > 0) + if (csharpEdits.Length > 0) { var csharpChanges = csharpEdits.Select(c => c.ToTextChange(changedText)); changedText = changedText.WithChanges(csharpChanges); @@ -78,10 +80,11 @@ public async override Task ExecuteAsync(FormattingContext cont return new FormattingResult(finalEdits); } - private async Task> FormatCSharpAsync(FormattingContext context, CancellationToken cancellationToken) + private async Task> FormatCSharpAsync(FormattingContext context, CancellationToken cancellationToken) { var sourceText = context.SourceText; - var csharpEdits = new List(); + + using var csharpEdits = new PooledArrayBuilder(); foreach (var mapping in context.CodeDocument.GetCSharpDocument().SourceMappings) { var span = new TextSpan(mapping.OriginalSpan.AbsoluteIndex, mapping.OriginalSpan.Length); @@ -97,6 +100,6 @@ private async Task> FormatCSharpAsync(FormattingContext context, csharpEdits.AddRange(edits.Where(e => range.Contains(e.Range))); } - return csharpEdits; + return csharpEdits.ToImmutable(); } } diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/MapCode/MapCodeEndpoint.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/MapCode/MapCodeEndpoint.cs index 77e5ccc5c54..e00d1fed49c 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/MapCode/MapCodeEndpoint.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/MapCode/MapCodeEndpoint.cs @@ -77,7 +77,7 @@ public void ApplyCapabilities(VSInternalServerCapabilities serverCapabilities, V private async Task HandleMappingsAsync(VSInternalMapCodeMapping[] mappings, Guid mapCodeCorrelationId, CancellationToken cancellationToken) { - using var _ = ArrayBuilderPool.GetPooledObject(out var changes); + using var _ = ListPool.GetPooledObject(out var changes); foreach (var mapping in mappings) { if (mapping.TextDocument is null || mapping.FocusLocations is null) @@ -129,7 +129,7 @@ public void ApplyCapabilities(VSInternalServerCapabilities serverCapabilities, V private async Task TryMapCodeAsync( RazorCodeDocument codeToMap, Location[][] locations, - ImmutableArray.Builder changes, + List changes, Guid mapCodeCorrelationId, VersionedDocumentContext documentContext, CancellationToken cancellationToken) @@ -141,7 +141,7 @@ private async Task TryMapCodeAsync( } var nodesToMap = ExtractValidNodesToMap(syntaxTree.Root); - if (nodesToMap.Count == 0) + if (nodesToMap.Length == 0) { return false; } @@ -159,9 +159,9 @@ private async Task TryMapCodeAsync( private async Task TryMapCodeAsync( Location[][] focusLocations, - List nodesToMap, + ImmutableArray nodesToMap, Guid mapCodeCorrelationId, - ImmutableArray.Builder changes, + List changes, VersionedDocumentContext documentContext, CancellationToken cancellationToken) { @@ -189,7 +189,7 @@ private async Task TryMapCodeAsync( continue; } - var razorNodesToMap = new List(); + using var razorNodesToMap = new PooledArrayBuilder(); foreach (var nodeToMap in nodesToMap) { // If node is C#, we send it to their language server to handle and ignore it from our end. @@ -263,10 +263,10 @@ private async Task TryMapCodeAsync( return false; } - private static List ExtractValidNodesToMap(SyntaxNode rootNode) + private static ImmutableArray ExtractValidNodesToMap(SyntaxNode rootNode) { - var validNodesToMap = new List(); - var stack = new Stack(); + using var validNodesToMap = new PooledArrayBuilder(); + using var _ = StackPool.GetPooledObject(out var stack); stack.Push(rootNode); while (stack.Count > 0) @@ -286,7 +286,7 @@ private static List ExtractValidNodesToMap(SyntaxNode rootNode) } } - return validNodesToMap; + return validNodesToMap.ToImmutable(); } // These are the nodes that we currently support for mapping. We should update @@ -306,7 +306,7 @@ private async Task TrySendCSharpDelegatedMappingRequestAsync( SyntaxNode nodeToMap, Location[][] focusLocations, Guid mapCodeCorrelationId, - ImmutableArray.Builder changes, + List changes, CancellationToken cancellationToken) { var delegatedRequest = new DelegatedMapCodeParams( @@ -344,10 +344,12 @@ private async Task GetCSharpFocusLocationsAsync(Location[][] focus { // If the focus locations are in a C# context, map them to the C# document. var csharpFocusLocations = new Location[focusLocations.Length][]; + using var csharpLocations = new PooledArrayBuilder(); for (var i = 0; i < focusLocations.Length; i++) { + csharpLocations.Clear(); + var locations = focusLocations[i]; - var csharpLocations = new List(); foreach (var potentialLocation in locations) { if (potentialLocation is null) @@ -379,7 +381,7 @@ private async Task GetCSharpFocusLocationsAsync(Location[][] focus } } - csharpFocusLocations[i] = [.. csharpLocations]; + csharpFocusLocations[i] = csharpLocations.ToArray(); } return csharpFocusLocations; @@ -388,10 +390,10 @@ private async Task GetCSharpFocusLocationsAsync(Location[][] focus // Map C# code back to Razor file private async Task TryHandleDelegatedResponseAsync( WorkspaceEdit edits, - ImmutableArray.Builder changes, + List changes, CancellationToken cancellationToken) { - using var _ = ArrayBuilderPool.GetPooledObject(out var csharpChanges); + using var _ = ListPool.GetPooledObject(out var csharpChanges); if (edits.DocumentChanges is not null && edits.DocumentChanges.Value.TryGetFirst(out var documentEdits)) { // We only support document edits for now. In the future once the client supports it, we should look @@ -425,7 +427,7 @@ private async Task TryHandleDelegatedResponseAsync( async Task TryProcessEditAsync( Uri generatedUri, TextEdit[] textEdits, - ImmutableArray.Builder csharpChanges, + List csharpChanges, CancellationToken cancellationToken) { foreach (var documentEdit in textEdits) @@ -458,11 +460,10 @@ async Task TryProcessEditAsync( } // Resolve edits that are at the same start location by merging them together. - private static void MergeEdits(ImmutableArray.Builder changes) + private static void MergeEdits(List changes) { - var groupedChanges = changes.GroupBy(c => c.TextDocument.Uri); - using var _ = ArrayBuilderPool.GetPooledObject(out var mergedChanges); - + var groupedChanges = changes.GroupBy(c => c.TextDocument.Uri).ToImmutableArray(); + changes.Clear(); foreach (var documentChanges in groupedChanges) { var edits = documentChanges.ToList(); @@ -490,10 +491,7 @@ private static void MergeEdits(ImmutableArray.Builder changes) Edits = edits.SelectMany(e => e.Edits).ToArray() }; - mergedChanges.Add(finalEditsForDoc); + changes.Add(finalEditsForDoc); } - - changes.Clear(); - changes.AddRange(mergedChanges); } } diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Refactoring/RenameEndpoint.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Refactoring/RenameEndpoint.cs index 0c630a681b0..75f50f0bccf 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Refactoring/RenameEndpoint.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Refactoring/RenameEndpoint.cs @@ -130,7 +130,7 @@ protected override bool IsSupported() return null; } - var documentChanges = new List>(); + using var _ = ListPool>.GetPooledObject(out var documentChanges); var fileRename = GetFileRenameForComponent(originComponentDocumentSnapshot, newPath); documentChanges.Add(fileRename); AddEditsForCodeDocument(documentChanges, originTagHelpers, request.NewName, request.TextDocument.Uri, codeDocument); diff --git a/src/Razor/src/Microsoft.VisualStudio.LegacyEditor.Razor/Parsing/VisualStudioRazorParser.cs b/src/Razor/src/Microsoft.VisualStudio.LegacyEditor.Razor/Parsing/VisualStudioRazorParser.cs index 74358614b5a..57964527885 100644 --- a/src/Razor/src/Microsoft.VisualStudio.LegacyEditor.Razor/Parsing/VisualStudioRazorParser.cs +++ b/src/Razor/src/Microsoft.VisualStudio.LegacyEditor.Razor/Parsing/VisualStudioRazorParser.cs @@ -11,6 +11,7 @@ using Microsoft.AspNetCore.Razor; using Microsoft.AspNetCore.Razor.Language; using Microsoft.AspNetCore.Razor.Language.Legacy; +using Microsoft.AspNetCore.Razor.PooledObjects; using Microsoft.AspNetCore.Razor.ProjectEngineHost; using Microsoft.CodeAnalysis.Razor; using Microsoft.CodeAnalysis.Razor.Logging; @@ -548,7 +549,7 @@ private void CompleteCodeDocumentRequestsForSnapshot(RazorCodeDocument codeDocum return; } - var matchingRequests = new List(); + using var matchingRequests = new PooledArrayBuilder(); for (var i = _codeDocumentRequests.Count - 1; i >= 0; i--) { var request = _codeDocumentRequests[i]; diff --git a/src/Razor/src/Microsoft.VisualStudio.RazorExtension/SyntaxVisualizer/IntraTextAdornmentTagger.cs b/src/Razor/src/Microsoft.VisualStudio.RazorExtension/SyntaxVisualizer/IntraTextAdornmentTagger.cs index 94c467af464..199adc91ee7 100644 --- a/src/Razor/src/Microsoft.VisualStudio.RazorExtension/SyntaxVisualizer/IntraTextAdornmentTagger.cs +++ b/src/Razor/src/Microsoft.VisualStudio.RazorExtension/SyntaxVisualizer/IntraTextAdornmentTagger.cs @@ -26,10 +26,13 @@ internal abstract class IntraTextAdornmentTagger : ITagger where TAdornment : UIElement { + private readonly List _invalidatedSpans = new List(); + + // not readonly because it's updated in AsyncUpdate + private Dictionary _adornmentCache = new Dictionary(); + protected readonly IWpfTextView view; - private Dictionary adornmentCache = new Dictionary(); protected ITextSnapshot snapshot { get; private set; } - private readonly List invalidatedSpans = new List(); protected IntraTextAdornmentTagger(IWpfTextView view) { @@ -69,12 +72,12 @@ private void HandleBufferChanged(object sender, TextContentChangedEventArgs args ///
protected void InvalidateSpans(IList spans) { - lock (invalidatedSpans) + lock (_invalidatedSpans) { - var wasEmpty = invalidatedSpans.Count == 0; - invalidatedSpans.AddRange(spans); + var wasEmpty = _invalidatedSpans.Count == 0; + _invalidatedSpans.AddRange(spans); - if (wasEmpty && invalidatedSpans.Count > 0) + if (wasEmpty && _invalidatedSpans.Count > 0) { ThreadHelper.JoinableTaskFactory.Run(async () => { @@ -95,19 +98,19 @@ private void AsyncUpdate() var translatedAdornmentCache = new Dictionary(); - foreach (var keyValuePair in adornmentCache) + foreach (var keyValuePair in _adornmentCache) { translatedAdornmentCache.Add(keyValuePair.Key.TranslateTo(snapshot, SpanTrackingMode.EdgeExclusive), keyValuePair.Value); } - adornmentCache = translatedAdornmentCache; + _adornmentCache = translatedAdornmentCache; } List translatedSpans; - lock (invalidatedSpans) + lock (_invalidatedSpans) { - translatedSpans = invalidatedSpans.Select(s => s.TranslateTo(snapshot, SpanTrackingMode.EdgeInclusive)).ToList(); - invalidatedSpans.Clear(); + translatedSpans = _invalidatedSpans.Select(s => s.TranslateTo(snapshot, SpanTrackingMode.EdgeInclusive)).ToList(); + _invalidatedSpans.Clear(); } if (translatedSpans.Count == 0) @@ -138,15 +141,14 @@ private void HandleLayoutChanged(object sender, TextViewLayoutChangedEventArgs e var visibleSpan = view.TextViewLines.FormattedSpan; // Filter out the adornments that are no longer visible. - var toRemove = new List( - from keyValuePair - in adornmentCache + var toRemove = from keyValuePair + in _adornmentCache where !keyValuePair.Key.TranslateTo(visibleSpan.Snapshot, SpanTrackingMode.EdgeExclusive).IntersectsWith(visibleSpan) - select keyValuePair.Key); + select keyValuePair.Key; foreach (var span in toRemove) { - adornmentCache.Remove(span); + _adornmentCache.Remove(span); } } @@ -194,7 +196,7 @@ private IEnumerable> GetAdornmentTagsOnSnapshot(N // Mark which adornments fall inside the requested spans with Keep=false // so that they can be removed from the cache if they no longer correspond to data tags. var toRemove = new HashSet(); - foreach (var ar in adornmentCache) + foreach (var ar in _adornmentCache) { if (spans.IntersectsWith(new NormalizedSnapshotSpanCollection(ar.Key))) { @@ -209,7 +211,7 @@ private IEnumerable> GetAdornmentTagsOnSnapshot(N var snapshotSpan = spanDataPair.Item1; var affinity = spanDataPair.Item2; var adornmentData = spanDataPair.Item3; - if (adornmentCache.TryGetValue(snapshotSpan, out adornment)) + if (_adornmentCache.TryGetValue(snapshotSpan, out adornment)) { if (UpdateAdornment(adornment, adornmentData)) { @@ -235,7 +237,7 @@ private IEnumerable> GetAdornmentTagsOnSnapshot(N // can help avoid the size change and the resulting unnecessary re-format. adornment.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity)); - adornmentCache.Add(snapshotSpan, adornment); + _adornmentCache.Add(snapshotSpan, adornment); } yield return new TagSpan(snapshotSpan, new IntraTextAdornmentTag(adornment, null, affinity)); @@ -243,7 +245,7 @@ private IEnumerable> GetAdornmentTagsOnSnapshot(N foreach (var snapshotSpan in toRemove) { - adornmentCache.Remove(snapshotSpan); + _adornmentCache.Remove(snapshotSpan); } } diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/CSharp/DefaultCSharpCodeActionProviderTest.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/CSharp/DefaultCSharpCodeActionProviderTest.cs index 24a3e95a99d..08e9082c0d7 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/CSharp/DefaultCSharpCodeActionProviderTest.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/CSharp/DefaultCSharpCodeActionProviderTest.cs @@ -25,8 +25,8 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer.CodeActions; public class DefaultCSharpCodeActionProviderTest : LanguageServerTestBase { - private readonly RazorVSInternalCodeAction[] _supportedCodeActions; - private readonly RazorVSInternalCodeAction[] _supportedImplicitExpressionCodeActions; + private readonly ImmutableArray _supportedCodeActions; + private readonly ImmutableArray _supportedImplicitExpressionCodeActions; public DefaultCSharpCodeActionProviderTest(ITestOutputHelper testOutput) : base(testOutput) @@ -34,12 +34,12 @@ public DefaultCSharpCodeActionProviderTest(ITestOutputHelper testOutput) _supportedCodeActions = DefaultCSharpCodeActionProvider .SupportedDefaultCodeActionNames .Select(name => new RazorVSInternalCodeAction { Name = name }) - .ToArray(); + .ToImmutableArray(); _supportedImplicitExpressionCodeActions = DefaultCSharpCodeActionProvider .SupportedImplicitExpressionCodeActionNames .Select(name => new RazorVSInternalCodeAction { Name = name }) - .ToArray(); + .ToImmutableArray(); } [Fact] @@ -67,8 +67,7 @@ public async Task ProvideAsync_ValidCodeActions_ReturnsProvidedCodeAction() var providedCodeActions = await provider.ProvideAsync(context, _supportedCodeActions, default); // Assert - Assert.NotNull(providedCodeActions); - Assert.Equal(_supportedCodeActions.Length, providedCodeActions.Count); + Assert.Equal(_supportedCodeActions.Length, providedCodeActions.Length); var providedNames = providedCodeActions.Select(action => action.Name); var expectedNames = _supportedCodeActions.Select(action => action.Name); Assert.Equal(expectedNames, providedNames); @@ -99,7 +98,6 @@ public async Task ProvideAsync_SupportsCodeActionResolveFalse_ValidCodeActions_R var providedCodeActions = await provider.ProvideAsync(context, _supportedCodeActions, default); // Assert - Assert.NotNull(providedCodeActions); Assert.Empty(providedCodeActions); } @@ -128,8 +126,7 @@ public async Task ProvideAsync_FunctionsBlock_SingleLine_ValidCodeActions_Return var providedCodeActions = await provider.ProvideAsync(context, _supportedCodeActions, default); // Assert - Assert.NotNull(providedCodeActions); - Assert.Equal(_supportedCodeActions.Length, providedCodeActions.Count); + Assert.Equal(_supportedCodeActions.Length, providedCodeActions.Length); var providedNames = providedCodeActions.Select(action => action.Name); var expectedNames = _supportedCodeActions.Select(action => action.Name); Assert.Equal(expectedNames, providedNames); @@ -162,8 +159,7 @@ public async Task ProvideAsync_FunctionsBlock_OpenBraceSameLine_ValidCodeActions var providedCodeActions = await provider.ProvideAsync(context, _supportedCodeActions, default); // Assert - Assert.NotNull(providedCodeActions); - Assert.Equal(_supportedCodeActions.Length, providedCodeActions.Count); + Assert.Equal(_supportedCodeActions.Length, providedCodeActions.Length); var providedNames = providedCodeActions.Select(action => action.Name); var expectedNames = _supportedCodeActions.Select(action => action.Name); Assert.Equal(expectedNames, providedNames); @@ -197,8 +193,7 @@ public async Task ProvideAsync_FunctionsBlock_OpenBraceNextLine_ValidCodeActions var providedCodeActions = await provider.ProvideAsync(context, _supportedCodeActions, default); // Assert - Assert.NotNull(providedCodeActions); - Assert.Equal(_supportedCodeActions.Length, providedCodeActions.Count); + Assert.Equal(_supportedCodeActions.Length, providedCodeActions.Length); var providedNames = providedCodeActions.Select(action => action.Name); var expectedNames = _supportedCodeActions.Select(action => action.Name); Assert.Equal(expectedNames, providedNames); @@ -225,20 +220,19 @@ public async Task ProvideAsync_InvalidCodeActions_ReturnsNoCodeActions() var provider = new DefaultCSharpCodeActionProvider(TestLanguageServerFeatureOptions.Instance); - var codeActions = new RazorVSInternalCodeAction[] - { + ImmutableArray codeActions = + [ new RazorVSInternalCodeAction() { Title = "Do something not really supported in razor", Name = "Non-existant name" } - }; + ]; // Act var providedCodeActions = await provider.ProvideAsync(context, codeActions, default); // Assert - Assert.NotNull(providedCodeActions); Assert.Empty(providedCodeActions); } @@ -264,20 +258,19 @@ public async Task ProvideAsync_InvalidCodeActions_ShowAllFeatureFlagOn_ReturnsCo var options = new ConfigurableLanguageServerFeatureOptions(new[] { $"--{nameof(ConfigurableLanguageServerFeatureOptions.ShowAllCSharpCodeActions)}" }); var provider = new DefaultCSharpCodeActionProvider(options); - var codeActions = new RazorVSInternalCodeAction[] - { + ImmutableArray codeActions = + [ new RazorVSInternalCodeAction() { Title = "Do something not really supported in razor", Name = "Non-existant name" } - }; + ]; // Act var providedCodeActions = await provider.ProvideAsync(context, codeActions, default); // Assert - Assert.NotNull(providedCodeActions); Assert.NotEmpty(providedCodeActions); } @@ -314,8 +307,7 @@ public async Task ProvideAsync_ImplicitExpression_ReturnsProvidedCodeAction() var providedCodeActions = await provider.ProvideAsync(context, _supportedCodeActions, default); // Assert - Assert.NotNull(providedCodeActions); - Assert.Equal(_supportedImplicitExpressionCodeActions.Length, providedCodeActions.Count); + Assert.Equal(_supportedImplicitExpressionCodeActions.Length, providedCodeActions.Length); var providedNames = providedCodeActions.Select(action => action.Name); var expectedNames = _supportedImplicitExpressionCodeActions.Select(action => action.Name); Assert.Equal(expectedNames, providedNames); diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/CSharp/TypeAccessibilityCodeActionProviderTest.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/CSharp/TypeAccessibilityCodeActionProviderTest.cs index faebcb9c5c5..6d433efb738 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/CSharp/TypeAccessibilityCodeActionProviderTest.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/CSharp/TypeAccessibilityCodeActionProviderTest.cs @@ -48,18 +48,18 @@ public async Task Handle_MissingDiagnostics_ReturnsEmpty() context.CodeDocument.SetFileKind(FileKinds.Legacy); var provider = new TypeAccessibilityCodeActionProvider(); - var csharpCodeActions = new[] { + ImmutableArray csharpCodeActions = + [ new RazorVSInternalCodeAction() { Title = "System.Net.Dns" } - }; + ]; // Act var results = await provider.ProvideAsync(context, csharpCodeActions, default); // Assert - Assert.NotNull(results); Assert.Empty(results); } @@ -103,18 +103,18 @@ public async Task Handle_InvalidDiagnostics_VSCode_ReturnsEmpty() context.CodeDocument.SetFileKind(FileKinds.Legacy); var provider = new TypeAccessibilityCodeActionProvider(); - var csharpCodeActions = new[] { + ImmutableArray csharpCodeActions = + [ new RazorVSInternalCodeAction() { Title = "System.Net.Dns" } - }; + ]; // Act var results = await provider.ProvideAsync(context, csharpCodeActions, default); // Assert - Assert.NotNull(results); Assert.Empty(results); } @@ -146,13 +146,12 @@ public async Task Handle_EmptyCodeActions_ReturnsEmpty() context.CodeDocument.SetFileKind(FileKinds.Legacy); var provider = new TypeAccessibilityCodeActionProvider(); - var csharpCodeActions = Array.Empty(); + var csharpCodeActions = ImmutableArray.Empty; // Act var results = await provider.ProvideAsync(context, csharpCodeActions, default); // Assert - Assert.NotNull(results); Assert.Empty(results); } @@ -201,7 +200,8 @@ public async Task Handle_ValidDiagnostic_ValidCodeAction_VSCode_ReturnsCodeActio context.CodeDocument.SetFileKind(FileKinds.Legacy); var provider = new TypeAccessibilityCodeActionProvider(); - var csharpCodeActions = new[] { + ImmutableArray csharpCodeActions = + [ new RazorVSInternalCodeAction() { Title = "System.IO.Path", @@ -212,13 +212,12 @@ public async Task Handle_ValidDiagnostic_ValidCodeAction_VSCode_ReturnsCodeActio Title = "System.IO.SomethingElse", Name = "CodeActionFromVSCode" } - }; + ]; // Act var results = await provider.ProvideAsync(context, csharpCodeActions, default); // Assert - Assert.NotNull(results); Assert.Collection(results, r => { @@ -260,7 +259,8 @@ public async Task Handle_CodeActionInSingleLineDirective_VS_ReturnsOnlyUsingCode context.CodeDocument.SetFileKind(FileKinds.Legacy); var provider = new TypeAccessibilityCodeActionProvider(); - var csharpCodeActions = new[] { + ImmutableArray csharpCodeActions = + [ new RazorVSInternalCodeAction() { Title = "System.IO.Path", @@ -271,13 +271,12 @@ public async Task Handle_CodeActionInSingleLineDirective_VS_ReturnsOnlyUsingCode Title = "using System.IO;", Name = "AddImport" } - }; + ]; // Act var results = await provider.ProvideAsync(context, csharpCodeActions, default); // Assert - Assert.NotNull(results); Assert.Collection(results, r => { @@ -312,7 +311,8 @@ public async Task Handle_ValidCodeAction_VS_ReturnsCodeActions() context.CodeDocument.SetFileKind(FileKinds.Legacy); var provider = new TypeAccessibilityCodeActionProvider(); - var csharpCodeActions = new[] { + ImmutableArray csharpCodeActions = + [ new RazorVSInternalCodeAction() { Title = "System.IO.Path", @@ -323,13 +323,12 @@ public async Task Handle_ValidCodeAction_VS_ReturnsCodeActions() Title = "using System.IO;", Name = "AddImport" } - }; + ]; // Act var results = await provider.ProvideAsync(context, csharpCodeActions, default); // Assert - Assert.NotNull(results); Assert.Collection(results, r => { @@ -390,7 +389,8 @@ public async Task Handle_ValidDiagnostic_MultipleValidCodeActions_VSCode_Returns context.CodeDocument.SetFileKind(FileKinds.Legacy); var provider = new TypeAccessibilityCodeActionProvider(); - var csharpCodeActions = new[] { + ImmutableArray csharpCodeActions = + [ new RazorVSInternalCodeAction() { Title = "Fully qualify 'Path' -> System.IO.Path", @@ -401,13 +401,12 @@ public async Task Handle_ValidDiagnostic_MultipleValidCodeActions_VSCode_Returns Title = "Fully qualify 'Path' -> SuperSpecialNamespace.Path", Name = "CodeActionFromVSCode" } - }; + ]; // Act var results = await provider.ProvideAsync(context, csharpCodeActions, default); // Assert - Assert.NotNull(results); Assert.Collection(results, r => { diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/CodeActionEndpointTest.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/CodeActionEndpointTest.cs index 41ecfb5c476..f032719c971 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/CodeActionEndpointTest.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/CodeActionEndpointTest.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Collections.Immutable; using System.Linq; using System.Text.Json; using System.Text.Json.Nodes; @@ -369,7 +370,7 @@ public async Task Handle_OneNullReturningProvider() var codeActionEndpoint = new CodeActionEndpoint( _documentMappingService, new IRazorCodeActionProvider[] { - new MockNullRazorCodeActionProvider() + new MockEmptyRazorCodeActionProvider() }, Array.Empty(), Array.Empty(), @@ -409,9 +410,9 @@ public async Task Handle_MultipleMixedProvider() documentMappingService, new IRazorCodeActionProvider[] { new MockRazorCodeActionProvider(), - new MockNullRazorCodeActionProvider(), + new MockEmptyRazorCodeActionProvider(), new MockRazorCodeActionProvider(), - new MockNullRazorCodeActionProvider(), + new MockEmptyRazorCodeActionProvider(), }, new ICSharpCodeActionProvider[] { new MockCSharpCodeActionProvider(), @@ -454,7 +455,7 @@ public async Task Handle_MultipleMixedProvider_SupportsCodeActionResolveTrue() new IRazorCodeActionProvider[] { new MockRazorCodeActionProvider(), new MockRazorCommandProvider(), - new MockNullRazorCodeActionProvider() + new MockEmptyRazorCodeActionProvider() }, Array.Empty(), Array.Empty(), @@ -558,7 +559,7 @@ public async Task Handle_MultipleMixedProvider_SupportsCodeActionResolveFalse() new IRazorCodeActionProvider[] { new MockRazorCodeActionProvider(), new MockRazorCommandProvider(), - new MockNullRazorCodeActionProvider() + new MockEmptyRazorCodeActionProvider() }, Array.Empty(), Array.Empty(), @@ -811,41 +812,42 @@ private static RazorCodeDocument CreateCodeDocument(string text) private class MockRazorCodeActionProvider : IRazorCodeActionProvider { - public Task?> ProvideAsync(RazorCodeActionContext context, CancellationToken cancellationToken) + public Task> ProvideAsync(RazorCodeActionContext context, CancellationToken cancellationToken) { - return Task.FromResult?>(new List() { new RazorVSInternalCodeAction() }); + return Task.FromResult>([new RazorVSInternalCodeAction()]); } } private class MockMultipleRazorCodeActionProvider : IRazorCodeActionProvider { - public Task?> ProvideAsync(RazorCodeActionContext context, CancellationToken cancellationToken) + public Task> ProvideAsync(RazorCodeActionContext context, CancellationToken cancellationToken) { - return Task.FromResult?>(new List() - { + return Task.FromResult>( + [ new RazorVSInternalCodeAction(), new RazorVSInternalCodeAction() - }); + ]); } } private class MockCSharpCodeActionProvider : ICSharpCodeActionProvider { - public Task?> ProvideAsync(RazorCodeActionContext context, IEnumerable codeActions, CancellationToken cancellationToken) + public Task> ProvideAsync(RazorCodeActionContext _1, ImmutableArray _2, CancellationToken _3) { - return Task.FromResult?>(new List() - { + return Task.FromResult>( + [ new RazorVSInternalCodeAction() - }); + ]); } } private class MockRazorCommandProvider : IRazorCodeActionProvider { - public Task?> ProvideAsync(RazorCodeActionContext context, CancellationToken cancellationToken) + public Task> ProvideAsync(RazorCodeActionContext _1, CancellationToken _2) { // O# Code Actions don't have `Data`, but `Commands` do - return Task.FromResult?>(new List() { + return Task.FromResult>( + [ new RazorVSInternalCodeAction() { Title = "SomeTitle", Data = JsonSerializer.SerializeToElement(new AddUsingsCodeActionParams() @@ -854,15 +856,15 @@ private class MockRazorCommandProvider : IRazorCodeActionProvider Uri = new Uri("C:/path/to/Page.razor") }) } - }); + ]); } } - private class MockNullRazorCodeActionProvider : IRazorCodeActionProvider + private class MockEmptyRazorCodeActionProvider : IRazorCodeActionProvider { - public Task?> ProvideAsync(RazorCodeActionContext context, CancellationToken cancellationToken) + public Task> ProvideAsync(RazorCodeActionContext _1, CancellationToken _2) { - return SpecializedTasks.Null>(); + return SpecializedTasks.EmptyImmutableArray(); } } diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/Html/DefaultHtmlCodeActionProviderTest.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/Html/DefaultHtmlCodeActionProviderTest.cs index e507f91b974..252fbe34eb0 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/Html/DefaultHtmlCodeActionProviderTest.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/Html/DefaultHtmlCodeActionProviderTest.cs @@ -46,13 +46,12 @@ public async Task ProvideAsync_WrapsResolvableCodeActions() var documentMappingService = Mock.Of(MockBehavior.Strict); var provider = new DefaultHtmlCodeActionProvider(documentMappingService); - var codeActions = new[] { new RazorVSInternalCodeAction() { Name = "Test" } }; + ImmutableArray codeActions = [ new RazorVSInternalCodeAction() { Name = "Test" } ]; // Act var providedCodeActions = await provider.ProvideAsync(context, codeActions, DisposalToken); // Assert - Assert.NotNull(providedCodeActions); var action = Assert.Single(providedCodeActions); Assert.Equal("Test", action.Name); Assert.Equal("Html", ((JsonElement)action.Data!).GetProperty("language").GetString()); @@ -99,33 +98,32 @@ public async Task ProvideAsync_RemapsAndFixesEdits() var provider = new DefaultHtmlCodeActionProvider(documentMappingServiceMock.Object); - var codeActions = new[] + ImmutableArray codeActions = + [ + new RazorVSInternalCodeAction() { - new RazorVSInternalCodeAction() + Name = "Test", + Edit = new WorkspaceEdit { - Name = "Test", - Edit = new WorkspaceEdit + DocumentChanges = new TextDocumentEdit[] { - DocumentChanges = new TextDocumentEdit[] + new TextDocumentEdit { - new TextDocumentEdit + TextDocument = new OptionalVersionedTextDocumentIdentifier { Uri= new Uri("c:/Test.razor.html"), Version = 1 }, + Edits = new TextEdit[] { - TextDocument = new OptionalVersionedTextDocumentIdentifier { Uri= new Uri("c:/Test.razor.html"), Version = 1 }, - Edits = new TextEdit[] - { - new TextEdit { NewText = "Goo" } - } + new TextEdit { NewText = "Goo" } } } } } - }; + } + ]; // Act var providedCodeActions = await provider.ProvideAsync(context, codeActions, DisposalToken); // Assert - Assert.NotNull(providedCodeActions); var action = Assert.Single(providedCodeActions); Assert.NotNull(action.Edit); Assert.True(action.Edit.TryGetDocumentChanges(out var changes)); diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/Razor/ComponentAccessibilityCodeActionProviderTest.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/Razor/ComponentAccessibilityCodeActionProviderTest.cs index d8be67e5eb2..e0f94799c57 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/Razor/ComponentAccessibilityCodeActionProviderTest.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/Razor/ComponentAccessibilityCodeActionProviderTest.cs @@ -49,7 +49,7 @@ public async Task Handle_NoTagName_DoesNotProvideLightBulb() var commandOrCodeActionContainer = await provider.ProvideAsync(context, default); // Assert - Assert.Null(commandOrCodeActionContainer); + Assert.Empty(commandOrCodeActionContainer); } [Fact] @@ -79,7 +79,7 @@ public async Task Handle_InvalidSyntaxTree_NoStartNode() var commandOrCodeActionContainer = await provider.ProvideAsync(context, default); // Assert - Assert.Null(commandOrCodeActionContainer); + Assert.Empty(commandOrCodeActionContainer); } [Fact] @@ -108,7 +108,7 @@ public async Task Handle_CursorOutsideComponent() var commandOrCodeActionContainer = await provider.ProvideAsync(context, default); // Assert - Assert.Null(commandOrCodeActionContainer); + Assert.Empty(commandOrCodeActionContainer); } [Fact] @@ -137,7 +137,6 @@ public async Task Handle_ExistingComponent_SupportsFileCreationTrue_ReturnsResul var commandOrCodeActionContainer = await provider.ProvideAsync(context, default); // Assert - Assert.NotNull(commandOrCodeActionContainer); Assert.Collection(commandOrCodeActionContainer, e => { @@ -186,7 +185,6 @@ public async Task Handle_ExistingComponent_CaseIncorrect_ReturnsResults() var commandOrCodeActionContainer = await provider.ProvideAsync(context, default); // Assert - Assert.NotNull(commandOrCodeActionContainer); Assert.Collection(commandOrCodeActionContainer, e => { @@ -237,7 +235,6 @@ @using Fully.Qualified var commandOrCodeActionContainer = await provider.ProvideAsync(context, default); // Assert - Assert.NotNull(commandOrCodeActionContainer); Assert.Collection(commandOrCodeActionContainer, e => { @@ -280,7 +277,6 @@ public async Task Handle_ExistingGenericComponent_SupportsFileCreationTrue_Retur var commandOrCodeActionContainer = await provider.ProvideAsync(context, default); // Assert - Assert.NotNull(commandOrCodeActionContainer); Assert.Collection(commandOrCodeActionContainer, e => { @@ -329,7 +325,6 @@ public async Task Handle_NewComponent_SupportsFileCreationTrue_ReturnsResult() var commandOrCodeActionContainer = await provider.ProvideAsync(context, default); // Assert - Assert.NotNull(commandOrCodeActionContainer); var command = Assert.Single(commandOrCodeActionContainer); Assert.Equal(LanguageServerSR.Create_Component_FromTag_Title, command.Title); Assert.NotNull(command.Data); @@ -361,7 +356,6 @@ public async Task Handle_NewComponent_CaretInAttribute_ReturnsResult() var commandOrCodeActionContainer = await provider.ProvideAsync(context, default); // Assert - Assert.NotNull(commandOrCodeActionContainer); var command = Assert.Single(commandOrCodeActionContainer); Assert.Equal(LanguageServerSR.Create_Component_FromTag_Title, command.Title); Assert.NotNull(command.Data); @@ -393,7 +387,6 @@ public async Task Handle_NewComponent_SupportsFileCreationFalse_ReturnsEmpty() var commandOrCodeActionContainer = await provider.ProvideAsync(context, default); // Assert - Assert.NotNull(commandOrCodeActionContainer); Assert.Empty(commandOrCodeActionContainer); } @@ -423,7 +416,6 @@ public async Task Handle_ExistingComponent_SupportsFileCreationFalse_ReturnsResu var commandOrCodeActionContainer = await provider.ProvideAsync(context, default); // Assert - Assert.NotNull(commandOrCodeActionContainer); Assert.Collection(commandOrCodeActionContainer, e => { diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/Razor/ExtractToCodeBehindCodeActionProviderTest.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/Razor/ExtractToCodeBehindCodeActionProviderTest.cs index 4b5b94fd9cb..51f71904390 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/Razor/ExtractToCodeBehindCodeActionProviderTest.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/Razor/ExtractToCodeBehindCodeActionProviderTest.cs @@ -53,7 +53,7 @@ public async Task Handle_InvalidFileKind() var commandOrCodeActionContainer = await provider.ProvideAsync(context, default); // Assert - Assert.Null(commandOrCodeActionContainer); + Assert.Empty(commandOrCodeActionContainer); } [Fact] @@ -83,7 +83,7 @@ public async Task Handle_OutsideCodeDirective() var commandOrCodeActionContainer = await provider.ProvideAsync(context, default); // Assert - Assert.Null(commandOrCodeActionContainer); + Assert.Empty(commandOrCodeActionContainer); } [Fact] @@ -113,7 +113,7 @@ public async Task Handle_InCodeDirectiveBlock_ReturnsNull() var commandOrCodeActionContainer = await provider.ProvideAsync(context, default); // Assert - Assert.Null(commandOrCodeActionContainer); + Assert.Empty(commandOrCodeActionContainer); } [Fact] @@ -143,7 +143,7 @@ public async Task Handle_InCodeDirectiveMalformed_ReturnsNull() var commandOrCodeActionContainer = await provider.ProvideAsync(context, default); // Assert - Assert.Null(commandOrCodeActionContainer); + Assert.Empty(commandOrCodeActionContainer); } [Fact] @@ -178,7 +178,7 @@ void Test() var commandOrCodeActionContainer = await provider.ProvideAsync(context, default); // Assert - Assert.Null(commandOrCodeActionContainer); + Assert.Empty(commandOrCodeActionContainer); } [Theory] @@ -219,7 +219,6 @@ public async Task Handle_InCodeDirective_SupportsFileCreationTrue_ReturnsResult( var commandOrCodeActionContainer = await provider.ProvideAsync(context, default); // Assert - Assert.NotNull(commandOrCodeActionContainer); var codeAction = Assert.Single(commandOrCodeActionContainer); var razorCodeActionResolutionParams = ((JsonElement)codeAction.Data!).Deserialize(); Assert.NotNull(razorCodeActionResolutionParams); @@ -263,7 +262,6 @@ public async Task Handle_AtEndOfCodeDirectiveWithNoSpace_ReturnsResult() var commandOrCodeActionContainer = await provider.ProvideAsync(context, default); // Assert - Assert.NotNull(commandOrCodeActionContainer); var codeAction = Assert.Single(commandOrCodeActionContainer); var razorCodeActionResolutionParams = ((JsonElement)codeAction.Data!).Deserialize(); Assert.NotNull(razorCodeActionResolutionParams); @@ -301,7 +299,7 @@ public async Task Handle_InCodeDirective_SupportsFileCreationFalse_ReturnsNull() var commandOrCodeActionContainer = await provider.ProvideAsync(context, default); // Assert - Assert.Null(commandOrCodeActionContainer); + Assert.Empty(commandOrCodeActionContainer); } [Fact] @@ -337,7 +335,6 @@ public async Task Handle_InFunctionsDirective_SupportsFileCreationTrue_ReturnsRe var commandOrCodeActionContainer = await provider.ProvideAsync(context, default); // Assert - Assert.NotNull(commandOrCodeActionContainer); var codeAction = Assert.Single(commandOrCodeActionContainer); var razorCodeActionResolutionParams = ((JsonElement)codeAction.Data!).Deserialize(); Assert.NotNull(razorCodeActionResolutionParams); @@ -375,7 +372,7 @@ public async Task Handle_NullRelativePath_ReturnsNull() var commandOrCodeActionContainer = await provider.ProvideAsync(context, default); // Assert - Assert.Null(commandOrCodeActionContainer); + Assert.Empty(commandOrCodeActionContainer); } private static RazorCodeActionContext CreateRazorCodeActionContext(VSCodeActionParams request, SourceLocation location, string filePath, string text, bool supportsFileCreation = true) diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/PooledObjects/QueuePool.Policy.cs b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/PooledObjects/QueuePool.Policy.cs new file mode 100644 index 00000000000..958d6361a6b --- /dev/null +++ b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/PooledObjects/QueuePool.Policy.cs @@ -0,0 +1,35 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT license. See License.txt in the project root for license information. + +using System.Collections.Generic; +using Microsoft.Extensions.ObjectPool; + +namespace Microsoft.AspNetCore.Razor.PooledObjects; + +internal static partial class QueuePool +{ + private class Policy : IPooledObjectPolicy> + { + public static readonly Policy Instance = new(); + + private Policy() + { + } + + public Queue Create() => new Queue(); + + public bool Return(Queue queue) + { + var count = queue.Count; + + queue.Clear(); + + if (count > DefaultPool.MaximumObjectSize) + { + queue.TrimExcess(); + } + + return true; + } + } +} diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/PooledObjects/QueuePool.cs b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/PooledObjects/QueuePool.cs new file mode 100644 index 00000000000..1b180a3b5ae --- /dev/null +++ b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/PooledObjects/QueuePool.cs @@ -0,0 +1,18 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT license. See License.txt in the project root for license information. + +using System.Collections.Generic; +using Microsoft.Extensions.ObjectPool; + +namespace Microsoft.AspNetCore.Razor.PooledObjects; + +internal static partial class QueuePool +{ + public static readonly ObjectPool> Default = DefaultPool.Create(Policy.Instance); + + public static PooledObject> GetPooledObject() + => Default.GetPooledObject(); + + public static PooledObject> GetPooledObject(out Queue queue) + => Default.GetPooledObject(out queue); +} From 91113cc9aba6bb112a94d6193829904c4490b146 Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Thu, 11 Jul 2024 09:08:57 -0700 Subject: [PATCH 049/176] Remove unused usings --- .../ImmutableArrayExtensions.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/ImmutableArrayExtensions.cs b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/ImmutableArrayExtensions.cs index 9bb9798a015..c750023359c 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/ImmutableArrayExtensions.cs +++ b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/ImmutableArrayExtensions.cs @@ -4,8 +4,6 @@ using System.Buffers; using System.Collections.Generic; using System.Runtime.InteropServices; -using System.Threading; -using Microsoft.AspNetCore.Razor; using Microsoft.AspNetCore.Razor.PooledObjects; namespace System.Collections.Immutable; From e4cfab9f53586ea20949e3d296600a6873225941 Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Thu, 11 Jul 2024 09:10:52 -0700 Subject: [PATCH 050/176] Don't bother ordering ImmutableArrays of length 1 --- .../ImmutableArrayExtensions.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/ImmutableArrayExtensions.cs b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/ImmutableArrayExtensions.cs index c750023359c..93407acd335 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/ImmutableArrayExtensions.cs +++ b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/ImmutableArrayExtensions.cs @@ -285,7 +285,7 @@ public int Compare(T? x, T? y) private static ImmutableArray OrderAsArrayCore(this ImmutableArray array, IComparer comparer) { - if (array.IsEmpty) + if (array.IsEmpty || array.Length == 1) { return array; } @@ -304,7 +304,7 @@ private static ImmutableArray OrderAsArrayCore(this ImmutableArray arra private static ImmutableArray OrderByAsArrayCore( this ImmutableArray array, Func keySelector, IComparer comparer) { - if (array.IsEmpty) + if (array.IsEmpty || array.Length == 1) { return array; } From 4f19d2fea2a86e1a6c4be312261a84ee10e90bde Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Thu, 11 Jul 2024 11:00:05 -0700 Subject: [PATCH 051/176] Improve perf of ImmutableArray Order* extension methods 1. Don't sort if the array has zero or 1 element. 2. Don't sort if the array or the keys are already ordered. 3. Avoid creating an `IComparer` until its time to actually sort Add tests for Comparison overloads --- .../ImmutableArrayExtensionsTests.cs | 156 ++++++--- .../ImmutableArrayExtensions.cs | 330 +++++++++++++++--- 2 files changed, 380 insertions(+), 106 deletions(-) diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared.Test/ImmutableArrayExtensionsTests.cs b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared.Test/ImmutableArrayExtensionsTests.cs index 5dd1f43216a..398fcbfae46 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared.Test/ImmutableArrayExtensionsTests.cs +++ b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared.Test/ImmutableArrayExtensionsTests.cs @@ -37,20 +37,23 @@ public void GetMostRecentUniqueItems() s => Assert.Equal("WoRlD", s)); } + private static Comparison OddBeforeEven + => (x, y) => (x % 2 != 0, y % 2 != 0) switch + { + (true, false) => -1, + (false, true) => 1, + _ => x.CompareTo(y) + }; + public static TheoryData, ImmutableArray> OrderAsArrayData - { - get + => new() { - return new() - { - { [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] }, - { [10, 9, 8, 7, 6, 5, 4, 3, 2, 1], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] }, - { [1, 3, 5, 7, 9, 2, 4, 6, 8, 10], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] }, - { [2, 5, 8, 1, 3, 9, 7, 4, 10, 6], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] }, - { [6, 10, 4, 7, 9, 3, 1, 8, 5, 2], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] }, - }; - } - } + { [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] }, + { [10, 9, 8, 7, 6, 5, 4, 3, 2, 1], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] }, + { [1, 3, 5, 7, 9, 2, 4, 6, 8, 10], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] }, + { [2, 5, 8, 1, 3, 9, 7, 4, 10, 6], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] }, + { [6, 10, 4, 7, 9, 3, 1, 8, 5, 2], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] }, + }; [Theory] [MemberData(nameof(OrderAsArrayData))] @@ -60,21 +63,34 @@ public void OrderAsArray(ImmutableArray data, ImmutableArray expected) Assert.Equal(expected, sorted); } - public static TheoryData, ImmutableArray> OrderDescendingAsArrayData - { - get + public static TheoryData, ImmutableArray> OrderAsArray_OddBeforeEvenData + => new() { - return new() - { - { [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [10, 9, 8, 7, 6, 5, 4, 3, 2, 1] }, - { [10, 9, 8, 7, 6, 5, 4, 3, 2, 1], [10, 9, 8, 7, 6, 5, 4, 3, 2, 1] }, - { [1, 3, 5, 7, 9, 2, 4, 6, 8, 10], [10, 9, 8, 7, 6, 5, 4, 3, 2, 1] }, - { [2, 5, 8, 1, 3, 9, 7, 4, 10, 6], [10, 9, 8, 7, 6, 5, 4, 3, 2, 1] }, - { [6, 10, 4, 7, 9, 3, 1, 8, 5, 2], [10, 9, 8, 7, 6, 5, 4, 3, 2, 1] }, - }; - } + { [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [1, 3, 5, 7, 9, 2, 4, 6, 8, 10] }, + { [10, 9, 8, 7, 6, 5, 4, 3, 2, 1], [1, 3, 5, 7, 9, 2, 4, 6, 8, 10] }, + { [1, 3, 5, 7, 9, 2, 4, 6, 8, 10], [1, 3, 5, 7, 9, 2, 4, 6, 8, 10] }, + { [2, 5, 8, 1, 3, 9, 7, 4, 10, 6], [1, 3, 5, 7, 9, 2, 4, 6, 8, 10] }, + { [6, 10, 4, 7, 9, 3, 1, 8, 5, 2], [1, 3, 5, 7, 9, 2, 4, 6, 8, 10] }, + }; + + [Theory] + [MemberData(nameof(OrderAsArray_OddBeforeEvenData))] + public void OrderAsArray_OddBeforeEven(ImmutableArray data, ImmutableArray expected) + { + var sorted = data.OrderAsArray(OddBeforeEven); + Assert.Equal(expected, sorted); } + public static TheoryData, ImmutableArray> OrderDescendingAsArrayData + => new() + { + { [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [10, 9, 8, 7, 6, 5, 4, 3, 2, 1] }, + { [10, 9, 8, 7, 6, 5, 4, 3, 2, 1], [10, 9, 8, 7, 6, 5, 4, 3, 2, 1] }, + { [1, 3, 5, 7, 9, 2, 4, 6, 8, 10], [10, 9, 8, 7, 6, 5, 4, 3, 2, 1] }, + { [2, 5, 8, 1, 3, 9, 7, 4, 10, 6], [10, 9, 8, 7, 6, 5, 4, 3, 2, 1] }, + { [6, 10, 4, 7, 9, 3, 1, 8, 5, 2], [10, 9, 8, 7, 6, 5, 4, 3, 2, 1] }, + }; + [Theory] [MemberData(nameof(OrderAsArrayData))] public void OrderDescendingAsArray(ImmutableArray data, ImmutableArray expected) @@ -83,6 +99,24 @@ public void OrderDescendingAsArray(ImmutableArray data, ImmutableArray Assert.Equal(expected, sorted); } + public static TheoryData, ImmutableArray> OrderDescendingAsArray_OddBeforeEvenData + => new() + { + { [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [10, 8, 6, 4, 2, 9, 7, 5, 3, 1] }, + { [10, 9, 8, 7, 6, 5, 4, 3, 2, 1], [10, 8, 6, 4, 2, 9, 7, 5, 3, 1] }, + { [1, 3, 5, 7, 9, 2, 4, 6, 8, 10], [10, 8, 6, 4, 2, 9, 7, 5, 3, 1] }, + { [2, 5, 8, 1, 3, 9, 7, 4, 10, 6], [10, 8, 6, 4, 2, 9, 7, 5, 3, 1] }, + { [6, 10, 4, 7, 9, 3, 1, 8, 5, 2], [10, 8, 6, 4, 2, 9, 7, 5, 3, 1] }, + }; + + [Theory] + [MemberData(nameof(OrderDescendingAsArray_OddBeforeEvenData))] + public void OrderDescendingAsArray_OddBeforeEven(ImmutableArray data, ImmutableArray expected) + { + var sorted = data.OrderDescendingAsArray(OddBeforeEven); + Assert.Equal(expected, sorted); + } + public readonly record struct ValueHolder(int Value) { public static implicit operator ValueHolder(int value) @@ -90,19 +124,14 @@ public static implicit operator ValueHolder(int value) } public static TheoryData, ImmutableArray> OrderByAsArrayData - { - get + => new() { - return new() - { - { [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] }, - { [10, 9, 8, 7, 6, 5, 4, 3, 2, 1], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] }, - { [1, 3, 5, 7, 9, 2, 4, 6, 8, 10], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] }, - { [2, 5, 8, 1, 3, 9, 7, 4, 10, 6], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] }, - { [6, 10, 4, 7, 9, 3, 1, 8, 5, 2], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] }, - }; - } - } + { [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] }, + { [10, 9, 8, 7, 6, 5, 4, 3, 2, 1], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] }, + { [1, 3, 5, 7, 9, 2, 4, 6, 8, 10], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] }, + { [2, 5, 8, 1, 3, 9, 7, 4, 10, 6], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] }, + { [6, 10, 4, 7, 9, 3, 1, 8, 5, 2], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] }, + }; [Theory] [MemberData(nameof(OrderByAsArrayData))] @@ -112,21 +141,34 @@ public void OrderByAsArray(ImmutableArray data, ImmutableArray(expected, sorted); } - public static TheoryData, ImmutableArray> OrderByDescendingAsArrayData - { - get + public static TheoryData, ImmutableArray> OrderByAsArray_OddBeforeEvenData + => new() { - return new() - { - { [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [10, 9, 8, 7, 6, 5, 4, 3, 2, 1] }, - { [10, 9, 8, 7, 6, 5, 4, 3, 2, 1], [10, 9, 8, 7, 6, 5, 4, 3, 2, 1] }, - { [1, 3, 5, 7, 9, 2, 4, 6, 8, 10], [10, 9, 8, 7, 6, 5, 4, 3, 2, 1] }, - { [2, 5, 8, 1, 3, 9, 7, 4, 10, 6], [10, 9, 8, 7, 6, 5, 4, 3, 2, 1] }, - { [6, 10, 4, 7, 9, 3, 1, 8, 5, 2], [10, 9, 8, 7, 6, 5, 4, 3, 2, 1] }, - }; - } + { [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [1, 3, 5, 7, 9, 2, 4, 6, 8, 10] }, + { [10, 9, 8, 7, 6, 5, 4, 3, 2, 1], [1, 3, 5, 7, 9, 2, 4, 6, 8, 10] }, + { [1, 3, 5, 7, 9, 2, 4, 6, 8, 10], [1, 3, 5, 7, 9, 2, 4, 6, 8, 10] }, + { [2, 5, 8, 1, 3, 9, 7, 4, 10, 6], [1, 3, 5, 7, 9, 2, 4, 6, 8, 10] }, + { [6, 10, 4, 7, 9, 3, 1, 8, 5, 2], [1, 3, 5, 7, 9, 2, 4, 6, 8, 10] }, + }; + + [Theory] + [MemberData(nameof(OrderByAsArray_OddBeforeEvenData))] + public void OrderByAsArray_OddBeforeEvent(ImmutableArray data, ImmutableArray expected) + { + var sorted = data.OrderByAsArray(static x => x.Value, OddBeforeEven); + Assert.Equal(expected, sorted); } + public static TheoryData, ImmutableArray> OrderByDescendingAsArrayData + => new() + { + { [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [10, 9, 8, 7, 6, 5, 4, 3, 2, 1] }, + { [10, 9, 8, 7, 6, 5, 4, 3, 2, 1], [10, 9, 8, 7, 6, 5, 4, 3, 2, 1] }, + { [1, 3, 5, 7, 9, 2, 4, 6, 8, 10], [10, 9, 8, 7, 6, 5, 4, 3, 2, 1] }, + { [2, 5, 8, 1, 3, 9, 7, 4, 10, 6], [10, 9, 8, 7, 6, 5, 4, 3, 2, 1] }, + { [6, 10, 4, 7, 9, 3, 1, 8, 5, 2], [10, 9, 8, 7, 6, 5, 4, 3, 2, 1] }, + }; + [Theory] [MemberData(nameof(OrderByDescendingAsArrayData))] public void OrderByDescendingAsArray(ImmutableArray data, ImmutableArray expected) @@ -134,4 +176,22 @@ public void OrderByDescendingAsArray(ImmutableArray data, Immutable var sorted = data.OrderByDescendingAsArray(static x => x.Value); Assert.Equal(expected, sorted); } + + public static TheoryData, ImmutableArray> OrderByDescendingAsArray_OddBeforeEvenData + => new() + { + { [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [10, 8, 6, 4, 2, 9, 7, 5, 3, 1] }, + { [10, 9, 8, 7, 6, 5, 4, 3, 2, 1], [10, 8, 6, 4, 2, 9, 7, 5, 3, 1] }, + { [1, 3, 5, 7, 9, 2, 4, 6, 8, 10], [10, 8, 6, 4, 2, 9, 7, 5, 3, 1] }, + { [2, 5, 8, 1, 3, 9, 7, 4, 10, 6], [10, 8, 6, 4, 2, 9, 7, 5, 3, 1] }, + { [6, 10, 4, 7, 9, 3, 1, 8, 5, 2], [10, 8, 6, 4, 2, 9, 7, 5, 3, 1] }, + }; + + [Theory] + [MemberData(nameof(OrderByDescendingAsArray_OddBeforeEvenData))] + public void OrderByDescendingAsArray_OddBeforeEven(ImmutableArray data, ImmutableArray expected) + { + var sorted = data.OrderByDescendingAsArray(static x => x.Value, OddBeforeEven); + Assert.Equal(expected, sorted); + } } diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/ImmutableArrayExtensions.cs b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/ImmutableArrayExtensions.cs index 93407acd335..29446206758 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/ImmutableArrayExtensions.cs +++ b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/ImmutableArrayExtensions.cs @@ -66,11 +66,11 @@ public static ImmutableArray SelectAsArray(this ImmutableAr { return source switch { - [] => [], - [var item] => [selector(item)], - [var item1, var item2] => [selector(item1), selector(item2)], - [var item1, var item2, var item3] => [selector(item1), selector(item2), selector(item3)], - [var item1, var item2, var item3, var item4] => [selector(item1), selector(item2), selector(item3), selector(item4)], + [] => [], + [var item] => [selector(item)], + [var item1, var item2] => [selector(item1), selector(item2)], + [var item1, var item2, var item3] => [selector(item1), selector(item2), selector(item3)], + [var item1, var item2, var item3, var item4] => [selector(item1), selector(item2), selector(item3), selector(item4)], var items => BuildResult(items, selector) }; @@ -209,121 +209,335 @@ public static int BinarySearchBy(this ImmutableArray array, TArg arg } public static ImmutableArray OrderAsArray(this ImmutableArray array) - => array.OrderAsArrayCore(GetComparer(comparer: null, descending: false)); + { + if (array.Length > 1) + { + var compareHelper = new CompareHelper(comparer: null, descending: false); + return array.OrderAsArrayCore(in compareHelper); + } + + return array; + } public static ImmutableArray OrderAsArray(this ImmutableArray array, IComparer comparer) - => array.OrderAsArrayCore(GetComparer(comparer, descending: false)); + { + if (array.Length > 1) + { + var compareHelper = new CompareHelper(comparer, descending: false); + return array.OrderAsArrayCore(in compareHelper); + } + + return array; + } public static ImmutableArray OrderAsArray(this ImmutableArray array, Comparison comparison) - => array.OrderAsArrayCore(GetComparer(comparison, descending: false)); + { + if (array.Length > 1) + { + var compareHelper = new CompareHelper(comparison, descending: false); + return array.OrderAsArrayCore(in compareHelper); + } + + return array; + } public static ImmutableArray OrderDescendingAsArray(this ImmutableArray array) - => array.OrderAsArrayCore(GetComparer(comparer: null, descending: true)); + { + if (array.Length > 1) + { + var compareHelper = new CompareHelper(comparer: null, descending: true); + return array.OrderAsArrayCore(in compareHelper); + } + + return array; + } public static ImmutableArray OrderDescendingAsArray(this ImmutableArray array, IComparer comparer) - => array.OrderAsArrayCore(GetComparer(comparer, descending: true)); + { + if (array.Length > 1) + { + var compareHelper = new CompareHelper(comparer, descending: true); + return array.OrderAsArrayCore(in compareHelper); + } + + return array; + } public static ImmutableArray OrderDescendingAsArray(this ImmutableArray array, Comparison comparison) - => array.OrderAsArrayCore(GetComparer(comparison, descending: true)); + { + if (array.Length > 1) + { + var compareHelper = new CompareHelper(comparison, descending: true); + return array.OrderAsArrayCore(in compareHelper); + } + + return array; + } public static ImmutableArray OrderByAsArray( this ImmutableArray array, Func keySelector) - => array.OrderByAsArrayCore(keySelector, GetComparer(comparer: null, descending: false)); + { + if (array.Length > 1) + { + var compareHelper = new CompareHelper(comparer: null, descending: false); + return array.OrderByAsArrayCore(keySelector, in compareHelper); + } + + return array; + } public static ImmutableArray OrderByAsArray( this ImmutableArray array, Func keySelector, IComparer comparer) - => array.OrderByAsArrayCore(keySelector, GetComparer(comparer, descending: false)); + { + if (array.Length > 1) + { + var compareHelper = new CompareHelper(comparer, descending: false); + return array.OrderByAsArrayCore(keySelector, in compareHelper); + } + + return array; + } public static ImmutableArray OrderByAsArray( this ImmutableArray array, Func keySelector, Comparison comparison) - => array.OrderByAsArrayCore(keySelector, GetComparer(comparison, descending: false)); + { + if (array.Length > 1) + { + var compareHelper = new CompareHelper(comparison, descending: false); + return array.OrderByAsArrayCore(keySelector, in compareHelper); + } + + return array; + } public static ImmutableArray OrderByDescendingAsArray( this ImmutableArray array, Func keySelector) - => array.OrderByAsArrayCore(keySelector, GetComparer(comparer: null, descending: true)); + { + if (array.Length > 1) + { + var compareHelper = new CompareHelper(comparer: null, descending: true); + return array.OrderByAsArrayCore(keySelector, in compareHelper); + } + + return array; + } public static ImmutableArray OrderByDescendingAsArray( this ImmutableArray array, Func keySelector, IComparer comparer) - => array.OrderByAsArrayCore(keySelector, GetComparer(comparer, descending: true)); + { + if (array.Length > 1) + { + var compareHelper = new CompareHelper(comparer, descending: true); + return array.OrderByAsArrayCore(keySelector, in compareHelper); + } + + return array; + } public static ImmutableArray OrderByDescendingAsArray( this ImmutableArray array, Func keySelector, Comparison comparison) - => array.OrderByAsArrayCore(keySelector, GetComparer(comparison, descending: true)); - - private static IComparer GetComparer(IComparer? comparer, bool descending) { - if (comparer is null) + if (array.Length > 1) { - return descending - ? DescendingComparer.Default - : Comparer.Default; + var compareHelper = new CompareHelper(comparison, descending: true); + return array.OrderByAsArrayCore(keySelector, in compareHelper); } - return descending - ? new DescendingComparer(comparer) - : comparer; + return array; } - private static IComparer GetComparer(Comparison comparison, bool descending) + private static ImmutableArray OrderAsArrayCore(this ImmutableArray array, ref readonly CompareHelper compareHelper) { - var comparer = Comparer.Create(comparison); + var items = array.AsSpan(); - return descending - ? new DescendingComparer(comparer) - : comparer; - } + if (AreOrdered(items, in compareHelper)) + { + // No need to sort - items are already ordered. + return array; + } - private sealed class DescendingComparer(IComparer comparer) : IComparer - { - private static IComparer? s_default; + var length = items.Length; + var newArray = new T[length]; + items.CopyTo(newArray); - public static IComparer Default => s_default ??= new DescendingComparer(Comparer.Default); + var comparer = compareHelper.GetOrCreateComparer(); - public int Compare(T? x, T? y) - => comparer.Compare(y!, x!); + Array.Sort(newArray, comparer); + + return ImmutableCollectionsMarshal.AsImmutableArray(newArray); } - private static ImmutableArray OrderAsArrayCore(this ImmutableArray array, IComparer comparer) + private static ImmutableArray OrderByAsArrayCore( + this ImmutableArray array, Func keySelector, ref readonly CompareHelper compareHelper) { - if (array.IsEmpty || array.Length == 1) + var items = array.AsSpan(); + var length = items.Length; + + using var _ = ArrayPool.Shared.GetPooledArray(minimumLength: length, out var keys); + + if (SelectKeys(items, keySelector, compareHelper, keys.AsSpan(0, length))) { + // No need to sort - keys are already ordered. return array; } - var span = array.AsSpan(); + var newArray = new TElement[length]; + items.CopyTo(newArray); - var length = span.Length; - var items = new T[length]; - span.CopyTo(items); + var comparer = compareHelper.GetOrCreateComparer(); - Array.Sort(items, comparer); + Array.Sort(keys, newArray, 0, length, comparer); - return ImmutableCollectionsMarshal.AsImmutableArray(items); + return ImmutableCollectionsMarshal.AsImmutableArray(newArray); } - private static ImmutableArray OrderByAsArrayCore( - this ImmutableArray array, Func keySelector, IComparer comparer) + /// + /// Walk through and determine whether they are already ordered using + /// the provided . + /// + /// + /// if the items are in order; otherwise . + /// + /// + /// When the items are already ordered, there's no need to perform a sort. + /// + private static bool AreOrdered(ReadOnlySpan items, ref readonly CompareHelper compareHelper) { - if (array.IsEmpty || array.Length == 1) + var isOutOfOrder = false; + + for (var i = 1; i < items.Length; i++) { - return array; + if (!compareHelper.InSortedOrder(items[i], items[i - 1])) + { + isOutOfOrder = true; + break; + } } - var span = array.AsSpan(); + return !isOutOfOrder; + } - var length = span.Length; - var items = new TElement[length]; - span.CopyTo(items); + /// + /// Walk through and convert each element to a key using . + /// While walking, each computed key is compared with the previous one using the provided + /// to determine whether they are already ordered. + /// + /// + /// if the keys are in order; otherwise . + /// + /// + /// When the keys are already ordered, there's no need to perform a sort. + /// + private static bool SelectKeys( + ReadOnlySpan items, Func keySelector, CompareHelper compareHelper, Span keys) + { + var isOutOfOrder = false; - using var _ = ArrayPool.Shared.GetPooledArray(minimumLength: length, out var keys); + keys[0] = keySelector(items[0]); - for (var i = 0; i < length; i++) + for (var i = 1; i < items.Length; i++) { keys[i] = keySelector(items[i]); + + if (!isOutOfOrder && !compareHelper.InSortedOrder(keys[i], keys[i - 1])) + { + isOutOfOrder = true; + + // Continue processing to finish converting elements to keys. However, we can stop comparing keys. + } } - Array.Sort(keys, items, 0, length, comparer); + return !isOutOfOrder; + } + + /// + /// Helper that avoids creating an until its needed. + /// + private readonly ref struct CompareHelper + { + private readonly IComparer _comparer; + private readonly Comparison _comparison; + private readonly bool _comparerSpecified; + private readonly bool _useComparer; + private readonly bool _descending; - return ImmutableCollectionsMarshal.AsImmutableArray(items); + public CompareHelper(IComparer? comparer, bool descending) + { + _comparerSpecified = comparer is not null; + _comparer = comparer ?? Comparer.Default; + _useComparer = true; + _descending = descending; + _comparison = null!; + } + + public CompareHelper(Comparison comparison, bool descending) + { + _comparison = comparison; + _useComparer = false; + _descending = descending; + _comparer = null!; + } + + public bool InSortedOrder(T? x, T? y) + { + // We assume that x and y are in sorted order if x is > y. + // We don't consider x == y to be sorted because the actual sor + // might not be stable, depending on T. + + return _useComparer + ? !_descending ? _comparer.Compare(x!, y!) > 0 : _comparer.Compare(y!, x!) > 0 + : !_descending ? _comparison(x!, y!) > 0 : _comparison(y!, x!) > 0; + } + + public IComparer GetOrCreateComparer() + // There are six cases to consider. + => (_useComparer, _comparerSpecified, _descending) switch + { + // Provided a comparer and the results are in ascending order. + (true, true, false) => _comparer, + + // Provided a comparer and the results are in descending order. + (true, true, true) => DescendingComparer.Create(_comparer), + + // Not provided a comparer and the results are in ascending order. + // In this case, _comparer was already set to Comparer.Default. + (true, false, false) => _comparer, + + // Not provided a comparer and the results are in descending order. + (true, false, true) => DescendingComparer.Default, + + // Provided a comparison delegate and the results are in ascending order. + (false, _, false) => Comparer.Create(_comparison), + + // Provided a comparison delegate and the results are in descending order. + (false, _, true) => DescendingComparer.Create(_comparison) + }; + } + + private abstract class DescendingComparer : IComparer + { + private static IComparer? s_default; + + public static IComparer Default => s_default ??= new WrappedComparer(Comparer.Default); + + public static IComparer Create(IComparer comparer) + => new WrappedComparer(comparer); + + public static IComparer Create(Comparison comparison) + => new WrappedComparison(comparison); + + public abstract int Compare(T? x, T? y); + + private sealed class WrappedComparer(IComparer comparer) : DescendingComparer + { + public override int Compare(T? x, T? y) + => comparer.Compare(y!, x!); + } + + private sealed class WrappedComparison(Comparison comparison) : DescendingComparer + { + public override int Compare(T? x, T? y) + => comparison(y!, x!); + } } } From ca16fcb387d03401d6ba740b5a5741b7cd8eebbd Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Thu, 11 Jul 2024 11:14:18 -0700 Subject: [PATCH 052/176] Fix indentation --- .../ImmutableArrayExtensions.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/ImmutableArrayExtensions.cs b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/ImmutableArrayExtensions.cs index 29446206758..d4dd11c7662 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/ImmutableArrayExtensions.cs +++ b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/ImmutableArrayExtensions.cs @@ -66,11 +66,11 @@ public static ImmutableArray SelectAsArray(this ImmutableAr { return source switch { - [] => [], - [var item] => [selector(item)], - [var item1, var item2] => [selector(item1), selector(item2)], - [var item1, var item2, var item3] => [selector(item1), selector(item2), selector(item3)], - [var item1, var item2, var item3, var item4] => [selector(item1), selector(item2), selector(item3), selector(item4)], + [] => [], + [var item] => [selector(item)], + [var item1, var item2] => [selector(item1), selector(item2)], + [var item1, var item2, var item3] => [selector(item1), selector(item2), selector(item3)], + [var item1, var item2, var item3, var item4] => [selector(item1), selector(item2), selector(item3), selector(item4)], var items => BuildResult(items, selector) }; From 9b1be711efc81504c21ffb3df9778d93ff1ee5dd Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Thu, 11 Jul 2024 12:06:21 -0700 Subject: [PATCH 053/176] Reorder parameters for IReadOnlyList extensions and move to shared --- .../Extensions/IReadOnlyListExtensions.cs | 58 ------------------- .../SourceGenerators/RazorSourceGenerator.cs | 6 +- .../ReadOnlyListExtensions.cs | 46 +++++++++++++++ 3 files changed, 50 insertions(+), 60 deletions(-) delete mode 100644 src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/Extensions/IReadOnlyListExtensions.cs diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/Extensions/IReadOnlyListExtensions.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/Extensions/IReadOnlyListExtensions.cs deleted file mode 100644 index 9dac69fe9cd..00000000000 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/Extensions/IReadOnlyListExtensions.cs +++ /dev/null @@ -1,58 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -#nullable disable - -using System; -using System.Collections.Generic; - -namespace Microsoft.AspNetCore.Razor.Language.Extensions; - -internal static class IReadOnlyListExtensions -{ - public static bool Any(this IReadOnlyList list, Func predicate, TArg arg) - { - if (list is null) - { - throw new ArgumentNullException(nameof(list)); - } - - if (predicate is null) - { - throw new ArgumentNullException(nameof(predicate)); - } - - for (var i = 0; i < list.Count; i++) - { - if (predicate(list[i], arg)) - { - return true; - } - } - - return false; - } - - public static bool All(this IReadOnlyList list, Func predicate, TArg arg) - { - if (list is null) - { - throw new ArgumentNullException(nameof(list)); - } - - if (predicate is null) - { - throw new ArgumentNullException(nameof(predicate)); - } - - for (var i = 0; i < list.Count; i++) - { - if (!predicate(list[i], arg)) - { - return false; - } - } - - return true; - } -} diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/SourceGenerators/RazorSourceGenerator.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/SourceGenerators/RazorSourceGenerator.cs index 2d30561712b..f7bdfb0310e 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/SourceGenerators/RazorSourceGenerator.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/SourceGenerators/RazorSourceGenerator.cs @@ -242,8 +242,10 @@ public void Initialize(IncrementalGeneratorInitializationContext context) { var compilation = CSharpCompilation.Create("components", references: refs); return compilation.GetTypesByMetadataName("Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder") - .Any(static (t, compilation) => t.DeclaredAccessibility == Accessibility.Public && - t.GetMembers("AddComponentParameter").Any(static m => m.DeclaredAccessibility == Accessibility.Public), compilation); + .Any(static t => + t.DeclaredAccessibility == Accessibility.Public && + t.GetMembers("AddComponentParameter") + .Any(static m => m.DeclaredAccessibility == Accessibility.Public)); }); IncrementalValuesProvider<(string, SourceGeneratorRazorCodeDocument)> processed(bool designTime) diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/ReadOnlyListExtensions.cs b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/ReadOnlyListExtensions.cs index 3cc2211eb70..33816476ce6 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/ReadOnlyListExtensions.cs +++ b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/ReadOnlyListExtensions.cs @@ -32,4 +32,50 @@ static ImmutableArray BuildResult(IReadOnlyList items, Func(this IReadOnlyList list, TArg arg, Func predicate) + { + if (list is null) + { + throw new ArgumentNullException(nameof(list)); + } + + if (predicate is null) + { + throw new ArgumentNullException(nameof(predicate)); + } + + for (var i = 0; i < list.Count; i++) + { + if (predicate(list[i], arg)) + { + return true; + } + } + + return false; + } + + public static bool All(this IReadOnlyList list, TArg arg, Func predicate) + { + if (list is null) + { + throw new ArgumentNullException(nameof(list)); + } + + if (predicate is null) + { + throw new ArgumentNullException(nameof(predicate)); + } + + for (var i = 0; i < list.Count; i++) + { + if (!predicate(list[i], arg)) + { + return false; + } + } + + return true; + } } From 9e49c20b4a64d31b2ae76bfd21d359bfc02ff2be Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Thu, 11 Jul 2024 12:07:48 -0700 Subject: [PATCH 054/176] Prefer collection expressions and remove argument null checks --- .../ReadOnlyListExtensions.cs | 30 ++++--------------- 1 file changed, 5 insertions(+), 25 deletions(-) diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/ReadOnlyListExtensions.cs b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/ReadOnlyListExtensions.cs index 33816476ce6..acee2b39f17 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/ReadOnlyListExtensions.cs +++ b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/ReadOnlyListExtensions.cs @@ -12,11 +12,11 @@ public static ImmutableArray SelectAsArray(this IReadOnlyLi { return source switch { - [] => ImmutableArray.Empty, - [var item] => ImmutableArray.Create(selector(item)), - [var item1, var item2] => ImmutableArray.Create(selector(item1), selector(item2)), - [var item1, var item2, var item3] => ImmutableArray.Create(selector(item1), selector(item2), selector(item3)), - [var item1, var item2, var item3, var item4] => ImmutableArray.Create(selector(item1), selector(item2), selector(item3), selector(item4)), + [] => [], + [var item] => [selector(item)], + [var item1, var item2] => [selector(item1), selector(item2)], + [var item1, var item2, var item3] => [selector(item1), selector(item2), selector(item3)], + [var item1, var item2, var item3, var item4] => [selector(item1), selector(item2), selector(item3), selector(item4)], var items => BuildResult(items, selector) }; @@ -35,16 +35,6 @@ static ImmutableArray BuildResult(IReadOnlyList items, Func(this IReadOnlyList list, TArg arg, Func predicate) { - if (list is null) - { - throw new ArgumentNullException(nameof(list)); - } - - if (predicate is null) - { - throw new ArgumentNullException(nameof(predicate)); - } - for (var i = 0; i < list.Count; i++) { if (predicate(list[i], arg)) @@ -58,16 +48,6 @@ public static bool Any(this IReadOnlyList list, TArg arg, Func(this IReadOnlyList list, TArg arg, Func predicate) { - if (list is null) - { - throw new ArgumentNullException(nameof(list)); - } - - if (predicate is null) - { - throw new ArgumentNullException(nameof(predicate)); - } - for (var i = 0; i < list.Count; i++) { if (!predicate(list[i], arg)) From a17a33a66fecf4e795f006d8a05fb52687f5cac4 Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Thu, 11 Jul 2024 12:31:36 -0700 Subject: [PATCH 055/176] Add other Any(...) and All(...) overloads for `IReadOnlyList` --- .../PooledObjects/PooledArrayBuilder`1.cs | 2 +- .../ReadOnlyListExtensions.cs | 147 +++++++++++++++++- .../Utilities/ThrowHelper.cs | 17 ++ 3 files changed, 161 insertions(+), 5 deletions(-) create mode 100644 src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Utilities/ThrowHelper.cs diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/PooledObjects/PooledArrayBuilder`1.cs b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/PooledObjects/PooledArrayBuilder`1.cs index 6e14fcbd52b..927fa4687b4 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/PooledObjects/PooledArrayBuilder`1.cs +++ b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/PooledObjects/PooledArrayBuilder`1.cs @@ -801,7 +801,7 @@ private static void ThrowIndexOutOfRangeException() ///
[DoesNotReturn] private static T ThrowInvalidOperation(string message) - => throw new InvalidOperationException(message); + => ThrowHelper.ThrowInvalidOperation(message); [MemberNotNull(nameof(_builder))] private void MoveInlineItemsToBuilder() diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/ReadOnlyListExtensions.cs b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/ReadOnlyListExtensions.cs index acee2b39f17..d5c4412e589 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/ReadOnlyListExtensions.cs +++ b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/ReadOnlyListExtensions.cs @@ -33,11 +33,65 @@ static ImmutableArray BuildResult(IReadOnlyList items, Func + /// Determines whether a list contains any elements. + ///
+ /// + /// The to check for emptiness. + /// + /// + /// if the list contains any elements; otherwise, . + /// + public static bool Any(this IReadOnlyList list) + => list.Count > 0; + + /// + /// Determines whether any element of a list satisfies a condition. + /// + /// + /// An whose elements to apply the predicate to. + /// + /// + /// A function to test each element for a condition. + /// + /// + /// if the list is not empty and at least one of its elements passes + /// the test in the specified predicate; otherwise, . + /// + public static bool Any(this IReadOnlyList list, Func predicate) + { + foreach (var item in list.AsEnumerable()) + { + if (predicate(item)) + { + return true; + } + } + + return false; + } + + /// + /// Determines whether any element of a list satisfies a condition. + /// + /// + /// An whose elements to apply the predicate to. + /// + /// + /// An argument to pass to . + /// + /// + /// A function to test each element for a condition. + /// + /// + /// if the list is not empty and at least one of its elements passes + /// the test in the specified predicate; otherwise, . + /// public static bool Any(this IReadOnlyList list, TArg arg, Func predicate) { - for (var i = 0; i < list.Count; i++) + foreach (var item in list.AsEnumerable()) { - if (predicate(list[i], arg)) + if (predicate(item, arg)) { return true; } @@ -46,11 +100,53 @@ public static bool Any(this IReadOnlyList list, TArg arg, Func + /// Determines whether all elements of a list satisfy a condition. + ///
+ /// + /// An whose elements to apply the predicate to. + /// + /// + /// A function to test each element for a condition. + /// + /// + /// if every element of the list passes the test + /// in the specified predicate, or if the list is empty; otherwise, + /// . + public static bool All(this IReadOnlyList list, Func predicate) + { + foreach (var item in list.AsEnumerable()) + { + if (!predicate(item)) + { + return false; + } + } + + return true; + } + + /// + /// Determines whether all elements of a list satisfy a condition. + /// + /// + /// An whose elements to apply the predicate to. + /// + /// + /// An argument to pass to . + /// + /// + /// A function to test each element for a condition. + /// + /// + /// if every element of the list passes the test + /// in the specified predicate, or if the list is empty; otherwise, + /// . public static bool All(this IReadOnlyList list, TArg arg, Func predicate) { - for (var i = 0; i < list.Count; i++) + foreach (var item in list.AsEnumerable()) { - if (!predicate(list[i], arg)) + if (!predicate(item, arg)) { return false; } @@ -58,4 +154,47 @@ public static bool All(this IReadOnlyList list, TArg arg, Func AsEnumerable(this IReadOnlyList source) => new(source); + + public readonly struct Enumerable(IReadOnlyList source) : IEnumerable + { + public Enumerator GetEnumerator() => new(source); + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + } + + public struct Enumerator(IReadOnlyList source) : IEnumerator + { + private int _index; + private T _current; + + public readonly T Current => _current!; + + readonly object IEnumerator.Current => _current!; + + public readonly void Dispose() + { + } + + public bool MoveNext() + { + if (_index < source.Count) + { + _current = source[_index]; + _index++; + return true; + } + + return false; + } + + public void Reset() + { + _index = 0; + _current = default!; + } + } } diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Utilities/ThrowHelper.cs b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Utilities/ThrowHelper.cs new file mode 100644 index 00000000000..1a78ee3a3d2 --- /dev/null +++ b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Utilities/ThrowHelper.cs @@ -0,0 +1,17 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT license. See License.txt in the project root for license information. + +using System; +using System.Diagnostics.CodeAnalysis; + +namespace Microsoft.AspNetCore.Razor.Utilities; + +internal static class ThrowHelper +{ + /// + /// This is present to help the JIT inline methods that need to throw an . + /// + [DoesNotReturn] + public static T ThrowInvalidOperation(string message) + => throw new InvalidOperationException(message); +} From 50b66b8932a350eef4f39122b0b92ac949c5113b Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Thu, 11 Jul 2024 13:31:52 -0700 Subject: [PATCH 056/176] Add First/Last/Single extension methods for IReadOnlyList This change adds `First()`, `FirstOrDefault()`, `Last()`, `LastOrDefault()`, Single()`, and `SingleOrDefault()` extension methods for `IReadOnlyList` along with a comprehensive set of overloads. In addition, I've added an `AsEnumerable()` that returns a struct that wraps `IReadOnlyList` with a struct enumerator. This makes it easy to foreach over an `IReadOnlyList` without allocating. --- .../ReadOnlyListExtensions.cs | 791 +++++++++++++++++- 1 file changed, 783 insertions(+), 8 deletions(-) diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/ReadOnlyListExtensions.cs b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/ReadOnlyListExtensions.cs index d5c4412e589..ee5f9773b50 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/ReadOnlyListExtensions.cs +++ b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/ReadOnlyListExtensions.cs @@ -3,6 +3,7 @@ using System.Collections.Immutable; using Microsoft.AspNetCore.Razor.PooledObjects; +using Microsoft.AspNetCore.Razor.Utilities; namespace System.Collections.Generic; @@ -155,21 +156,746 @@ public static bool All(this IReadOnlyList list, TArg arg, Func AsEnumerable(this IReadOnlyList source) => new(source); + /// + /// Returns the first element of a list. + /// + /// + /// An to return the first element of. + /// + /// + /// The first element in the specified list. + /// + /// + /// The list is empty. + /// + public static T First(this IReadOnlyList list) + => list.Count > 0 ? list[0] : ThrowHelper.ThrowInvalidOperation(SR.Contains_no_elements); - public readonly struct Enumerable(IReadOnlyList source) : IEnumerable + /// + /// Returns the first element in a list that satisfies a specified condition. + /// + /// + /// An to return an element from. + /// + /// + /// A function to test each element for a condition. + /// + /// + /// The first element in the list that passes the test in the specified predicate function. + /// + /// + /// No element satisfies the condition in . + /// + public static T First(this IReadOnlyList list, Func predicate) + { + foreach (var item in list.AsEnumerable()) + { + if (predicate(item)) + { + return item; + } + } + + return ThrowHelper.ThrowInvalidOperation(SR.Contains_no_matching_elements); + } + + /// + /// Returns the first element in a list that satisfies a specified condition. + /// + /// + /// An to return an element from. + /// + /// + /// An argument to pass to . + /// + /// + /// A function to test each element for a condition. + /// + /// + /// The first element in the list that passes the test in the specified predicate function. + /// + /// + /// No element satisfies the condition in . + /// + public static T First(this IReadOnlyList list, TArg arg, Func predicate) { - public Enumerator GetEnumerator() => new(source); + foreach (var item in list.AsEnumerable()) + { + if (predicate(item, arg)) + { + return item; + } + } + + return ThrowHelper.ThrowInvalidOperation(SR.Contains_no_matching_elements); + } + + /// + /// Returns the first element of a list, or a default value if no element is found. + /// + /// + /// An to return the first element of. + /// + /// + /// () if is empty; otherwise, + /// the first element in . + /// + public static T? FirstOrDefault(this IReadOnlyList list) + => list.Count > 0 ? list[0] : default; + + /// + /// Returns the first element of a list, or a specified default value if the list contains no elements. + /// + /// + /// An to return the first element of. + /// + /// + /// The default value to return if the list is empty + /// + /// + /// if is empty; otherwise, + /// the first element in . + /// + public static T FirstOrDefault(this IReadOnlyList list, T defaultValue) + => list.Count > 0 ? list[0] : defaultValue; + + /// + /// Returns the first element of the list that satisfies a condition or a default value if no such element is found. + /// + /// + /// An to return an element from. + /// + /// + /// A function to test each element for a condition. + /// + /// + /// () if is empty or if no element + /// passes the test specified by ; otherwise, the first element in + /// that passes the test specified by . + /// + public static T? FirstOrDefault(this IReadOnlyList list, Func predicate) + { + foreach (var item in list.AsEnumerable()) + { + if (predicate(item)) + { + return item; + } + } + + return default; + } + + /// + /// Returns the first element of the list that satisfies a condition or a default value if no such element is found. + /// + /// + /// An to return an element from. + /// + /// + /// An argument to pass to . + /// + /// + /// A function to test each element for a condition. + /// + /// + /// () if is empty or if no element + /// passes the test specified by ; otherwise, the first element in + /// that passes the test specified by . + /// + public static T? FirstOrDefault(this IReadOnlyList list, TArg arg, Func predicate) + { + foreach (var item in list.AsEnumerable()) + { + if (predicate(item, arg)) + { + return item; + } + } + + return default; + } + + /// + /// Returns the last element of a list. + /// + /// + /// An to return the last element of. + /// + /// + /// The value at the last position in the list. + /// + /// + /// The list is empty. + /// + public static T Last(this IReadOnlyList list) + => list.Count > 0 ? list[^1] : ThrowHelper.ThrowInvalidOperation(SR.Contains_no_elements); + + /// + /// Returns the last element of a list that satisfies a specified condition. + /// + /// + /// An to return an element from. + /// + /// + /// A function to test each element for a condition. + /// + /// + /// The last element in the list that passes the test in the specified predicate function. + /// + /// + /// No element satisfies the condition in . + /// + public static T Last(this IReadOnlyList list, Func predicate) + { + foreach (var item in list.AsEnumerable().Reverse()) + { + if (predicate(item)) + { + return item; + } + } + + return ThrowHelper.ThrowInvalidOperation(SR.Contains_no_matching_elements); + } + + /// + /// Returns the last element of a list that satisfies a specified condition. + /// + /// + /// An to return an element from. + /// + /// + /// An argument to pass to . + /// + /// + /// A function to test each element for a condition. + /// + /// + /// The last element in the list that passes the test in the specified predicate function. + /// + /// + /// No element satisfies the condition in . + /// + public static T Last(this IReadOnlyList list, TArg arg, Func predicate) + { + foreach (var item in list.AsEnumerable().Reverse()) + { + if (predicate(item, arg)) + { + return item; + } + } + + return ThrowHelper.ThrowInvalidOperation(SR.Contains_no_matching_elements); + } + + /// + /// Returns the last element of a list, or a default value if the list contains no elements. + /// + /// + /// An to return the last element of. + /// + /// + /// () if is empty; otherwise, + /// the last element in . + /// + public static T? LastOrDefault(this IReadOnlyList list) + => list.Count > 0 ? list[^1] : default; + + /// + /// Returns the last element of a list, or a specified default value if the list contains no elements. + /// + /// + /// An to return the last element of. + /// + /// + /// The default value to return if the list is empty + /// + /// + /// if is empty; otherwise, + /// the last element in . + /// + public static T LastOrDefault(this IReadOnlyList list, T defaultValue) + => list.Count > 0 ? list[^1] : defaultValue; + + /// + /// Returns the last element of a list that satisfies a condition or a default value if no such element is found. + /// + /// + /// An to return an element from. + /// + /// + /// A function to test each element for a condition. + /// + /// + /// () if is empty or if no element + /// passes the test specified by ; otherwise, the last element in + /// that passes the test specified by . + /// + public static T? LastOrDefault(this IReadOnlyList list, Func predicate) + { + foreach (var item in list.AsEnumerable().Reverse()) + { + if (predicate(item)) + { + return item; + } + } + + return default; + } + + /// + /// Returns the last element of a list that satisfies a condition or a default value if no such element is found. + /// + /// + /// An to return an element from. + /// + /// + /// An argument to pass to . + /// + /// + /// A function to test each element for a condition. + /// + /// + /// () if is empty or if no element + /// passes the test specified by ; otherwise, the last element in + /// that passes the test specified by . + /// + public static T? LastOrDefault(this IReadOnlyList list, TArg arg, Func predicate) + { + foreach (var item in list.AsEnumerable().Reverse()) + { + if (predicate(item, arg)) + { + return item; + } + } + + return default; + } + + /// + /// Returns the last element of a list that satisfies a condition, or a specified default value if no such element is found. + /// + /// + /// An to return an element from. + /// + /// + /// A function to test each element for a condition. + /// + /// + /// The default value to return if the list is empty. + /// + /// + /// if is empty or if no element + /// passes the test specified by ; otherwise, the last element in + /// that passes the test specified by . + /// + public static T LastOrDefault(this IReadOnlyList list, Func predicate, T defaultValue) + { + foreach (var item in list.AsEnumerable().Reverse()) + { + if (predicate(item)) + { + return item; + } + } + + return defaultValue; + } + + /// + /// Returns the last element of a list that satisfies a condition, or a specified default value if no such element is found. + /// + /// + /// An to return an element from. + /// + /// + /// An argument to pass to . + /// + /// + /// A function to test each element for a condition. + /// + /// + /// The default value to return if the list is empty. + /// + /// + /// if is empty or if no element + /// passes the test specified by ; otherwise, the last element in + /// that passes the test specified by . + /// + public static T LastOrDefault(this IReadOnlyList list, TArg arg, Func predicate, T defaultValue) + { + foreach (var item in list.AsEnumerable().Reverse()) + { + if (predicate(item, arg)) + { + return item; + } + } + + return defaultValue; + } + + /// + /// Returns the only element of a list, and throws an exception if there is not exactly one element in the list. + /// + /// + /// An to return the single element of. + /// + /// + /// The single element of the list. + /// + /// + /// The list is empty. + /// + /// + /// The list contains more than one element. + /// + public static T Single(this IReadOnlyList list) + { + return list.Count switch + { + 1 => list[0], + 0 => ThrowHelper.ThrowInvalidOperation(SR.Contains_no_elements), + _ => ThrowHelper.ThrowInvalidOperation(SR.Contains_more_than_one_element) + }; + } + + /// + /// Returns the only element of a list that satisfies a specified condition, + /// and throws an exception if more than one such element exists. + /// + /// + /// An to return a single element from. + /// + /// + /// A function to test an element for a condition. + /// + /// + /// The single element of the list that satisfies a condition. + /// + /// + /// No element satisfies the condition in . + /// + /// + /// More than one element satisfies the condition in . + /// + public static T Single(this IReadOnlyList list, Func predicate) + { + var firstSeen = false; + T? result = default; + + foreach (var item in list.AsEnumerable()) + { + if (predicate(item)) + { + if (firstSeen) + { + return ThrowHelper.ThrowInvalidOperation(SR.Contains_more_than_one_matching_element); + } + + firstSeen = true; + result = item; + } + } + + if (!firstSeen) + { + return ThrowHelper.ThrowInvalidOperation(SR.Contains_no_matching_elements); + } + + return result!; + } + + /// + /// Returns the only element of a list that satisfies a specified condition, + /// and throws an exception if more than one such element exists. + /// + /// + /// An to return a single element from. + /// + /// + /// An argument to pass to . + /// + /// + /// A function to test an element for a condition. + /// + /// + /// The single element of the list that satisfies a condition. + /// + /// + /// No element satisfies the condition in . + /// + /// + /// More than one element satisfies the condition in . + /// + public static T Single(this IReadOnlyList list, TArg arg, Func predicate) + { + var firstSeen = false; + T? result = default; + + foreach (var item in list.AsEnumerable()) + { + if (predicate(item, arg)) + { + if (firstSeen) + { + return ThrowHelper.ThrowInvalidOperation(SR.Contains_more_than_one_matching_element); + } + + firstSeen = true; + result = item; + } + } + + if (!firstSeen) + { + return ThrowHelper.ThrowInvalidOperation(SR.Contains_no_matching_elements); + } + + return result!; + } + + /// + /// Returns the only element of a list, or a default value if the list is empty; + /// this method throws an exception if there is more than one element in the list. + /// + /// + /// An to return the single element of. + /// + /// + /// The single element in the list, or () + /// if the list contains no elements. + /// + /// + /// The list contains more than one element. + /// + public static T? SingleOrDefault(this IReadOnlyList list) + { + return list.Count switch + { + 1 => list[0], + 0 => default, + _ => ThrowHelper.ThrowInvalidOperation(SR.Contains_more_than_one_element) + }; + } + + /// + /// Returns the only element of a list, or a specified default value if the list is empty; + /// this method throws an exception if there is more than one element in the list. + /// + /// + /// An to return the single element of. + /// + /// + /// The default value to return if the list is empty + /// + /// + /// The single element in the list, or + /// if the list contains no elements. + /// + /// + /// The list contains more than one element. + /// + public static T SingleOrDefault(this IReadOnlyList list, T defaultValue) + { + return list.Count switch + { + 1 => list[0], + 0 => defaultValue, + _ => ThrowHelper.ThrowInvalidOperation(SR.Contains_more_than_one_element) + }; + } + + /// + /// Returns the only element of a list that satisfies a specified condition or a default value + /// if no such element exists; this method throws an exception if more than one element satisfies the condition. + /// + /// + /// An to return a single element from. + /// + /// + /// A function to test an element for a condition. + /// + /// + /// The single element of the list that satisfies the condition, or + /// () if no such element is found. + /// + /// + /// More than one element satisfies the condition in . + /// + public static T? SingleOrDefault(this IReadOnlyList list, Func predicate) + { + var firstSeen = false; + T? result = default; + + foreach (var item in list.AsEnumerable()) + { + if (predicate(item)) + { + if (firstSeen) + { + return ThrowHelper.ThrowInvalidOperation(SR.Contains_more_than_one_matching_element); + } + + firstSeen = true; + result = item; + } + } + + return result; + } + + /// + /// Returns the only element of a list that satisfies a specified condition or a default value + /// if no such element exists; this method throws an exception if more than one element satisfies the condition. + /// + /// + /// An to return a single element from. + /// + /// + /// An argument to pass to . + /// + /// + /// A function to test an element for a condition. + /// + /// + /// The single element of the list that satisfies the condition, or + /// () if no such element is found. + /// + /// + /// More than one element satisfies the condition in . + /// + public static T? SingleOrDefault(this IReadOnlyList list, TArg arg, Func predicate) + { + var firstSeen = false; + T? result = default; + + foreach (var item in list.AsEnumerable()) + { + if (predicate(item, arg)) + { + if (firstSeen) + { + return ThrowHelper.ThrowInvalidOperation(SR.Contains_more_than_one_matching_element); + } + + firstSeen = true; + result = item; + } + } + + return result; + } + + /// + /// Returns the only element of a list that satisfies a specified condition, or a specified default value + /// if no such element exists; this method throws an exception if more than one element satisfies the condition. + /// + /// + /// An to return a single element from. + /// + /// + /// A function to test an element for a condition. + /// + /// + /// The default value to return if the list is empty. + /// + /// + /// The single element of the list that satisfies the condition, or + /// if no such element is found. + /// + /// + /// More than one element satisfies the condition in . + /// + public static T SingleOrDefault(this IReadOnlyList list, Func predicate, T defaultValue) + { + var firstSeen = false; + var result = defaultValue; + + foreach (var item in list.AsEnumerable()) + { + if (predicate(item)) + { + if (firstSeen) + { + return ThrowHelper.ThrowInvalidOperation(SR.Contains_more_than_one_matching_element); + } + + firstSeen = true; + result = item; + } + } + + return result; + } + + /// + /// Returns the only element of a list that satisfies a specified condition, or a specified default value + /// if no such element exists; this method throws an exception if more than one element satisfies the condition. + /// + /// + /// An to return a single element from. + /// + /// + /// An argument to pass to . + /// + /// + /// A function to test an element for a condition. + /// + /// + /// The default value to return if the list is empty. + /// + /// + /// The single element of the list that satisfies the condition, or + /// if no such element is found. + /// + /// + /// More than one element satisfies the condition in . + /// + public static T SingleOrDefault(this IReadOnlyList list, TArg arg, Func predicate, T defaultValue) + { + var firstSeen = false; + var result = defaultValue; + + foreach (var item in list.AsEnumerable()) + { + if (predicate(item, arg)) + { + if (firstSeen) + { + return ThrowHelper.ThrowInvalidOperation(SR.Contains_more_than_one_matching_element); + } + + firstSeen = true; + result = item; + } + } + + return result; + } + + public static Enumerable AsEnumerable(this IReadOnlyList list) => new(list); + + public readonly struct Enumerable(IReadOnlyList list) : IEnumerable + { + public Enumerator GetEnumerator() => new(list); IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + public ReverseEnumerable Reverse() => new(list); } - public struct Enumerator(IReadOnlyList source) : IEnumerator + public struct Enumerator(IReadOnlyList list) : IEnumerator { - private int _index; - private T _current; + private readonly IReadOnlyList _list = list; + private int _index = 0; + private T _current = default!; public readonly T Current => _current!; @@ -181,9 +907,9 @@ public readonly void Dispose() public bool MoveNext() { - if (_index < source.Count) + if (_index < _list.Count) { - _current = source[_index]; + _current = _list[_index]; _index++; return true; } @@ -197,4 +923,53 @@ public void Reset() _current = default!; } } + + public readonly struct ReverseEnumerable(IReadOnlyList list) : IEnumerable + { + public ReverseEnumerator GetEnumerator() => new(list); + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + } + + public struct ReverseEnumerator : IEnumerator + { + private readonly IReadOnlyList _list; + private int _index; + private T _current; + + public readonly T Current => _current!; + + readonly object IEnumerator.Current => _current!; + + public ReverseEnumerator(IReadOnlyList list) + { + _list = list; + _index = _list.Count - 1; + _current = default!; + } + + public readonly void Dispose() + { + } + + public bool MoveNext() + { + if (_index >= 0) + { + _current = _list[_index]; + _index--; + return true; + } + + return false; + } + + public void Reset() + { + _index = _list.Count - 1; + _current = default!; + } + } } From 1cfff80b7a8ac3138c6e1d56bfcc3cf3d9f4fb89 Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Thu, 11 Jul 2024 13:42:41 -0700 Subject: [PATCH 057/176] Add unit tests for ReadOnlyListExtensions --- .../ReadOnlyListExtensions.cs | 186 ++++++++++++++++++ 1 file changed, 186 insertions(+) create mode 100644 src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared.Test/ReadOnlyListExtensions.cs diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared.Test/ReadOnlyListExtensions.cs b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared.Test/ReadOnlyListExtensions.cs new file mode 100644 index 00000000000..29aabbf892f --- /dev/null +++ b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared.Test/ReadOnlyListExtensions.cs @@ -0,0 +1,186 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT license. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using Xunit; +using SR = Microsoft.AspNetCore.Razor.Utilities.Shared.Resources.SR; + +namespace Microsoft.AspNetCore.Razor.Utilities.Shared.Test; + +public class ReadOnlyListExtensionsTest +{ + private static Func IsEven => x => x % 2 == 0; + private static Func IsOdd => x => x % 2 != 0; + + [Fact] + public void Any() + { + var list = new List(); + var readOnlyList = (IReadOnlyList)list; + + Assert.False(readOnlyList.Any()); + + list.Add(19); + + Assert.True(readOnlyList.Any()); + + list.Add(23); + + Assert.True(readOnlyList.Any(IsOdd)); + + // ... but no even numbers + Assert.False(readOnlyList.Any(IsEven)); + } + + [Fact] + public void All() + { + var list = new List(); + var readOnlyList = (IReadOnlyList)list; + + Assert.True(readOnlyList.All(IsEven)); + + list.Add(19); + + Assert.False(readOnlyList.All(IsEven)); + + list.Add(23); + + Assert.True(readOnlyList.All(IsOdd)); + + list.Add(42); + + Assert.False(readOnlyList.All(IsOdd)); + } + + [Fact] + public void FirstAndLast() + { + var list = new List(); + var readOnlyList = (IReadOnlyList)list; + + var exception1 = Assert.Throws(() => readOnlyList.First()); + Assert.Equal(SR.Contains_no_elements, exception1.Message); + + Assert.Equal(default, readOnlyList.FirstOrDefault()); + + var exception2 = Assert.Throws(() => readOnlyList.Last()); + Assert.Equal(SR.Contains_no_elements, exception1.Message); + + Assert.Equal(default, readOnlyList.LastOrDefault()); + + list.Add(19); + + Assert.Equal(19, readOnlyList.First()); + Assert.Equal(19, readOnlyList.FirstOrDefault()); + Assert.Equal(19, readOnlyList.Last()); + Assert.Equal(19, readOnlyList.LastOrDefault()); + + list.Add(23); + + Assert.Equal(19, readOnlyList.First()); + Assert.Equal(19, readOnlyList.FirstOrDefault()); + Assert.Equal(23, readOnlyList.Last()); + Assert.Equal(23, readOnlyList.LastOrDefault()); + } + + [Fact] + public void FirstAndLastWithPredicate() + { + var list = new List(); + var readOnlyList = (IReadOnlyList)list; + + var exception1 = Assert.Throws(() => readOnlyList.First(IsOdd)); + Assert.Equal(SR.Contains_no_matching_elements, exception1.Message); + + Assert.Equal(default, readOnlyList.FirstOrDefault(IsOdd)); + + var exception2 = Assert.Throws(() => readOnlyList.Last(IsOdd)); + Assert.Equal(SR.Contains_no_matching_elements, exception2.Message); + + Assert.Equal(default, readOnlyList.LastOrDefault(IsOdd)); + + list.Add(19); + + Assert.Equal(19, readOnlyList.First(IsOdd)); + Assert.Equal(19, readOnlyList.FirstOrDefault(IsOdd)); + Assert.Equal(19, readOnlyList.Last(IsOdd)); + Assert.Equal(19, readOnlyList.LastOrDefault(IsOdd)); + + list.Add(23); + + Assert.Equal(19, readOnlyList.First(IsOdd)); + Assert.Equal(19, readOnlyList.FirstOrDefault(IsOdd)); + Assert.Equal(23, readOnlyList.Last(IsOdd)); + Assert.Equal(23, readOnlyList.LastOrDefault(IsOdd)); + + var exception3 = Assert.Throws(() => readOnlyList.First(IsEven)); + Assert.Equal(SR.Contains_no_matching_elements, exception3.Message); + + Assert.Equal(default, readOnlyList.FirstOrDefault(IsEven)); + + var exception4 = Assert.Throws(() => readOnlyList.Last(IsEven)); + Assert.Equal(SR.Contains_no_matching_elements, exception4.Message); + + Assert.Equal(default, readOnlyList.LastOrDefault(IsEven)); + + list.Add(42); + + Assert.Equal(42, readOnlyList.First(IsEven)); + Assert.Equal(42, readOnlyList.FirstOrDefault(IsEven)); + Assert.Equal(42, readOnlyList.Last(IsEven)); + Assert.Equal(42, readOnlyList.LastOrDefault(IsEven)); + } + + [Fact] + public void Single() + { + var list = new List(); + var readOnlyList = (IReadOnlyList)list; + + var exception1 = Assert.Throws(() => readOnlyList.Single()); + Assert.Equal(SR.Contains_no_elements, exception1.Message); + Assert.Equal(default, readOnlyList.SingleOrDefault()); + + list.Add(19); + + Assert.Equal(19, readOnlyList.Single()); + Assert.Equal(19, readOnlyList.SingleOrDefault()); + + list.Add(23); + + var exception2 = Assert.Throws(() => readOnlyList.Single()); + Assert.Equal(SR.Contains_more_than_one_element, exception2.Message); + var exception3 = Assert.Throws(() => readOnlyList.SingleOrDefault()); + Assert.Equal(SR.Contains_more_than_one_element, exception2.Message); + } + + [Fact] + public void SingleWithPredicate() + { + var list = new List(); + var readOnlyList = (IReadOnlyList)list; + + var exception1 = Assert.Throws(() => readOnlyList.Single(IsOdd)); + Assert.Equal(SR.Contains_no_matching_elements, exception1.Message); + Assert.Equal(default, readOnlyList.SingleOrDefault(IsOdd)); + + list.Add(19); + + Assert.Equal(19, readOnlyList.Single(IsOdd)); + Assert.Equal(19, readOnlyList.SingleOrDefault(IsOdd)); + + list.Add(23); + + var exception2 = Assert.Throws(() => readOnlyList.Single(IsOdd)); + Assert.Equal(SR.Contains_more_than_one_matching_element, exception2.Message); + var exception3 = Assert.Throws(() => readOnlyList.SingleOrDefault(IsOdd)); + Assert.Equal(SR.Contains_more_than_one_matching_element, exception2.Message); + + list.Add(42); + + Assert.Equal(42, readOnlyList.Single(IsEven)); + Assert.Equal(42, readOnlyList.SingleOrDefault(IsEven)); + } +} From 5deabb014ca133286cb12ef72a406b81bc1f650e Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Thu, 11 Jul 2024 13:50:09 -0700 Subject: [PATCH 058/176] Add TArg-variant overloads to LINQ-style methods in PooledArrayBuilder --- .../PooledObjects/PooledArrayBuilder`1.cs | 252 ++++++++++++++++++ 1 file changed, 252 insertions(+) diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/PooledObjects/PooledArrayBuilder`1.cs b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/PooledObjects/PooledArrayBuilder`1.cs index 927fa4687b4..584eb22ed8f 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/PooledObjects/PooledArrayBuilder`1.cs +++ b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/PooledObjects/PooledArrayBuilder`1.cs @@ -497,6 +497,32 @@ public readonly bool Any(Func predicate) return false; } + /// + /// Determines whether any element in this builder satisfies a condition. + /// + /// + /// An argument to pass to . + /// + /// + /// A function to test each element for a condition. + /// + /// + /// if this builder is not empty and at least one of its elements passes + /// the test in the specified predicate; otherwise, . + /// + public readonly bool Any(TArg arg, Func predicate) + { + foreach (var item in this) + { + if (predicate(item, arg)) + { + return true; + } + } + + return false; + } + /// /// Determines whether all elements in this builder satisfy a condition. /// @@ -520,6 +546,32 @@ public readonly bool All(Func predicate) return true; } + /// + /// Determines whether all elements in this builder satisfy a condition. + /// + /// + /// An argument to pass to . + /// + /// + /// A function to test each element for a condition. + /// + /// + /// if every element in this builder passes the test + /// in the specified predicate, or if the builder is empty; otherwise, + /// . + public readonly bool All(TArg arg, Func predicate) + { + foreach (var item in this) + { + if (!predicate(item, arg)) + { + return false; + } + } + + return true; + } + /// /// Returns the first element in this builder. /// @@ -557,6 +609,34 @@ public readonly T First(Func predicate) return ThrowInvalidOperation(SR.Contains_no_matching_elements); } + /// + /// Returns the first element in this builder that satisfies a specified condition. + /// + /// + /// An argument to pass to . + /// + /// + /// A function to test each element for a condition. + /// + /// + /// The first element in this builder that passes the test in the specified predicate function. + /// + /// + /// No element satisfies the condition in . + /// + public readonly T First(TArg arg, Func predicate) + { + foreach (var item in this) + { + if (predicate(item, arg)) + { + return item; + } + } + + return ThrowInvalidOperation(SR.Contains_no_matching_elements); + } + /// /// Returns the first element in this builder, or a default value if the builder is empty. /// @@ -592,6 +672,34 @@ public readonly T First(Func predicate) return default; } + /// + /// Returns the first element in this builder that satisfies a condition, or a default value + /// if no such element is found. + /// + /// + /// An argument to pass to . + /// + /// + /// A function to test each element for a condition. + /// + /// + /// () if this builder is empty or if no element + /// passes the test specified by ; otherwise, the first element in this + /// builder that passes the test specified by . + /// + public readonly T? FirstOrDefault(TArg arg, Func predicate) + { + foreach (var item in this) + { + if (predicate(item, arg)) + { + return item; + } + } + + return default; + } + /// /// Returns the last element in this builder. /// @@ -630,6 +738,35 @@ public readonly T Last(Func predicate) return ThrowInvalidOperation(SR.Contains_no_matching_elements); } + /// + /// Returns the last element in this builder that satisfies a specified condition. + /// + /// + /// An argument to pass to . + /// + /// + /// A function to test each element for a condition. + /// + /// + /// The last element in this builder that passes the test in the specified predicate function. + /// + /// + /// No element satisfies the condition in . + /// + public readonly T Last(TArg arg, Func predicate) + { + for (var i = Count - 1; i >= 0; i--) + { + var item = this[i]; + if (predicate(item, arg)) + { + return item; + } + } + + return ThrowInvalidOperation(SR.Contains_no_matching_elements); + } + /// /// Returns the last element in this builder, or a default value if the builder is empty. /// @@ -666,6 +803,35 @@ public readonly T Last(Func predicate) return default; } + /// + /// Returns the last element in this builder that satisfies a condition, or a default value + /// if no such element is found. + /// + /// + /// An argument to pass to . + /// + /// + /// A function to test each element for a condition. + /// + /// + /// () if this builder is empty or if no element + /// passes the test specified by ; otherwise, the last element in this + /// builder that passes the test specified by . + /// + public readonly T? LastOrDefault(TArg arg, Func predicate) + { + for (var i = Count - 1; i >= 0; i--) + { + var item = this[i]; + if (predicate(item, arg)) + { + return item; + } + } + + return default; + } + /// /// Returns the only element in this builder, and throws an exception if there is not exactly one element. /// @@ -731,6 +897,52 @@ public readonly T Single(Func predicate) return result!; } + /// + /// Returns the only element in this builder that satisfies a specified condition, + /// and throws an exception if more than one such element exists. + /// + /// + /// An argument to pass to . + /// + /// + /// A function to test an element for a condition. + /// + /// + /// The single element in this builder that satisfies a condition. + /// + /// + /// No element satisfies the condition in . + /// + /// + /// More than one element satisfies the condition in . + /// + public readonly T Single(TArg arg, Func predicate) + { + var firstSeen = false; + T? result = default; + + foreach (var item in this) + { + if (predicate(item, arg)) + { + if (firstSeen) + { + return ThrowInvalidOperation(SR.Contains_more_than_one_matching_element); + } + + firstSeen = true; + result = item; + } + } + + if (!firstSeen) + { + return ThrowInvalidOperation(SR.Contains_no_matching_elements); + } + + return result!; + } + /// /// Returns the only element in this builder, or a default value if the builder is empty; /// this method throws an exception if there is more than one element in the builder. @@ -789,6 +1001,46 @@ public readonly T Single(Func predicate) return result; } + /// + /// Returns the only element in this builder that satisfies a specified condition or a default + /// value if no such element exists; this method throws an exception if more than one element + /// satisfies the condition. + /// + /// + /// An argument to pass to . + /// + /// + /// A function to test an element for a condition. + /// + /// + /// The single element in this builder that satisfies the condition, or + /// () if no such element is found. + /// + /// + /// More than one element satisfies the condition in predicate. + /// + public readonly T? SingleOrDefault(TArg arg, Func predicate) + { + var firstSeen = false; + T? result = default; + + foreach (var item in this) + { + if (predicate(item, arg)) + { + if (firstSeen) + { + return ThrowInvalidOperation(SR.Contains_more_than_one_matching_element); + } + + firstSeen = true; + result = item; + } + } + + return result; + } + /// /// This is present to help the JIT inline methods that need to throw an . /// From 0dc2455aed02488006204202ece45fec0df67360 Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Thu, 11 Jul 2024 14:00:26 -0700 Subject: [PATCH 059/176] Add defaultValue-variants for PooledArrayBuilder LINQ-style APIs --- .../PooledObjects/PooledArrayBuilder`1.cs | 253 ++++++++++++++++++ 1 file changed, 253 insertions(+) diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/PooledObjects/PooledArrayBuilder`1.cs b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/PooledObjects/PooledArrayBuilder`1.cs index 584eb22ed8f..57a94f9863d 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/PooledObjects/PooledArrayBuilder`1.cs +++ b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/PooledObjects/PooledArrayBuilder`1.cs @@ -647,6 +647,19 @@ public readonly T First(TArg arg, Func predicate) public readonly T? FirstOrDefault() => Count > 0 ? this[0] : default; + /// + /// Returns the first element in this builder, or a specified default value if the builder is empty. + /// + /// + /// The default value to return if this builder is empty. + /// + /// + /// if this builder is empty; otherwise, + /// the first element in this builder. + /// + public readonly T FirstOrDefault(T defaultValue) + => Count > 0 ? this[0] : defaultValue; + /// /// Returns the first element in this builder that satisfies a condition, or a default value /// if no such element is found. @@ -672,6 +685,34 @@ public readonly T First(TArg arg, Func predicate) return default; } + /// + /// Returns the first element in this builder that satisfies a condition, or a specified default value + /// if no such element is found. + /// + /// + /// A function to test each element for a condition. + /// + /// + /// The default value to return if this builder is empty. + /// + /// + /// if this builder is empty or if no element + /// passes the test specified by ; otherwise, the first element in this + /// builder that passes the test specified by . + /// + public readonly T FirstOrDefault(Func predicate, T defaultValue) + { + foreach (var item in this) + { + if (predicate(item)) + { + return item; + } + } + + return defaultValue; + } + /// /// Returns the first element in this builder that satisfies a condition, or a default value /// if no such element is found. @@ -700,6 +741,37 @@ public readonly T First(TArg arg, Func predicate) return default; } + /// + /// Returns the first element in this builder that satisfies a condition, or a default value + /// if no such element is found. + /// + /// + /// An argument to pass to . + /// + /// + /// A function to test each element for a condition. + /// + /// + /// The default value to return if this builder is empty. + /// + /// + /// if this builder is empty or if no element + /// passes the test specified by ; otherwise, the first element in this + /// builder that passes the test specified by . + /// + public readonly T FirstOrDefault(TArg arg, Func predicate, T defaultValue) + { + foreach (var item in this) + { + if (predicate(item, arg)) + { + return item; + } + } + + return defaultValue; + } + /// /// Returns the last element in this builder. /// @@ -777,6 +849,19 @@ public readonly T Last(TArg arg, Func predicate) public readonly T? LastOrDefault() => Count > 0 ? this[^1] : default; + /// + /// Returns the last element in this builder, or a specified default value if the builder is empty. + /// + /// + /// The default value to return if this builder is empty. + /// + /// + /// if this builder is empty; otherwise, + /// the last element in this builder. + /// + public readonly T LastOrDefault(T defaultValue) + => Count > 0 ? this[^1] : defaultValue; + /// /// Returns the last element in this builder that satisfies a condition, or a default value /// if no such element is found. @@ -803,6 +888,35 @@ public readonly T Last(TArg arg, Func predicate) return default; } + /// + /// Returns the last element in this builder that satisfies a condition, or a specified default value + /// if no such element is found. + /// + /// + /// A function to test each element for a condition. + /// + /// + /// The default value to return if this builder is empty. + /// + /// + /// if this builder is empty or if no element + /// passes the test specified by ; otherwise, the last element in this + /// builder that passes the test specified by . + /// + public readonly T LastOrDefault(Func predicate, T defaultValue) + { + for (var i = Count - 1; i >= 0; i--) + { + var item = this[i]; + if (predicate(item)) + { + return item; + } + } + + return defaultValue; + } + /// /// Returns the last element in this builder that satisfies a condition, or a default value /// if no such element is found. @@ -832,6 +946,38 @@ public readonly T Last(TArg arg, Func predicate) return default; } + /// + /// Returns the last element in this builder that satisfies a condition, or a default value + /// if no such element is found. + /// + /// + /// An argument to pass to . + /// + /// + /// A function to test each element for a condition. + /// + /// + /// The default value to return if this builder is empty. + /// + /// + /// if this builder is empty or if no element + /// passes the test specified by ; otherwise, the last element in this + /// builder that passes the test specified by . + /// + public readonly T LastOrDefault(TArg arg, Func predicate, T defaultValue) + { + for (var i = Count - 1; i >= 0; i--) + { + var item = this[i]; + if (predicate(item, arg)) + { + return item; + } + } + + return defaultValue; + } + /// /// Returns the only element in this builder, and throws an exception if there is not exactly one element. /// @@ -964,6 +1110,30 @@ public readonly T Single(TArg arg, Func predicate) }; } + /// + /// Returns the only element in this builder, or a specified default value if the builder is empty; + /// this method throws an exception if there is more than one element in the builder. + /// + /// + /// The default value to return if this builder is empty. + /// + /// + /// The single element in this builder, or + /// if this builder contains no elements. + /// + /// + /// The builder contains more than one element. + /// + public readonly T SingleOrDefault(T defaultValue) + { + return Count switch + { + 1 => this[0], + 0 => defaultValue, + _ => ThrowInvalidOperation(SR.Contains_more_than_one_element) + }; + } + /// /// Returns the only element in this builder that satisfies a specified condition or a default /// value if no such element exists; this method throws an exception if more than one element @@ -1001,6 +1171,46 @@ public readonly T Single(TArg arg, Func predicate) return result; } + /// + /// Returns the only element in this builder that satisfies a specified condition or a specified default + /// value if no such element exists; this method throws an exception if more than one element + /// satisfies the condition. + /// + /// + /// A function to test an element for a condition. + /// + /// + /// The default value to return if this builder is empty. + /// + /// + /// The single element in this builder that satisfies the condition, or + /// if no such element is found. + /// + /// + /// More than one element satisfies the condition in predicate. + /// + public readonly T SingleOrDefault(Func predicate, T defaultValue) + { + var firstSeen = false; + var result = defaultValue; + + foreach (var item in this) + { + if (predicate(item)) + { + if (firstSeen) + { + return ThrowInvalidOperation(SR.Contains_more_than_one_matching_element); + } + + firstSeen = true; + result = item; + } + } + + return result; + } + /// /// Returns the only element in this builder that satisfies a specified condition or a default /// value if no such element exists; this method throws an exception if more than one element @@ -1041,6 +1251,49 @@ public readonly T Single(TArg arg, Func predicate) return result; } + /// + /// Returns the only element in this builder that satisfies a specified condition or a specified default + /// value if no such element exists; this method throws an exception if more than one element + /// satisfies the condition. + /// + /// + /// An argument to pass to . + /// + /// + /// A function to test an element for a condition. + /// + /// + /// The default value to return if this builder is empty. + /// + /// + /// The single element in this builder that satisfies the condition, or + /// if no such element is found. + /// + /// + /// More than one element satisfies the condition in predicate. + /// + public readonly T SingleOrDefault(TArg arg, Func predicate, T defaultValue) + { + var firstSeen = false; + var result = defaultValue; + + foreach (var item in this) + { + if (predicate(item, arg)) + { + if (firstSeen) + { + return ThrowInvalidOperation(SR.Contains_more_than_one_matching_element); + } + + firstSeen = true; + result = item; + } + } + + return result; + } + /// /// This is present to help the JIT inline methods that need to throw an . /// From ff73a1d7818c69955554107b8c9092bad9d8e731 Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Thu, 11 Jul 2024 15:15:44 -0700 Subject: [PATCH 060/176] Push array.Length checks down to avoid code duplication --- .../ImmutableArrayExtensionsTests.cs | 121 +++++++++++++ .../ImmutableArrayExtensions.cs | 159 +++++++----------- 2 files changed, 178 insertions(+), 102 deletions(-) diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared.Test/ImmutableArrayExtensionsTests.cs b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared.Test/ImmutableArrayExtensionsTests.cs index 398fcbfae46..7a04d9083b4 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared.Test/ImmutableArrayExtensionsTests.cs +++ b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared.Test/ImmutableArrayExtensionsTests.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Immutable; +using System.Runtime.InteropServices; using Xunit; namespace Microsoft.AspNetCore.Razor.Utilities.Shared.Test; @@ -194,4 +195,124 @@ public void OrderByDescendingAsArray_OddBeforeEven(ImmutableArray d var sorted = data.OrderByDescendingAsArray(static x => x.Value, OddBeforeEven); Assert.Equal(expected, sorted); } + + [Fact] + public void OrderAsArray_EmptyArrayReturnsSameArray() + { + var array = ImmutableCollectionsMarshal.AsArray(ImmutableArray.Empty); + var immutableArray = ImmutableArray.Empty; + + immutableArray = immutableArray.OrderAsArray(); + Assert.Same(array, ImmutableCollectionsMarshal.AsArray(immutableArray)); + } + + [Fact] + public void OrderAsArray_SingleElementArrayReturnsSameArray() + { + var array = new int[] { 42 }; + var immutableArray = ImmutableCollectionsMarshal.AsImmutableArray(array); + + immutableArray = immutableArray.OrderAsArray(); + Assert.Same(array, ImmutableCollectionsMarshal.AsArray(immutableArray)); + } + + [Fact] + public void OrderAsArray_SortedArrayReturnsSameArray() + { + var values = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; + var immutableArray = ImmutableCollectionsMarshal.AsImmutableArray(values); + + immutableArray = immutableArray.OrderAsArray(); + Assert.Same(values, ImmutableCollectionsMarshal.AsArray(immutableArray)); + } + + [Fact] + public void OrderDescendingAsArray_EmptyArrayReturnsSameArray() + { + var array = ImmutableCollectionsMarshal.AsArray(ImmutableArray.Empty); + var immutableArray = ImmutableArray.Empty; + + immutableArray = immutableArray.OrderDescendingAsArray(); + Assert.Same(array, ImmutableCollectionsMarshal.AsArray(immutableArray)); + } + + [Fact] + public void OrderDescendingAsArray_SingleElementArrayReturnsSameArray() + { + var array = new int[] { 42 }; + var immutableArray = ImmutableCollectionsMarshal.AsImmutableArray(array); + + immutableArray = immutableArray.OrderDescendingAsArray(); + Assert.Same(array, ImmutableCollectionsMarshal.AsArray(immutableArray)); + } + + [Fact] + public void OrderDescendingAsArray_SortedArrayReturnsSameArray() + { + var values = new int[] { 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 }; + var presortedArray = ImmutableCollectionsMarshal.AsImmutableArray(values); + + presortedArray = presortedArray.OrderDescendingAsArray(); + Assert.Same(values, ImmutableCollectionsMarshal.AsArray(presortedArray)); + } + + [Fact] + public void OrderByAsArray_EmptyArrayReturnsSameArray() + { + var array = ImmutableCollectionsMarshal.AsArray(ImmutableArray.Empty); + var immutableArray = ImmutableArray.Empty; + + immutableArray = immutableArray.OrderByAsArray(static x => x.Value); + Assert.Same(array, ImmutableCollectionsMarshal.AsArray(immutableArray)); + } + + [Fact] + public void OrderByAsArray_SingleElementArrayReturnsSameArray() + { + var array = new ValueHolder[] { 42 }; + var immutableArray = ImmutableCollectionsMarshal.AsImmutableArray(array); + + immutableArray = immutableArray.OrderByAsArray(static x => x.Value); + Assert.Same(array, ImmutableCollectionsMarshal.AsArray(immutableArray)); + } + + [Fact] + public void OrderByAsArray_SortedArrayReturnsSameArray() + { + var values = new ValueHolder[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; + var presortedArray = ImmutableCollectionsMarshal.AsImmutableArray(values); + + presortedArray = presortedArray.OrderByAsArray(static x => x.Value); + Assert.Same(values, ImmutableCollectionsMarshal.AsArray(presortedArray)); + } + + [Fact] + public void OrderByDescendingAsArray_EmptyArrayReturnsSameArray() + { + var array = ImmutableCollectionsMarshal.AsArray(ImmutableArray.Empty); + var immutableArray = ImmutableArray.Empty; + + immutableArray = immutableArray.OrderByDescendingAsArray(static x => x.Value); + Assert.Same(array, ImmutableCollectionsMarshal.AsArray(immutableArray)); + } + + [Fact] + public void OrderByDescendingAsArray_SingleElementArrayReturnsSameArray() + { + var array = new ValueHolder[] { 42 }; + var immutableArray = ImmutableCollectionsMarshal.AsImmutableArray(array); + + immutableArray = immutableArray.OrderByDescendingAsArray(static x => x.Value); + Assert.Same(array, ImmutableCollectionsMarshal.AsArray(immutableArray)); + } + + [Fact] + public void OrderByDescendingAsArray_SortedArrayReturnsSameArray() + { + var values = new ValueHolder[] { 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 }; + var presortedArray = ImmutableCollectionsMarshal.AsImmutableArray(values); + + presortedArray = presortedArray.OrderByDescendingAsArray(static x => x.Value); + Assert.Same(values, ImmutableCollectionsMarshal.AsArray(presortedArray)); + } } diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/ImmutableArrayExtensions.cs b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/ImmutableArrayExtensions.cs index d4dd11c7662..42e3dc5e81e 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/ImmutableArrayExtensions.cs +++ b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/ImmutableArrayExtensions.cs @@ -221,174 +221,129 @@ public static ImmutableArray OrderAsArray(this ImmutableArray array) public static ImmutableArray OrderAsArray(this ImmutableArray array, IComparer comparer) { - if (array.Length > 1) - { - var compareHelper = new CompareHelper(comparer, descending: false); - return array.OrderAsArrayCore(in compareHelper); - } - - return array; + var compareHelper = new CompareHelper(comparer, descending: false); + return array.OrderAsArrayCore(in compareHelper); } public static ImmutableArray OrderAsArray(this ImmutableArray array, Comparison comparison) { - if (array.Length > 1) - { - var compareHelper = new CompareHelper(comparison, descending: false); - return array.OrderAsArrayCore(in compareHelper); - } - - return array; + var compareHelper = new CompareHelper(comparison, descending: false); + return array.OrderAsArrayCore(in compareHelper); } public static ImmutableArray OrderDescendingAsArray(this ImmutableArray array) { - if (array.Length > 1) - { - var compareHelper = new CompareHelper(comparer: null, descending: true); - return array.OrderAsArrayCore(in compareHelper); - } - - return array; + var compareHelper = new CompareHelper(comparer: null, descending: true); + return array.OrderAsArrayCore(in compareHelper); } public static ImmutableArray OrderDescendingAsArray(this ImmutableArray array, IComparer comparer) { - if (array.Length > 1) - { - var compareHelper = new CompareHelper(comparer, descending: true); - return array.OrderAsArrayCore(in compareHelper); - } - - return array; + var compareHelper = new CompareHelper(comparer, descending: true); + return array.OrderAsArrayCore(in compareHelper); } public static ImmutableArray OrderDescendingAsArray(this ImmutableArray array, Comparison comparison) { - if (array.Length > 1) - { - var compareHelper = new CompareHelper(comparison, descending: true); - return array.OrderAsArrayCore(in compareHelper); - } - - return array; + var compareHelper = new CompareHelper(comparison, descending: true); + return array.OrderAsArrayCore(in compareHelper); } public static ImmutableArray OrderByAsArray( this ImmutableArray array, Func keySelector) { - if (array.Length > 1) - { - var compareHelper = new CompareHelper(comparer: null, descending: false); - return array.OrderByAsArrayCore(keySelector, in compareHelper); - } - - return array; + var compareHelper = new CompareHelper(comparer: null, descending: false); + return array.OrderByAsArrayCore(keySelector, in compareHelper); } public static ImmutableArray OrderByAsArray( this ImmutableArray array, Func keySelector, IComparer comparer) { - if (array.Length > 1) - { - var compareHelper = new CompareHelper(comparer, descending: false); - return array.OrderByAsArrayCore(keySelector, in compareHelper); - } - - return array; + var compareHelper = new CompareHelper(comparer, descending: false); + return array.OrderByAsArrayCore(keySelector, in compareHelper); } public static ImmutableArray OrderByAsArray( this ImmutableArray array, Func keySelector, Comparison comparison) { - if (array.Length > 1) - { - var compareHelper = new CompareHelper(comparison, descending: false); - return array.OrderByAsArrayCore(keySelector, in compareHelper); - } - - return array; + var compareHelper = new CompareHelper(comparison, descending: false); + return array.OrderByAsArrayCore(keySelector, in compareHelper); } public static ImmutableArray OrderByDescendingAsArray( this ImmutableArray array, Func keySelector) { - if (array.Length > 1) - { - var compareHelper = new CompareHelper(comparer: null, descending: true); - return array.OrderByAsArrayCore(keySelector, in compareHelper); - } - - return array; + var compareHelper = new CompareHelper(comparer: null, descending: true); + return array.OrderByAsArrayCore(keySelector, in compareHelper); } public static ImmutableArray OrderByDescendingAsArray( this ImmutableArray array, Func keySelector, IComparer comparer) { - if (array.Length > 1) - { - var compareHelper = new CompareHelper(comparer, descending: true); - return array.OrderByAsArrayCore(keySelector, in compareHelper); - } - - return array; + var compareHelper = new CompareHelper(comparer, descending: true); + return array.OrderByAsArrayCore(keySelector, in compareHelper); } public static ImmutableArray OrderByDescendingAsArray( this ImmutableArray array, Func keySelector, Comparison comparison) { - if (array.Length > 1) - { - var compareHelper = new CompareHelper(comparison, descending: true); - return array.OrderByAsArrayCore(keySelector, in compareHelper); - } - - return array; + var compareHelper = new CompareHelper(comparison, descending: true); + return array.OrderByAsArrayCore(keySelector, in compareHelper); } private static ImmutableArray OrderAsArrayCore(this ImmutableArray array, ref readonly CompareHelper compareHelper) { - var items = array.AsSpan(); - - if (AreOrdered(items, in compareHelper)) + if (array.Length > 1) { - // No need to sort - items are already ordered. - return array; - } + var items = array.AsSpan(); + + if (AreOrdered(items, in compareHelper)) + { + // No need to sort - items are already ordered. + return array; + } - var length = items.Length; - var newArray = new T[length]; - items.CopyTo(newArray); + var length = items.Length; + var newArray = new T[length]; + items.CopyTo(newArray); - var comparer = compareHelper.GetOrCreateComparer(); + var comparer = compareHelper.GetOrCreateComparer(); - Array.Sort(newArray, comparer); + Array.Sort(newArray, comparer); - return ImmutableCollectionsMarshal.AsImmutableArray(newArray); + return ImmutableCollectionsMarshal.AsImmutableArray(newArray); + } + + return array; } private static ImmutableArray OrderByAsArrayCore( this ImmutableArray array, Func keySelector, ref readonly CompareHelper compareHelper) { - var items = array.AsSpan(); - var length = items.Length; + if (array.Length > 1) + { + var items = array.AsSpan(); + var length = items.Length; - using var _ = ArrayPool.Shared.GetPooledArray(minimumLength: length, out var keys); + using var _ = ArrayPool.Shared.GetPooledArray(minimumLength: length, out var keys); - if (SelectKeys(items, keySelector, compareHelper, keys.AsSpan(0, length))) - { - // No need to sort - keys are already ordered. - return array; - } + if (SelectKeys(items, keySelector, compareHelper, keys.AsSpan(0, length))) + { + // No need to sort - keys are already ordered. + return array; + } + + var newArray = new TElement[length]; + items.CopyTo(newArray); - var newArray = new TElement[length]; - items.CopyTo(newArray); + var comparer = compareHelper.GetOrCreateComparer(); - var comparer = compareHelper.GetOrCreateComparer(); + Array.Sort(keys, newArray, 0, length, comparer); - Array.Sort(keys, newArray, 0, length, comparer); + return ImmutableCollectionsMarshal.AsImmutableArray(newArray); + } - return ImmutableCollectionsMarshal.AsImmutableArray(newArray); + return array; } /// From 4e29f57a36ae7e6084d1d09516c6e16e610d0542 Mon Sep 17 00:00:00 2001 From: David Wengier Date: Fri, 12 Jul 2024 08:58:04 +1000 Subject: [PATCH 061/176] Logging --- .../Cohost/ShortCircuitingRemoteServiceProvider.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/ShortCircuitingRemoteServiceProvider.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/ShortCircuitingRemoteServiceProvider.cs index e49bb65bbed..bfb2acb58ea 100644 --- a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/ShortCircuitingRemoteServiceProvider.cs +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/ShortCircuitingRemoteServiceProvider.cs @@ -73,6 +73,7 @@ private static Dictionary BuildFactoryMap() var solutionInfo = new RazorPinnedSolutionInfoWrapper(); testOutputHelper.WriteLine($"Pretend OOP call for {typeof(TService).Name}, invocation: {Path.GetFileNameWithoutExtension(callerFilePath)}.{callerMemberName}"); + testOutputHelper.WriteLine($"Project assembly path: `{solution.Projects.First().CompilationOutputInfo.AssemblyPath ?? "null"}`"); return await invocation(service, solutionInfo, cancellationToken); } } From cbc5e4aa85167707f2972bc75345792dc57fbe45 Mon Sep 17 00:00:00 2001 From: David Wengier Date: Fri, 12 Jul 2024 10:27:42 +1000 Subject: [PATCH 062/176] Stop loggign from OOP in tests, because logging in OOP is dodgy --- .../ShortCircuitingRemoteServiceProvider.cs | 4 +- .../Cohost/TestTraceSourceProvider.cs | 52 ------------------- 2 files changed, 3 insertions(+), 53 deletions(-) delete mode 100644 src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/TestTraceSourceProvider.cs diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/ShortCircuitingRemoteServiceProvider.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/ShortCircuitingRemoteServiceProvider.cs index bfb2acb58ea..128d2d6815c 100644 --- a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/ShortCircuitingRemoteServiceProvider.cs +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/ShortCircuitingRemoteServiceProvider.cs @@ -3,11 +3,13 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.IO; using System.Linq; using System.Runtime.CompilerServices; using System.Threading; using System.Threading.Tasks; +using Microsoft.AspNetCore.Razor.Test.Common.VisualStudio; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.ExternalAccess.Razor; using Microsoft.CodeAnalysis.Razor.Remote; @@ -26,7 +28,7 @@ internal class ShortCircuitingRemoteServiceProvider(ITestOutputHelper testOutput { private static readonly Dictionary s_factoryMap = BuildFactoryMap(); - private readonly IServiceProvider _serviceProvider = new TestTraceSourceProvider(testOutputHelper); + private readonly IServiceProvider _serviceProvider = VsMocks.CreateServiceProvider(b => b.AddService(serviceInstance: null)); private static Dictionary BuildFactoryMap() { diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/TestTraceSourceProvider.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/TestTraceSourceProvider.cs deleted file mode 100644 index b61b1a61d3c..00000000000 --- a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/TestTraceSourceProvider.cs +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the MIT license. See License.txt in the project root for license information. - -using System; -using System.Diagnostics; -using Xunit.Abstractions; - -namespace Microsoft.VisualStudio.LanguageServices.Razor.Test.Cohost; - -/// -/// An implementation of IServiceProvider that only provides a TraceSource, that writes to test output -/// -internal class TestTraceSourceProvider(ITestOutputHelper testOutputHelper) : IServiceProvider -{ - public object GetService(Type serviceType) - { - if (serviceType == typeof(TraceSource)) - { - return new TestOutputTraceSource(testOutputHelper); - } - - throw new NotImplementedException(); - } - - private class TestOutputTraceSource : TraceSource - { - public TestOutputTraceSource(ITestOutputHelper testOutputHelper) - : base("OOP", SourceLevels.All) - { - Listeners.Add(new TestOutputTraceListener(testOutputHelper)); - } - - private class TestOutputTraceListener(ITestOutputHelper testOutputHelper) : TraceListener - { - public override void Write(string message) - { - // ITestOutputHelper doesn't have a Write method, but all we lose is some extra ServiceHub details like log level - } - - public override void WriteLine(string message) - { - // Ignore some specific ServiceHub noise, since we're not using ServiceHub anyway - if (message.StartsWith("Added local RPC method") || message == "Listening started.") - { - return; - } - - testOutputHelper.WriteLine(message); - } - } - } -} From d408918897e214472a48e4ba81c942242ddc23f6 Mon Sep 17 00:00:00 2001 From: David Wengier Date: Fri, 12 Jul 2024 10:27:55 +1000 Subject: [PATCH 063/176] =?UTF-8?q?Dispose=20of=20disposables=20?= =?UTF-8?q?=F0=9F=A4=A6=E2=80=8D=E2=99=82=EF=B8=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Cohost/ShortCircuitingRemoteServiceProvider.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/ShortCircuitingRemoteServiceProvider.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/ShortCircuitingRemoteServiceProvider.cs index 128d2d6815c..fefdd323c1e 100644 --- a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/ShortCircuitingRemoteServiceProvider.cs +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/ShortCircuitingRemoteServiceProvider.cs @@ -69,13 +69,13 @@ private static Dictionary BuildFactoryMap() // We don't ever use this stream, because we never really use ServiceHub, but going through its factory method means the // remote services under test are using their full MEF composition etc. so we get excellent coverage. var (stream, _) = FullDuplexStream.CreatePair(); - var service = (TService)await factory.CreateAsync(stream, _serviceProvider, serviceActivationOptions: default, testServiceBroker, authorizationServiceClient: default!); + using var service = (IDisposable)await factory.CreateAsync(stream, _serviceProvider, serviceActivationOptions: default, testServiceBroker, authorizationServiceClient: default!); // This is never used, we short-circuited things by passing the solution direct to the InterceptingServiceBroker var solutionInfo = new RazorPinnedSolutionInfoWrapper(); testOutputHelper.WriteLine($"Pretend OOP call for {typeof(TService).Name}, invocation: {Path.GetFileNameWithoutExtension(callerFilePath)}.{callerMemberName}"); testOutputHelper.WriteLine($"Project assembly path: `{solution.Projects.First().CompilationOutputInfo.AssemblyPath ?? "null"}`"); - return await invocation(service, solutionInfo, cancellationToken); + return await invocation((TService)service, solutionInfo, cancellationToken); } } From 5090e74580641ebdc445b67beeceaa553f8a7630 Mon Sep 17 00:00:00 2001 From: David Wengier Date: Fri, 12 Jul 2024 10:27:59 +1000 Subject: [PATCH 064/176] Whitespace --- .../RazorServiceFactoryBase.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorServiceFactoryBase.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorServiceFactoryBase.cs index 23f1e83b20f..c3c7e248391 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorServiceFactoryBase.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorServiceFactoryBase.cs @@ -35,11 +35,11 @@ public RazorServiceFactoryBase(RazorServiceDescriptorsWrapper razorServiceDescri } public async Task CreateAsync( - Stream stream, - IServiceProvider hostProvidedServices, - ServiceActivationOptions serviceActivationOptions, - IServiceBroker serviceBroker, - AuthorizationServiceClient? authorizationServiceClient) + Stream stream, + IServiceProvider hostProvidedServices, + ServiceActivationOptions serviceActivationOptions, + IServiceBroker serviceBroker, + AuthorizationServiceClient? authorizationServiceClient) { // Dispose the AuthorizationServiceClient since we won't be using it authorizationServiceClient?.Dispose(); From c78deb4c25efec5cdb9ed203954cdd283d15537b Mon Sep 17 00:00:00 2001 From: David Wengier Date: Fri, 12 Jul 2024 11:48:16 +1000 Subject: [PATCH 065/176] Tell the compiler that services are disposable --- .../Remote/IRemoteClientInitializationService.cs | 3 ++- .../Remote/IRemoteFoldingRangeService.cs | 3 ++- .../Remote/IRemoteHtmlDocumentService.cs | 3 ++- .../Remote/IRemoteLinkedEditingRangeService.cs | 3 ++- .../Remote/IRemoteSemanticTokensService.cs | 2 +- .../Remote/IRemoteServiceProvider.cs | 2 +- .../Remote/IRemoteTagHelperProviderService.cs | 3 ++- .../Remote/IRemoteUriPresentationService.cs | 2 +- .../Remote/RemoteServiceProvider.cs | 2 +- 9 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteClientInitializationService.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteClientInitializationService.cs index 8089bc68099..32c9d4bd1ac 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteClientInitializationService.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteClientInitializationService.cs @@ -1,12 +1,13 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT license. See License.txt in the project root for license information. +using System; using System.Threading; using System.Threading.Tasks; namespace Microsoft.CodeAnalysis.Razor.Remote; -internal interface IRemoteClientInitializationService +internal interface IRemoteClientInitializationService : IDisposable { ValueTask InitializeAsync(RemoteClientInitializationOptions initializationOptions, CancellationToken cancellationToken); diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteFoldingRangeService.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteFoldingRangeService.cs index f709ed98631..c3368da527e 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteFoldingRangeService.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteFoldingRangeService.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT license. See License.txt in the project root for license information. +using System; using System.Collections.Immutable; using System.Threading; using System.Threading.Tasks; @@ -9,7 +10,7 @@ namespace Microsoft.CodeAnalysis.Razor.Remote; -internal interface IRemoteFoldingRangeService +internal interface IRemoteFoldingRangeService : IDisposable { ValueTask> GetFoldingRangesAsync(RazorPinnedSolutionInfoWrapper solutionInfo, DocumentId documentId, ImmutableArray htmlRanges, CancellationToken cancellationToken); } diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteHtmlDocumentService.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteHtmlDocumentService.cs index 832a851949a..de87623fe74 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteHtmlDocumentService.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteHtmlDocumentService.cs @@ -1,13 +1,14 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT license. See License.txt in the project root for license information. +using System; using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.ExternalAccess.Razor; namespace Microsoft.CodeAnalysis.Razor.Remote; -internal interface IRemoteHtmlDocumentService +internal interface IRemoteHtmlDocumentService : IDisposable { ValueTask GetHtmlDocumentTextAsync(RazorPinnedSolutionInfoWrapper solutionInfo, DocumentId razorDocumentId, CancellationToken cancellationToken); } diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteLinkedEditingRangeService.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteLinkedEditingRangeService.cs index 0520974b6fd..87f94ac9f10 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteLinkedEditingRangeService.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteLinkedEditingRangeService.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT license. See License.txt in the project root for license information. +using System; using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.ExternalAccess.Razor; @@ -8,7 +9,7 @@ namespace Microsoft.CodeAnalysis.Razor.Remote; -internal interface IRemoteLinkedEditingRangeService +internal interface IRemoteLinkedEditingRangeService : IDisposable { ValueTask GetRangesAsync(RazorPinnedSolutionInfoWrapper solutionInfo, DocumentId razorDocumentId, LinePosition linePosition, CancellationToken cancellationToken); } diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteSemanticTokensService.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteSemanticTokensService.cs index 19778bfcfea..1d2f1b0a8ea 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteSemanticTokensService.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteSemanticTokensService.cs @@ -9,7 +9,7 @@ namespace Microsoft.CodeAnalysis.Razor.Remote; -internal interface IRemoteSemanticTokensService +internal interface IRemoteSemanticTokensService : IDisposable { ValueTask GetSemanticTokensDataAsync( RazorPinnedSolutionInfoWrapper solutionInfo, diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteServiceProvider.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteServiceProvider.cs index a2cf6917beb..e8241e0aa2c 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteServiceProvider.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteServiceProvider.cs @@ -17,5 +17,5 @@ internal interface IRemoteServiceProvider CancellationToken cancellationToken, [CallerFilePath] string? callerFilePath = null, [CallerMemberName] string? callerMemberName = null) - where TService : class; + where TService : class, IDisposable; } diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteTagHelperProviderService.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteTagHelperProviderService.cs index eb17de0887c..b2ddfd2af45 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteTagHelperProviderService.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteTagHelperProviderService.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT license. See License.txt in the project root for license information. +using System; using System.Collections.Immutable; using System.Threading; using System.Threading.Tasks; @@ -10,7 +11,7 @@ namespace Microsoft.CodeAnalysis.Razor.Remote; -internal interface IRemoteTagHelperProviderService +internal interface IRemoteTagHelperProviderService : IDisposable { ValueTask GetTagHelpersDeltaAsync( RazorPinnedSolutionInfoWrapper solutionInfo, diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteUriPresentationService.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteUriPresentationService.cs index 4c9e3707bef..1d13c9c5743 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteUriPresentationService.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteUriPresentationService.cs @@ -9,7 +9,7 @@ namespace Microsoft.CodeAnalysis.Razor.Remote; -internal interface IRemoteUriPresentationService +internal interface IRemoteUriPresentationService : IDisposable { ValueTask GetPresentationAsync(RazorPinnedSolutionInfoWrapper solutionInfo, DocumentId razorDocumentId, LinePositionSpan span, Uri[]? uris, CancellationToken cancellationToken); } diff --git a/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/Remote/RemoteServiceProvider.cs b/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/Remote/RemoteServiceProvider.cs index 77361646138..bbbb114f011 100644 --- a/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/Remote/RemoteServiceProvider.cs +++ b/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/Remote/RemoteServiceProvider.cs @@ -47,7 +47,7 @@ internal sealed class RemoteServiceProvider( CancellationToken cancellationToken, [CallerFilePath] string? callerFilePath = null, [CallerMemberName] string? callerMemberName = null) - where TService : class + where TService : class, IDisposable { var client = await TryGetClientAsync(cancellationToken).ConfigureAwait(false); if (client is null) From b1f89e0e025e5a0ef25f5c2abffa62228df52dbd Mon Sep 17 00:00:00 2001 From: David Wengier Date: Fri, 12 Jul 2024 11:49:59 +1000 Subject: [PATCH 066/176] Abstract IServiceBroker away so that we can test services without needing anything from service broker --- .../RemoteFoldingRangeService.cs | 3 +- .../RemoteFoldingRangeServiceFactory.cs | 3 +- .../RemoteHtmlDocumentService.cs | 3 +- .../RemoteHtmlDocumentServiceFactory.cs | 3 +- ...eInterceptor.cs => IRazorServiceBroker.cs} | 2 +- .../RemoteClientInitializationService.cs | 3 +- ...emoteClientInitializationServiceFactory.cs | 3 +- .../RemoteLinkedEditingRangeService.cs | 3 +- .../RemoteLinkedEditingRangeServiceFactory.cs | 3 +- .../RazorDocumentServiceBase.cs | 3 +- .../RazorServiceBase.cs | 16 ++++------ .../RazorServiceBroker.cs | 32 +++++++++++++++++++ .../RazorServiceFactoryBase.cs | 17 ++++++++-- .../RemoteSemanticTokensService.cs | 3 +- .../RemoteSemanticTokensServiceFactory.cs | 3 +- .../RemoteTagHelperProviderService.cs | 3 +- .../RemoteTagHelperProviderServiceFactory.cs | 3 +- .../RemoteUriPresentationService.cs | 3 +- .../RemoteUriPresentationServiceFactory.cs | 3 +- 19 files changed, 69 insertions(+), 43 deletions(-) rename src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/{IBrokeredServiceInterceptor.cs => IRazorServiceBroker.cs} (93%) create mode 100644 src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorServiceBroker.cs diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/FoldingRanges/RemoteFoldingRangeService.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/FoldingRanges/RemoteFoldingRangeService.cs index 5d8f4264552..0d171ddc3d1 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/FoldingRanges/RemoteFoldingRangeService.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/FoldingRanges/RemoteFoldingRangeService.cs @@ -11,13 +11,12 @@ using Microsoft.CodeAnalysis.Razor.Remote; using Microsoft.CodeAnalysis.Razor.Workspaces; using Microsoft.CodeAnalysis.Remote.Razor.ProjectSystem; -using Microsoft.ServiceHub.Framework; using Microsoft.VisualStudio.LanguageServer.Protocol; namespace Microsoft.CodeAnalysis.Remote.Razor; internal sealed class RemoteFoldingRangeService( - IServiceBroker serviceBroker, + IRazorServiceBroker serviceBroker, IFoldingRangeService foldingRangeService, DocumentSnapshotFactory documentSnapshotFactory, IFilePathService filePathService) diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/FoldingRanges/RemoteFoldingRangeServiceFactory.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/FoldingRanges/RemoteFoldingRangeServiceFactory.cs index e0fbb4a6d33..6afdd17fa6c 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/FoldingRanges/RemoteFoldingRangeServiceFactory.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/FoldingRanges/RemoteFoldingRangeServiceFactory.cs @@ -5,7 +5,6 @@ using Microsoft.CodeAnalysis.Razor.Remote; using Microsoft.CodeAnalysis.Razor.Workspaces; using Microsoft.CodeAnalysis.Remote.Razor.ProjectSystem; -using Microsoft.ServiceHub.Framework; using Microsoft.VisualStudio.Composition; namespace Microsoft.CodeAnalysis.Remote.Razor; @@ -18,7 +17,7 @@ public RemoteFoldingRangeServiceFactory() { } - protected override IRemoteFoldingRangeService CreateService(IServiceBroker serviceBroker, ExportProvider exportProvider) + protected override IRemoteFoldingRangeService CreateService(IRazorServiceBroker serviceBroker, ExportProvider exportProvider) { var infoService = exportProvider.GetExportedValue(); var documentSnapshotFactory = exportProvider.GetExportedValue(); diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/HtmlDocuments/RemoteHtmlDocumentService.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/HtmlDocuments/RemoteHtmlDocumentService.cs index 783bd565c7b..fd7d305251c 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/HtmlDocuments/RemoteHtmlDocumentService.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/HtmlDocuments/RemoteHtmlDocumentService.cs @@ -7,12 +7,11 @@ using Microsoft.CodeAnalysis.Razor.Remote; using Microsoft.CodeAnalysis.Razor.Workspaces; using Microsoft.CodeAnalysis.Remote.Razor.ProjectSystem; -using Microsoft.ServiceHub.Framework; namespace Microsoft.CodeAnalysis.Remote.Razor; internal sealed class RemoteHtmlDocumentService( - IServiceBroker serviceBroker, + IRazorServiceBroker serviceBroker, DocumentSnapshotFactory documentSnapshotFactory) : RazorDocumentServiceBase(serviceBroker, documentSnapshotFactory), IRemoteHtmlDocumentService { diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/HtmlDocuments/RemoteHtmlDocumentServiceFactory.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/HtmlDocuments/RemoteHtmlDocumentServiceFactory.cs index f6d6cf62983..f55a1a0a5e9 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/HtmlDocuments/RemoteHtmlDocumentServiceFactory.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/HtmlDocuments/RemoteHtmlDocumentServiceFactory.cs @@ -3,7 +3,6 @@ using Microsoft.CodeAnalysis.Razor.Remote; using Microsoft.CodeAnalysis.Remote.Razor.ProjectSystem; -using Microsoft.ServiceHub.Framework; using Microsoft.VisualStudio.Composition; namespace Microsoft.CodeAnalysis.Remote.Razor; @@ -16,7 +15,7 @@ public RemoteHtmlDocumentServiceFactory() { } - protected override IRemoteHtmlDocumentService CreateService(IServiceBroker serviceBroker, ExportProvider exportProvider) + protected override IRemoteHtmlDocumentService CreateService(IRazorServiceBroker serviceBroker, ExportProvider exportProvider) { var documentSnapshotFactory = exportProvider.GetExportedValue(); return new RemoteHtmlDocumentService(serviceBroker, documentSnapshotFactory); diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/IBrokeredServiceInterceptor.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/IRazorServiceBroker.cs similarity index 93% rename from src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/IBrokeredServiceInterceptor.cs rename to src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/IRazorServiceBroker.cs index a2a3c23a48b..7f2d59ae0d6 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/IBrokeredServiceInterceptor.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/IRazorServiceBroker.cs @@ -12,7 +12,7 @@ namespace Microsoft.CodeAnalysis.Remote.Razor; /// /// An abstraction to avoid calling the static helper defined in Roslyn /// -internal interface IBrokeredServiceInterceptor +internal interface IRazorServiceBroker : IDisposable { ValueTask RunServiceAsync(Func implementation, CancellationToken cancellationToken); diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Initialization/RemoteClientInitializationService.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Initialization/RemoteClientInitializationService.cs index bb9d11ee466..d5d316c971e 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Initialization/RemoteClientInitializationService.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Initialization/RemoteClientInitializationService.cs @@ -5,12 +5,11 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis.Razor.Remote; using Microsoft.CodeAnalysis.Remote.Razor.SemanticTokens; -using Microsoft.ServiceHub.Framework; namespace Microsoft.CodeAnalysis.Remote.Razor; internal sealed class RemoteClientInitializationService( - IServiceBroker serviceBroker) + IRazorServiceBroker serviceBroker) : RazorServiceBase(serviceBroker), IRemoteClientInitializationService { public ValueTask InitializeAsync(RemoteClientInitializationOptions options, CancellationToken cancellationToken) diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Initialization/RemoteClientInitializationServiceFactory.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Initialization/RemoteClientInitializationServiceFactory.cs index 9a17b756487..c1cb47432a3 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Initialization/RemoteClientInitializationServiceFactory.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Initialization/RemoteClientInitializationServiceFactory.cs @@ -2,7 +2,6 @@ // Licensed under the MIT license. See License.txt in the project root for license information. using Microsoft.CodeAnalysis.Razor.Remote; -using Microsoft.ServiceHub.Framework; using Microsoft.VisualStudio.Composition; namespace Microsoft.CodeAnalysis.Remote.Razor; @@ -15,7 +14,7 @@ public RemoteClientInitializationServiceFactory() { } - protected override IRemoteClientInitializationService CreateService(IServiceBroker serviceBroker, ExportProvider exportProvider) + protected override IRemoteClientInitializationService CreateService(IRazorServiceBroker serviceBroker, ExportProvider exportProvider) { return new RemoteClientInitializationService(serviceBroker); } diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/LinkedEditingRange/RemoteLinkedEditingRangeService.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/LinkedEditingRange/RemoteLinkedEditingRangeService.cs index 8222947648a..d03ed067087 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/LinkedEditingRange/RemoteLinkedEditingRangeService.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/LinkedEditingRange/RemoteLinkedEditingRangeService.cs @@ -9,12 +9,11 @@ using Microsoft.CodeAnalysis.Razor.Remote; using Microsoft.CodeAnalysis.Remote.Razor.ProjectSystem; using Microsoft.CodeAnalysis.Text; -using Microsoft.ServiceHub.Framework; namespace Microsoft.CodeAnalysis.Remote.Razor; internal sealed class RemoteLinkedEditingRangeService( - IServiceBroker serviceBroker, + IRazorServiceBroker serviceBroker, DocumentSnapshotFactory documentSnapshotFactory, ILoggerFactory loggerFactory) : RazorDocumentServiceBase(serviceBroker, documentSnapshotFactory), IRemoteLinkedEditingRangeService diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/LinkedEditingRange/RemoteLinkedEditingRangeServiceFactory.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/LinkedEditingRange/RemoteLinkedEditingRangeServiceFactory.cs index fb94aad1bca..29c5d7699b3 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/LinkedEditingRange/RemoteLinkedEditingRangeServiceFactory.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/LinkedEditingRange/RemoteLinkedEditingRangeServiceFactory.cs @@ -4,7 +4,6 @@ using Microsoft.CodeAnalysis.Razor.Logging; using Microsoft.CodeAnalysis.Razor.Remote; using Microsoft.CodeAnalysis.Remote.Razor.ProjectSystem; -using Microsoft.ServiceHub.Framework; using Microsoft.VisualStudio.Composition; namespace Microsoft.CodeAnalysis.Remote.Razor; @@ -17,7 +16,7 @@ public RemoteLinkedEditingRangeServiceFactory() { } - protected override IRemoteLinkedEditingRangeService CreateService(IServiceBroker serviceBroker, ExportProvider exportProvider) + protected override IRemoteLinkedEditingRangeService CreateService(IRazorServiceBroker serviceBroker, ExportProvider exportProvider) { var documentSnapshotFactory = exportProvider.GetExportedValue(); var loggerFactory = exportProvider.GetExportedValue(); diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorDocumentServiceBase.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorDocumentServiceBase.cs index e05a3fa00e8..bf2f8c0ef61 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorDocumentServiceBase.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorDocumentServiceBase.cs @@ -6,12 +6,11 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis.ExternalAccess.Razor; using Microsoft.CodeAnalysis.Remote.Razor.ProjectSystem; -using Microsoft.ServiceHub.Framework; namespace Microsoft.CodeAnalysis.Remote.Razor; internal abstract class RazorDocumentServiceBase( - IServiceBroker serviceBroker, + IRazorServiceBroker serviceBroker, DocumentSnapshotFactory documentSnapshotFactory) : RazorServiceBase(serviceBroker) { diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorServiceBase.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorServiceBase.cs index 35855fe0acb..c9ea08672ec 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorServiceBase.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorServiceBase.cs @@ -5,30 +5,26 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.ExternalAccess.Razor; -using Microsoft.CodeAnalysis.ExternalAccess.Razor.Api; -using Microsoft.ServiceHub.Framework; namespace Microsoft.CodeAnalysis.Remote.Razor; internal abstract class RazorServiceBase : IDisposable { - private readonly ServiceBrokerClient _serviceBrokerClient; - private readonly IBrokeredServiceInterceptor? _brokeredServiceInterceptor; + private readonly IRazorServiceBroker _razorServiceBroker; - public RazorServiceBase(IServiceBroker serviceBroker) + public RazorServiceBase(IRazorServiceBroker razorServiceBroker) { - _brokeredServiceInterceptor = serviceBroker as IBrokeredServiceInterceptor; - _serviceBrokerClient = new ServiceBrokerClient(serviceBroker, joinableTaskFactory: null); + _razorServiceBroker = razorServiceBroker; } protected ValueTask RunServiceAsync(Func implementation, CancellationToken cancellationToken) - => _brokeredServiceInterceptor?.RunServiceAsync(implementation, cancellationToken) ?? RazorBrokeredServiceImplementation.RunServiceAsync(implementation, cancellationToken); + => _razorServiceBroker.RunServiceAsync(implementation, cancellationToken); protected ValueTask RunServiceAsync(RazorPinnedSolutionInfoWrapper solutionInfo, Func> implementation, CancellationToken cancellationToken) - => _brokeredServiceInterceptor?.RunServiceAsync(solutionInfo, implementation, cancellationToken) ?? RazorBrokeredServiceImplementation.RunServiceAsync(solutionInfo, _serviceBrokerClient, implementation, cancellationToken); + => _razorServiceBroker.RunServiceAsync(solutionInfo, implementation, cancellationToken); public void Dispose() { - _serviceBrokerClient.Dispose(); + _razorServiceBroker.Dispose(); } } diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorServiceBroker.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorServiceBroker.cs new file mode 100644 index 00000000000..928ffed1f99 --- /dev/null +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorServiceBroker.cs @@ -0,0 +1,32 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT license. See License.txt in the project root for license information. + +using System; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.ExternalAccess.Razor; +using Microsoft.CodeAnalysis.ExternalAccess.Razor.Api; +using Microsoft.ServiceHub.Framework; + +namespace Microsoft.CodeAnalysis.Remote.Razor; + +internal class RazorServiceBroker : IRazorServiceBroker +{ + private readonly ServiceBrokerClient _serviceBrokerClient; + + public RazorServiceBroker(IServiceBroker serviceBroker) + { + _serviceBrokerClient = new ServiceBrokerClient(serviceBroker, joinableTaskFactory: null); + } + + public ValueTask RunServiceAsync(Func implementation, CancellationToken cancellationToken) + => RazorBrokeredServiceImplementation.RunServiceAsync(implementation, cancellationToken); + + public ValueTask RunServiceAsync(RazorPinnedSolutionInfoWrapper solutionInfo, Func> implementation, CancellationToken cancellationToken) + => RazorBrokeredServiceImplementation.RunServiceAsync(solutionInfo, _serviceBrokerClient, implementation, cancellationToken); + + public void Dispose() + { + _serviceBrokerClient.Dispose(); + } +} diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorServiceFactoryBase.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorServiceFactoryBase.cs index c3c7e248391..32d4f4e6084 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorServiceFactoryBase.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorServiceFactoryBase.cs @@ -53,7 +53,9 @@ public async Task CreateAsync( var exportProvider = await RemoteMefComposition.GetExportProviderAsync().ConfigureAwait(false); - var service = CreateService(serviceBroker, exportProvider); + var razorServiceBroker = new RazorServiceBroker(serviceBroker); + + var service = CreateService(razorServiceBroker, exportProvider); serverConnection.AddLocalRpcTarget(service); serverConnection.StartListening(); @@ -61,5 +63,16 @@ public async Task CreateAsync( return service; } - protected abstract TService CreateService(IServiceBroker serviceBroker, ExportProvider exportProvider); + protected abstract TService CreateService(IRazorServiceBroker serviceBroker, ExportProvider exportProvider); + + internal TestAccessor GetTestAccessor() + { + return new TestAccessor(this); + } + + internal readonly struct TestAccessor(RazorServiceFactoryBase instance) + { + public TService CreateService(IRazorServiceBroker serviceBroker, ExportProvider exportProvider) + => instance.CreateService(serviceBroker, exportProvider); + } } diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/SemanticTokens/RemoteSemanticTokensService.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/SemanticTokens/RemoteSemanticTokensService.cs index 613236838fb..ed8ba161e1d 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/SemanticTokens/RemoteSemanticTokensService.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/SemanticTokens/RemoteSemanticTokensService.cs @@ -9,12 +9,11 @@ using Microsoft.CodeAnalysis.Razor.SemanticTokens; using Microsoft.CodeAnalysis.Remote.Razor.ProjectSystem; using Microsoft.CodeAnalysis.Text; -using Microsoft.ServiceHub.Framework; namespace Microsoft.CodeAnalysis.Remote.Razor; internal sealed class RemoteSemanticTokensService( - IServiceBroker serviceBroker, + IRazorServiceBroker serviceBroker, IRazorSemanticTokensInfoService razorSemanticTokensInfoService, DocumentSnapshotFactory documentSnapshotFactory) : RazorDocumentServiceBase(serviceBroker, documentSnapshotFactory), IRemoteSemanticTokensService diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/SemanticTokens/RemoteSemanticTokensServiceFactory.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/SemanticTokens/RemoteSemanticTokensServiceFactory.cs index 87e5dd42bef..71134768ec1 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/SemanticTokens/RemoteSemanticTokensServiceFactory.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/SemanticTokens/RemoteSemanticTokensServiceFactory.cs @@ -4,7 +4,6 @@ using Microsoft.CodeAnalysis.Razor.Remote; using Microsoft.CodeAnalysis.Razor.SemanticTokens; using Microsoft.CodeAnalysis.Remote.Razor.ProjectSystem; -using Microsoft.ServiceHub.Framework; using Microsoft.VisualStudio.Composition; namespace Microsoft.CodeAnalysis.Remote.Razor; @@ -17,7 +16,7 @@ public RemoteSemanticTokensServiceFactory() { } - protected override IRemoteSemanticTokensService CreateService(IServiceBroker serviceBroker, ExportProvider exportProvider) + protected override IRemoteSemanticTokensService CreateService(IRazorServiceBroker serviceBroker, ExportProvider exportProvider) { var infoService = exportProvider.GetExportedValue(); var documentSnapshotFactory = exportProvider.GetExportedValue(); diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/TagHelpers/RemoteTagHelperProviderService.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/TagHelpers/RemoteTagHelperProviderService.cs index d095a0c8fc5..7d8d80659a1 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/TagHelpers/RemoteTagHelperProviderService.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/TagHelpers/RemoteTagHelperProviderService.cs @@ -10,12 +10,11 @@ using Microsoft.AspNetCore.Razor.Utilities; using Microsoft.CodeAnalysis.ExternalAccess.Razor; using Microsoft.CodeAnalysis.Razor.Remote; -using Microsoft.ServiceHub.Framework; namespace Microsoft.CodeAnalysis.Remote.Razor; internal sealed class RemoteTagHelperProviderService( - IServiceBroker serviceBroker, + IRazorServiceBroker serviceBroker, RemoteTagHelperResolver tagHelperResolver, RemoteTagHelperDeltaProvider tagHelperDeltaProvider) : RazorServiceBase(serviceBroker), IRemoteTagHelperProviderService diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/TagHelpers/RemoteTagHelperProviderServiceFactory.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/TagHelpers/RemoteTagHelperProviderServiceFactory.cs index 1cad94d5c67..c1a3b34a2c9 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/TagHelpers/RemoteTagHelperProviderServiceFactory.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/TagHelpers/RemoteTagHelperProviderServiceFactory.cs @@ -3,7 +3,6 @@ using Microsoft.AspNetCore.Razor; using Microsoft.CodeAnalysis.Razor.Remote; -using Microsoft.ServiceHub.Framework; using Microsoft.VisualStudio.Composition; namespace Microsoft.CodeAnalysis.Remote.Razor; @@ -16,7 +15,7 @@ public RemoteTagHelperProviderServiceFactory() { } - protected override IRemoteTagHelperProviderService CreateService(IServiceBroker serviceBroker, ExportProvider exportProvider) + protected override IRemoteTagHelperProviderService CreateService(IRazorServiceBroker serviceBroker, ExportProvider exportProvider) { var tagHelperResolver = exportProvider.GetExportedValue().AssumeNotNull(); var tagHelperDeltaProvider = exportProvider.GetExportedValue().AssumeNotNull(); diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/UriPresentation/RemoteUriPresentationService.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/UriPresentation/RemoteUriPresentationService.cs index 4f655b1d2e5..507f90011c2 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/UriPresentation/RemoteUriPresentationService.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/UriPresentation/RemoteUriPresentationService.cs @@ -13,12 +13,11 @@ using Microsoft.CodeAnalysis.Razor.Workspaces; using Microsoft.CodeAnalysis.Remote.Razor.ProjectSystem; using Microsoft.CodeAnalysis.Text; -using Microsoft.ServiceHub.Framework; namespace Microsoft.CodeAnalysis.Remote.Razor; internal sealed class RemoteUriPresentationService( - IServiceBroker serviceBroker, + IRazorServiceBroker serviceBroker, IRazorDocumentMappingService documentMappingService, DocumentSnapshotFactory documentSnapshotFactory, ILoggerFactory loggerFactory) diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/UriPresentation/RemoteUriPresentationServiceFactory.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/UriPresentation/RemoteUriPresentationServiceFactory.cs index 20499a8bb35..ecb75c9d11b 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/UriPresentation/RemoteUriPresentationServiceFactory.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/UriPresentation/RemoteUriPresentationServiceFactory.cs @@ -5,7 +5,6 @@ using Microsoft.CodeAnalysis.Razor.Logging; using Microsoft.CodeAnalysis.Razor.Remote; using Microsoft.CodeAnalysis.Remote.Razor.ProjectSystem; -using Microsoft.ServiceHub.Framework; using Microsoft.VisualStudio.Composition; namespace Microsoft.CodeAnalysis.Remote.Razor; @@ -18,7 +17,7 @@ public RemoteUriPresentationServiceFactory() { } - protected override IRemoteUriPresentationService CreateService(IServiceBroker serviceBroker, ExportProvider exportProvider) + protected override IRemoteUriPresentationService CreateService(IRazorServiceBroker serviceBroker, ExportProvider exportProvider) { var documentMappingService = exportProvider.GetExportedValue(); var documentSnapshotFactory = exportProvider.GetExportedValue(); From 45a08219b9d8018aaeb97c78f147a9d404ee5dee Mon Sep 17 00:00:00 2001 From: David Wengier Date: Fri, 12 Jul 2024 11:51:05 +1000 Subject: [PATCH 067/176] Create MEF composition and services directly in testing --- .../RemoteMefComposition.cs | 3 ++- .../Cohost/CohostTestBase.cs | 18 ++++++++++++--- ...ovider.cs => TestRemoteServiceProvider.cs} | 23 +++++++------------ ...gServiceBroker.cs => TestServiceBroker.cs} | 21 ++++------------- 4 files changed, 30 insertions(+), 35 deletions(-) rename src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/{ShortCircuitingRemoteServiceProvider.cs => TestRemoteServiceProvider.cs} (68%) rename src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/{InterceptingServiceBroker.cs => TestServiceBroker.cs} (53%) diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RemoteMefComposition.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RemoteMefComposition.cs index 0a8b90be376..a86c3fcf0c6 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RemoteMefComposition.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RemoteMefComposition.cs @@ -20,8 +20,9 @@ internal static class RemoteMefComposition public static Task GetExportProviderAsync() => s_exportProviderLazy.GetValueAsync(); + // Internal for testing // Inspired by https://github.com/dotnet/roslyn/blob/25aa74d725e801b8232dbb3e5abcda0fa72da8c5/src/Workspaces/Remote/ServiceHub/Host/RemoteWorkspaceManager.cs#L77 - private static async Task CreateExportProviderAsync() + internal static async Task CreateExportProviderAsync() { var resolver = new Resolver(SimpleAssemblyLoader.Instance); var discovery = new AttributedPartDiscovery(resolver, isNonPublicSupported: true); // MEFv2 only diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostTestBase.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostTestBase.cs index cc0800edf62..9a57b3b42d8 100644 --- a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostTestBase.cs +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostTestBase.cs @@ -8,22 +8,34 @@ using Microsoft.AspNetCore.Razor.Test.Common.Workspaces; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Razor.Remote; +using Microsoft.CodeAnalysis.Remote.Razor; using Microsoft.CodeAnalysis.Text; +using Microsoft.VisualStudio.Composition; using Xunit.Abstractions; namespace Microsoft.VisualStudio.LanguageServices.Razor.Test.Cohost; public abstract class CohostTestBase(ITestOutputHelper testOutputHelper) : WorkspaceTestBase(testOutputHelper) { + private ExportProvider? _exportProvider; private IRemoteServiceProvider? _remoteServiceProvider; private protected IRemoteServiceProvider RemoteServiceProvider => _remoteServiceProvider.AssumeNotNull(); - protected override Task InitializeAsync() + protected override async Task InitializeAsync() { - _remoteServiceProvider = new ShortCircuitingRemoteServiceProvider(TestOutputHelper); + await base.InitializeAsync(); - return base.InitializeAsync(); + _exportProvider = await RemoteMefComposition.CreateExportProviderAsync(); + + _remoteServiceProvider = new TestRemoteServiceProvider(_exportProvider); + } + + protected override async Task DisposeAsync() + { + _exportProvider?.Dispose(); + + await base.DisposeAsync(); } protected TextDocument CreateRazorDocument(string contents) diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/ShortCircuitingRemoteServiceProvider.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/TestRemoteServiceProvider.cs similarity index 68% rename from src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/ShortCircuitingRemoteServiceProvider.cs rename to src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/TestRemoteServiceProvider.cs index fefdd323c1e..88b0b7f5d8a 100644 --- a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/ShortCircuitingRemoteServiceProvider.cs +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/TestRemoteServiceProvider.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; using System.Diagnostics; -using System.IO; using System.Linq; using System.Runtime.CompilerServices; using System.Threading; @@ -15,16 +14,15 @@ using Microsoft.CodeAnalysis.Razor.Remote; using Microsoft.CodeAnalysis.Remote.Razor; using Microsoft.ServiceHub.Framework; -using Nerdbank.Streams; +using Microsoft.VisualStudio.Composition; using Xunit; -using Xunit.Abstractions; namespace Microsoft.VisualStudio.LanguageServices.Razor.Test.Cohost; /// /// An implementation of IRemoteServiceProvider that doesn't actually do anything remote, but rather directly calls service methods /// -internal class ShortCircuitingRemoteServiceProvider(ITestOutputHelper testOutputHelper) : IRemoteServiceProvider +internal class TestRemoteServiceProvider(ExportProvider exportProvider) : IRemoteServiceProvider { private static readonly Dictionary s_factoryMap = BuildFactoryMap(); @@ -60,22 +58,17 @@ private static Dictionary BuildFactoryMap() CancellationToken cancellationToken, [CallerFilePath] string? callerFilePath = null, [CallerMemberName] string? callerMemberName = null) - where TService : class + where TService : class, IDisposable { Assert.True(s_factoryMap.TryGetValue(typeof(TService), out var factory)); - var testServiceBroker = new InterceptingServiceBroker(solution); + var testServiceBroker = new TestServiceBroker(solution); - // We don't ever use this stream, because we never really use ServiceHub, but going through its factory method means the - // remote services under test are using their full MEF composition etc. so we get excellent coverage. - var (stream, _) = FullDuplexStream.CreatePair(); - using var service = (IDisposable)await factory.CreateAsync(stream, _serviceProvider, serviceActivationOptions: default, testServiceBroker, authorizationServiceClient: default!); + var serviceFactory = (RazorServiceFactoryBase)factory; + using var service = serviceFactory.GetTestAccessor().CreateService(testServiceBroker, exportProvider); - // This is never used, we short-circuited things by passing the solution direct to the InterceptingServiceBroker + // This is never used, we short-circuited things by passing the solution direct to the TestServiceBroker var solutionInfo = new RazorPinnedSolutionInfoWrapper(); - - testOutputHelper.WriteLine($"Pretend OOP call for {typeof(TService).Name}, invocation: {Path.GetFileNameWithoutExtension(callerFilePath)}.{callerMemberName}"); - testOutputHelper.WriteLine($"Project assembly path: `{solution.Projects.First().CompilationOutputInfo.AssemblyPath ?? "null"}`"); - return await invocation((TService)service, solutionInfo, cancellationToken); + return await invocation(service, solutionInfo, cancellationToken); } } diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/InterceptingServiceBroker.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/TestServiceBroker.cs similarity index 53% rename from src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/InterceptingServiceBroker.cs rename to src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/TestServiceBroker.cs index 364f0effc00..8dfd9f38217 100644 --- a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/InterceptingServiceBroker.cs +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/TestServiceBroker.cs @@ -2,31 +2,16 @@ // Licensed under the MIT license. See License.txt in the project root for license information. using System; -using System.IO.Pipelines; using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.ExternalAccess.Razor; using Microsoft.CodeAnalysis.Remote.Razor; -using Microsoft.ServiceHub.Framework; namespace Microsoft.VisualStudio.LanguageServices.Razor.Test.Cohost; -internal class InterceptingServiceBroker(Solution solution) : IServiceBroker, IBrokeredServiceInterceptor +internal class TestServiceBroker(Solution solution) : IRazorServiceBroker { - public event EventHandler? AvailabilityChanged { add { } remove { } } - - public ValueTask GetPipeAsync(ServiceMoniker serviceMoniker, ServiceActivationOptions options = default, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public ValueTask GetProxyAsync(ServiceRpcDescriptor serviceDescriptor, ServiceActivationOptions options = default, CancellationToken cancellationToken = default) - where T : class - { - throw new NotImplementedException(); - } - public ValueTask RunServiceAsync(Func implementation, CancellationToken cancellationToken) { return implementation(cancellationToken); @@ -36,4 +21,8 @@ public ValueTask RunServiceAsync(RazorPinnedSolutionInfoWrapper solutionIn { return implementation(solution); } + + public void Dispose() + { + } } From 66e42475cc074e18a12984b786b7b8143573fc9f Mon Sep 17 00:00:00 2001 From: David Wengier Date: Fri, 12 Jul 2024 12:39:22 +1000 Subject: [PATCH 068/176] Clean up, and allow multple services to be used by a single endpoint --- .../ToolingTestBase.cs | 10 ++++ .../Cohost/CohostTestBase.cs | 14 +---- .../Cohost/ServiceFactoryMap.cs | 48 +++++++++++++++ .../Cohost/TestRemoteServiceProvider.cs | 58 ++++++++----------- .../Cohost/TestServiceBroker.cs | 12 +++- 5 files changed, 93 insertions(+), 49 deletions(-) create mode 100644 src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/ServiceFactoryMap.cs diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/ToolingTestBase.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/ToolingTestBase.cs index 8dad3a87185..15885cad28e 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/ToolingTestBase.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/ToolingTestBase.cs @@ -166,6 +166,16 @@ protected void AddDisposable(IDisposable disposable) _disposables.Add(disposable); } + /// + /// Register an instance to be disposed when the test completes. + /// + protected T AddDisposable(T disposable) + where T : IDisposable + { + AddDisposable((IDisposable)disposable); + return disposable; + } + /// /// Register a set of instances to be disposed when the test completes. /// diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostTestBase.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostTestBase.cs index 9a57b3b42d8..775a3f08ebf 100644 --- a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostTestBase.cs +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostTestBase.cs @@ -10,14 +10,12 @@ using Microsoft.CodeAnalysis.Razor.Remote; using Microsoft.CodeAnalysis.Remote.Razor; using Microsoft.CodeAnalysis.Text; -using Microsoft.VisualStudio.Composition; using Xunit.Abstractions; namespace Microsoft.VisualStudio.LanguageServices.Razor.Test.Cohost; public abstract class CohostTestBase(ITestOutputHelper testOutputHelper) : WorkspaceTestBase(testOutputHelper) { - private ExportProvider? _exportProvider; private IRemoteServiceProvider? _remoteServiceProvider; private protected IRemoteServiceProvider RemoteServiceProvider => _remoteServiceProvider.AssumeNotNull(); @@ -26,16 +24,8 @@ protected override async Task InitializeAsync() { await base.InitializeAsync(); - _exportProvider = await RemoteMefComposition.CreateExportProviderAsync(); - - _remoteServiceProvider = new TestRemoteServiceProvider(_exportProvider); - } - - protected override async Task DisposeAsync() - { - _exportProvider?.Dispose(); - - await base.DisposeAsync(); + var exportProvider = AddDisposable(await RemoteMefComposition.CreateExportProviderAsync()); + _remoteServiceProvider = AddDisposable(new TestRemoteServiceProvider(exportProvider)); } protected TextDocument CreateRazorDocument(string contents) diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/ServiceFactoryMap.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/ServiceFactoryMap.cs new file mode 100644 index 00000000000..ec32e4503a2 --- /dev/null +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/ServiceFactoryMap.cs @@ -0,0 +1,48 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT license. See License.txt in the project root for license information. + +using Microsoft.CodeAnalysis.Remote.Razor; +using Microsoft.ServiceHub.Framework; +using System.Collections.Generic; +using System.Linq; +using System; +using Xunit; + +namespace Microsoft.VisualStudio.LanguageServices.Razor.Test.Cohost; + +internal static class ServiceFactoryMap +{ + private static readonly Dictionary s_factoryMap = BuildFactoryMap(); + + private static Dictionary BuildFactoryMap() + { + var result = new Dictionary(); + + foreach (var type in typeof(RazorServiceFactoryBase<>).Assembly.GetTypes()) + { + if (!type.IsAbstract && + typeof(IServiceHubServiceFactory).IsAssignableFrom(type)) + { + Assert.Equal(typeof(RazorServiceFactoryBase<>), type.BaseType.GetGenericTypeDefinition()); + + var genericType = type.BaseType.GetGenericArguments().FirstOrDefault(); + if (genericType != null) + { + // ServiceHub requires a parameterless constructor, so we can safely rely on it existing too + var factory = (IServiceHubServiceFactory)Activator.CreateInstance(type); + result.Add(genericType, factory); + } + } + } + + return result; + } + + public static RazorServiceFactoryBase GetServiceFactory() + where TService : class + { + Assert.True(s_factoryMap.TryGetValue(typeof(TService), out var factory)); + + return (RazorServiceFactoryBase)factory; + } +} diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/TestRemoteServiceProvider.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/TestRemoteServiceProvider.cs index 88b0b7f5d8a..72745c0ed25 100644 --- a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/TestRemoteServiceProvider.cs +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/TestRemoteServiceProvider.cs @@ -3,53 +3,35 @@ using System; using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; using System.Runtime.CompilerServices; using System.Threading; using System.Threading.Tasks; -using Microsoft.AspNetCore.Razor.Test.Common.VisualStudio; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.ExternalAccess.Razor; using Microsoft.CodeAnalysis.Razor.Remote; -using Microsoft.CodeAnalysis.Remote.Razor; -using Microsoft.ServiceHub.Framework; using Microsoft.VisualStudio.Composition; -using Xunit; namespace Microsoft.VisualStudio.LanguageServices.Razor.Test.Cohost; /// /// An implementation of IRemoteServiceProvider that doesn't actually do anything remote, but rather directly calls service methods /// -internal class TestRemoteServiceProvider(ExportProvider exportProvider) : IRemoteServiceProvider +internal class TestRemoteServiceProvider(ExportProvider exportProvider) : IRemoteServiceProvider, IDisposable { - private static readonly Dictionary s_factoryMap = BuildFactoryMap(); + private readonly TestServiceBroker _testServiceBroker = new TestServiceBroker(); + private readonly Dictionary _services = new Dictionary(); - private readonly IServiceProvider _serviceProvider = VsMocks.CreateServiceProvider(b => b.AddService(serviceInstance: null)); - - private static Dictionary BuildFactoryMap() + private TService GetOrCreateService() + where TService : class, IDisposable { - var result = new Dictionary(); - - foreach (var type in typeof(RazorServiceFactoryBase<>).Assembly.GetTypes()) + if (!_services.TryGetValue(typeof(TService), out var service)) { - if (!type.IsAbstract && - typeof(IServiceHubServiceFactory).IsAssignableFrom(type)) - { - Assert.Equal(typeof(RazorServiceFactoryBase<>), type.BaseType.GetGenericTypeDefinition()); - - var genericType = type.BaseType.GetGenericArguments().FirstOrDefault(); - if (genericType != null) - { - // ServiceHub requires a parameterless constructor, so we can safely rely on it existing too - var factory = (IServiceHubServiceFactory)Activator.CreateInstance(type); - result.Add(genericType, factory); - } - } + var factory = ServiceFactoryMap.GetServiceFactory(); + service = factory.GetTestAccessor().CreateService(_testServiceBroker, exportProvider); + _services.Add(typeof(TService), service); } - return result; + return (TService)service; } public async ValueTask TryInvokeAsync( @@ -60,15 +42,21 @@ private static Dictionary BuildFactoryMap() [CallerMemberName] string? callerMemberName = null) where TService : class, IDisposable { - Assert.True(s_factoryMap.TryGetValue(typeof(TService), out var factory)); - - var testServiceBroker = new TestServiceBroker(solution); - - var serviceFactory = (RazorServiceFactoryBase)factory; - using var service = serviceFactory.GetTestAccessor().CreateService(testServiceBroker, exportProvider); + var service = GetOrCreateService(); - // This is never used, we short-circuited things by passing the solution direct to the TestServiceBroker + // In an ideal world we'd be able to maintain a dictionary of solution checksums in TestServiceBroker, and use + // the RazorPinnedSolutionInfoWrapper properly, but we need Roslyn changes for that. For now, this works fine + // as we don't have any code that makes multiple parallel calls to TryInvokeAsync in the same test. var solutionInfo = new RazorPinnedSolutionInfoWrapper(); + _testServiceBroker.UpdateSolution(solution); return await invocation(service, solutionInfo, cancellationToken); } + + public void Dispose() + { + foreach (var service in _services.Values) + { + service.Dispose(); + } + } } diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/TestServiceBroker.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/TestServiceBroker.cs index 8dfd9f38217..57e026d1d1c 100644 --- a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/TestServiceBroker.cs +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/TestServiceBroker.cs @@ -4,14 +4,22 @@ using System; using System.Threading; using System.Threading.Tasks; +using Microsoft.AspNetCore.Razor; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.ExternalAccess.Razor; using Microsoft.CodeAnalysis.Remote.Razor; namespace Microsoft.VisualStudio.LanguageServices.Razor.Test.Cohost; -internal class TestServiceBroker(Solution solution) : IRazorServiceBroker +internal class TestServiceBroker : IRazorServiceBroker { + private Solution? _solution; + + public void UpdateSolution(Solution solution) + { + _solution = solution; + } + public ValueTask RunServiceAsync(Func implementation, CancellationToken cancellationToken) { return implementation(cancellationToken); @@ -19,7 +27,7 @@ public ValueTask RunServiceAsync(Func implementati public ValueTask RunServiceAsync(RazorPinnedSolutionInfoWrapper solutionInfo, Func> implementation, CancellationToken cancellationToken) { - return implementation(solution); + return implementation(_solution.AssumeNotNull()); } public void Dispose() From 6d563c334c391202bba2cf89c4071e010e11276a Mon Sep 17 00:00:00 2001 From: Alex Gavrilov Date: Fri, 12 Jul 2024 00:44:02 -0700 Subject: [PATCH 069/176] Fix NRE when invoking completion in empty document (#10610) * Fix NRE when invoking completion in empty document In empty document completion context will have RazorDocumentSyntax as Owner. RazorDoucmentSyntax has null as the parent, which makes sense. However compiler thinks we can't have a null here, while obviously we do. I'm adding a null check and a test for this case. We would probably further discuss the implications here. I tried to track down how we get null in a non-nullable field, but it's a bit confusing since the class gets generated. * Move RazorDocumentSyntax special case inside switch per CR suggestion * Fixing build --- .../Completion/TagHelperCompletionProvider.cs | 6 ++++-- .../TagHelperCompletionProviderTest.cs | 17 +++++++++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Completion/TagHelperCompletionProvider.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Completion/TagHelperCompletionProvider.cs index 45eaf100a43..ba07f35576c 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Completion/TagHelperCompletionProvider.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Completion/TagHelperCompletionProvider.cs @@ -48,7 +48,7 @@ public ImmutableArray GetCompletionItems(RazorCompletionCon if (owner is null) { Debug.Fail("Owner should never be null."); - return ImmutableArray.Empty; + return []; } owner = owner switch @@ -56,6 +56,8 @@ public ImmutableArray GetCompletionItems(RazorCompletionCon // This provider is trying to find the nearest Start or End tag. Most of the time, that's a level up, but if the index the user is typing at // is a token of a start or end tag directly, we already have the node we want. MarkupStartTagSyntax or MarkupEndTagSyntax or MarkupTagHelperStartTagSyntax or MarkupTagHelperEndTagSyntax or MarkupTagHelperAttributeSyntax => owner, + // Invoking completion in an empty file will give us RazorDocumentSyntax which always has null parent + RazorDocumentSyntax => owner, // Either the parent is a context we can handle, or it's not and we shouldn't show completions. _ => owner.Parent }; @@ -118,7 +120,7 @@ static bool InOrAtEndOfAttribute(SyntaxNode attributeSyntax, int absoluteIndex) } // Invalid location for TagHelper completions. - return ImmutableArray.Empty; + return []; } private ImmutableArray GetAttributeCompletions( diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Completion/TagHelperCompletionProviderTest.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Completion/TagHelperCompletionProviderTest.cs index 7aa04148090..befa32e49dc 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Completion/TagHelperCompletionProviderTest.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Completion/TagHelperCompletionProviderTest.cs @@ -89,6 +89,23 @@ public void GetCompletionAt_AtEmptyTagName_ReturnsCompletions() completion => Assert.Equal("test2", completion.InsertText)); } + [Fact] + public void GetCompletionAt_InEmptyDocument_ReturnsEmptyCompletionArray() + { + // Arrange + var service = new TagHelperCompletionProvider(RazorTagHelperCompletionService, TestRazorLSPOptionsMonitor.Create()); + var context = CreateRazorCompletionContext( + "$$", + isRazorFile: true, + tagHelpers: DefaultTagHelpers); + + // Act + var completions = service.GetCompletionItems(context); + + // Assert + Assert.Empty(completions); + } + [Fact] public void GetCompletionAt_OutsideOfTagName_DoesNotReturnCompletions() { From 52debafc6068be464b24c62164dbb18738bd4c34 Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Fri, 12 Jul 2024 08:41:51 -0700 Subject: [PATCH 070/176] Remove one more unneeded array.Length check --- .../ImmutableArrayExtensions.cs | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/ImmutableArrayExtensions.cs b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/ImmutableArrayExtensions.cs index 42e3dc5e81e..c6c618123e2 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/ImmutableArrayExtensions.cs +++ b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/ImmutableArrayExtensions.cs @@ -210,13 +210,8 @@ public static int BinarySearchBy(this ImmutableArray array, TArg arg public static ImmutableArray OrderAsArray(this ImmutableArray array) { - if (array.Length > 1) - { - var compareHelper = new CompareHelper(comparer: null, descending: false); - return array.OrderAsArrayCore(in compareHelper); - } - - return array; + var compareHelper = new CompareHelper(comparer: null, descending: false); + return array.OrderAsArrayCore(in compareHelper); } public static ImmutableArray OrderAsArray(this ImmutableArray array, IComparer comparer) From ed5ddf056ae7749ed81a0999cf556684d346c5ba Mon Sep 17 00:00:00 2001 From: David Wengier Date: Mon, 15 Jul 2024 11:09:16 +1000 Subject: [PATCH 071/176] Cleanup linked editing range tests, and allow the use of real components --- ...> CohostLinkedEditingRangeEndpointTest.cs} | 26 ++++++++-- .../Cohost/CohostTestBase.cs | 47 +++++++++++++------ .../Cohost/ServiceFactoryMap.cs | 2 +- .../Cohost/TestRemoteServiceProvider.cs | 4 +- .../Cohost/TestServiceBroker.cs | 4 +- 5 files changed, 60 insertions(+), 23 deletions(-) rename src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/{CohostLinkedEditingRangeTest.cs => CohostLinkedEditingRangeEndpointTest.cs} (83%) diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostLinkedEditingRangeTest.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostLinkedEditingRangeEndpointTest.cs similarity index 83% rename from src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostLinkedEditingRangeTest.cs rename to src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostLinkedEditingRangeEndpointTest.cs index b84ad7a36ee..cf0d7346013 100644 --- a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostLinkedEditingRangeTest.cs +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostLinkedEditingRangeEndpointTest.cs @@ -13,10 +13,30 @@ using Xunit; using Xunit.Abstractions; -namespace Microsoft.VisualStudio.LanguageServices.Razor.Test.Cohost; +namespace Microsoft.VisualStudio.Razor.LanguageClient.Cohost; -public class CohostLinkedEditingRangeTest(ITestOutputHelper testOutputHelper) : CohostTestBase(testOutputHelper) +public class CohostLinkedEditingRangeEndpointTest(ITestOutputHelper testOutputHelper) : CohostTestBase(testOutputHelper) { + [Theory] + [InlineData("$$PageTitle", "PageTitle")] + [InlineData("Page$$Title", "PageTitle")] + [InlineData("PageTitle$$", "PageTitle")] + [InlineData("PageTitle", "$$PageTitle")] + [InlineData("PageTitle", "Page$$Title")] + [InlineData("PageTitle", "PageTitle$$")] + public async Task Component_StartAndEndTag(string startTag, string endTag) + { + var input = $""" + This is a Razor document. + + <[|{startTag}|]>This is the title + + The end. + """; + + await VerifyLinkedEditingRangeAsync(input); + } + [Theory] [InlineData("$$div")] [InlineData("di$$v")] @@ -141,7 +161,7 @@ The end. private async Task VerifyLinkedEditingRangeAsync(string input) { TestFileMarkupParser.GetPositionAndSpans(input, out input, out int cursorPosition, out ImmutableArray spans); - var document = CreateRazorDocument(input); + var document = CreateProjectAndRazorDocument(input); var sourceText = await document.GetTextAsync(DisposalToken); sourceText.GetLineAndOffset(cursorPosition, out var lineIndex, out var characterIndex); diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostTestBase.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostTestBase.cs index 775a3f08ebf..61b0d52d5a8 100644 --- a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostTestBase.cs +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostTestBase.cs @@ -2,7 +2,9 @@ // Licensed under the MIT license. See License.txt in the project root for license information. using System.IO; +using System.Linq; using System.Threading.Tasks; +using Basic.Reference.Assemblies; using Microsoft.AspNetCore.Razor; using Microsoft.AspNetCore.Razor.Test.Common; using Microsoft.AspNetCore.Razor.Test.Common.Workspaces; @@ -12,7 +14,7 @@ using Microsoft.CodeAnalysis.Text; using Xunit.Abstractions; -namespace Microsoft.VisualStudio.LanguageServices.Razor.Test.Cohost; +namespace Microsoft.VisualStudio.Razor.LanguageClient.Cohost; public abstract class CohostTestBase(ITestOutputHelper testOutputHelper) : WorkspaceTestBase(testOutputHelper) { @@ -28,7 +30,7 @@ protected override async Task InitializeAsync() _remoteServiceProvider = AddDisposable(new TestRemoteServiceProvider(exportProvider)); } - protected TextDocument CreateRazorDocument(string contents) + protected TextDocument CreateProjectAndRazorDocument(string contents) { var projectFilePath = TestProjectData.SomeProject.FilePath; var documentFilePath = TestProjectData.SomeProjectComponentFile1.FilePath; @@ -36,19 +38,34 @@ protected TextDocument CreateRazorDocument(string contents) var projectId = ProjectId.CreateNewId(debugName: projectName); var documentId = DocumentId.CreateNewId(projectId, debugName: documentFilePath); - var solution = Workspace.CurrentSolution.AddProject(ProjectInfo.Create( - projectId, - VersionStamp.Create(), - name: projectName, - assemblyName: projectName, - LanguageNames.CSharp, - documentFilePath)); - - solution = solution.AddAdditionalDocument( - documentId, - documentFilePath, - SourceText.From(contents), - filePath: documentFilePath); + var projectInfo = ProjectInfo + .Create( + projectId, + VersionStamp.Create(), + name: projectName, + assemblyName: projectName, + LanguageNames.CSharp, + documentFilePath) + .WithMetadataReferences(AspNet80.ReferenceInfos.All.Select(r => r.Reference)); + + var solution = Workspace.CurrentSolution.AddProject(projectInfo); + + solution = solution + .AddAdditionalDocument( + documentId, + documentFilePath, + SourceText.From(contents), + filePath: documentFilePath) + .AddAdditionalDocument( + DocumentId.CreateNewId(projectId), + name: "_Imports.razor", + text: SourceText.From(""" + @using Microsoft.AspNetCore.Components + @using Microsoft.AspNetCore.Components.Authorization + @using Microsoft.AspNetCore.Components.Routing + @using Microsoft.AspNetCore.Components.Web + """), + filePath: TestProjectData.SomeProjectComponentImportFile1.FilePath); return solution.GetAdditionalDocument(documentId).AssumeNotNull(); } diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/ServiceFactoryMap.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/ServiceFactoryMap.cs index ec32e4503a2..ecfa97db825 100644 --- a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/ServiceFactoryMap.cs +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/ServiceFactoryMap.cs @@ -8,7 +8,7 @@ using System; using Xunit; -namespace Microsoft.VisualStudio.LanguageServices.Razor.Test.Cohost; +namespace Microsoft.VisualStudio.Razor.LanguageClient.Cohost; internal static class ServiceFactoryMap { diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/TestRemoteServiceProvider.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/TestRemoteServiceProvider.cs index 72745c0ed25..3a82d4defce 100644 --- a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/TestRemoteServiceProvider.cs +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/TestRemoteServiceProvider.cs @@ -11,12 +11,12 @@ using Microsoft.CodeAnalysis.Razor.Remote; using Microsoft.VisualStudio.Composition; -namespace Microsoft.VisualStudio.LanguageServices.Razor.Test.Cohost; +namespace Microsoft.VisualStudio.Razor.LanguageClient.Cohost; /// /// An implementation of IRemoteServiceProvider that doesn't actually do anything remote, but rather directly calls service methods /// -internal class TestRemoteServiceProvider(ExportProvider exportProvider) : IRemoteServiceProvider, IDisposable +internal sealed class TestRemoteServiceProvider(ExportProvider exportProvider) : IRemoteServiceProvider, IDisposable { private readonly TestServiceBroker _testServiceBroker = new TestServiceBroker(); private readonly Dictionary _services = new Dictionary(); diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/TestServiceBroker.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/TestServiceBroker.cs index 57e026d1d1c..e0674da6f11 100644 --- a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/TestServiceBroker.cs +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/TestServiceBroker.cs @@ -9,9 +9,9 @@ using Microsoft.CodeAnalysis.ExternalAccess.Razor; using Microsoft.CodeAnalysis.Remote.Razor; -namespace Microsoft.VisualStudio.LanguageServices.Razor.Test.Cohost; +namespace Microsoft.VisualStudio.Razor.LanguageClient.Cohost; -internal class TestServiceBroker : IRazorServiceBroker +internal sealed class TestServiceBroker : IRazorServiceBroker { private Solution? _solution; From 96ba294262842e30811e3711b03be33357ef803f Mon Sep 17 00:00:00 2001 From: David Wengier Date: Mon, 15 Jul 2024 16:21:04 +1000 Subject: [PATCH 072/176] Share some files --- .../LanguageServer}/TestClientCapabilitiesService.cs | 0 .../LanguageServer}/TestRazorSemanticTokensLegendService.cs | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename src/Razor/test/{Microsoft.AspNetCore.Razor.LanguageServer.Test => Microsoft.AspNetCore.Razor.Test.Common.Tooling/LanguageServer}/TestClientCapabilitiesService.cs (100%) rename src/Razor/test/{Microsoft.AspNetCore.Razor.LanguageServer.Test/Semantic => Microsoft.AspNetCore.Razor.Test.Common.Tooling/LanguageServer}/TestRazorSemanticTokensLegendService.cs (100%) diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/TestClientCapabilitiesService.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/LanguageServer/TestClientCapabilitiesService.cs similarity index 100% rename from src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/TestClientCapabilitiesService.cs rename to src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/LanguageServer/TestClientCapabilitiesService.cs diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Semantic/TestRazorSemanticTokensLegendService.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/LanguageServer/TestRazorSemanticTokensLegendService.cs similarity index 100% rename from src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Semantic/TestRazorSemanticTokensLegendService.cs rename to src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/LanguageServer/TestRazorSemanticTokensLegendService.cs From 2ff5ca055b0effdf83f1b20fc06d797828231feb Mon Sep 17 00:00:00 2001 From: David Wengier Date: Mon, 15 Jul 2024 16:34:55 +1000 Subject: [PATCH 073/176] Create semantic tokens tests for cohosting --- .../CohostSemanticTokensRangeEndpoint.cs | 17 +- .../CohostSemanticTokensRangeEndpointTest.cs | 202 ++++++++++++++++++ .../Cohost/CohostTestBase.cs | 38 +++- ...lStudio.LanguageServices.Razor.Test.csproj | 4 + .../TestFiles/SemanticTokens/Legacy.txt | 54 +++++ .../SemanticTokens/Legacy_with_background.txt | 60 ++++++ .../TestFiles/SemanticTokens/Razor.txt | 71 ++++++ .../SemanticTokens/Razor_with_background.txt | 86 ++++++++ 8 files changed, 527 insertions(+), 5 deletions(-) create mode 100644 src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostSemanticTokensRangeEndpointTest.cs create mode 100644 src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/TestFiles/SemanticTokens/Legacy.txt create mode 100644 src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/TestFiles/SemanticTokens/Legacy_with_background.txt create mode 100644 src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/TestFiles/SemanticTokens/Razor.txt create mode 100644 src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/TestFiles/SemanticTokens/Razor_with_background.txt diff --git a/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/CohostSemanticTokensRangeEndpoint.cs b/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/CohostSemanticTokensRangeEndpoint.cs index d59809ccb74..cf12d711944 100644 --- a/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/CohostSemanticTokensRangeEndpoint.cs +++ b/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/CohostSemanticTokensRangeEndpoint.cs @@ -9,11 +9,13 @@ using Microsoft.AspNetCore.Razor; using Microsoft.AspNetCore.Razor.LanguageServer.Hosting; using Microsoft.AspNetCore.Razor.Telemetry; +using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.ExternalAccess.Razor.Cohost; using Microsoft.CodeAnalysis.Razor.Logging; using Microsoft.CodeAnalysis.Razor.Remote; using Microsoft.CodeAnalysis.Razor.SemanticTokens; using Microsoft.CodeAnalysis.Razor.Workspaces; +using Microsoft.CodeAnalysis.Text; using Microsoft.VisualStudio.LanguageServer.Protocol; using Microsoft.VisualStudio.Razor.LanguageClient.Extensions; using Microsoft.VisualStudio.Razor.Settings; @@ -68,11 +70,16 @@ internal sealed class CohostSemanticTokensRangeEndpoint( protected override RazorTextDocumentIdentifier? GetRazorTextDocumentIdentifier(SemanticTokensRangeParams request) => request.TextDocument.ToRazorTextDocumentIdentifier(); - protected override async Task HandleRequestAsync(SemanticTokensRangeParams request, RazorCohostRequestContext context, CancellationToken cancellationToken) + protected override Task HandleRequestAsync(SemanticTokensRangeParams request, RazorCohostRequestContext context, CancellationToken cancellationToken) { var razorDocument = context.TextDocument.AssumeNotNull(); var span = request.Range.ToLinePositionSpan(); + return HandleRequestAsync(razorDocument, span, cancellationToken); + } + + private async Task HandleRequestAsync(TextDocument razorDocument, LinePositionSpan span, CancellationToken cancellationToken) + { var colorBackground = _clientSettingsManager.GetClientSettings().AdvancedSettings.ColorBackground; var correlationId = Guid.NewGuid(); @@ -93,4 +100,12 @@ internal sealed class CohostSemanticTokensRangeEndpoint( return null; } + + internal TestAccessor GetTestAccessor() => new(this); + + internal readonly struct TestAccessor(CohostSemanticTokensRangeEndpoint instance) + { + public Task HandleRequestAsync(TextDocument razorDocument, LinePositionSpan span, CancellationToken cancellationToken) + => instance.HandleRequestAsync(razorDocument, span, cancellationToken); + } } diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostSemanticTokensRangeEndpointTest.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostSemanticTokensRangeEndpointTest.cs new file mode 100644 index 00000000000..55f80474f43 --- /dev/null +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostSemanticTokensRangeEndpointTest.cs @@ -0,0 +1,202 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT license. See License.txt in the project root for license information. + +using System.IO; +using System.Runtime.CompilerServices; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Razor.Language; +using Microsoft.AspNetCore.Razor.LanguageServer.Semantic; +using Microsoft.AspNetCore.Razor.PooledObjects; +using Microsoft.AspNetCore.Razor.Telemetry; +using Microsoft.CodeAnalysis.Razor.Settings; +using Microsoft.CodeAnalysis.Razor.Workspaces; +using Microsoft.CodeAnalysis.Remote.Razor.SemanticTokens; +using Microsoft.CodeAnalysis.Text; +using Microsoft.VisualStudio.Razor.Settings; +using Microsoft.VisualStudio.Utilities; +using Roslyn.Test.Utilities; +using Xunit; +using Xunit.Abstractions; + +namespace Microsoft.VisualStudio.Razor.LanguageClient.Cohost; + +public class CohostSemanticTokensRangeEndpointTest(ITestOutputHelper testOutputHelper) : CohostTestBase(testOutputHelper) +{ + [Theory] + [CombinatorialData] + public async Task Razor(bool colorBackground) + { + var input = """ + @page "/" + @using System + +
This is some HTML
+ + + + @* hello there *@ + + + @if (true) + { + Html! + } + + @code + { + // I am also good, thanks for asking + + /* + No problem. + */ + + private string someValue; + + public void M() + { + RenderFragment x = @
This is some HTML in a render fragment
; + } + } + """; + + await VerifySemanticTokensAsync(input, colorBackground); + } + + [Theory] + [CombinatorialData] + public async Task Legacy(bool colorBackground) + { + var input = """ + @page "/" + @using System + +
This is some HTML
+ + + + @functions + { + public void M() + { + } + } + + @section MySection { +
Section content
+ } + """; + + await VerifySemanticTokensAsync(input, colorBackground, fileKind: FileKinds.Legacy); + } + + private async Task VerifySemanticTokensAsync(string input, bool colorBackground, string? fileKind = null, [CallerMemberName] string? testName = null) + { + var document = CreateProjectAndRazorDocument(input, fileKind); + var sourceText = await document.GetTextAsync(DisposalToken); + + var legend = TestRazorSemanticTokensLegendService.Instance; + + // We need to manually initialize the OOP service so we can get semantic token info later + RemoteSemanticTokensLegendService.SetLegend(legend.TokenTypes.All, legend.TokenModifiers.All); + + var clientSettingsManager = new ClientSettingsManager([], null, null); + clientSettingsManager.Update(ClientAdvancedSettings.Default with { ColorBackground = colorBackground }); + + var endpoint = new CohostSemanticTokensRangeEndpoint(RemoteServiceProvider, clientSettingsManager, legend, NoOpTelemetryReporter.Instance, LoggerFactory); + + var span = new LinePositionSpan(new(0, 0), new(sourceText.Lines.Count, 0)); + + var result = await endpoint.GetTestAccessor().HandleRequestAsync(document, span, DisposalToken); + + var actualFileContents = GetTestOutput(sourceText, result?.Data); + + if (colorBackground) + { + testName += "_with_background"; + } + + var baselineFileName = $@"TestFiles\SemanticTokens\{testName}.txt"; + if (GenerateBaselines.ShouldGenerate) + { + WriteBaselineFile(actualFileContents, baselineFileName); + } + + var expectedFileContents = GetBaselineFileContents(baselineFileName); + AssertEx.EqualOrDiff(expectedFileContents, actualFileContents); + } + + private string GetBaselineFileContents(string baselineFileName) + { + var semanticFile = TestFile.Create(baselineFileName, GetType().Assembly); + if (!semanticFile.Exists()) + { + return string.Empty; + } + + return semanticFile.ReadAllText(); + } + + private static void WriteBaselineFile(string fileContents, string baselineFileName) + { + var projectPath = TestProject.GetProjectDirectory(typeof(CohostSemanticTokensRangeEndpointTest), layer: TestProject.Layer.Tooling); + var baselineFileFullPath = Path.Combine(projectPath, baselineFileName); + File.WriteAllText(baselineFileFullPath, fileContents); + } + + private static string GetTestOutput(SourceText sourceText, int[]? data) + { + if (data == null) + { + return string.Empty; + } + + using var _ = StringBuilderPool.GetPooledObject(out var builder); + builder.AppendLine("Line Δ, Char Δ, Length, Type, Modifier(s), Text"); + var tokenTypes = TestRazorSemanticTokensLegendService.Instance.TokenTypes.All; + var prevLength = 0; + var lineIndex = 0; + var lineOffset = 0; + for (var i = 0; i < data.Length; i += 5) + { + var lineDelta = data[i]; + var charDelta = data[i + 1]; + var length = data[i + 2]; + + Assert.False(i != 0 && lineDelta == 0 && charDelta == 0, "line delta and character delta are both 0, which is invalid as we shouldn't be producing overlapping tokens"); + Assert.False(i != 0 && lineDelta == 0 && charDelta < prevLength, "Previous length is longer than char offset from previous start, meaning tokens will overlap"); + + if (lineDelta != 0) + { + lineOffset = 0; + } + + lineIndex += lineDelta; + lineOffset += charDelta; + + var type = tokenTypes[data[i + 3]]; + var modifier = GetTokenModifierString(data[i + 4]); + var text = sourceText.GetSubTextString(new TextSpan(sourceText.Lines[lineIndex].Start + lineOffset, length)); + builder.AppendLine($"{lineDelta} {charDelta} {length} {type} {modifier} [{text}]"); + + prevLength = length; + } + + return builder.ToString(); + } + + private static string GetTokenModifierString(int tokenModifiers) + { + var modifiers = TestRazorSemanticTokensLegendService.Instance.TokenModifiers.All; + + var modifiersBuilder = ArrayBuilder.GetInstance(); + for (var i = 0; i < modifiers.Length; i++) + { + if ((tokenModifiers & (1 << i % 32)) != 0) + { + modifiersBuilder.Add(modifiers[i]); + } + } + + return $"[{string.Join(", ", modifiersBuilder.ToArrayAndFree())}]"; + } +} diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostTestBase.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostTestBase.cs index 61b0d52d5a8..614097f847e 100644 --- a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostTestBase.cs +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostTestBase.cs @@ -6,6 +6,7 @@ using System.Threading.Tasks; using Basic.Reference.Assemblies; using Microsoft.AspNetCore.Razor; +using Microsoft.AspNetCore.Razor.Language; using Microsoft.AspNetCore.Razor.Test.Common; using Microsoft.AspNetCore.Razor.Test.Common.Workspaces; using Microsoft.CodeAnalysis; @@ -18,6 +19,7 @@ namespace Microsoft.VisualStudio.Razor.LanguageClient.Cohost; public abstract class CohostTestBase(ITestOutputHelper testOutputHelper) : WorkspaceTestBase(testOutputHelper) { + private const string CSharpVirtualDocumentSuffix = ".g.cs"; private IRemoteServiceProvider? _remoteServiceProvider; private protected IRemoteServiceProvider RemoteServiceProvider => _remoteServiceProvider.AssumeNotNull(); @@ -28,12 +30,27 @@ protected override async Task InitializeAsync() var exportProvider = AddDisposable(await RemoteMefComposition.CreateExportProviderAsync()); _remoteServiceProvider = AddDisposable(new TestRemoteServiceProvider(exportProvider)); + + RemoteLanguageServerFeatureOptions.SetOptions(new() + { + CSharpVirtualDocumentSuffix = CSharpVirtualDocumentSuffix, + HtmlVirtualDocumentSuffix = ".g.html", + IncludeProjectKeyInGeneratedFilePath = false, + UsePreciseSemanticTokenRanges = false, + UseRazorCohostServer = true + }); } - protected TextDocument CreateProjectAndRazorDocument(string contents) + protected TextDocument CreateProjectAndRazorDocument(string contents, string? fileKind = null) { + // Using IsLegacy means null == component, so easier for test authors + var isComponent = !FileKinds.IsLegacy(fileKind); + + var documentFilePath = isComponent + ? TestProjectData.SomeProjectComponentFile1.FilePath + : TestProjectData.SomeProjectFile1.FilePath; + var projectFilePath = TestProjectData.SomeProject.FilePath; - var documentFilePath = TestProjectData.SomeProjectComponentFile1.FilePath; var projectName = Path.GetFileNameWithoutExtension(projectFilePath); var projectId = ProjectId.CreateNewId(debugName: projectName); var documentId = DocumentId.CreateNewId(projectId, debugName: documentFilePath); @@ -56,16 +73,29 @@ protected TextDocument CreateProjectAndRazorDocument(string contents) documentFilePath, SourceText.From(contents), filePath: documentFilePath) + .AddDocument( + DocumentId.CreateNewId(projectId), + name: documentFilePath + CSharpVirtualDocumentSuffix, + SourceText.From(""), + filePath: documentFilePath + CSharpVirtualDocumentSuffix) .AddAdditionalDocument( DocumentId.CreateNewId(projectId), - name: "_Imports.razor", + name: TestProjectData.SomeProjectComponentImportFile1.FilePath, text: SourceText.From(""" @using Microsoft.AspNetCore.Components @using Microsoft.AspNetCore.Components.Authorization + @using Microsoft.AspNetCore.Components.Forms @using Microsoft.AspNetCore.Components.Routing @using Microsoft.AspNetCore.Components.Web """), - filePath: TestProjectData.SomeProjectComponentImportFile1.FilePath); + filePath: TestProjectData.SomeProjectComponentImportFile1.FilePath) + .AddAdditionalDocument( + DocumentId.CreateNewId(projectId), + name: "_ViewImports.cshtml", + text: SourceText.From(""" + @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers + """), + filePath: TestProjectData.SomeProjectImportFile.FilePath); return solution.GetAdditionalDocument(documentId).AssumeNotNull(); } diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Microsoft.VisualStudio.LanguageServices.Razor.Test.csproj b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Microsoft.VisualStudio.LanguageServices.Razor.Test.csproj index 264ae60a47e..441ecb802fe 100644 --- a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Microsoft.VisualStudio.LanguageServices.Razor.Test.csproj +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Microsoft.VisualStudio.LanguageServices.Razor.Test.csproj @@ -30,4 +30,8 @@ + + + + diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/TestFiles/SemanticTokens/Legacy.txt b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/TestFiles/SemanticTokens/Legacy.txt new file mode 100644 index 00000000000..99325b3275a --- /dev/null +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/TestFiles/SemanticTokens/Legacy.txt @@ -0,0 +1,54 @@ +Line Δ, Char Δ, Length, Type, Modifier(s), Text +0 0 1 razorTransition [] [@] +0 1 4 razorDirective [] [page] +0 5 3 string [] ["/"] +1 0 1 razorTransition [] [@] +0 1 5 keyword [] [using] +0 6 6 namespace name [] [System] +2 0 1 markupTagDelimiter [] [<] +0 1 3 markupElement [] [div] +0 3 1 markupTagDelimiter [] [>] +0 18 1 markupTagDelimiter [] [<] +0 1 1 markupTagDelimiter [] [/] +0 1 3 markupElement [] [div] +0 3 1 markupTagDelimiter [] [>] +2 0 1 markupTagDelimiter [] [<] +0 1 9 razorTagHelperElement [] [component] +0 10 4 razorTagHelperAttribute [] [type] +0 4 1 markupOperator [] [=] +0 1 1 markupAttributeQuote [] ["] +0 1 6 keyword [] [typeof] +0 6 1 punctuation [] [(] +0 1 9 property name [] [Component] +0 9 1 punctuation [] [)] +0 1 1 markupAttributeQuote [] ["] +0 2 11 razorTagHelperAttribute [] [render-mode] +0 11 1 markupOperator [] [=] +0 1 1 markupAttributeQuote [] ["] +0 1 17 enum member name [] [ServerPrerendered] +0 17 1 markupAttributeQuote [] ["] +0 2 1 markupTagDelimiter [] [/] +0 1 1 markupTagDelimiter [] [>] +2 0 1 razorTransition [] [@] +0 1 9 razorDirective [] [functions] +1 0 1 razorTransition [] [{] +1 4 6 keyword [] [public] +0 7 4 keyword [] [void] +0 5 1 method name [] [M] +0 1 1 punctuation [] [(] +0 1 1 punctuation [] [)] +1 4 1 punctuation [] [{] +1 4 1 punctuation [] [}] +1 0 1 razorTransition [] [}] +2 0 1 razorTransition [] [@] +0 1 7 razorDirective [] [section] +0 8 9 local name [] [MySection] +0 10 1 razorTransition [] [{] +1 4 1 markupTagDelimiter [] [<] +0 1 3 markupElement [] [div] +0 3 1 markupTagDelimiter [] [>] +0 16 1 markupTagDelimiter [] [<] +0 1 1 markupTagDelimiter [] [/] +0 1 3 markupElement [] [div] +0 3 1 markupTagDelimiter [] [>] +1 0 1 razorTransition [] [}] diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/TestFiles/SemanticTokens/Legacy_with_background.txt b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/TestFiles/SemanticTokens/Legacy_with_background.txt new file mode 100644 index 00000000000..c2a10eb327f --- /dev/null +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/TestFiles/SemanticTokens/Legacy_with_background.txt @@ -0,0 +1,60 @@ +Line Δ, Char Δ, Length, Type, Modifier(s), Text +0 0 1 razorTransition [] [@] +0 1 4 razorDirective [] [page] +0 5 3 string [razorCode] ["/"] +1 0 1 razorTransition [] [@] +0 1 5 keyword [razorCode] [using] +0 5 1 markupTextLiteral [razorCode] [ ] +0 1 6 namespace name [razorCode] [System] +2 0 1 markupTagDelimiter [] [<] +0 1 3 markupElement [] [div] +0 3 1 markupTagDelimiter [] [>] +0 18 1 markupTagDelimiter [] [<] +0 1 1 markupTagDelimiter [] [/] +0 1 3 markupElement [] [div] +0 3 1 markupTagDelimiter [] [>] +2 0 1 markupTagDelimiter [] [<] +0 1 9 razorTagHelperElement [] [component] +0 10 4 razorTagHelperAttribute [] [type] +0 4 1 markupOperator [] [=] +0 1 1 markupAttributeQuote [] ["] +0 1 6 keyword [razorCode] [typeof] +0 6 1 punctuation [razorCode] [(] +0 1 9 property name [razorCode] [Component] +0 9 1 punctuation [razorCode] [)] +0 1 1 markupAttributeQuote [] ["] +0 2 11 razorTagHelperAttribute [] [render-mode] +0 11 1 markupOperator [] [=] +0 1 1 markupAttributeQuote [] ["] +0 1 17 enum member name [razorCode] [ServerPrerendered] +0 17 1 markupAttributeQuote [] ["] +0 2 1 markupTagDelimiter [] [/] +0 1 1 markupTagDelimiter [] [>] +2 0 1 razorTransition [] [@] +0 1 9 razorDirective [] [functions] +1 0 1 razorTransition [] [{] +1 0 4 markupTextLiteral [razorCode] [ ] +0 4 6 keyword [razorCode] [public] +0 6 1 markupTextLiteral [razorCode] [ ] +0 1 4 keyword [razorCode] [void] +0 4 1 markupTextLiteral [razorCode] [ ] +0 1 1 method name [razorCode] [M] +0 1 1 punctuation [razorCode] [(] +0 1 1 punctuation [razorCode] [)] +1 0 4 markupTextLiteral [razorCode] [ ] +0 4 1 punctuation [razorCode] [{] +1 0 4 markupTextLiteral [razorCode] [ ] +0 4 1 punctuation [razorCode] [}] +1 0 1 razorTransition [] [}] +2 0 1 razorTransition [] [@] +0 1 7 razorDirective [] [section] +0 8 9 local name [razorCode] [MySection] +0 10 1 razorTransition [] [{] +1 4 1 markupTagDelimiter [] [<] +0 1 3 markupElement [] [div] +0 3 1 markupTagDelimiter [] [>] +0 16 1 markupTagDelimiter [] [<] +0 1 1 markupTagDelimiter [] [/] +0 1 3 markupElement [] [div] +0 3 1 markupTagDelimiter [] [>] +1 0 1 razorTransition [] [}] diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/TestFiles/SemanticTokens/Razor.txt b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/TestFiles/SemanticTokens/Razor.txt new file mode 100644 index 00000000000..14db5713c1e --- /dev/null +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/TestFiles/SemanticTokens/Razor.txt @@ -0,0 +1,71 @@ +Line Δ, Char Δ, Length, Type, Modifier(s), Text +0 0 1 razorTransition [] [@] +0 1 4 razorDirective [] [page] +0 5 3 string [] ["/"] +1 0 1 razorTransition [] [@] +0 1 5 keyword [] [using] +0 6 6 namespace name [] [System] +2 0 1 markupTagDelimiter [] [<] +0 1 3 markupElement [] [div] +0 3 1 markupTagDelimiter [] [>] +0 18 1 markupTagDelimiter [] [<] +0 1 1 markupTagDelimiter [] [/] +0 1 3 markupElement [] [div] +0 3 1 markupTagDelimiter [] [>] +2 0 1 markupTagDelimiter [] [<] +0 1 9 razorComponentElement [] [InputText] +0 10 5 razorComponentAttribute [] [Value] +0 5 1 markupOperator [] [=] +0 1 1 markupAttributeQuote [] ["] +0 1 9 markupAttributeValue [] [someValue] +0 9 1 markupAttributeQuote [] ["] +0 2 1 markupTagDelimiter [] [/] +0 1 1 markupTagDelimiter [] [>] +2 0 1 razorCommentTransition [] [@] +0 1 1 razorCommentStar [] [*] +0 1 13 razorComment [] [ hello there ] +0 13 1 razorCommentStar [] [*] +0 1 1 razorCommentTransition [] [@] +1 0 4 markupCommentPunctuation [] [] +2 0 1 razorTransition [] [@] +0 1 2 keyword - control [] [if] +0 3 1 punctuation [] [(] +0 1 4 keyword [] [true] +0 4 1 punctuation [] [)] +1 0 1 punctuation [] [{] +1 4 6 razorDirective [] [] +0 11 7 razorDirective [] [] +1 0 1 punctuation [] [}] +2 0 1 razorTransition [] [@] +0 1 4 razorDirective [] [code] +1 0 1 razorTransition [] [{] +1 4 36 comment [] [// I am also good, thanks for asking] +2 4 2 comment [] [/*] +1 0 19 comment [] [ No problem.] +1 0 6 comment [] [ */] +2 4 7 keyword [] [private] +0 8 6 keyword [] [string] +0 7 9 field name [] [someValue] +0 9 1 punctuation [] [;] +2 4 6 keyword [] [public] +0 7 4 keyword [] [void] +0 5 1 method name [] [M] +0 1 1 punctuation [] [(] +0 1 1 punctuation [] [)] +1 4 1 punctuation [] [{] +1 8 14 delegate name [] [RenderFragment] +0 15 1 local name [] [x] +0 2 1 operator [] [=] +0 2 1 razorTransition [] [@] +0 1 1 markupTagDelimiter [] [<] +0 1 3 markupElement [] [div] +0 3 1 markupTagDelimiter [] [>] +0 39 1 markupTagDelimiter [] [<] +0 1 1 markupTagDelimiter [] [/] +0 1 3 markupElement [] [div] +0 3 1 markupTagDelimiter [] [>] +0 1 1 punctuation [] [;] +1 4 1 punctuation [] [}] +1 0 1 razorTransition [] [}] diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/TestFiles/SemanticTokens/Razor_with_background.txt b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/TestFiles/SemanticTokens/Razor_with_background.txt new file mode 100644 index 00000000000..59dc6ecd00f --- /dev/null +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/TestFiles/SemanticTokens/Razor_with_background.txt @@ -0,0 +1,86 @@ +Line Δ, Char Δ, Length, Type, Modifier(s), Text +0 0 1 razorTransition [] [@] +0 1 4 razorDirective [] [page] +0 5 3 string [razorCode] ["/"] +1 0 1 razorTransition [] [@] +0 1 5 keyword [razorCode] [using] +0 5 1 markupTextLiteral [razorCode] [ ] +0 1 6 namespace name [razorCode] [System] +2 0 1 markupTagDelimiter [] [<] +0 1 3 markupElement [] [div] +0 3 1 markupTagDelimiter [] [>] +0 18 1 markupTagDelimiter [] [<] +0 1 1 markupTagDelimiter [] [/] +0 1 3 markupElement [] [div] +0 3 1 markupTagDelimiter [] [>] +2 0 1 markupTagDelimiter [] [<] +0 1 9 razorComponentElement [] [InputText] +0 10 5 razorComponentAttribute [] [Value] +0 5 1 markupOperator [] [=] +0 1 1 markupAttributeQuote [] ["] +0 1 9 markupAttributeValue [] [someValue] +0 9 1 markupAttributeQuote [] ["] +0 2 1 markupTagDelimiter [] [/] +0 1 1 markupTagDelimiter [] [>] +2 0 1 razorCommentTransition [] [@] +0 1 1 razorCommentStar [] [*] +0 1 13 razorComment [] [ hello there ] +0 13 1 razorCommentStar [] [*] +0 1 1 razorCommentTransition [] [@] +1 0 4 markupCommentPunctuation [] [] +2 0 1 razorTransition [razorCode] [@] +0 1 2 keyword - control [razorCode] [if] +0 2 1 markupTextLiteral [razorCode] [ ] +0 1 1 punctuation [razorCode] [(] +0 1 4 keyword [razorCode] [true] +0 4 1 punctuation [razorCode] [)] +1 0 1 punctuation [razorCode] [{] +1 4 6 razorDirective [] [] +0 11 7 razorDirective [] [] +1 0 1 punctuation [razorCode] [}] +2 0 1 razorTransition [] [@] +0 1 4 razorDirective [] [code] +1 0 1 razorTransition [] [{] +1 0 4 markupTextLiteral [razorCode] [ ] +0 4 36 comment [razorCode] [// I am also good, thanks for asking] +2 0 4 markupTextLiteral [razorCode] [ ] +0 4 2 comment [razorCode] [/*] +1 0 19 comment [razorCode] [ No problem.] +1 0 6 comment [razorCode] [ */] +2 0 4 markupTextLiteral [razorCode] [ ] +0 4 7 keyword [razorCode] [private] +0 7 1 markupTextLiteral [razorCode] [ ] +0 1 6 keyword [razorCode] [string] +0 6 1 markupTextLiteral [razorCode] [ ] +0 1 9 field name [razorCode] [someValue] +0 9 1 punctuation [razorCode] [;] +2 0 4 markupTextLiteral [razorCode] [ ] +0 4 6 keyword [razorCode] [public] +0 6 1 markupTextLiteral [razorCode] [ ] +0 1 4 keyword [razorCode] [void] +0 4 1 markupTextLiteral [razorCode] [ ] +0 1 1 method name [razorCode] [M] +0 1 1 punctuation [razorCode] [(] +0 1 1 punctuation [razorCode] [)] +1 0 4 markupTextLiteral [razorCode] [ ] +0 4 1 punctuation [razorCode] [{] +1 0 8 markupTextLiteral [razorCode] [ ] +0 8 14 delegate name [razorCode] [RenderFragment] +0 14 1 markupTextLiteral [razorCode] [ ] +0 1 1 local name [razorCode] [x] +0 1 1 markupTextLiteral [razorCode] [ ] +0 1 1 operator [razorCode] [=] +0 2 1 razorTransition [razorCode] [@] +0 1 1 markupTagDelimiter [] [<] +0 1 3 markupElement [] [div] +0 3 1 markupTagDelimiter [] [>] +0 39 1 markupTagDelimiter [] [<] +0 1 1 markupTagDelimiter [] [/] +0 1 3 markupElement [] [div] +0 3 1 markupTagDelimiter [] [>] +0 1 1 punctuation [razorCode] [;] +1 0 4 markupTextLiteral [razorCode] [ ] +0 4 1 punctuation [razorCode] [}] +1 0 1 razorTransition [] [}] From 7a7998fd6605a4c2079b0fcf7c0ea07852f19228 Mon Sep 17 00:00:00 2001 From: David Wengier Date: Mon, 15 Jul 2024 17:06:11 +1000 Subject: [PATCH 074/176] =?UTF-8?q?Fix=20test=20data=20=F0=9F=A4=A6?= =?UTF-8?q?=E2=80=8D=E2=99=82=EF=B8=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../TestProjectData.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/TestProjectData.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/TestProjectData.cs index 181b115054e..15100f19680 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/TestProjectData.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/TestProjectData.cs @@ -25,10 +25,10 @@ static TestProjectData() SomeProject = new HostProject(Path.Combine(someProjectPath, "SomeProject.csproj"), someProjectObjPath, RazorConfiguration.Default, "SomeProject"); SomeProjectFile1 = new HostDocument(Path.Combine(someProjectPath, "File1.cshtml"), "File1.cshtml", FileKinds.Legacy); SomeProjectFile2 = new HostDocument(Path.Combine(someProjectPath, "File2.cshtml"), "File2.cshtml", FileKinds.Legacy); - SomeProjectImportFile = new HostDocument(Path.Combine(someProjectPath, "_Imports.cshtml"), "_Imports.cshtml", FileKinds.Legacy); + SomeProjectImportFile = new HostDocument(Path.Combine(someProjectPath, "_ViewImports.cshtml"), "_ViewImports.cshtml", FileKinds.Legacy); SomeProjectNestedFile3 = new HostDocument(Path.Combine(someProjectPath, "Nested", "File3.cshtml"), "Nested\\File3.cshtml", FileKinds.Legacy); SomeProjectNestedFile4 = new HostDocument(Path.Combine(someProjectPath, "Nested", "File4.cshtml"), "Nested\\File4.cshtml", FileKinds.Legacy); - SomeProjectNestedImportFile = new HostDocument(Path.Combine(someProjectPath, "Nested", "_Imports.cshtml"), "Nested\\_Imports.cshtml", FileKinds.Legacy); + SomeProjectNestedImportFile = new HostDocument(Path.Combine(someProjectPath, "Nested", "_ViewImports.cshtml"), "Nested\\_ViewImports.cshtml", FileKinds.Legacy); SomeProjectComponentFile1 = new HostDocument(Path.Combine(someProjectPath, "File1.razor"), "File1.razor", FileKinds.Component); SomeProjectComponentFile2 = new HostDocument(Path.Combine(someProjectPath, "File2.razor"), "File2.razor", FileKinds.Component); SomeProjectComponentImportFile1 = new HostDocument(Path.Combine(someProjectPath, "_Imports.razor"), "_Imports.razor", FileKinds.Component); @@ -42,10 +42,10 @@ static TestProjectData() AnotherProject = new HostProject(Path.Combine(anotherProjectPath, "AnotherProject.csproj"), anotherProjectObjPath, RazorConfiguration.Default, "AnotherProject"); AnotherProjectFile1 = new HostDocument(Path.Combine(anotherProjectPath, "File1.cshtml"), "File1.cshtml", FileKinds.Legacy); AnotherProjectFile2 = new HostDocument(Path.Combine(anotherProjectPath, "File2.cshtml"), "File2.cshtml", FileKinds.Legacy); - AnotherProjectImportFile = new HostDocument(Path.Combine(anotherProjectPath, "_Imports.cshtml"), "_Imports.cshtml", FileKinds.Legacy); + AnotherProjectImportFile = new HostDocument(Path.Combine(anotherProjectPath, "_ViewImports.cshtml"), "_ViewImports.cshtml", FileKinds.Legacy); AnotherProjectNestedFile3 = new HostDocument(Path.Combine(anotherProjectPath, "Nested", "File3.cshtml"), "Nested\\File1.cshtml", FileKinds.Legacy); AnotherProjectNestedFile4 = new HostDocument(Path.Combine(anotherProjectPath, "Nested", "File4.cshtml"), "Nested\\File2.cshtml", FileKinds.Legacy); - AnotherProjectNestedImportFile = new HostDocument(Path.Combine(anotherProjectPath, "Nested", "_Imports.cshtml"), "Nested\\_Imports.cshtml", FileKinds.Legacy); + AnotherProjectNestedImportFile = new HostDocument(Path.Combine(anotherProjectPath, "Nested", "_ViewImports.cshtml"), "Nested\\_ViewImports.cshtml", FileKinds.Legacy); AnotherProjectComponentFile1 = new HostDocument(Path.Combine(anotherProjectPath, "File1.razor"), "File1.razor", FileKinds.Component); AnotherProjectComponentFile2 = new HostDocument(Path.Combine(anotherProjectPath, "File2.razor"), "File2.razor", FileKinds.Component); AnotherProjectNestedComponentFile3 = new HostDocument(Path.Combine(anotherProjectPath, "Nested", "File3.razor"), "Nested\\File1.razor", FileKinds.Component); From a96e5f1e957a102076c3cafd0c76e855b3e7ff78 Mon Sep 17 00:00:00 2001 From: David Wengier Date: Mon, 15 Jul 2024 17:18:51 +1000 Subject: [PATCH 075/176] =?UTF-8?q?Fix=20bad=20tests=20that=20relied=20on?= =?UTF-8?q?=20previously=20bad=20test=20data=20=F0=9F=A4=A6=E2=80=8D?= =?UTF-8?q?=E2=99=82=EF=B8=8F=F0=9F=A4=A6=E2=80=8D=E2=99=82=EF=B8=8F?= =?UTF-8?q?=F0=9F=A4=A6=E2=80=8D=E2=99=82=EF=B8=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../TestImportProjectFeature.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/TestImportProjectFeature.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/TestImportProjectFeature.cs index ccb8d36bb09..92949eb6d03 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/TestImportProjectFeature.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/TestImportProjectFeature.cs @@ -26,7 +26,7 @@ public IReadOnlyList GetImports(RazorProjectItem projectItem) private void AddHierarchicalImports(RazorProjectItem projectItem, List imports) { // We want items in descending order. FindHierarchicalItems returns items in ascending order. - var importProjectItems = ProjectEngine.FileSystem.FindHierarchicalItems(projectItem.FilePath, "_Imports.cshtml").Reverse(); + var importProjectItems = ProjectEngine.FileSystem.FindHierarchicalItems(projectItem.FilePath, "_ViewImports.cshtml").Reverse(); imports.AddRange(importProjectItems); } } From 66427f4ef8b3193217956e6917e0415807259eff Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Mon, 15 Jul 2024 08:07:08 -0700 Subject: [PATCH 076/176] convert enumerables and enumerators to ref structs --- .../ReadOnlyListExtensions.cs | 32 ++++--------------- 1 file changed, 6 insertions(+), 26 deletions(-) diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/ReadOnlyListExtensions.cs b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/ReadOnlyListExtensions.cs index ee5f9773b50..61855e0ec91 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/ReadOnlyListExtensions.cs +++ b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/ReadOnlyListExtensions.cs @@ -880,30 +880,20 @@ public static T SingleOrDefault(this IReadOnlyList list, TArg arg, F public static Enumerable AsEnumerable(this IReadOnlyList list) => new(list); - public readonly struct Enumerable(IReadOnlyList list) : IEnumerable + public readonly ref struct Enumerable(IReadOnlyList list) { public Enumerator GetEnumerator() => new(list); - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - public ReverseEnumerable Reverse() => new(list); } - public struct Enumerator(IReadOnlyList list) : IEnumerator + public ref struct Enumerator(IReadOnlyList list) { private readonly IReadOnlyList _list = list; private int _index = 0; private T _current = default!; - public readonly T Current => _current!; - - readonly object IEnumerator.Current => _current!; - - public readonly void Dispose() - { - } + public readonly T Current => _current; public bool MoveNext() { @@ -924,24 +914,18 @@ public void Reset() } } - public readonly struct ReverseEnumerable(IReadOnlyList list) : IEnumerable + public readonly ref struct ReverseEnumerable(IReadOnlyList list) { public ReverseEnumerator GetEnumerator() => new(list); - - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); } - public struct ReverseEnumerator : IEnumerator + public ref struct ReverseEnumerator { private readonly IReadOnlyList _list; private int _index; private T _current; - public readonly T Current => _current!; - - readonly object IEnumerator.Current => _current!; + public readonly T Current => _current; public ReverseEnumerator(IReadOnlyList list) { @@ -950,10 +934,6 @@ public ReverseEnumerator(IReadOnlyList list) _current = default!; } - public readonly void Dispose() - { - } - public bool MoveNext() { if (_index >= 0) From 9c1c4f42a660a372359c479f4dbf062dec48b224 Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Mon, 15 Jul 2024 08:16:35 -0700 Subject: [PATCH 077/176] convert enumerables and enumerators to ref structs --- .../ReadOnlyListExtensions.cs | 29 +++++++------------ 1 file changed, 10 insertions(+), 19 deletions(-) diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/ReadOnlyListExtensions.cs b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/ReadOnlyListExtensions.cs index d5cc1e4c64c..0be8b6be86d 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/ReadOnlyListExtensions.cs +++ b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/ReadOnlyListExtensions.cs @@ -33,35 +33,26 @@ static ImmutableArray BuildResult(IReadOnlyList items, Func AsEnumerable(this IReadOnlyList source) => new(source); + public static Enumerable AsEnumerable(this IReadOnlyList list) => new(list); - public readonly struct Enumerable(IReadOnlyList source) : IEnumerable + public readonly ref struct Enumerable(IReadOnlyList list) { - public Enumerator GetEnumerator() => new(source); - - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + public Enumerator GetEnumerator() => new(list); } - public struct Enumerator(IReadOnlyList source) : IEnumerator + public ref struct Enumerator(IReadOnlyList list) { - private int _index; - private T _current; - - public readonly T Current => _current!; + private readonly IReadOnlyList _list = list; + private int _index = 0; + private T _current = default!; - readonly object IEnumerator.Current => _current!; - - public readonly void Dispose() - { - } + public readonly T Current => _current; public bool MoveNext() { - if (_index < source.Count) + if (_index < _list.Count) { - _current = source[_index]; + _current = _list[_index]; _index++; return true; } From 2ebe03ee23ca3b30910a13ff7fa46dd3f4256163 Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Mon, 15 Jul 2024 08:17:29 -0700 Subject: [PATCH 078/176] Pass variable rather than reading property again --- .../src/Language/DefaultRazorTagHelperContextDiscoveryPhase.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/DefaultRazorTagHelperContextDiscoveryPhase.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/DefaultRazorTagHelperContextDiscoveryPhase.cs index a059ae0a44c..03c343695c8 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/DefaultRazorTagHelperContextDiscoveryPhase.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/DefaultRazorTagHelperContextDiscoveryPhase.cs @@ -174,7 +174,7 @@ void ComputeNonComponentTagHelpersMap() if (!_nonComponentTagHelperMap.TryGetValue(currentAssemblyName, out currentTagHelpers)) { currentTagHelpers = s_pool.Get(); - _nonComponentTagHelperMap.Add(tagHelper.AssemblyName, currentTagHelpers); + _nonComponentTagHelperMap.Add(currentAssemblyName, currentTagHelpers); } } From 125fcd8ed5c115bd7492843f08d810f01dcb0e8b Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Mon, 15 Jul 2024 08:33:30 -0700 Subject: [PATCH 079/176] Clean up RazorServiceFactoryBase a bit --- .../RazorServiceFactoryBase.cs | 29 +++++-------------- 1 file changed, 7 insertions(+), 22 deletions(-) diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorServiceFactoryBase.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorServiceFactoryBase.cs index 32d4f4e6084..7c380ab1e36 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorServiceFactoryBase.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorServiceFactoryBase.cs @@ -13,26 +13,14 @@ namespace Microsoft.CodeAnalysis.Remote.Razor; -/// -/// -/// /// -/// Implementors of (and thus this class) MUST provide a parameterless constructor or ServiceHub will fail to construct them. +/// Implementors of (and thus this class) MUST provide a parameterless constructor +/// or ServiceHub will fail to construct them. /// -internal abstract class RazorServiceFactoryBase : IServiceHubServiceFactory where TService : class +internal abstract class RazorServiceFactoryBase(RazorServiceDescriptorsWrapper serviceDescriptors) : IServiceHubServiceFactory + where TService : class { - private readonly RazorServiceDescriptorsWrapper _razorServiceDescriptors; - - /// - /// - /// - /// - /// Implementors of (and thus this class) MUST provide a parameterless constructor or ServiceHub will fail to construct them. - /// - public RazorServiceFactoryBase(RazorServiceDescriptorsWrapper razorServiceDescriptors) - { - _razorServiceDescriptors = razorServiceDescriptors; - } + private readonly RazorServiceDescriptorsWrapper _serviceDescriptors = serviceDescriptors; public async Task CreateAsync( Stream stream, @@ -48,7 +36,7 @@ public async Task CreateAsync( var pipe = stream.UsePipe(); - var descriptor = _razorServiceDescriptors.GetDescriptorForServiceFactory(typeof(TService)); + var descriptor = _serviceDescriptors.GetDescriptorForServiceFactory(typeof(TService)); var serverConnection = descriptor.WithTraceSource(traceSource).ConstructRpcConnection(pipe); var exportProvider = await RemoteMefComposition.GetExportProviderAsync().ConfigureAwait(false); @@ -65,10 +53,7 @@ public async Task CreateAsync( protected abstract TService CreateService(IRazorServiceBroker serviceBroker, ExportProvider exportProvider); - internal TestAccessor GetTestAccessor() - { - return new TestAccessor(this); - } + internal TestAccessor GetTestAccessor() => new(this); internal readonly struct TestAccessor(RazorServiceFactoryBase instance) { From 12b2025a4a8f3a760cf9d55b84758fee34928ad2 Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Mon, 15 Jul 2024 08:36:04 -0700 Subject: [PATCH 080/176] Rename RazorServiceBase to RazorBrokeredServiceBase and clean up a bit --- .../RemoteClientInitializationService.cs | 2 +- ...ServiceBase.cs => RazorBrokeredServiceBase.cs} | 15 +++++---------- .../RazorDocumentServiceBase.cs | 2 +- .../TagHelpers/RemoteTagHelperProviderService.cs | 2 +- 4 files changed, 8 insertions(+), 13 deletions(-) rename src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/{RazorServiceBase.cs => RazorBrokeredServiceBase.cs} (58%) diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Initialization/RemoteClientInitializationService.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Initialization/RemoteClientInitializationService.cs index d5d316c971e..56bcbb52619 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Initialization/RemoteClientInitializationService.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Initialization/RemoteClientInitializationService.cs @@ -10,7 +10,7 @@ namespace Microsoft.CodeAnalysis.Remote.Razor; internal sealed class RemoteClientInitializationService( IRazorServiceBroker serviceBroker) - : RazorServiceBase(serviceBroker), IRemoteClientInitializationService + : RazorBrokeredServiceBase(serviceBroker), IRemoteClientInitializationService { public ValueTask InitializeAsync(RemoteClientInitializationOptions options, CancellationToken cancellationToken) => RunServiceAsync(ct => diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorServiceBase.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorBrokeredServiceBase.cs similarity index 58% rename from src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorServiceBase.cs rename to src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorBrokeredServiceBase.cs index c9ea08672ec..abf4b6fde01 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorServiceBase.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorBrokeredServiceBase.cs @@ -8,23 +8,18 @@ namespace Microsoft.CodeAnalysis.Remote.Razor; -internal abstract class RazorServiceBase : IDisposable +internal abstract class RazorBrokeredServiceBase(IRazorServiceBroker serviceBroker) : IDisposable { - private readonly IRazorServiceBroker _razorServiceBroker; - - public RazorServiceBase(IRazorServiceBroker razorServiceBroker) - { - _razorServiceBroker = razorServiceBroker; - } + private readonly IRazorServiceBroker _serviceBroker = serviceBroker; protected ValueTask RunServiceAsync(Func implementation, CancellationToken cancellationToken) - => _razorServiceBroker.RunServiceAsync(implementation, cancellationToken); + => _serviceBroker.RunServiceAsync(implementation, cancellationToken); protected ValueTask RunServiceAsync(RazorPinnedSolutionInfoWrapper solutionInfo, Func> implementation, CancellationToken cancellationToken) - => _razorServiceBroker.RunServiceAsync(solutionInfo, implementation, cancellationToken); + => _serviceBroker.RunServiceAsync(solutionInfo, implementation, cancellationToken); public void Dispose() { - _razorServiceBroker.Dispose(); + _serviceBroker.Dispose(); } } diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorDocumentServiceBase.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorDocumentServiceBase.cs index bf2f8c0ef61..6361d5ec64a 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorDocumentServiceBase.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorDocumentServiceBase.cs @@ -12,7 +12,7 @@ namespace Microsoft.CodeAnalysis.Remote.Razor; internal abstract class RazorDocumentServiceBase( IRazorServiceBroker serviceBroker, DocumentSnapshotFactory documentSnapshotFactory) - : RazorServiceBase(serviceBroker) + : RazorBrokeredServiceBase(serviceBroker) { protected DocumentSnapshotFactory DocumentSnapshotFactory { get; } = documentSnapshotFactory; diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/TagHelpers/RemoteTagHelperProviderService.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/TagHelpers/RemoteTagHelperProviderService.cs index 7d8d80659a1..7564b3f7f4b 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/TagHelpers/RemoteTagHelperProviderService.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/TagHelpers/RemoteTagHelperProviderService.cs @@ -17,7 +17,7 @@ internal sealed class RemoteTagHelperProviderService( IRazorServiceBroker serviceBroker, RemoteTagHelperResolver tagHelperResolver, RemoteTagHelperDeltaProvider tagHelperDeltaProvider) - : RazorServiceBase(serviceBroker), IRemoteTagHelperProviderService + : RazorBrokeredServiceBase(serviceBroker), IRemoteTagHelperProviderService { private readonly RemoteTagHelperResolver _tagHelperResolver = tagHelperResolver; private readonly RemoteTagHelperDeltaProvider _tagHelperDeltaProvider = tagHelperDeltaProvider; From 24e35a1771488d8ee9ad87e8e632bab64c3cd962 Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Mon, 15 Jul 2024 09:32:10 -0700 Subject: [PATCH 081/176] Rework RazorServiceFactoryBase into nested class with simple args --- eng/targets/Services.props | 14 ++-- .../Remote/RazorServices.cs | 4 +- .../RemoteFoldingRangeService.Factory.cs | 15 +++++ .../RemoteFoldingRangeService.cs | 29 +++++---- .../RemoteFoldingRangeServiceFactory.cs | 27 -------- .../RemoteHtmlDocumentService.Factory.cs | 15 +++++ .../RemoteHtmlDocumentService.cs | 10 +-- .../RemoteHtmlDocumentServiceFactory.cs | 23 ------- ...moteClientInitializationService.Factory.cs | 15 +++++ .../RemoteClientInitializationService.cs | 4 +- ...emoteClientInitializationServiceFactory.cs | 21 ------ ...RemoteLinkedEditingRangeService.Factory.cs | 15 +++++ .../RemoteLinkedEditingRangeService.cs | 22 +++---- .../RemoteLinkedEditingRangeServiceFactory.cs | 26 -------- .../RazorBrokeredServiceBase.FactoryBase`1.cs | 65 +++++++++++++++++++ .../RazorBrokeredServiceBase.cs | 15 ++++- .../RazorDocumentServiceBase.cs | 13 ++-- .../RazorServiceFactoryBase.cs | 63 ------------------ .../RemoteSemanticTokensService.Factory.cs | 15 +++++ .../RemoteSemanticTokensService.cs | 28 +++++--- .../RemoteSemanticTokensServiceFactory.cs | 25 ------- .../ServiceArgs.cs | 12 ++++ .../RemoteTagHelperProviderService.Factory.cs | 15 +++++ .../RemoteTagHelperProviderService.cs | 10 +-- .../RemoteTagHelperProviderServiceFactory.cs | 24 ------- .../RemoteUriPresentationService.Factory.cs | 15 +++++ .../RemoteUriPresentationService.cs | 28 ++++---- .../RemoteUriPresentationServiceFactory.cs | 27 -------- .../Cohost/ServiceFactoryMap.cs | 14 ++-- 29 files changed, 287 insertions(+), 322 deletions(-) create mode 100644 src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/FoldingRanges/RemoteFoldingRangeService.Factory.cs delete mode 100644 src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/FoldingRanges/RemoteFoldingRangeServiceFactory.cs create mode 100644 src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/HtmlDocuments/RemoteHtmlDocumentService.Factory.cs delete mode 100644 src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/HtmlDocuments/RemoteHtmlDocumentServiceFactory.cs create mode 100644 src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Initialization/RemoteClientInitializationService.Factory.cs delete mode 100644 src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Initialization/RemoteClientInitializationServiceFactory.cs create mode 100644 src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/LinkedEditingRange/RemoteLinkedEditingRangeService.Factory.cs delete mode 100644 src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/LinkedEditingRange/RemoteLinkedEditingRangeServiceFactory.cs create mode 100644 src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorBrokeredServiceBase.FactoryBase`1.cs delete mode 100644 src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorServiceFactoryBase.cs create mode 100644 src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/SemanticTokens/RemoteSemanticTokensService.Factory.cs delete mode 100644 src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/SemanticTokens/RemoteSemanticTokensServiceFactory.cs create mode 100644 src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/ServiceArgs.cs create mode 100644 src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/TagHelpers/RemoteTagHelperProviderService.Factory.cs delete mode 100644 src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/TagHelpers/RemoteTagHelperProviderServiceFactory.cs create mode 100644 src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/UriPresentation/RemoteUriPresentationService.Factory.cs delete mode 100644 src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/UriPresentation/RemoteUriPresentationServiceFactory.cs diff --git a/eng/targets/Services.props b/eng/targets/Services.props index 9b8e60c7d2f..9990daed115 100644 --- a/eng/targets/Services.props +++ b/eng/targets/Services.props @@ -15,12 +15,12 @@ For example, if your service interface is IRemoteFrobulatorService, then the Include should be "Microsoft.VisualStudio.Razor.Frobulator". --> - - - - - - - + + + + + + + diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/RazorServices.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/RazorServices.cs index a4584786c06..a33f9dd3fa9 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/RazorServices.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/RazorServices.cs @@ -1,8 +1,6 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT license. See License.txt in the project root for license information. -using System.Collections.Immutable; -using MessagePack.Formatters; using Microsoft.AspNetCore.Razor.Serialization.MessagePack.Resolvers; using Microsoft.CodeAnalysis.ExternalAccess.Razor; @@ -15,7 +13,7 @@ internal static class RazorServices public static readonly RazorServiceDescriptorsWrapper Descriptors = new( ComponentName, featureDisplayNameProvider: feature => $"Razor {feature} Feature", - additionalFormatters: ImmutableArray.Empty, + additionalFormatters: [], additionalResolvers: TopLevelResolvers.All, interfaces: [ diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/FoldingRanges/RemoteFoldingRangeService.Factory.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/FoldingRanges/RemoteFoldingRangeService.Factory.cs new file mode 100644 index 00000000000..34abbcf45cf --- /dev/null +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/FoldingRanges/RemoteFoldingRangeService.Factory.cs @@ -0,0 +1,15 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT license. See License.txt in the project root for license information. + +using Microsoft.CodeAnalysis.Razor.Remote; + +namespace Microsoft.CodeAnalysis.Remote.Razor; + +internal sealed partial class RemoteFoldingRangeService +{ + internal sealed class Factory : FactoryBase + { + protected override IRemoteFoldingRangeService CreateService(in ServiceArgs args) + => new RemoteFoldingRangeService(in args); + } +} diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/FoldingRanges/RemoteFoldingRangeService.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/FoldingRanges/RemoteFoldingRangeService.cs index 0d171ddc3d1..6331b182b60 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/FoldingRanges/RemoteFoldingRangeService.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/FoldingRanges/RemoteFoldingRangeService.cs @@ -12,31 +12,34 @@ using Microsoft.CodeAnalysis.Razor.Workspaces; using Microsoft.CodeAnalysis.Remote.Razor.ProjectSystem; using Microsoft.VisualStudio.LanguageServer.Protocol; +using ExternalHandlers = Microsoft.CodeAnalysis.ExternalAccess.Razor.Cohost.Handlers; namespace Microsoft.CodeAnalysis.Remote.Razor; -internal sealed class RemoteFoldingRangeService( - IRazorServiceBroker serviceBroker, - IFoldingRangeService foldingRangeService, - DocumentSnapshotFactory documentSnapshotFactory, - IFilePathService filePathService) - : RazorDocumentServiceBase(serviceBroker, documentSnapshotFactory), IRemoteFoldingRangeService +internal sealed partial class RemoteFoldingRangeService(in ServiceArgs args) : RazorDocumentServiceBase(in args), IRemoteFoldingRangeService { - private readonly IFoldingRangeService _foldingRangeService = foldingRangeService; - private readonly IFilePathService _filePathService = filePathService; - - public ValueTask> GetFoldingRangesAsync(RazorPinnedSolutionInfoWrapper solutionInfo, DocumentId documentId, ImmutableArray htmlRanges, CancellationToken cancellationToken) + private readonly IFoldingRangeService _foldingRangeService = args.ExportProvider.GetExportedValue(); + private readonly IFilePathService _filePathService = args.ExportProvider.GetExportedValue(); + + public ValueTask> GetFoldingRangesAsync( + RazorPinnedSolutionInfoWrapper solutionInfo, + DocumentId documentId, + ImmutableArray htmlRanges, + CancellationToken cancellationToken) => RunServiceAsync( solutionInfo, documentId, context => GetFoldingRangesAsync(context, htmlRanges, cancellationToken), cancellationToken); - private async ValueTask> GetFoldingRangesAsync(RemoteDocumentContext context, ImmutableArray htmlRanges, CancellationToken cancellationToken) + private async ValueTask> GetFoldingRangesAsync( + RemoteDocumentContext context, + ImmutableArray htmlRanges, + CancellationToken cancellationToken) { var generatedDocument = await context.GetGeneratedDocumentAsync(_filePathService, cancellationToken).ConfigureAwait(false); - var csharpRanges = await ExternalAccess.Razor.Cohost.Handlers.FoldingRanges.GetFoldingRangesAsync(generatedDocument, cancellationToken).ConfigureAwait(false); + var csharpRanges = await ExternalHandlers.FoldingRanges.GetFoldingRangesAsync(generatedDocument, cancellationToken).ConfigureAwait(false); var convertedCSharp = csharpRanges.SelectAsArray(ToFoldingRange); var convertedHtml = htmlRanges.SelectAsArray(RemoteFoldingRange.ToLspFoldingRange); @@ -47,7 +50,7 @@ private async ValueTask> GetFoldingRangesAsyn } public static FoldingRange ToFoldingRange(Roslyn.LanguageServer.Protocol.FoldingRange r) - => new FoldingRange + => new() { StartLine = r.StartLine, StartCharacter = r.StartCharacter, diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/FoldingRanges/RemoteFoldingRangeServiceFactory.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/FoldingRanges/RemoteFoldingRangeServiceFactory.cs deleted file mode 100644 index 6afdd17fa6c..00000000000 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/FoldingRanges/RemoteFoldingRangeServiceFactory.cs +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the MIT license. See License.txt in the project root for license information. - -using Microsoft.CodeAnalysis.Razor.FoldingRanges; -using Microsoft.CodeAnalysis.Razor.Remote; -using Microsoft.CodeAnalysis.Razor.Workspaces; -using Microsoft.CodeAnalysis.Remote.Razor.ProjectSystem; -using Microsoft.VisualStudio.Composition; - -namespace Microsoft.CodeAnalysis.Remote.Razor; - -internal sealed class RemoteFoldingRangeServiceFactory : RazorServiceFactoryBase -{ - // WARNING: We must always have a parameterless constructor in order to be properly handled by ServiceHub. - public RemoteFoldingRangeServiceFactory() - : base(RazorServices.Descriptors) - { - } - - protected override IRemoteFoldingRangeService CreateService(IRazorServiceBroker serviceBroker, ExportProvider exportProvider) - { - var infoService = exportProvider.GetExportedValue(); - var documentSnapshotFactory = exportProvider.GetExportedValue(); - var filePathService = exportProvider.GetExportedValue(); - return new RemoteFoldingRangeService(serviceBroker, infoService, documentSnapshotFactory, filePathService); - } -} diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/HtmlDocuments/RemoteHtmlDocumentService.Factory.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/HtmlDocuments/RemoteHtmlDocumentService.Factory.cs new file mode 100644 index 00000000000..91db19d8774 --- /dev/null +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/HtmlDocuments/RemoteHtmlDocumentService.Factory.cs @@ -0,0 +1,15 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT license. See License.txt in the project root for license information. + +using Microsoft.CodeAnalysis.Razor.Remote; + +namespace Microsoft.CodeAnalysis.Remote.Razor; + +internal sealed partial class RemoteHtmlDocumentService +{ + internal sealed class Factory : FactoryBase + { + protected override IRemoteHtmlDocumentService CreateService(in ServiceArgs args) + => new RemoteHtmlDocumentService(in args); + } +} diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/HtmlDocuments/RemoteHtmlDocumentService.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/HtmlDocuments/RemoteHtmlDocumentService.cs index fd7d305251c..a2c32ea5df4 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/HtmlDocuments/RemoteHtmlDocumentService.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/HtmlDocuments/RemoteHtmlDocumentService.cs @@ -10,12 +10,12 @@ namespace Microsoft.CodeAnalysis.Remote.Razor; -internal sealed class RemoteHtmlDocumentService( - IRazorServiceBroker serviceBroker, - DocumentSnapshotFactory documentSnapshotFactory) - : RazorDocumentServiceBase(serviceBroker, documentSnapshotFactory), IRemoteHtmlDocumentService +internal sealed partial class RemoteHtmlDocumentService(in ServiceArgs args) : RazorDocumentServiceBase(in args), IRemoteHtmlDocumentService { - public ValueTask GetHtmlDocumentTextAsync(RazorPinnedSolutionInfoWrapper solutionInfo, DocumentId razorDocumentId, CancellationToken cancellationToken) + public ValueTask GetHtmlDocumentTextAsync( + RazorPinnedSolutionInfoWrapper solutionInfo, + DocumentId razorDocumentId, + CancellationToken cancellationToken) => RunServiceAsync( solutionInfo, razorDocumentId, diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/HtmlDocuments/RemoteHtmlDocumentServiceFactory.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/HtmlDocuments/RemoteHtmlDocumentServiceFactory.cs deleted file mode 100644 index f55a1a0a5e9..00000000000 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/HtmlDocuments/RemoteHtmlDocumentServiceFactory.cs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the MIT license. See License.txt in the project root for license information. - -using Microsoft.CodeAnalysis.Razor.Remote; -using Microsoft.CodeAnalysis.Remote.Razor.ProjectSystem; -using Microsoft.VisualStudio.Composition; - -namespace Microsoft.CodeAnalysis.Remote.Razor; - -internal sealed class RemoteHtmlDocumentServiceFactory : RazorServiceFactoryBase -{ - // WARNING: We must always have a parameterless constructor in order to be properly handled by ServiceHub. - public RemoteHtmlDocumentServiceFactory() - : base(RazorServices.Descriptors) - { - } - - protected override IRemoteHtmlDocumentService CreateService(IRazorServiceBroker serviceBroker, ExportProvider exportProvider) - { - var documentSnapshotFactory = exportProvider.GetExportedValue(); - return new RemoteHtmlDocumentService(serviceBroker, documentSnapshotFactory); - } -} diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Initialization/RemoteClientInitializationService.Factory.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Initialization/RemoteClientInitializationService.Factory.cs new file mode 100644 index 00000000000..2fbdc9ff968 --- /dev/null +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Initialization/RemoteClientInitializationService.Factory.cs @@ -0,0 +1,15 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT license. See License.txt in the project root for license information. + +using Microsoft.CodeAnalysis.Razor.Remote; + +namespace Microsoft.CodeAnalysis.Remote.Razor; + +internal sealed partial class RemoteClientInitializationService +{ + internal sealed class Factory : FactoryBase + { + protected override IRemoteClientInitializationService CreateService(in ServiceArgs args) + => new RemoteClientInitializationService(in args); + } +} diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Initialization/RemoteClientInitializationService.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Initialization/RemoteClientInitializationService.cs index 56bcbb52619..8bca0800e63 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Initialization/RemoteClientInitializationService.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Initialization/RemoteClientInitializationService.cs @@ -8,9 +8,7 @@ namespace Microsoft.CodeAnalysis.Remote.Razor; -internal sealed class RemoteClientInitializationService( - IRazorServiceBroker serviceBroker) - : RazorBrokeredServiceBase(serviceBroker), IRemoteClientInitializationService +internal sealed partial class RemoteClientInitializationService(in ServiceArgs args) : RazorBrokeredServiceBase(in args), IRemoteClientInitializationService { public ValueTask InitializeAsync(RemoteClientInitializationOptions options, CancellationToken cancellationToken) => RunServiceAsync(ct => diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Initialization/RemoteClientInitializationServiceFactory.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Initialization/RemoteClientInitializationServiceFactory.cs deleted file mode 100644 index c1cb47432a3..00000000000 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Initialization/RemoteClientInitializationServiceFactory.cs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the MIT license. See License.txt in the project root for license information. - -using Microsoft.CodeAnalysis.Razor.Remote; -using Microsoft.VisualStudio.Composition; - -namespace Microsoft.CodeAnalysis.Remote.Razor; - -internal sealed class RemoteClientInitializationServiceFactory : RazorServiceFactoryBase -{ - // WARNING: We must always have a parameterless constructor in order to be properly handled by ServiceHub. - public RemoteClientInitializationServiceFactory() - : base(RazorServices.Descriptors) - { - } - - protected override IRemoteClientInitializationService CreateService(IRazorServiceBroker serviceBroker, ExportProvider exportProvider) - { - return new RemoteClientInitializationService(serviceBroker); - } -} diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/LinkedEditingRange/RemoteLinkedEditingRangeService.Factory.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/LinkedEditingRange/RemoteLinkedEditingRangeService.Factory.cs new file mode 100644 index 00000000000..aceaf61116f --- /dev/null +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/LinkedEditingRange/RemoteLinkedEditingRangeService.Factory.cs @@ -0,0 +1,15 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT license. See License.txt in the project root for license information. + +using Microsoft.CodeAnalysis.Razor.Remote; + +namespace Microsoft.CodeAnalysis.Remote.Razor; + +internal sealed partial class RemoteLinkedEditingRangeService +{ + internal sealed class Factory : FactoryBase + { + protected override IRemoteLinkedEditingRangeService CreateService(in ServiceArgs args) + => new RemoteLinkedEditingRangeService(in args); + } +} diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/LinkedEditingRange/RemoteLinkedEditingRangeService.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/LinkedEditingRange/RemoteLinkedEditingRangeService.cs index d03ed067087..3afc7fe1cf6 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/LinkedEditingRange/RemoteLinkedEditingRangeService.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/LinkedEditingRange/RemoteLinkedEditingRangeService.cs @@ -5,29 +5,29 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis.ExternalAccess.Razor; using Microsoft.CodeAnalysis.Razor.LinkedEditingRange; -using Microsoft.CodeAnalysis.Razor.Logging; using Microsoft.CodeAnalysis.Razor.Remote; using Microsoft.CodeAnalysis.Remote.Razor.ProjectSystem; using Microsoft.CodeAnalysis.Text; namespace Microsoft.CodeAnalysis.Remote.Razor; -internal sealed class RemoteLinkedEditingRangeService( - IRazorServiceBroker serviceBroker, - DocumentSnapshotFactory documentSnapshotFactory, - ILoggerFactory loggerFactory) - : RazorDocumentServiceBase(serviceBroker, documentSnapshotFactory), IRemoteLinkedEditingRangeService +internal sealed partial class RemoteLinkedEditingRangeService(in ServiceArgs args) : RazorDocumentServiceBase(in args), IRemoteLinkedEditingRangeService { - private readonly ILogger _logger = loggerFactory.GetOrCreateLogger(); - - public ValueTask GetRangesAsync(RazorPinnedSolutionInfoWrapper solutionInfo, DocumentId razorDocumentId, LinePosition linePosition, CancellationToken cancellationToken) + public ValueTask GetRangesAsync( + RazorPinnedSolutionInfoWrapper solutionInfo, + DocumentId razorDocumentId, + LinePosition linePosition, + CancellationToken cancellationToken) => RunServiceAsync( solutionInfo, razorDocumentId, context => GetRangesAsync(context, linePosition, cancellationToken), cancellationToken); - public async ValueTask GetRangesAsync(RemoteDocumentContext context, LinePosition linePosition, CancellationToken cancellationToken) + public async ValueTask GetRangesAsync( + RemoteDocumentContext context, + LinePosition linePosition, + CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { @@ -36,6 +36,6 @@ internal sealed class RemoteLinkedEditingRangeService( var codeDocument = await context.GetCodeDocumentAsync(cancellationToken).ConfigureAwait(false); - return LinkedEditingRangeHelper.GetLinkedSpans(linePosition, codeDocument, _logger); + return LinkedEditingRangeHelper.GetLinkedSpans(linePosition, codeDocument, Logger); } } diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/LinkedEditingRange/RemoteLinkedEditingRangeServiceFactory.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/LinkedEditingRange/RemoteLinkedEditingRangeServiceFactory.cs deleted file mode 100644 index 29c5d7699b3..00000000000 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/LinkedEditingRange/RemoteLinkedEditingRangeServiceFactory.cs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the MIT license. See License.txt in the project root for license information. - -using Microsoft.CodeAnalysis.Razor.Logging; -using Microsoft.CodeAnalysis.Razor.Remote; -using Microsoft.CodeAnalysis.Remote.Razor.ProjectSystem; -using Microsoft.VisualStudio.Composition; - -namespace Microsoft.CodeAnalysis.Remote.Razor; - -internal sealed class RemoteLinkedEditingRangeServiceFactory : RazorServiceFactoryBase -{ - // WARNING: We must always have a parameterless constructor in order to be properly handled by ServiceHub. - public RemoteLinkedEditingRangeServiceFactory() - : base(RazorServices.Descriptors) - { - } - - protected override IRemoteLinkedEditingRangeService CreateService(IRazorServiceBroker serviceBroker, ExportProvider exportProvider) - { - var documentSnapshotFactory = exportProvider.GetExportedValue(); - var loggerFactory = exportProvider.GetExportedValue(); - - return new RemoteLinkedEditingRangeService(serviceBroker, documentSnapshotFactory, loggerFactory); - } -} diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorBrokeredServiceBase.FactoryBase`1.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorBrokeredServiceBase.FactoryBase`1.cs new file mode 100644 index 00000000000..018890b0a71 --- /dev/null +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorBrokeredServiceBase.FactoryBase`1.cs @@ -0,0 +1,65 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT license. See License.txt in the project root for license information. + +using System; +using System.IO; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Razor.Remote; +using Microsoft.CodeAnalysis.Remote.Razor.Logging; +using Microsoft.ServiceHub.Framework; +using Microsoft.ServiceHub.Framework.Services; +using Microsoft.VisualStudio.Composition; +using Nerdbank.Streams; + +namespace Microsoft.CodeAnalysis.Remote.Razor; + +internal abstract partial class RazorBrokeredServiceBase +{ + /// + /// Implementors of (and thus this class) MUST provide a parameterless constructor + /// or ServiceHub will fail to construct them. + /// + internal abstract class FactoryBase : IServiceHubServiceFactory + where TService : class + { + public async Task CreateAsync( + Stream stream, + IServiceProvider hostProvidedServices, + ServiceActivationOptions serviceActivationOptions, + IServiceBroker serviceBroker, + AuthorizationServiceClient? authorizationServiceClient) + { + // Dispose the AuthorizationServiceClient since we won't be using it + authorizationServiceClient?.Dispose(); + + var traceSource = RemoteLoggerFactory.Initialize(hostProvidedServices); + + var pipe = stream.UsePipe(); + + var descriptor = RazorServices.Descriptors.GetDescriptorForServiceFactory(typeof(TService)); + var serverConnection = descriptor.WithTraceSource(traceSource).ConstructRpcConnection(pipe); + + var exportProvider = await RemoteMefComposition.GetExportProviderAsync().ConfigureAwait(false); + + var razorServiceBroker = new RazorServiceBroker(serviceBroker); + var args = new ServiceArgs(razorServiceBroker, exportProvider); + + var service = CreateService(in args); + + serverConnection.AddLocalRpcTarget(service); + serverConnection.StartListening(); + + return service; + } + + protected abstract TService CreateService(in ServiceArgs args); + + internal TestAccessor GetTestAccessor() => new(this); + + internal readonly struct TestAccessor(FactoryBase instance) + { + public TService CreateService(IRazorServiceBroker serviceBroker, ExportProvider exportProvider) + => instance.CreateService(new(serviceBroker, exportProvider)); + } + } +} diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorBrokeredServiceBase.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorBrokeredServiceBase.cs index abf4b6fde01..a49efdbf11f 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorBrokeredServiceBase.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorBrokeredServiceBase.cs @@ -5,12 +5,23 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.ExternalAccess.Razor; +using Microsoft.CodeAnalysis.Razor.Logging; namespace Microsoft.CodeAnalysis.Remote.Razor; -internal abstract class RazorBrokeredServiceBase(IRazorServiceBroker serviceBroker) : IDisposable +internal abstract partial class RazorBrokeredServiceBase : IDisposable { - private readonly IRazorServiceBroker _serviceBroker = serviceBroker; + private readonly IRazorServiceBroker _serviceBroker; + + protected readonly ILogger Logger; + + protected RazorBrokeredServiceBase(in ServiceArgs args) + { + _serviceBroker = args.ServiceBroker; + + var loggerFactory = args.ExportProvider.GetExportedValue(); + Logger = loggerFactory.GetOrCreateLogger(GetType()); + } protected ValueTask RunServiceAsync(Func implementation, CancellationToken cancellationToken) => _serviceBroker.RunServiceAsync(implementation, cancellationToken); diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorDocumentServiceBase.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorDocumentServiceBase.cs index 6361d5ec64a..85b747d60a4 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorDocumentServiceBase.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorDocumentServiceBase.cs @@ -9,14 +9,15 @@ namespace Microsoft.CodeAnalysis.Remote.Razor; -internal abstract class RazorDocumentServiceBase( - IRazorServiceBroker serviceBroker, - DocumentSnapshotFactory documentSnapshotFactory) - : RazorBrokeredServiceBase(serviceBroker) +internal abstract class RazorDocumentServiceBase(in ServiceArgs args) : RazorBrokeredServiceBase(in args) { - protected DocumentSnapshotFactory DocumentSnapshotFactory { get; } = documentSnapshotFactory; + protected DocumentSnapshotFactory DocumentSnapshotFactory { get; } = args.ExportProvider.GetExportedValue(); - protected ValueTask RunServiceAsync(RazorPinnedSolutionInfoWrapper solutionInfo, DocumentId razorDocumentId, Func> implementation, CancellationToken cancellationToken) + protected ValueTask RunServiceAsync( + RazorPinnedSolutionInfoWrapper solutionInfo, + DocumentId razorDocumentId, + Func> implementation, + CancellationToken cancellationToken) { return RunServiceAsync( solutionInfo, diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorServiceFactoryBase.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorServiceFactoryBase.cs deleted file mode 100644 index 7c380ab1e36..00000000000 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorServiceFactoryBase.cs +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the MIT license. See License.txt in the project root for license information. - -using System; -using System.IO; -using System.Threading.Tasks; -using Microsoft.CodeAnalysis.ExternalAccess.Razor; -using Microsoft.CodeAnalysis.Remote.Razor.Logging; -using Microsoft.ServiceHub.Framework; -using Microsoft.ServiceHub.Framework.Services; -using Microsoft.VisualStudio.Composition; -using Nerdbank.Streams; - -namespace Microsoft.CodeAnalysis.Remote.Razor; - -/// -/// Implementors of (and thus this class) MUST provide a parameterless constructor -/// or ServiceHub will fail to construct them. -/// -internal abstract class RazorServiceFactoryBase(RazorServiceDescriptorsWrapper serviceDescriptors) : IServiceHubServiceFactory - where TService : class -{ - private readonly RazorServiceDescriptorsWrapper _serviceDescriptors = serviceDescriptors; - - public async Task CreateAsync( - Stream stream, - IServiceProvider hostProvidedServices, - ServiceActivationOptions serviceActivationOptions, - IServiceBroker serviceBroker, - AuthorizationServiceClient? authorizationServiceClient) - { - // Dispose the AuthorizationServiceClient since we won't be using it - authorizationServiceClient?.Dispose(); - - var traceSource = RemoteLoggerFactory.Initialize(hostProvidedServices); - - var pipe = stream.UsePipe(); - - var descriptor = _serviceDescriptors.GetDescriptorForServiceFactory(typeof(TService)); - var serverConnection = descriptor.WithTraceSource(traceSource).ConstructRpcConnection(pipe); - - var exportProvider = await RemoteMefComposition.GetExportProviderAsync().ConfigureAwait(false); - - var razorServiceBroker = new RazorServiceBroker(serviceBroker); - - var service = CreateService(razorServiceBroker, exportProvider); - - serverConnection.AddLocalRpcTarget(service); - serverConnection.StartListening(); - - return service; - } - - protected abstract TService CreateService(IRazorServiceBroker serviceBroker, ExportProvider exportProvider); - - internal TestAccessor GetTestAccessor() => new(this); - - internal readonly struct TestAccessor(RazorServiceFactoryBase instance) - { - public TService CreateService(IRazorServiceBroker serviceBroker, ExportProvider exportProvider) - => instance.CreateService(serviceBroker, exportProvider); - } -} diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/SemanticTokens/RemoteSemanticTokensService.Factory.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/SemanticTokens/RemoteSemanticTokensService.Factory.cs new file mode 100644 index 00000000000..9658e0e35fc --- /dev/null +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/SemanticTokens/RemoteSemanticTokensService.Factory.cs @@ -0,0 +1,15 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT license. See License.txt in the project root for license information. + +using Microsoft.CodeAnalysis.Razor.Remote; + +namespace Microsoft.CodeAnalysis.Remote.Razor; + +internal sealed partial class RemoteSemanticTokensService +{ + internal sealed class Factory : FactoryBase + { + protected override IRemoteSemanticTokensService CreateService(in ServiceArgs args) + => new RemoteSemanticTokensService(in args); + } +} diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/SemanticTokens/RemoteSemanticTokensService.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/SemanticTokens/RemoteSemanticTokensService.cs index ed8ba161e1d..5db2f30a61c 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/SemanticTokens/RemoteSemanticTokensService.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/SemanticTokens/RemoteSemanticTokensService.cs @@ -12,23 +12,33 @@ namespace Microsoft.CodeAnalysis.Remote.Razor; -internal sealed class RemoteSemanticTokensService( - IRazorServiceBroker serviceBroker, - IRazorSemanticTokensInfoService razorSemanticTokensInfoService, - DocumentSnapshotFactory documentSnapshotFactory) - : RazorDocumentServiceBase(serviceBroker, documentSnapshotFactory), IRemoteSemanticTokensService +internal sealed partial class RemoteSemanticTokensService(in ServiceArgs args) : RazorDocumentServiceBase(in args), IRemoteSemanticTokensService { - private readonly IRazorSemanticTokensInfoService _razorSemanticTokensInfoService = razorSemanticTokensInfoService; - public ValueTask GetSemanticTokensDataAsync(RazorPinnedSolutionInfoWrapper solutionInfo, DocumentId razorDocumentId, LinePositionSpan span, bool colorBackground, Guid correlationId, CancellationToken cancellationToken) + private readonly IRazorSemanticTokensInfoService _semanticTokensInfoService = args.ExportProvider.GetExportedValue(); + + public ValueTask GetSemanticTokensDataAsync( + RazorPinnedSolutionInfoWrapper solutionInfo, + DocumentId razorDocumentId, + LinePositionSpan span, + bool colorBackground, + Guid correlationId, + CancellationToken cancellationToken) => RunServiceAsync( solutionInfo, razorDocumentId, context => GetSemanticTokensDataAsync(context, span, colorBackground, correlationId, cancellationToken), cancellationToken); - private async ValueTask GetSemanticTokensDataAsync(RemoteDocumentContext context, LinePositionSpan span, bool colorBackground, Guid correlationId, CancellationToken cancellationToken) + private async ValueTask GetSemanticTokensDataAsync( + RemoteDocumentContext context, + LinePositionSpan span, + bool colorBackground, + Guid correlationId, + CancellationToken cancellationToken) { - return await _razorSemanticTokensInfoService.GetSemanticTokensAsync(context, span, colorBackground, correlationId, cancellationToken).ConfigureAwait(false); + return await _semanticTokensInfoService + .GetSemanticTokensAsync(context, span, colorBackground, correlationId, cancellationToken) + .ConfigureAwait(false); } } diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/SemanticTokens/RemoteSemanticTokensServiceFactory.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/SemanticTokens/RemoteSemanticTokensServiceFactory.cs deleted file mode 100644 index 71134768ec1..00000000000 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/SemanticTokens/RemoteSemanticTokensServiceFactory.cs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the MIT license. See License.txt in the project root for license information. - -using Microsoft.CodeAnalysis.Razor.Remote; -using Microsoft.CodeAnalysis.Razor.SemanticTokens; -using Microsoft.CodeAnalysis.Remote.Razor.ProjectSystem; -using Microsoft.VisualStudio.Composition; - -namespace Microsoft.CodeAnalysis.Remote.Razor; - -internal sealed class RemoteSemanticTokensServiceFactory : RazorServiceFactoryBase -{ - // WARNING: We must always have a parameterless constructor in order to be properly handled by ServiceHub. - public RemoteSemanticTokensServiceFactory() - : base(RazorServices.Descriptors) - { - } - - protected override IRemoteSemanticTokensService CreateService(IRazorServiceBroker serviceBroker, ExportProvider exportProvider) - { - var infoService = exportProvider.GetExportedValue(); - var documentSnapshotFactory = exportProvider.GetExportedValue(); - return new RemoteSemanticTokensService(serviceBroker, infoService, documentSnapshotFactory); - } -} diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/ServiceArgs.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/ServiceArgs.cs new file mode 100644 index 00000000000..8c87e02425f --- /dev/null +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/ServiceArgs.cs @@ -0,0 +1,12 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT license. See License.txt in the project root for license information. + +using Microsoft.VisualStudio.Composition; + +namespace Microsoft.CodeAnalysis.Remote.Razor; + +internal readonly struct ServiceArgs(IRazorServiceBroker serviceBroker, ExportProvider exportProvider) +{ + public readonly IRazorServiceBroker ServiceBroker = serviceBroker; + public readonly ExportProvider ExportProvider = exportProvider; +} diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/TagHelpers/RemoteTagHelperProviderService.Factory.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/TagHelpers/RemoteTagHelperProviderService.Factory.cs new file mode 100644 index 00000000000..c88fa2eef9a --- /dev/null +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/TagHelpers/RemoteTagHelperProviderService.Factory.cs @@ -0,0 +1,15 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT license. See License.txt in the project root for license information. + +using Microsoft.CodeAnalysis.Razor.Remote; + +namespace Microsoft.CodeAnalysis.Remote.Razor; + +internal sealed partial class RemoteTagHelperProviderService +{ + internal sealed class Factory : FactoryBase + { + protected override IRemoteTagHelperProviderService CreateService(in ServiceArgs args) + => new RemoteTagHelperProviderService(in args); + } +} diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/TagHelpers/RemoteTagHelperProviderService.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/TagHelpers/RemoteTagHelperProviderService.cs index 7564b3f7f4b..59aced6d0d4 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/TagHelpers/RemoteTagHelperProviderService.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/TagHelpers/RemoteTagHelperProviderService.cs @@ -13,14 +13,10 @@ namespace Microsoft.CodeAnalysis.Remote.Razor; -internal sealed class RemoteTagHelperProviderService( - IRazorServiceBroker serviceBroker, - RemoteTagHelperResolver tagHelperResolver, - RemoteTagHelperDeltaProvider tagHelperDeltaProvider) - : RazorBrokeredServiceBase(serviceBroker), IRemoteTagHelperProviderService +internal sealed partial class RemoteTagHelperProviderService(in ServiceArgs args) : RazorBrokeredServiceBase(in args), IRemoteTagHelperProviderService { - private readonly RemoteTagHelperResolver _tagHelperResolver = tagHelperResolver; - private readonly RemoteTagHelperDeltaProvider _tagHelperDeltaProvider = tagHelperDeltaProvider; + private readonly RemoteTagHelperResolver _tagHelperResolver = args.ExportProvider.GetExportedValue(); + private readonly RemoteTagHelperDeltaProvider _tagHelperDeltaProvider = args.ExportProvider.GetExportedValue(); public ValueTask FetchTagHelpersAsync( RazorPinnedSolutionInfoWrapper solutionInfo, diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/TagHelpers/RemoteTagHelperProviderServiceFactory.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/TagHelpers/RemoteTagHelperProviderServiceFactory.cs deleted file mode 100644 index c1a3b34a2c9..00000000000 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/TagHelpers/RemoteTagHelperProviderServiceFactory.cs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the MIT license. See License.txt in the project root for license information. - -using Microsoft.AspNetCore.Razor; -using Microsoft.CodeAnalysis.Razor.Remote; -using Microsoft.VisualStudio.Composition; - -namespace Microsoft.CodeAnalysis.Remote.Razor; - -internal sealed class RemoteTagHelperProviderServiceFactory : RazorServiceFactoryBase -{ - // WARNING: We must always have a parameterless constructor in order to be properly handled by ServiceHub. - public RemoteTagHelperProviderServiceFactory() - : base(RazorServices.Descriptors) - { - } - - protected override IRemoteTagHelperProviderService CreateService(IRazorServiceBroker serviceBroker, ExportProvider exportProvider) - { - var tagHelperResolver = exportProvider.GetExportedValue().AssumeNotNull(); - var tagHelperDeltaProvider = exportProvider.GetExportedValue().AssumeNotNull(); - return new RemoteTagHelperProviderService(serviceBroker, tagHelperResolver, tagHelperDeltaProvider); - } -} diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/UriPresentation/RemoteUriPresentationService.Factory.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/UriPresentation/RemoteUriPresentationService.Factory.cs new file mode 100644 index 00000000000..e6fc5fb26e9 --- /dev/null +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/UriPresentation/RemoteUriPresentationService.Factory.cs @@ -0,0 +1,15 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT license. See License.txt in the project root for license information. + +using Microsoft.CodeAnalysis.Razor.Remote; + +namespace Microsoft.CodeAnalysis.Remote.Razor; + +internal sealed partial class RemoteUriPresentationService +{ + internal sealed class Factory : FactoryBase + { + protected override IRemoteUriPresentationService CreateService(in ServiceArgs args) + => new RemoteUriPresentationService(in args); + } +} diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/UriPresentation/RemoteUriPresentationService.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/UriPresentation/RemoteUriPresentationService.cs index 507f90011c2..d6957346f78 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/UriPresentation/RemoteUriPresentationService.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/UriPresentation/RemoteUriPresentationService.cs @@ -7,7 +7,6 @@ using Microsoft.CodeAnalysis.ExternalAccess.Razor; using Microsoft.CodeAnalysis.Razor.DocumentMapping; using Microsoft.CodeAnalysis.Razor.DocumentPresentation; -using Microsoft.CodeAnalysis.Razor.Logging; using Microsoft.CodeAnalysis.Razor.Protocol; using Microsoft.CodeAnalysis.Razor.Remote; using Microsoft.CodeAnalysis.Razor.Workspaces; @@ -16,24 +15,27 @@ namespace Microsoft.CodeAnalysis.Remote.Razor; -internal sealed class RemoteUriPresentationService( - IRazorServiceBroker serviceBroker, - IRazorDocumentMappingService documentMappingService, - DocumentSnapshotFactory documentSnapshotFactory, - ILoggerFactory loggerFactory) - : RazorDocumentServiceBase(serviceBroker, documentSnapshotFactory), IRemoteUriPresentationService +internal sealed partial class RemoteUriPresentationService(in ServiceArgs args) : RazorDocumentServiceBase(in args), IRemoteUriPresentationService { - private readonly IRazorDocumentMappingService _documentMappingService = documentMappingService; - private readonly ILogger _logger = loggerFactory.GetOrCreateLogger(); - - public ValueTask GetPresentationAsync(RazorPinnedSolutionInfoWrapper solutionInfo, DocumentId razorDocumentId, LinePositionSpan span, Uri[]? uris, CancellationToken cancellationToken) + private readonly IRazorDocumentMappingService _documentMappingService = args.ExportProvider.GetExportedValue(); + + public ValueTask GetPresentationAsync( + RazorPinnedSolutionInfoWrapper solutionInfo, + DocumentId razorDocumentId, + LinePositionSpan span, + Uri[]? uris, + CancellationToken cancellationToken) => RunServiceAsync( solutionInfo, razorDocumentId, context => GetPresentationAsync(context, span, uris, cancellationToken), cancellationToken); - private async ValueTask GetPresentationAsync(RemoteDocumentContext context, LinePositionSpan span, Uri[]? uris, CancellationToken cancellationToken) + private async ValueTask GetPresentationAsync( + RemoteDocumentContext context, + LinePositionSpan span, + Uri[]? uris, + CancellationToken cancellationToken) { var sourceText = await context.GetSourceTextAsync(cancellationToken).ConfigureAwait(false); if (!sourceText.TryGetAbsoluteIndex(span.Start.Line, span.Start.Character, out var index)) @@ -53,7 +55,7 @@ internal sealed class RemoteUriPresentationService( return null; } - var razorFileUri = UriPresentationHelper.GetComponentFileNameFromUriPresentationRequest(uris, _logger); + var razorFileUri = UriPresentationHelper.GetComponentFileNameFromUriPresentationRequest(uris, Logger); if (razorFileUri is null) { return null; diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/UriPresentation/RemoteUriPresentationServiceFactory.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/UriPresentation/RemoteUriPresentationServiceFactory.cs deleted file mode 100644 index ecb75c9d11b..00000000000 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/UriPresentation/RemoteUriPresentationServiceFactory.cs +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the MIT license. See License.txt in the project root for license information. - -using Microsoft.CodeAnalysis.Razor.DocumentMapping; -using Microsoft.CodeAnalysis.Razor.Logging; -using Microsoft.CodeAnalysis.Razor.Remote; -using Microsoft.CodeAnalysis.Remote.Razor.ProjectSystem; -using Microsoft.VisualStudio.Composition; - -namespace Microsoft.CodeAnalysis.Remote.Razor; - -internal sealed class RemoteUriPresentationServiceFactory : RazorServiceFactoryBase -{ - // WARNING: We must always have a parameterless constructor in order to be properly handled by ServiceHub. - public RemoteUriPresentationServiceFactory() - : base(RazorServices.Descriptors) - { - } - - protected override IRemoteUriPresentationService CreateService(IRazorServiceBroker serviceBroker, ExportProvider exportProvider) - { - var documentMappingService = exportProvider.GetExportedValue(); - var documentSnapshotFactory = exportProvider.GetExportedValue(); - var loggerFactory = exportProvider.GetExportedValue(); - return new RemoteUriPresentationService(serviceBroker, documentMappingService, documentSnapshotFactory, loggerFactory); - } -} diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/ServiceFactoryMap.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/ServiceFactoryMap.cs index ecfa97db825..3454edf28c0 100644 --- a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/ServiceFactoryMap.cs +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/ServiceFactoryMap.cs @@ -1,11 +1,11 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT license. See License.txt in the project root for license information. -using Microsoft.CodeAnalysis.Remote.Razor; -using Microsoft.ServiceHub.Framework; +using System; using System.Collections.Generic; using System.Linq; -using System; +using Microsoft.CodeAnalysis.Remote.Razor; +using Microsoft.ServiceHub.Framework; using Xunit; namespace Microsoft.VisualStudio.Razor.LanguageClient.Cohost; @@ -18,12 +18,12 @@ private static Dictionary BuildFactoryMap() { var result = new Dictionary(); - foreach (var type in typeof(RazorServiceFactoryBase<>).Assembly.GetTypes()) + foreach (var type in typeof(RazorBrokeredServiceBase.FactoryBase<>).Assembly.GetTypes()) { if (!type.IsAbstract && typeof(IServiceHubServiceFactory).IsAssignableFrom(type)) { - Assert.Equal(typeof(RazorServiceFactoryBase<>), type.BaseType.GetGenericTypeDefinition()); + Assert.Equal(typeof(RazorBrokeredServiceBase.FactoryBase<>), type.BaseType.GetGenericTypeDefinition()); var genericType = type.BaseType.GetGenericArguments().FirstOrDefault(); if (genericType != null) @@ -38,11 +38,11 @@ private static Dictionary BuildFactoryMap() return result; } - public static RazorServiceFactoryBase GetServiceFactory() + public static RazorBrokeredServiceBase.FactoryBase GetServiceFactory() where TService : class { Assert.True(s_factoryMap.TryGetValue(typeof(TService), out var factory)); - return (RazorServiceFactoryBase)factory; + return (RazorBrokeredServiceBase.FactoryBase)factory; } } From fcea6f78b6f39e272cd997cb8f0125e61b8b43c0 Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Mon, 15 Jul 2024 09:33:15 -0700 Subject: [PATCH 082/176] Prefer single in ServiceFactoryMap to fail fast for tests --- .../Cohost/ServiceFactoryMap.cs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/ServiceFactoryMap.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/ServiceFactoryMap.cs index 3454edf28c0..6a98a82fe6c 100644 --- a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/ServiceFactoryMap.cs +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/ServiceFactoryMap.cs @@ -25,13 +25,11 @@ private static Dictionary BuildFactoryMap() { Assert.Equal(typeof(RazorBrokeredServiceBase.FactoryBase<>), type.BaseType.GetGenericTypeDefinition()); - var genericType = type.BaseType.GetGenericArguments().FirstOrDefault(); - if (genericType != null) - { - // ServiceHub requires a parameterless constructor, so we can safely rely on it existing too - var factory = (IServiceHubServiceFactory)Activator.CreateInstance(type); - result.Add(genericType, factory); - } + var genericType = type.BaseType.GetGenericArguments().Single(); + + // ServiceHub requires a parameterless constructor, so we can safely rely on it existing too + var factory = (IServiceHubServiceFactory)Activator.CreateInstance(type); + result.Add(genericType, factory); } } From fe1c8ad4345f1bd653f923b44d9320b9485f8fba Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Mon, 15 Jul 2024 09:52:39 -0700 Subject: [PATCH 083/176] Clean up ServiceFactoryMap and rename to BrokeredServiceFactory --- .../RazorBrokeredServiceBase.FactoryBase`1.cs | 5 ++--- ...actoryMap.cs => BrokeredServiceFactory.cs} | 21 +++++++++++++++++-- .../CohostLinkedEditingRangeEndpointTest.cs | 1 - .../Cohost/TestRemoteServiceProvider.cs | 11 +++++----- 4 files changed, 27 insertions(+), 11 deletions(-) rename src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/{ServiceFactoryMap.cs => BrokeredServiceFactory.cs} (65%) diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorBrokeredServiceBase.FactoryBase`1.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorBrokeredServiceBase.FactoryBase`1.cs index 018890b0a71..316c16d69d9 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorBrokeredServiceBase.FactoryBase`1.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorBrokeredServiceBase.FactoryBase`1.cs @@ -8,7 +8,6 @@ using Microsoft.CodeAnalysis.Remote.Razor.Logging; using Microsoft.ServiceHub.Framework; using Microsoft.ServiceHub.Framework.Services; -using Microsoft.VisualStudio.Composition; using Nerdbank.Streams; namespace Microsoft.CodeAnalysis.Remote.Razor; @@ -58,8 +57,8 @@ public async Task CreateAsync( internal readonly struct TestAccessor(FactoryBase instance) { - public TService CreateService(IRazorServiceBroker serviceBroker, ExportProvider exportProvider) - => instance.CreateService(new(serviceBroker, exportProvider)); + public TService CreateService(in ServiceArgs args) + => instance.CreateService(in args); } } } diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/ServiceFactoryMap.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/BrokeredServiceFactory.cs similarity index 65% rename from src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/ServiceFactoryMap.cs rename to src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/BrokeredServiceFactory.cs index 6a98a82fe6c..fb858f4db0e 100644 --- a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/ServiceFactoryMap.cs +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/BrokeredServiceFactory.cs @@ -10,7 +10,16 @@ namespace Microsoft.VisualStudio.Razor.LanguageClient.Cohost; -internal static class ServiceFactoryMap +/// +/// Creates Razor brokered services. +/// +/// +/// This class holds instances in a static +/// field. This should work fine in tests, since brokered service factories are intended to be stateless. +/// However, if a factory is introduced that maintains state, this class will need to be revisited to +/// avoid holding onto state across tests. +/// +internal static class BrokeredServiceFactory { private static readonly Dictionary s_factoryMap = BuildFactoryMap(); @@ -36,11 +45,19 @@ private static Dictionary BuildFactoryMap() return result; } - public static RazorBrokeredServiceBase.FactoryBase GetServiceFactory() + private static RazorBrokeredServiceBase.FactoryBase GetServiceFactory() where TService : class { Assert.True(s_factoryMap.TryGetValue(typeof(TService), out var factory)); return (RazorBrokeredServiceBase.FactoryBase)factory; } + + public static TService CreateService(in ServiceArgs args) + where TService : class + { + var factory = GetServiceFactory(); + + return factory.GetTestAccessor().CreateService(in args); + } } diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostLinkedEditingRangeEndpointTest.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostLinkedEditingRangeEndpointTest.cs index cf0d7346013..6cac132252b 100644 --- a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostLinkedEditingRangeEndpointTest.cs +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostLinkedEditingRangeEndpointTest.cs @@ -9,7 +9,6 @@ using Microsoft.CodeAnalysis.Testing; using Microsoft.CodeAnalysis.Text; using Microsoft.VisualStudio.LanguageServer.Protocol; -using Microsoft.VisualStudio.Razor.LanguageClient.Cohost; using Xunit; using Xunit.Abstractions; diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/TestRemoteServiceProvider.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/TestRemoteServiceProvider.cs index 3a82d4defce..3f59e22cc8d 100644 --- a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/TestRemoteServiceProvider.cs +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/TestRemoteServiceProvider.cs @@ -9,6 +9,7 @@ using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.ExternalAccess.Razor; using Microsoft.CodeAnalysis.Razor.Remote; +using Microsoft.CodeAnalysis.Remote.Razor; using Microsoft.VisualStudio.Composition; namespace Microsoft.VisualStudio.Razor.LanguageClient.Cohost; @@ -18,16 +19,16 @@ namespace Microsoft.VisualStudio.Razor.LanguageClient.Cohost; /// internal sealed class TestRemoteServiceProvider(ExportProvider exportProvider) : IRemoteServiceProvider, IDisposable { - private readonly TestServiceBroker _testServiceBroker = new TestServiceBroker(); - private readonly Dictionary _services = new Dictionary(); + private readonly TestServiceBroker _serviceBroker = new(); + private readonly Dictionary _services = []; private TService GetOrCreateService() where TService : class, IDisposable { if (!_services.TryGetValue(typeof(TService), out var service)) { - var factory = ServiceFactoryMap.GetServiceFactory(); - service = factory.GetTestAccessor().CreateService(_testServiceBroker, exportProvider); + var args = new ServiceArgs(_serviceBroker, exportProvider); + service = BrokeredServiceFactory.CreateService(in args); _services.Add(typeof(TService), service); } @@ -48,7 +49,7 @@ private TService GetOrCreateService() // the RazorPinnedSolutionInfoWrapper properly, but we need Roslyn changes for that. For now, this works fine // as we don't have any code that makes multiple parallel calls to TryInvokeAsync in the same test. var solutionInfo = new RazorPinnedSolutionInfoWrapper(); - _testServiceBroker.UpdateSolution(solution); + _serviceBroker.UpdateSolution(solution); return await invocation(service, solutionInfo, cancellationToken); } From 76bb9253c1cca5eb526f926fdea8cd75f997ce88 Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Mon, 15 Jul 2024 10:13:21 -0700 Subject: [PATCH 084/176] Rename IRemoteServiceProvider to IRemoteServiceInvoker --- ...iceProvider.cs => IRemoteServiceInvoker.cs} | 2 +- .../Cohost/CohostFoldingRangeEndpoint.cs | 6 +++--- .../Cohost/CohostLinkedEditingRangeEndpoint.cs | 6 +++--- .../CohostSemanticTokensRangeEndpoint.cs | 6 +++--- .../Cohost/CohostUriPresentationEndpoint.cs | 6 +++--- .../Cohost/HtmlDocumentPublisher.cs | 6 +++--- .../Remote/OutOfProcTagHelperResolver.cs | 8 ++++---- ...viceProvider.cs => RemoteServiceInvoker.cs} | 8 ++++---- .../CohostLinkedEditingRangeEndpointTest.cs | 2 +- .../Cohost/CohostTestBase.cs | 6 +++--- ...Provider.cs => TestRemoteServiceInvoker.cs} | 5 +++-- ...OfProcTagHelperResolverTest.TestResolver.cs | 4 ++-- .../Remote/OutOfProcTagHelperResolverTest.cs | 18 +++++++++--------- 13 files changed, 42 insertions(+), 41 deletions(-) rename src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/{IRemoteServiceProvider.cs => IRemoteServiceInvoker.cs} (94%) rename src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/Remote/{RemoteServiceProvider.cs => RemoteServiceInvoker.cs} (97%) rename src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/{TestRemoteServiceProvider.cs => TestRemoteServiceInvoker.cs} (89%) diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteServiceProvider.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteServiceInvoker.cs similarity index 94% rename from src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteServiceProvider.cs rename to src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteServiceInvoker.cs index e8241e0aa2c..c2746cfacba 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteServiceProvider.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteServiceInvoker.cs @@ -9,7 +9,7 @@ namespace Microsoft.CodeAnalysis.Razor.Remote; -internal interface IRemoteServiceProvider +internal interface IRemoteServiceInvoker { ValueTask TryInvokeAsync( Solution solution, diff --git a/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/CohostFoldingRangeEndpoint.cs b/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/CohostFoldingRangeEndpoint.cs index fe0d0cf3821..963b975ba39 100644 --- a/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/CohostFoldingRangeEndpoint.cs +++ b/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/CohostFoldingRangeEndpoint.cs @@ -27,13 +27,13 @@ namespace Microsoft.VisualStudio.Razor.LanguageClient.Cohost; [method: ImportingConstructor] #pragma warning restore RS0030 // Do not use banned APIs internal class CohostFoldingRangeEndpoint( - IRemoteServiceProvider remoteServiceProvider, + IRemoteServiceInvoker remoteServiceInvoker, IHtmlDocumentSynchronizer htmlDocumentSynchronizer, LSPRequestInvoker requestInvoker, ILoggerFactory loggerFactory) : AbstractRazorCohostDocumentRequestHandler, IDynamicRegistrationProvider { - private readonly IRemoteServiceProvider _remoteServiceProvider = remoteServiceProvider; + private readonly IRemoteServiceInvoker _remoteServiceInvoker = remoteServiceInvoker; private readonly IHtmlDocumentSynchronizer _htmlDocumentSynchronizer = htmlDocumentSynchronizer; private readonly LSPRequestInvoker _requestInvoker = requestInvoker; private readonly ILogger _logger = loggerFactory.GetOrCreateLogger(); @@ -78,7 +78,7 @@ internal class CohostFoldingRangeEndpoint( } _logger.LogDebug($"Calling OOP with the {htmlRanges.Length} html ranges, so it can fill in the rest"); - var data = await _remoteServiceProvider.TryInvokeAsync>( + var data = await _remoteServiceInvoker.TryInvokeAsync>( razorDocument.Project.Solution, (service, solutionInfo, cancellationToken) => service.GetFoldingRangesAsync(solutionInfo, razorDocument.Id, htmlRanges, cancellationToken), cancellationToken).ConfigureAwait(false); diff --git a/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/CohostLinkedEditingRangeEndpoint.cs b/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/CohostLinkedEditingRangeEndpoint.cs index a288d8c4883..f1f42f472dc 100644 --- a/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/CohostLinkedEditingRangeEndpoint.cs +++ b/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/CohostLinkedEditingRangeEndpoint.cs @@ -24,10 +24,10 @@ namespace Microsoft.VisualStudio.Razor.LanguageClient.Cohost; [ExportCohostStatelessLspService(typeof(CohostLinkedEditingRangeEndpoint))] [method: ImportingConstructor] #pragma warning restore RS0030 // Do not use banned APIs -internal class CohostLinkedEditingRangeEndpoint(IRemoteServiceProvider remoteServiceProvider, ILoggerFactory loggerFactory) +internal class CohostLinkedEditingRangeEndpoint(IRemoteServiceInvoker remoteServiceInvoker, ILoggerFactory loggerFactory) : AbstractRazorCohostDocumentRequestHandler, IDynamicRegistrationProvider { - private readonly IRemoteServiceProvider _remoteServiceProvider = remoteServiceProvider; + private readonly IRemoteServiceInvoker _remoteServiceInvoker = remoteServiceInvoker; private readonly ILogger _logger = loggerFactory.GetOrCreateLogger(); protected override bool MutatesSolutionState => false; @@ -59,7 +59,7 @@ internal class CohostLinkedEditingRangeEndpoint(IRemoteServiceProvider remoteSer private async Task HandleRequestAsync(LinkedEditingRangeParams request, TextDocument razorDocument, CancellationToken cancellationToken) { - var linkedRanges = await _remoteServiceProvider.TryInvokeAsync( + var linkedRanges = await _remoteServiceInvoker.TryInvokeAsync( razorDocument.Project.Solution, (service, solutionInfo, cancellationToken) => service.GetRangesAsync(solutionInfo, razorDocument.Id, request.Position.ToLinePosition(), cancellationToken), cancellationToken).ConfigureAwait(false); diff --git a/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/CohostSemanticTokensRangeEndpoint.cs b/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/CohostSemanticTokensRangeEndpoint.cs index d59809ccb74..f241f4d75b4 100644 --- a/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/CohostSemanticTokensRangeEndpoint.cs +++ b/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/CohostSemanticTokensRangeEndpoint.cs @@ -28,14 +28,14 @@ namespace Microsoft.VisualStudio.Razor.LanguageClient.Cohost; [method: ImportingConstructor] #pragma warning restore RS0030 // Do not use banned APIs internal sealed class CohostSemanticTokensRangeEndpoint( - IRemoteServiceProvider remoteServiceProvider, + IRemoteServiceInvoker remoteServiceInvoker, IClientSettingsManager clientSettingsManager, ISemanticTokensLegendService semanticTokensLegendService, ITelemetryReporter telemetryReporter, ILoggerFactory loggerFactory) : AbstractRazorCohostDocumentRequestHandler, IDynamicRegistrationProvider { - private readonly IRemoteServiceProvider _remoteServiceProvider = remoteServiceProvider; + private readonly IRemoteServiceInvoker _remoteServiceInvoker = remoteServiceInvoker; private readonly IClientSettingsManager _clientSettingsManager = clientSettingsManager; private readonly ISemanticTokensLegendService _semanticTokensLegendService = semanticTokensLegendService; private readonly ITelemetryReporter _telemetryReporter = telemetryReporter; @@ -78,7 +78,7 @@ internal sealed class CohostSemanticTokensRangeEndpoint( var correlationId = Guid.NewGuid(); using var _ = _telemetryReporter.TrackLspRequest(Methods.TextDocumentSemanticTokensRangeName, RazorLSPConstants.CohostLanguageServerName, correlationId); - var tokens = await _remoteServiceProvider.TryInvokeAsync( + var tokens = await _remoteServiceInvoker.TryInvokeAsync( razorDocument.Project.Solution, (service, solutionInfo, cancellationToken) => service.GetSemanticTokensDataAsync(solutionInfo, razorDocument.Id, span, colorBackground, correlationId, cancellationToken), cancellationToken).ConfigureAwait(false); diff --git a/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/CohostUriPresentationEndpoint.cs b/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/CohostUriPresentationEndpoint.cs index 6199d564f93..b067987020a 100644 --- a/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/CohostUriPresentationEndpoint.cs +++ b/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/CohostUriPresentationEndpoint.cs @@ -23,13 +23,13 @@ namespace Microsoft.VisualStudio.Razor.LanguageClient.Cohost; [method: ImportingConstructor] #pragma warning restore RS0030 // Do not use banned APIs internal class CohostUriPresentationEndpoint( - IRemoteServiceProvider remoteServiceProvider, + IRemoteServiceInvoker remoteServiceInvoker, IHtmlDocumentSynchronizer htmlDocumentSynchronizer, IFilePathService filePathService, LSPRequestInvoker requestInvoker) : AbstractRazorCohostDocumentRequestHandler, IDynamicRegistrationProvider { - private readonly IRemoteServiceProvider _remoteServiceProvider = remoteServiceProvider; + private readonly IRemoteServiceInvoker _remoteServiceInvoker = remoteServiceInvoker; private readonly IHtmlDocumentSynchronizer _htmlDocumentSynchronizer = htmlDocumentSynchronizer; private readonly IFilePathService _filePathService = filePathService; private readonly LSPRequestInvoker _requestInvoker = requestInvoker; @@ -62,7 +62,7 @@ internal class CohostUriPresentationEndpoint( { var razorDocument = context.TextDocument.AssumeNotNull(); - var data = await _remoteServiceProvider.TryInvokeAsync( + var data = await _remoteServiceInvoker.TryInvokeAsync( razorDocument.Project.Solution, (service, solutionInfo, cancellationToken) => service.GetPresentationAsync(solutionInfo, razorDocument.Id, request.Range.ToLinePositionSpan(), request.Uris, cancellationToken), cancellationToken).ConfigureAwait(false); diff --git a/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/HtmlDocumentPublisher.cs b/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/HtmlDocumentPublisher.cs index 8f9cb2694fb..ffa0a35e7f0 100644 --- a/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/HtmlDocumentPublisher.cs +++ b/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/HtmlDocumentPublisher.cs @@ -18,19 +18,19 @@ namespace Microsoft.VisualStudio.Razor.LanguageClient.Cohost; [Export(typeof(IHtmlDocumentPublisher))] [method: ImportingConstructor] internal sealed class HtmlDocumentPublisher( - IRemoteServiceProvider remoteServiceProvider, + IRemoteServiceInvoker remoteServiceInvoker, LSPDocumentManager documentManager, JoinableTaskContext joinableTaskContext, ILoggerFactory loggerFactory) : IHtmlDocumentPublisher { - private readonly IRemoteServiceProvider _remoteServiceProvider = remoteServiceProvider; + private readonly IRemoteServiceInvoker _remoteServiceInvoker = remoteServiceInvoker; private readonly JoinableTaskContext _joinableTaskContext = joinableTaskContext; private readonly TrackingLSPDocumentManager _documentManager = documentManager as TrackingLSPDocumentManager ?? throw new InvalidOperationException("Expected TrackingLSPDocumentManager"); private readonly ILogger _logger = loggerFactory.GetOrCreateLogger(); public Task GetHtmlSourceFromOOPAsync(TextDocument document, CancellationToken cancellationToken) { - return _remoteServiceProvider.TryInvokeAsync(document.Project.Solution, + return _remoteServiceInvoker.TryInvokeAsync(document.Project.Solution, (service, solutionInfo, ct) => service.GetHtmlDocumentTextAsync(solutionInfo, document.Id, ct), cancellationToken).AsTask(); } diff --git a/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/Remote/OutOfProcTagHelperResolver.cs b/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/Remote/OutOfProcTagHelperResolver.cs index 4633908173a..63a8133a6e1 100644 --- a/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/Remote/OutOfProcTagHelperResolver.cs +++ b/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/Remote/OutOfProcTagHelperResolver.cs @@ -23,11 +23,11 @@ namespace Microsoft.VisualStudio.Razor.Remote; [Export(typeof(ITagHelperResolver))] [method: ImportingConstructor] internal class OutOfProcTagHelperResolver( - IRemoteServiceProvider remoteServiceProvider, + IRemoteServiceInvoker remoteServiceInvoker, ILoggerFactory loggerFactory, ITelemetryReporter telemetryReporter) : ITagHelperResolver { - private readonly IRemoteServiceProvider _remoteServiceProvider = remoteServiceProvider; + private readonly IRemoteServiceInvoker _remoteServiceInvoker = remoteServiceInvoker; private readonly ILogger _logger = loggerFactory.GetOrCreateLogger(); private readonly CompilationTagHelperResolver _innerResolver = new(telemetryReporter); private readonly TagHelperResultCache _resultCache = new(); @@ -75,7 +75,7 @@ protected virtual async ValueTask> ResolveTa var projectHandle = new ProjectSnapshotHandle(workspaceProject.Id, projectSnapshot.Configuration, projectSnapshot.RootNamespace); - var deltaResult = await _remoteServiceProvider.TryInvokeAsync( + var deltaResult = await _remoteServiceInvoker.TryInvokeAsync( workspaceProject.Solution, (service, solutionInfo, innerCancellationToken) => service.GetTagHelpersDeltaAsync(solutionInfo, projectHandle, lastResultId, innerCancellationToken), @@ -110,7 +110,7 @@ protected virtual async ValueTask> ResolveTa if (checksumsToFetch.Count > 0) { // There are checksums that we don't have cached tag helpers for, so we need to fetch them from OOP. - var fetchResult = await _remoteServiceProvider.TryInvokeAsync( + var fetchResult = await _remoteServiceInvoker.TryInvokeAsync( workspaceProject.Solution, (service, solutionInfo, innerCancellationToken) => service.FetchTagHelpersAsync(solutionInfo, projectHandle, checksumsToFetch.DrainToImmutable(), innerCancellationToken), diff --git a/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/Remote/RemoteServiceProvider.cs b/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/Remote/RemoteServiceInvoker.cs similarity index 97% rename from src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/Remote/RemoteServiceProvider.cs rename to src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/Remote/RemoteServiceInvoker.cs index bbbb114f011..f801ce7286d 100644 --- a/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/Remote/RemoteServiceProvider.cs +++ b/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/Remote/RemoteServiceInvoker.cs @@ -18,23 +18,23 @@ namespace Microsoft.VisualStudio.Razor.Remote; -[Export(typeof(IRemoteServiceProvider))] +[Export(typeof(IRemoteServiceInvoker))] [method: ImportingConstructor] -internal sealed class RemoteServiceProvider( +internal sealed class RemoteServiceInvoker( IWorkspaceProvider workspaceProvider, LanguageServerFeatureOptions languageServerFeatureOptions, IClientCapabilitiesService clientCapabilitiesService, ISemanticTokensLegendService semanticTokensLegendService, ITelemetryReporter telemetryReporter, ILoggerFactory loggerFactory) - : IRemoteServiceProvider + : IRemoteServiceInvoker { private readonly IWorkspaceProvider _workspaceProvider = workspaceProvider; private readonly LanguageServerFeatureOptions _languageServerFeatureOptions = languageServerFeatureOptions; private readonly IClientCapabilitiesService _clientCapabilitiesService = clientCapabilitiesService; private readonly ISemanticTokensLegendService _semanticTokensLegendService = semanticTokensLegendService; private readonly ITelemetryReporter _telemetryReporter = telemetryReporter; - private readonly ILogger _logger = loggerFactory.GetOrCreateLogger(); + private readonly ILogger _logger = loggerFactory.GetOrCreateLogger(); private readonly object _gate = new(); private ValueTask? _isInitializedTask; diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostLinkedEditingRangeEndpointTest.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostLinkedEditingRangeEndpointTest.cs index 6cac132252b..3b31488b882 100644 --- a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostLinkedEditingRangeEndpointTest.cs +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostLinkedEditingRangeEndpointTest.cs @@ -164,7 +164,7 @@ private async Task VerifyLinkedEditingRangeAsync(string input) var sourceText = await document.GetTextAsync(DisposalToken); sourceText.GetLineAndOffset(cursorPosition, out var lineIndex, out var characterIndex); - var endpoint = new CohostLinkedEditingRangeEndpoint(RemoteServiceProvider, LoggerFactory); + var endpoint = new CohostLinkedEditingRangeEndpoint(RemoteServiceInvoker, LoggerFactory); var request = new LinkedEditingRangeParams() { diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostTestBase.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostTestBase.cs index 61b0d52d5a8..c7f67c0e657 100644 --- a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostTestBase.cs +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostTestBase.cs @@ -18,16 +18,16 @@ namespace Microsoft.VisualStudio.Razor.LanguageClient.Cohost; public abstract class CohostTestBase(ITestOutputHelper testOutputHelper) : WorkspaceTestBase(testOutputHelper) { - private IRemoteServiceProvider? _remoteServiceProvider; + private IRemoteServiceInvoker? _remoteServiceInvoker; - private protected IRemoteServiceProvider RemoteServiceProvider => _remoteServiceProvider.AssumeNotNull(); + private protected IRemoteServiceInvoker RemoteServiceInvoker => _remoteServiceInvoker.AssumeNotNull(); protected override async Task InitializeAsync() { await base.InitializeAsync(); var exportProvider = AddDisposable(await RemoteMefComposition.CreateExportProviderAsync()); - _remoteServiceProvider = AddDisposable(new TestRemoteServiceProvider(exportProvider)); + _remoteServiceInvoker = AddDisposable(new TestRemoteServiceInvoker(exportProvider)); } protected TextDocument CreateProjectAndRazorDocument(string contents) diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/TestRemoteServiceProvider.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/TestRemoteServiceInvoker.cs similarity index 89% rename from src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/TestRemoteServiceProvider.cs rename to src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/TestRemoteServiceInvoker.cs index 3f59e22cc8d..c71ac3835a4 100644 --- a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/TestRemoteServiceProvider.cs +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/TestRemoteServiceInvoker.cs @@ -15,9 +15,10 @@ namespace Microsoft.VisualStudio.Razor.LanguageClient.Cohost; /// -/// An implementation of IRemoteServiceProvider that doesn't actually do anything remote, but rather directly calls service methods +/// An implementation of that doesn't actually do anything remote, +/// but rather directly calls service methods /// -internal sealed class TestRemoteServiceProvider(ExportProvider exportProvider) : IRemoteServiceProvider, IDisposable +internal sealed class TestRemoteServiceInvoker(ExportProvider exportProvider) : IRemoteServiceInvoker, IDisposable { private readonly TestServiceBroker _serviceBroker = new(); private readonly Dictionary _services = []; diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Remote/OutOfProcTagHelperResolverTest.TestResolver.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Remote/OutOfProcTagHelperResolverTest.TestResolver.cs index 51da04bafdb..b4c20289aa6 100644 --- a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Remote/OutOfProcTagHelperResolverTest.TestResolver.cs +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Remote/OutOfProcTagHelperResolverTest.TestResolver.cs @@ -21,10 +21,10 @@ namespace Microsoft.VisualStudio.Razor.Remote; public partial class OutOfProcTagHelperResolverTest { private class TestResolver( - IRemoteServiceProvider remoteClientProvider, + IRemoteServiceInvoker remoteServiceInvoker, ILoggerFactory loggerFactory, ITelemetryReporter telemetryReporter) - : OutOfProcTagHelperResolver(remoteClientProvider, loggerFactory, telemetryReporter) + : OutOfProcTagHelperResolver(remoteServiceInvoker, loggerFactory, telemetryReporter) { public Func>>? OnResolveOutOfProcess { get; init; } diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Remote/OutOfProcTagHelperResolverTest.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Remote/OutOfProcTagHelperResolverTest.cs index 25671a2d391..f05af0e1399 100644 --- a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Remote/OutOfProcTagHelperResolverTest.cs +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Remote/OutOfProcTagHelperResolverTest.cs @@ -39,7 +39,7 @@ public partial class OutOfProcTagHelperResolverTest : VisualStudioTestBase private readonly Project _workspaceProject; private readonly TestProjectSnapshotManager _projectManager; - private readonly IRemoteServiceProvider _remoteClientProvider; + private readonly IRemoteServiceInvoker _remoteServiceInvoker; public OutOfProcTagHelperResolverTest(ITestOutputHelper testOutput) : base(testOutput) @@ -47,7 +47,7 @@ public OutOfProcTagHelperResolverTest(ITestOutputHelper testOutput) var workspace = new AdhocWorkspace(); AddDisposable(workspace); - _remoteClientProvider = StrictMock.Of(); + _remoteServiceInvoker = StrictMock.Of(); var info = ProjectInfo.Create(ProjectId.CreateNewId("Test"), VersionStamp.Default, "Test", "Test", LanguageNames.CSharp, filePath: "Test.csproj"); _workspaceProject = workspace.CurrentSolution.AddProject(info).GetProject(info.Id).AssumeNotNull(); @@ -85,7 +85,7 @@ await _projectManager.UpdateAsync(updater => var calledOutOfProcess = false; - var resolver = new TestResolver(_remoteClientProvider, LoggerFactory, NoOpTelemetryReporter.Instance) + var resolver = new TestResolver(_remoteServiceInvoker, LoggerFactory, NoOpTelemetryReporter.Instance) { OnResolveOutOfProcess = (p) => { @@ -117,7 +117,7 @@ await _projectManager.UpdateAsync(updater => var calledInProcess = false; - var resolver = new TestResolver(_remoteClientProvider, LoggerFactory, NoOpTelemetryReporter.Instance) + var resolver = new TestResolver(_remoteServiceInvoker, LoggerFactory, NoOpTelemetryReporter.Instance) { OnResolveInProcess = (p) => { @@ -151,7 +151,7 @@ await _projectManager.UpdateAsync(updater => var calledInProcess = false; var cancellationToken = new CancellationToken(canceled: true); - var resolver = new TestResolver(_remoteClientProvider, LoggerFactory, NoOpTelemetryReporter.Instance) + var resolver = new TestResolver(_remoteServiceInvoker, LoggerFactory, NoOpTelemetryReporter.Instance) { OnResolveInProcess = (p) => { @@ -179,7 +179,7 @@ await _projectManager.UpdateAsync(updater => public void CalculateTagHelpersFromDelta_NewProject() { // Arrange - var resolver = new TestResolver(_remoteClientProvider, LoggerFactory, NoOpTelemetryReporter.Instance); + var resolver = new TestResolver(_remoteServiceInvoker, LoggerFactory, NoOpTelemetryReporter.Instance); var initialDelta = new TagHelperDeltaResult(IsDelta: false, ResultId: 1, Added: Project1TagHelperChecksums, Removed: []); // Act @@ -193,7 +193,7 @@ public void CalculateTagHelpersFromDelta_NewProject() public void CalculateTagHelpersFromDelta_DeltaFailedToApplyToKnownProject() { // Arrange - var resolver = new TestResolver(_remoteClientProvider, LoggerFactory, NoOpTelemetryReporter.Instance); + var resolver = new TestResolver(_remoteServiceInvoker, LoggerFactory, NoOpTelemetryReporter.Instance); var initialDelta = new TagHelperDeltaResult(IsDelta: false, ResultId: 1, Added: Project1TagHelperChecksums, Removed: []); resolver.PublicProduceChecksumsFromDelta(Project1Id, lastResultId: -1, initialDelta); var newTagHelperSet = ImmutableArray.Create(TagHelper1_Project1.Checksum); @@ -210,7 +210,7 @@ public void CalculateTagHelpersFromDelta_DeltaFailedToApplyToKnownProject() public void CalculateTagHelpersFromDelta_NoopResult() { // Arrange - var resolver = new TestResolver(_remoteClientProvider, LoggerFactory, NoOpTelemetryReporter.Instance); + var resolver = new TestResolver(_remoteServiceInvoker, LoggerFactory, NoOpTelemetryReporter.Instance); var initialDelta = new TagHelperDeltaResult(IsDelta: false, ResultId: 1, Added: Project1TagHelperChecksums, Removed: []); resolver.PublicProduceChecksumsFromDelta(Project1Id, lastResultId: -1, initialDelta); var noopDelta = new TagHelperDeltaResult(IsDelta: true, initialDelta.ResultId, Added: [], Removed: []); @@ -226,7 +226,7 @@ public void CalculateTagHelpersFromDelta_NoopResult() public void CalculateTagHelpersFromDelta_ReplacedTagHelpers() { // Arrange - var resolver = new TestResolver(_remoteClientProvider, LoggerFactory, NoOpTelemetryReporter.Instance); + var resolver = new TestResolver(_remoteServiceInvoker, LoggerFactory, NoOpTelemetryReporter.Instance); var initialDelta = new TagHelperDeltaResult(IsDelta: false, ResultId: 1, Added: Project1TagHelperChecksums, Removed: []); resolver.PublicProduceChecksumsFromDelta(Project1Id, lastResultId: -1, initialDelta); var changedDelta = new TagHelperDeltaResult(IsDelta: true, initialDelta.ResultId + 1, Added: [TagHelper2_Project2.Checksum], Removed: [TagHelper2_Project1.Checksum]); From da4bd7da6c852fca826e20a161c6e670be314dff Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Mon, 15 Jul 2024 12:07:30 -0700 Subject: [PATCH 085/176] Add RazorBrokeredServiceData and rework remote logging --- .../Logging/RemoteLoggerFactory.cs | 28 ++++++++++++------- .../Logging/SimpleLoggerFactory.cs | 21 ++++++++++++++ ...cs => TraceSourceLoggerProvider.Logger.cs} | 18 ++++-------- .../Logging/TraceSourceLoggerProvider.cs | 15 ++++++++++ .../RazorBrokeredServiceBase.FactoryBase`1.cs | 17 +++++++++-- .../RazorBrokeredServiceData.cs | 9 ++++++ 6 files changed, 83 insertions(+), 25 deletions(-) create mode 100644 src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Logging/SimpleLoggerFactory.cs rename src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Logging/{RemoteLoggerFactory.Logger.cs => TraceSourceLoggerProvider.Logger.cs} (54%) create mode 100644 src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Logging/TraceSourceLoggerProvider.cs create mode 100644 src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorBrokeredServiceData.cs diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Logging/RemoteLoggerFactory.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Logging/RemoteLoggerFactory.cs index 39f9a2c44bf..9fc5e90a687 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Logging/RemoteLoggerFactory.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Logging/RemoteLoggerFactory.cs @@ -3,34 +3,42 @@ using System; using System.Composition; -using System.Diagnostics; +using Microsoft.AspNetCore.Razor; using Microsoft.CodeAnalysis.Razor.Logging; namespace Microsoft.CodeAnalysis.Remote.Razor.Logging; -[Export(typeof(ILoggerFactory)), Shared] -[method: ImportingConstructor] -internal partial class RemoteLoggerFactory() : ILoggerFactory +[Shared] +[Export(typeof(ILoggerFactory))] +[Export(typeof(RemoteLoggerFactory))] +internal sealed class RemoteLoggerFactory : ILoggerFactory { - private static TraceSource? s_traceSource; + private ILoggerFactory? _targetLoggerFactory; - internal static TraceSource Initialize(IServiceProvider hostProvidedServices) + private ILoggerFactory TargetLoggerFactory => _targetLoggerFactory.AssumeNotNull(); + + internal void SetTargetLoggerFactory(ILoggerFactory loggerFactory) { - s_traceSource ??= (TraceSource)hostProvidedServices.GetService(typeof(TraceSource)); - return s_traceSource; + if (_targetLoggerFactory is not null) + { + throw new InvalidOperationException($"{nameof(_targetLoggerFactory)} is already set."); + } + + _targetLoggerFactory = loggerFactory; } public void AddLoggerProvider(ILoggerProvider provider) { - throw new NotImplementedException(); + TargetLoggerFactory.AddLoggerProvider(provider); } public ILogger GetOrCreateLogger(string categoryName) { - return new Logger(categoryName); + return TargetLoggerFactory.GetOrCreateLogger(categoryName); } public void Dispose() { + // Don't dispose the inner ILoggerFactory because we don't own it. } } diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Logging/SimpleLoggerFactory.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Logging/SimpleLoggerFactory.cs new file mode 100644 index 00000000000..469c1a7991f --- /dev/null +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Logging/SimpleLoggerFactory.cs @@ -0,0 +1,21 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT license. See License.txt in the project root for license information. + +using System.Collections.Immutable; +using System.Diagnostics; +using Microsoft.CodeAnalysis.Razor.Logging; + +namespace Microsoft.CodeAnalysis.Remote.Razor.Logging; + +internal sealed class SimpleLoggerFactory : AbstractLoggerFactory +{ + public static ILoggerFactory Empty { get; } = new SimpleLoggerFactory([]); + + private SimpleLoggerFactory(ImmutableArray loggerProviders) + : base(loggerProviders) + { + } + + public static ILoggerFactory CreateWithTraceSource(TraceSource traceSource) + => new SimpleLoggerFactory([new TraceSourceLoggerProvider(traceSource)]); +} diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Logging/RemoteLoggerFactory.Logger.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Logging/TraceSourceLoggerProvider.Logger.cs similarity index 54% rename from src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Logging/RemoteLoggerFactory.Logger.cs rename to src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Logging/TraceSourceLoggerProvider.Logger.cs index fd6ccaf9adb..f19b2ce78b4 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Logging/RemoteLoggerFactory.Logger.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Logging/TraceSourceLoggerProvider.Logger.cs @@ -7,35 +7,29 @@ namespace Microsoft.CodeAnalysis.Remote.Razor.Logging; -internal partial class RemoteLoggerFactory +internal partial class TraceSourceLoggerProvider { - private class Logger(string categoryName) : ILogger + private class Logger(TraceSource traceSource, string categoryName) : ILogger { public bool IsEnabled(LogLevel logLevel) => true; public void Log(LogLevel logLevel, string message, Exception? exception) { - if (s_traceSource is null) - { - // We can't log if there is no trace source to log to - return; - } - switch (logLevel) { case LogLevel.Information: - s_traceSource.TraceEvent(TraceEventType.Information, id: 0, "[{0}] {1}", categoryName, message); + traceSource.TraceEvent(TraceEventType.Information, id: 0, "[{0}] {1}", categoryName, message); break; case LogLevel.Trace: case LogLevel.Debug: - s_traceSource.TraceEvent(TraceEventType.Verbose, id: 0, "[{0}] {1}", categoryName, message); + traceSource.TraceEvent(TraceEventType.Verbose, id: 0, "[{0}] {1}", categoryName, message); break; case LogLevel.Warning: - s_traceSource.TraceEvent(TraceEventType.Warning, id: 0, "[{0}] {1}", categoryName, message); + traceSource.TraceEvent(TraceEventType.Warning, id: 0, "[{0}] {1}", categoryName, message); break; case LogLevel.Error: case LogLevel.Critical: - s_traceSource.TraceEvent(TraceEventType.Error, id: 0, "[{0}] {1} {2}", categoryName, message, exception!); + traceSource.TraceEvent(TraceEventType.Error, id: 0, "[{0}] {1} {2}", categoryName, message, exception!); break; } } diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Logging/TraceSourceLoggerProvider.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Logging/TraceSourceLoggerProvider.cs new file mode 100644 index 00000000000..222f79cde29 --- /dev/null +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Logging/TraceSourceLoggerProvider.cs @@ -0,0 +1,15 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT license. See License.txt in the project root for license information. + +using System.Diagnostics; +using Microsoft.CodeAnalysis.Razor.Logging; + +namespace Microsoft.CodeAnalysis.Remote.Razor.Logging; + +internal partial class TraceSourceLoggerProvider(TraceSource traceSource) : ILoggerProvider +{ + public ILogger CreateLogger(string categoryName) + { + return new Logger(traceSource, categoryName); + } +} diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorBrokeredServiceBase.FactoryBase`1.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorBrokeredServiceBase.FactoryBase`1.cs index 316c16d69d9..690b1c7938b 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorBrokeredServiceBase.FactoryBase`1.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorBrokeredServiceBase.FactoryBase`1.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. See License.txt in the project root for license information. using System; +using System.Diagnostics; using System.IO; using System.Threading.Tasks; using Microsoft.CodeAnalysis.Razor.Remote; @@ -31,15 +32,25 @@ public async Task CreateAsync( // Dispose the AuthorizationServiceClient since we won't be using it authorizationServiceClient?.Dispose(); - var traceSource = RemoteLoggerFactory.Initialize(hostProvidedServices); + var traceSource = (TraceSource?)hostProvidedServices.GetService(typeof(TraceSource)); + var brokeredServiceData = (RazorBrokeredServiceData?)hostProvidedServices.GetService(typeof(RazorBrokeredServiceData)); + + var exportProvider = brokeredServiceData?.ExportProvider + ?? await RemoteMefComposition.GetExportProviderAsync().ConfigureAwait(false); + + var targetLoggerFactory = brokeredServiceData?.LoggerFactory + ?? (traceSource is not null + ? SimpleLoggerFactory.CreateWithTraceSource(traceSource) + : SimpleLoggerFactory.Empty); + + var remoteLoggerFactory = exportProvider.GetExportedValue(); + remoteLoggerFactory.SetTargetLoggerFactory(targetLoggerFactory); var pipe = stream.UsePipe(); var descriptor = RazorServices.Descriptors.GetDescriptorForServiceFactory(typeof(TService)); var serverConnection = descriptor.WithTraceSource(traceSource).ConstructRpcConnection(pipe); - var exportProvider = await RemoteMefComposition.GetExportProviderAsync().ConfigureAwait(false); - var razorServiceBroker = new RazorServiceBroker(serviceBroker); var args = new ServiceArgs(razorServiceBroker, exportProvider); diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorBrokeredServiceData.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorBrokeredServiceData.cs new file mode 100644 index 00000000000..70282c79bd5 --- /dev/null +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorBrokeredServiceData.cs @@ -0,0 +1,9 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT license. See License.txt in the project root for license information. + +using Microsoft.CodeAnalysis.Razor.Logging; +using Microsoft.VisualStudio.Composition; + +namespace Microsoft.CodeAnalysis.Remote.Razor; + +internal sealed record class RazorBrokeredServiceData(ExportProvider? ExportProvider, ILoggerFactory? LoggerFactory); From e32163cc515038ab80bfcbe169b1057ac0040432 Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Mon, 15 Jul 2024 12:15:45 -0700 Subject: [PATCH 086/176] Ensure that the RpcConnection is disposed --- .../RazorBrokeredServiceBase.FactoryBase`1.cs | 2 +- .../RazorServiceBroker.cs | 5 ++++- .../Microsoft.CodeAnalysis.Remote.Razor/ServiceArgs.cs | 8 +++----- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorBrokeredServiceBase.FactoryBase`1.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorBrokeredServiceBase.FactoryBase`1.cs index 690b1c7938b..5f64cd99433 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorBrokeredServiceBase.FactoryBase`1.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorBrokeredServiceBase.FactoryBase`1.cs @@ -51,7 +51,7 @@ public async Task CreateAsync( var descriptor = RazorServices.Descriptors.GetDescriptorForServiceFactory(typeof(TService)); var serverConnection = descriptor.WithTraceSource(traceSource).ConstructRpcConnection(pipe); - var razorServiceBroker = new RazorServiceBroker(serviceBroker); + var razorServiceBroker = new RazorServiceBroker(serviceBroker, serverConnection); var args = new ServiceArgs(razorServiceBroker, exportProvider); var service = CreateService(in args); diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorServiceBroker.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorServiceBroker.cs index 928ffed1f99..5128a4f7dd8 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorServiceBroker.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorServiceBroker.cs @@ -13,10 +13,12 @@ namespace Microsoft.CodeAnalysis.Remote.Razor; internal class RazorServiceBroker : IRazorServiceBroker { private readonly ServiceBrokerClient _serviceBrokerClient; + private readonly ServiceRpcDescriptor.RpcConnection _serverConnection; - public RazorServiceBroker(IServiceBroker serviceBroker) + public RazorServiceBroker(IServiceBroker serviceBroker, ServiceRpcDescriptor.RpcConnection serverConnection) { _serviceBrokerClient = new ServiceBrokerClient(serviceBroker, joinableTaskFactory: null); + _serverConnection = serverConnection; } public ValueTask RunServiceAsync(Func implementation, CancellationToken cancellationToken) @@ -28,5 +30,6 @@ public ValueTask RunServiceAsync(RazorPinnedSolutionInfoWrapper solutionIn public void Dispose() { _serviceBrokerClient.Dispose(); + _serverConnection.Dispose(); } } diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/ServiceArgs.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/ServiceArgs.cs index 8c87e02425f..248a492da9e 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/ServiceArgs.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/ServiceArgs.cs @@ -5,8 +5,6 @@ namespace Microsoft.CodeAnalysis.Remote.Razor; -internal readonly struct ServiceArgs(IRazorServiceBroker serviceBroker, ExportProvider exportProvider) -{ - public readonly IRazorServiceBroker ServiceBroker = serviceBroker; - public readonly ExportProvider ExportProvider = exportProvider; -} +internal readonly record struct ServiceArgs( + IRazorServiceBroker ServiceBroker, + ExportProvider ExportProvider); From 8cf2152cb378dedc4af79ac7ee3a17a26230dd46 Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Mon, 15 Jul 2024 12:26:07 -0700 Subject: [PATCH 087/176] Don't inherit all service interfaces from IDisposable --- .../Remote/IRemoteClientInitializationService.cs | 3 +-- .../Remote/IRemoteFoldingRangeService.cs | 3 +-- .../Remote/IRemoteHtmlDocumentService.cs | 3 +-- .../Remote/IRemoteLinkedEditingRangeService.cs | 3 +-- .../Remote/IRemoteSemanticTokensService.cs | 2 +- .../Remote/IRemoteServiceInvoker.cs | 2 +- .../Remote/IRemoteTagHelperProviderService.cs | 3 +-- .../Remote/IRemoteUriPresentationService.cs | 2 +- .../Remote/RemoteServiceInvoker.cs | 2 +- .../Cohost/TestRemoteServiceInvoker.cs | 11 +++++++---- 10 files changed, 16 insertions(+), 18 deletions(-) diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteClientInitializationService.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteClientInitializationService.cs index 32c9d4bd1ac..8089bc68099 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteClientInitializationService.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteClientInitializationService.cs @@ -1,13 +1,12 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT license. See License.txt in the project root for license information. -using System; using System.Threading; using System.Threading.Tasks; namespace Microsoft.CodeAnalysis.Razor.Remote; -internal interface IRemoteClientInitializationService : IDisposable +internal interface IRemoteClientInitializationService { ValueTask InitializeAsync(RemoteClientInitializationOptions initializationOptions, CancellationToken cancellationToken); diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteFoldingRangeService.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteFoldingRangeService.cs index c3368da527e..f709ed98631 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteFoldingRangeService.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteFoldingRangeService.cs @@ -1,7 +1,6 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT license. See License.txt in the project root for license information. -using System; using System.Collections.Immutable; using System.Threading; using System.Threading.Tasks; @@ -10,7 +9,7 @@ namespace Microsoft.CodeAnalysis.Razor.Remote; -internal interface IRemoteFoldingRangeService : IDisposable +internal interface IRemoteFoldingRangeService { ValueTask> GetFoldingRangesAsync(RazorPinnedSolutionInfoWrapper solutionInfo, DocumentId documentId, ImmutableArray htmlRanges, CancellationToken cancellationToken); } diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteHtmlDocumentService.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteHtmlDocumentService.cs index de87623fe74..832a851949a 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteHtmlDocumentService.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteHtmlDocumentService.cs @@ -1,14 +1,13 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT license. See License.txt in the project root for license information. -using System; using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.ExternalAccess.Razor; namespace Microsoft.CodeAnalysis.Razor.Remote; -internal interface IRemoteHtmlDocumentService : IDisposable +internal interface IRemoteHtmlDocumentService { ValueTask GetHtmlDocumentTextAsync(RazorPinnedSolutionInfoWrapper solutionInfo, DocumentId razorDocumentId, CancellationToken cancellationToken); } diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteLinkedEditingRangeService.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteLinkedEditingRangeService.cs index 87f94ac9f10..0520974b6fd 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteLinkedEditingRangeService.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteLinkedEditingRangeService.cs @@ -1,7 +1,6 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT license. See License.txt in the project root for license information. -using System; using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.ExternalAccess.Razor; @@ -9,7 +8,7 @@ namespace Microsoft.CodeAnalysis.Razor.Remote; -internal interface IRemoteLinkedEditingRangeService : IDisposable +internal interface IRemoteLinkedEditingRangeService { ValueTask GetRangesAsync(RazorPinnedSolutionInfoWrapper solutionInfo, DocumentId razorDocumentId, LinePosition linePosition, CancellationToken cancellationToken); } diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteSemanticTokensService.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteSemanticTokensService.cs index 1d2f1b0a8ea..19778bfcfea 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteSemanticTokensService.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteSemanticTokensService.cs @@ -9,7 +9,7 @@ namespace Microsoft.CodeAnalysis.Razor.Remote; -internal interface IRemoteSemanticTokensService : IDisposable +internal interface IRemoteSemanticTokensService { ValueTask GetSemanticTokensDataAsync( RazorPinnedSolutionInfoWrapper solutionInfo, diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteServiceInvoker.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteServiceInvoker.cs index c2746cfacba..28345360952 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteServiceInvoker.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteServiceInvoker.cs @@ -17,5 +17,5 @@ internal interface IRemoteServiceInvoker CancellationToken cancellationToken, [CallerFilePath] string? callerFilePath = null, [CallerMemberName] string? callerMemberName = null) - where TService : class, IDisposable; + where TService : class; } diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteTagHelperProviderService.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteTagHelperProviderService.cs index b2ddfd2af45..eb17de0887c 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteTagHelperProviderService.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteTagHelperProviderService.cs @@ -1,7 +1,6 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT license. See License.txt in the project root for license information. -using System; using System.Collections.Immutable; using System.Threading; using System.Threading.Tasks; @@ -11,7 +10,7 @@ namespace Microsoft.CodeAnalysis.Razor.Remote; -internal interface IRemoteTagHelperProviderService : IDisposable +internal interface IRemoteTagHelperProviderService { ValueTask GetTagHelpersDeltaAsync( RazorPinnedSolutionInfoWrapper solutionInfo, diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteUriPresentationService.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteUriPresentationService.cs index 1d13c9c5743..4c9e3707bef 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteUriPresentationService.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteUriPresentationService.cs @@ -9,7 +9,7 @@ namespace Microsoft.CodeAnalysis.Razor.Remote; -internal interface IRemoteUriPresentationService : IDisposable +internal interface IRemoteUriPresentationService { ValueTask GetPresentationAsync(RazorPinnedSolutionInfoWrapper solutionInfo, DocumentId razorDocumentId, LinePositionSpan span, Uri[]? uris, CancellationToken cancellationToken); } diff --git a/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/Remote/RemoteServiceInvoker.cs b/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/Remote/RemoteServiceInvoker.cs index f801ce7286d..e60330a4d91 100644 --- a/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/Remote/RemoteServiceInvoker.cs +++ b/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/Remote/RemoteServiceInvoker.cs @@ -47,7 +47,7 @@ internal sealed class RemoteServiceInvoker( CancellationToken cancellationToken, [CallerFilePath] string? callerFilePath = null, [CallerMemberName] string? callerMemberName = null) - where TService : class, IDisposable + where TService : class { var client = await TryGetClientAsync(cancellationToken).ConfigureAwait(false); if (client is null) diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/TestRemoteServiceInvoker.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/TestRemoteServiceInvoker.cs index c71ac3835a4..a89dede6719 100644 --- a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/TestRemoteServiceInvoker.cs +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/TestRemoteServiceInvoker.cs @@ -21,10 +21,10 @@ namespace Microsoft.VisualStudio.Razor.LanguageClient.Cohost; internal sealed class TestRemoteServiceInvoker(ExportProvider exportProvider) : IRemoteServiceInvoker, IDisposable { private readonly TestServiceBroker _serviceBroker = new(); - private readonly Dictionary _services = []; + private readonly Dictionary _services = []; private TService GetOrCreateService() - where TService : class, IDisposable + where TService : class { if (!_services.TryGetValue(typeof(TService), out var service)) { @@ -42,7 +42,7 @@ private TService GetOrCreateService() CancellationToken cancellationToken, [CallerFilePath] string? callerFilePath = null, [CallerMemberName] string? callerMemberName = null) - where TService : class, IDisposable + where TService : class { var service = GetOrCreateService(); @@ -58,7 +58,10 @@ public void Dispose() { foreach (var service in _services.Values) { - service.Dispose(); + if (service is IDisposable d) + { + d.Dispose(); + } } } } From 41a04758b3ea3570f0652c5323c0b1aae55e03b2 Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Mon, 15 Jul 2024 13:41:02 -0700 Subject: [PATCH 088/176] Rework cohosting test infrastructure a bit --- ...cs => IRazorBrokeredServiceInterceptor.cs} | 13 ++++--- .../RazorBrokeredServiceBase.FactoryBase`1.cs | 11 +----- .../RazorBrokeredServiceBase.cs | 21 ++++++++--- .../RazorBrokeredServiceData.cs | 5 ++- .../RazorServiceBroker.cs | 35 ------------------- .../RemoteMefComposition.cs | 28 ++++++++++----- .../ServiceArgs.cs | 7 ++-- .../Cohost/BrokeredServiceFactory.cs | 30 +++++++++++----- .../Cohost/CohostTestBase.cs | 18 +++++++--- .../Cohost/TestRemoteServiceInvoker.cs | 31 ++++++++++------ .../Cohost/TestServiceBroker.cs | 15 +++++--- 11 files changed, 121 insertions(+), 93 deletions(-) rename src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/{IRazorServiceBroker.cs => IRazorBrokeredServiceInterceptor.cs} (52%) delete mode 100644 src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorServiceBroker.cs diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/IRazorServiceBroker.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/IRazorBrokeredServiceInterceptor.cs similarity index 52% rename from src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/IRazorServiceBroker.cs rename to src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/IRazorBrokeredServiceInterceptor.cs index 7f2d59ae0d6..39b4b236cf6 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/IRazorServiceBroker.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/IRazorBrokeredServiceInterceptor.cs @@ -10,11 +10,16 @@ namespace Microsoft.CodeAnalysis.Remote.Razor; /// -/// An abstraction to avoid calling the static helper defined in Roslyn +/// An abstraction to avoid calling the static helper defined in Roslyn. /// -internal interface IRazorServiceBroker : IDisposable +internal interface IRazorBrokeredServiceInterceptor { - ValueTask RunServiceAsync(Func implementation, CancellationToken cancellationToken); + ValueTask RunServiceAsync( + Func implementation, + CancellationToken cancellationToken); - ValueTask RunServiceAsync(RazorPinnedSolutionInfoWrapper solutionInfo, Func> implementation, CancellationToken cancellationToken); + ValueTask RunServiceAsync( + RazorPinnedSolutionInfoWrapper solutionInfo, + Func> implementation, + CancellationToken cancellationToken); } diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorBrokeredServiceBase.FactoryBase`1.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorBrokeredServiceBase.FactoryBase`1.cs index 5f64cd99433..7373048b73b 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorBrokeredServiceBase.FactoryBase`1.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorBrokeredServiceBase.FactoryBase`1.cs @@ -51,8 +51,7 @@ public async Task CreateAsync( var descriptor = RazorServices.Descriptors.GetDescriptorForServiceFactory(typeof(TService)); var serverConnection = descriptor.WithTraceSource(traceSource).ConstructRpcConnection(pipe); - var razorServiceBroker = new RazorServiceBroker(serviceBroker, serverConnection); - var args = new ServiceArgs(razorServiceBroker, exportProvider); + var args = new ServiceArgs(serviceBroker, exportProvider, serverConnection, brokeredServiceData?.Interceptor); var service = CreateService(in args); @@ -63,13 +62,5 @@ public async Task CreateAsync( } protected abstract TService CreateService(in ServiceArgs args); - - internal TestAccessor GetTestAccessor() => new(this); - - internal readonly struct TestAccessor(FactoryBase instance) - { - public TService CreateService(in ServiceArgs args) - => instance.CreateService(in args); - } } } diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorBrokeredServiceBase.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorBrokeredServiceBase.cs index a49efdbf11f..a44062833d7 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorBrokeredServiceBase.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorBrokeredServiceBase.cs @@ -5,32 +5,43 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.ExternalAccess.Razor; +using Microsoft.CodeAnalysis.ExternalAccess.Razor.Api; using Microsoft.CodeAnalysis.Razor.Logging; +using Microsoft.ServiceHub.Framework; namespace Microsoft.CodeAnalysis.Remote.Razor; internal abstract partial class RazorBrokeredServiceBase : IDisposable { - private readonly IRazorServiceBroker _serviceBroker; + private readonly ServiceBrokerClient _serviceBrokerClient; + private readonly ServiceRpcDescriptor.RpcConnection? _serverConnection; + private readonly IRazorBrokeredServiceInterceptor? _interceptor; protected readonly ILogger Logger; protected RazorBrokeredServiceBase(in ServiceArgs args) { - _serviceBroker = args.ServiceBroker; + _serviceBrokerClient = new ServiceBrokerClient(args.ServiceBroker, joinableTaskFactory: null); + _serverConnection = args.ServerConnection; + _interceptor = args.Interceptor; var loggerFactory = args.ExportProvider.GetExportedValue(); Logger = loggerFactory.GetOrCreateLogger(GetType()); } protected ValueTask RunServiceAsync(Func implementation, CancellationToken cancellationToken) - => _serviceBroker.RunServiceAsync(implementation, cancellationToken); + => _interceptor is not null + ? _interceptor.RunServiceAsync(implementation, cancellationToken) + : RazorBrokeredServiceImplementation.RunServiceAsync(implementation, cancellationToken); protected ValueTask RunServiceAsync(RazorPinnedSolutionInfoWrapper solutionInfo, Func> implementation, CancellationToken cancellationToken) - => _serviceBroker.RunServiceAsync(solutionInfo, implementation, cancellationToken); + => _interceptor is not null + ? _interceptor.RunServiceAsync(solutionInfo, implementation, cancellationToken) + : RazorBrokeredServiceImplementation.RunServiceAsync(solutionInfo, _serviceBrokerClient, implementation, cancellationToken); public void Dispose() { - _serviceBroker.Dispose(); + _serviceBrokerClient.Dispose(); + _serverConnection?.Dispose(); } } diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorBrokeredServiceData.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorBrokeredServiceData.cs index 70282c79bd5..862fef2f615 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorBrokeredServiceData.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorBrokeredServiceData.cs @@ -6,4 +6,7 @@ namespace Microsoft.CodeAnalysis.Remote.Razor; -internal sealed record class RazorBrokeredServiceData(ExportProvider? ExportProvider, ILoggerFactory? LoggerFactory); +internal sealed record class RazorBrokeredServiceData( + ExportProvider? ExportProvider, + ILoggerFactory? LoggerFactory, + IRazorBrokeredServiceInterceptor? Interceptor); diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorServiceBroker.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorServiceBroker.cs deleted file mode 100644 index 5128a4f7dd8..00000000000 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorServiceBroker.cs +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the MIT license. See License.txt in the project root for license information. - -using System; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.CodeAnalysis.ExternalAccess.Razor; -using Microsoft.CodeAnalysis.ExternalAccess.Razor.Api; -using Microsoft.ServiceHub.Framework; - -namespace Microsoft.CodeAnalysis.Remote.Razor; - -internal class RazorServiceBroker : IRazorServiceBroker -{ - private readonly ServiceBrokerClient _serviceBrokerClient; - private readonly ServiceRpcDescriptor.RpcConnection _serverConnection; - - public RazorServiceBroker(IServiceBroker serviceBroker, ServiceRpcDescriptor.RpcConnection serverConnection) - { - _serviceBrokerClient = new ServiceBrokerClient(serviceBroker, joinableTaskFactory: null); - _serverConnection = serverConnection; - } - - public ValueTask RunServiceAsync(Func implementation, CancellationToken cancellationToken) - => RazorBrokeredServiceImplementation.RunServiceAsync(implementation, cancellationToken); - - public ValueTask RunServiceAsync(RazorPinnedSolutionInfoWrapper solutionInfo, Func> implementation, CancellationToken cancellationToken) - => RazorBrokeredServiceImplementation.RunServiceAsync(solutionInfo, _serviceBrokerClient, implementation, cancellationToken); - - public void Dispose() - { - _serviceBrokerClient.Dispose(); - _serverConnection.Dispose(); - } -} diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RemoteMefComposition.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RemoteMefComposition.cs index a86c3fcf0c6..d031f2ec34d 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RemoteMefComposition.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RemoteMefComposition.cs @@ -3,6 +3,7 @@ using System.Collections.Immutable; using System.Reflection; +using System.Threading; using System.Threading.Tasks; using Microsoft.VisualStudio.Composition; using Microsoft.VisualStudio.Threading; @@ -13,25 +14,34 @@ internal static class RemoteMefComposition { internal static readonly ImmutableArray RemoteHostAssemblies = [typeof(RemoteMefComposition).Assembly]; -#pragma warning disable VSTHRD012 // Provide JoinableTaskFactory where allowed - private static readonly AsyncLazy s_exportProviderLazy = new(CreateExportProviderAsync); -#pragma warning restore VSTHRD012 // Provide JoinableTaskFactory where allowed + private static readonly AsyncLazy s_lazyConfiguration = new(CreateConfigurationAsync, joinableTaskFactory: null); - public static Task GetExportProviderAsync() - => s_exportProviderLazy.GetValueAsync(); + private static readonly AsyncLazy s_lazyExportProvider = new(CreateExportProviderAsync, joinableTaskFactory: null); - // Internal for testing - // Inspired by https://github.com/dotnet/roslyn/blob/25aa74d725e801b8232dbb3e5abcda0fa72da8c5/src/Workspaces/Remote/ServiceHub/Host/RemoteWorkspaceManager.cs#L77 - internal static async Task CreateExportProviderAsync() + public static Task GetConfigurationAsync(CancellationToken cancellationToken = default) + => s_lazyConfiguration.GetValueAsync(cancellationToken); + + public static Task GetExportProviderAsync(CancellationToken cancellationToken = default) + => s_lazyExportProvider.GetValueAsync(cancellationToken); + + private static async Task CreateConfigurationAsync() { var resolver = new Resolver(SimpleAssemblyLoader.Instance); var discovery = new AttributedPartDiscovery(resolver, isNonPublicSupported: true); // MEFv2 only var parts = await discovery.CreatePartsAsync(RemoteHostAssemblies).ConfigureAwait(false); var catalog = ComposableCatalog.Create(resolver).AddParts(parts); - var configuration = CompositionConfiguration.Create(catalog).ThrowOnErrors(); + return CompositionConfiguration.Create(catalog).ThrowOnErrors(); + } + + // Internal for testing + // Inspired by https://github.com/dotnet/roslyn/blob/25aa74d725e801b8232dbb3e5abcda0fa72da8c5/src/Workspaces/Remote/ServiceHub/Host/RemoteWorkspaceManager.cs#L77 + private static async Task CreateExportProviderAsync() + { + var configuration = await s_lazyConfiguration.GetValueAsync(); var runtimeComposition = RuntimeComposition.CreateRuntimeComposition(configuration); var exportProviderFactory = runtimeComposition.CreateExportProviderFactory(); + return exportProviderFactory.CreateExportProvider(); } diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/ServiceArgs.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/ServiceArgs.cs index 248a492da9e..d177444e658 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/ServiceArgs.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/ServiceArgs.cs @@ -1,10 +1,13 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT license. See License.txt in the project root for license information. +using Microsoft.ServiceHub.Framework; using Microsoft.VisualStudio.Composition; namespace Microsoft.CodeAnalysis.Remote.Razor; internal readonly record struct ServiceArgs( - IRazorServiceBroker ServiceBroker, - ExportProvider ExportProvider); + IServiceBroker ServiceBroker, + ExportProvider ExportProvider, + ServiceRpcDescriptor.RpcConnection? ServerConnection = null, + IRazorBrokeredServiceInterceptor? Interceptor = null); diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/BrokeredServiceFactory.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/BrokeredServiceFactory.cs index fb858f4db0e..849d87876f7 100644 --- a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/BrokeredServiceFactory.cs +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/BrokeredServiceFactory.cs @@ -3,9 +3,15 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Razor.Test.Common.VisualStudio; +using Microsoft.CodeAnalysis.Razor.Logging; using Microsoft.CodeAnalysis.Remote.Razor; using Microsoft.ServiceHub.Framework; +using Microsoft.VisualStudio.Composition; +using Nerdbank.Streams; using Xunit; namespace Microsoft.VisualStudio.Razor.LanguageClient.Cohost; @@ -45,19 +51,27 @@ private static Dictionary BuildFactoryMap() return result; } - private static RazorBrokeredServiceBase.FactoryBase GetServiceFactory() + public static async Task CreateServiceAsync( + TestServiceBroker serviceBroker, ExportProvider exportProvider, ILoggerFactory loggerFactory) where TService : class { Assert.True(s_factoryMap.TryGetValue(typeof(TService), out var factory)); - return (RazorBrokeredServiceBase.FactoryBase)factory; - } + var (clientStream, serverStream) = FullDuplexStream.CreatePair(); + var brokeredServiceData = new RazorBrokeredServiceData(exportProvider, loggerFactory, serviceBroker); + var hostProvidedServices = VsMocks.CreateServiceProvider(b => + { + b.AddService(brokeredServiceData); - public static TService CreateService(in ServiceArgs args) - where TService : class - { - var factory = GetServiceFactory(); + // Don't provide a trace source. Brokered services and MEF components will rely on ILoggerFactory. + b.AddService((object?)null); + }); - return factory.GetTestAccessor().CreateService(in args); + return (TService)await factory.CreateAsync( + serverStream, + hostProvidedServices, + serviceActivationOptions: default, + serviceBroker, + authorizationServiceClient: default!); } } diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostTestBase.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostTestBase.cs index c7f67c0e657..16fa2ab3516 100644 --- a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostTestBase.cs +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostTestBase.cs @@ -9,25 +9,33 @@ using Microsoft.AspNetCore.Razor.Test.Common; using Microsoft.AspNetCore.Razor.Test.Common.Workspaces; using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.Razor.Remote; using Microsoft.CodeAnalysis.Remote.Razor; using Microsoft.CodeAnalysis.Text; +using Microsoft.VisualStudio.Composition; using Xunit.Abstractions; namespace Microsoft.VisualStudio.Razor.LanguageClient.Cohost; public abstract class CohostTestBase(ITestOutputHelper testOutputHelper) : WorkspaceTestBase(testOutputHelper) { - private IRemoteServiceInvoker? _remoteServiceInvoker; + private TestRemoteServiceInvoker? _remoteServiceInvoker; - private protected IRemoteServiceInvoker RemoteServiceInvoker => _remoteServiceInvoker.AssumeNotNull(); + private protected TestRemoteServiceInvoker RemoteServiceInvoker => _remoteServiceInvoker.AssumeNotNull(); protected override async Task InitializeAsync() { await base.InitializeAsync(); - var exportProvider = AddDisposable(await RemoteMefComposition.CreateExportProviderAsync()); - _remoteServiceInvoker = AddDisposable(new TestRemoteServiceInvoker(exportProvider)); + // Create a new isolated MEF composition but use the cached configuration for performance. + var configuration = await RemoteMefComposition.GetConfigurationAsync(DisposalToken); + var runtimeComposition = RuntimeComposition.CreateRuntimeComposition(configuration); + var exportProviderFactory = runtimeComposition.CreateExportProviderFactory(); + var exportProvider = exportProviderFactory.CreateExportProvider(); + + AddDisposable(exportProvider); + + _remoteServiceInvoker = new TestRemoteServiceInvoker(JoinableTaskContext, exportProvider, LoggerFactory); + AddDisposable(_remoteServiceInvoker); } protected TextDocument CreateProjectAndRazorDocument(string contents) diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/TestRemoteServiceInvoker.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/TestRemoteServiceInvoker.cs index a89dede6719..4ef4a5f4e88 100644 --- a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/TestRemoteServiceInvoker.cs +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/TestRemoteServiceInvoker.cs @@ -8,32 +8,41 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.ExternalAccess.Razor; +using Microsoft.CodeAnalysis.Razor.Logging; using Microsoft.CodeAnalysis.Razor.Remote; using Microsoft.CodeAnalysis.Remote.Razor; using Microsoft.VisualStudio.Composition; +using Microsoft.VisualStudio.Threading; namespace Microsoft.VisualStudio.Razor.LanguageClient.Cohost; /// /// An implementation of that doesn't actually do anything remote, -/// but rather directly calls service methods +/// but rather directly calls service methods. /// -internal sealed class TestRemoteServiceInvoker(ExportProvider exportProvider) : IRemoteServiceInvoker, IDisposable +internal sealed class TestRemoteServiceInvoker( + JoinableTaskContext joinableTaskContext, + ExportProvider exportProvider, + ILoggerFactory loggerFactory) : IRemoteServiceInvoker, IDisposable { private readonly TestServiceBroker _serviceBroker = new(); private readonly Dictionary _services = []; + private readonly ReentrantSemaphore _reentrantSemaphore = ReentrantSemaphore.Create(initialCount: 1, joinableTaskContext); - private TService GetOrCreateService() + private async Task GetOrCreateServiceAsync() where TService : class { - if (!_services.TryGetValue(typeof(TService), out var service)) + return await _reentrantSemaphore.ExecuteAsync(async () => { - var args = new ServiceArgs(_serviceBroker, exportProvider); - service = BrokeredServiceFactory.CreateService(in args); - _services.Add(typeof(TService), service); - } + if (!_services.TryGetValue(typeof(TService), out var service)) + { + var args = new ServiceArgs(_serviceBroker, exportProvider); + service = await BrokeredServiceFactory.CreateServiceAsync(_serviceBroker, exportProvider, loggerFactory); + _services.Add(typeof(TService), service); + } - return (TService)service; + return (TService)service; + }); } public async ValueTask TryInvokeAsync( @@ -44,7 +53,7 @@ private TService GetOrCreateService() [CallerMemberName] string? callerMemberName = null) where TService : class { - var service = GetOrCreateService(); + var service = await GetOrCreateServiceAsync(); // In an ideal world we'd be able to maintain a dictionary of solution checksums in TestServiceBroker, and use // the RazorPinnedSolutionInfoWrapper properly, but we need Roslyn changes for that. For now, this works fine @@ -56,6 +65,8 @@ private TService GetOrCreateService() public void Dispose() { + _reentrantSemaphore.Dispose(); + foreach (var service in _services.Values) { if (service is IDisposable d) diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/TestServiceBroker.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/TestServiceBroker.cs index e0674da6f11..c543f7d32a3 100644 --- a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/TestServiceBroker.cs +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/TestServiceBroker.cs @@ -2,19 +2,23 @@ // Licensed under the MIT license. See License.txt in the project root for license information. using System; +using System.IO.Pipelines; using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.Razor; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.ExternalAccess.Razor; using Microsoft.CodeAnalysis.Remote.Razor; +using Microsoft.ServiceHub.Framework; namespace Microsoft.VisualStudio.Razor.LanguageClient.Cohost; -internal sealed class TestServiceBroker : IRazorServiceBroker +internal sealed class TestServiceBroker : IServiceBroker, IRazorBrokeredServiceInterceptor { private Solution? _solution; + public event EventHandler? AvailabilityChanged; + public void UpdateSolution(Solution solution) { _solution = solution; @@ -30,7 +34,10 @@ public ValueTask RunServiceAsync(RazorPinnedSolutionInfoWrapper solutionIn return implementation(_solution.AssumeNotNull()); } - public void Dispose() - { - } + public ValueTask GetPipeAsync(ServiceMoniker serviceMoniker, ServiceActivationOptions options = default, CancellationToken cancellationToken = default) + => throw new NotImplementedException(); + + public ValueTask GetProxyAsync(ServiceRpcDescriptor serviceDescriptor, ServiceActivationOptions options = default, CancellationToken cancellationToken = default) + where T : class + => throw new NotImplementedException(); } From 20e107f86ba898283abc2af61dd91b29e834ddfb Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Mon, 15 Jul 2024 13:42:28 -0700 Subject: [PATCH 089/176] Use correct MEF interfaces --- .../Cohost/RazorCohostClientCapabilitiesService.cs | 5 +---- .../Cohost/RazorCohostDynamicRegistrationService.cs | 5 +---- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/RazorCohostClientCapabilitiesService.cs b/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/RazorCohostClientCapabilitiesService.cs index 7a0abddcfd9..cde4f43bbd8 100644 --- a/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/RazorCohostClientCapabilitiesService.cs +++ b/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/RazorCohostClientCapabilitiesService.cs @@ -2,17 +2,14 @@ // Licensed under the MIT license. See License.txt in the project root for license information. using System; -using System.Composition; +using System.ComponentModel.Composition; using Microsoft.CodeAnalysis.Razor.Protocol; using Microsoft.VisualStudio.LanguageServer.Protocol; namespace Microsoft.VisualStudio.Razor.LanguageClient.Cohost; -#pragma warning disable RS0030 // Do not use banned APIs -[Shared] [Export(typeof(RazorCohostClientCapabilitiesService))] [Export(typeof(IClientCapabilitiesService))] -#pragma warning restore RS0030 // Do not use banned APIs internal class RazorCohostClientCapabilitiesService : IClientCapabilitiesService { private VSInternalClientCapabilities? _clientCapabilities; diff --git a/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/RazorCohostDynamicRegistrationService.cs b/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/RazorCohostDynamicRegistrationService.cs index 5eab1db55f7..29d86c5cb60 100644 --- a/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/RazorCohostDynamicRegistrationService.cs +++ b/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/RazorCohostDynamicRegistrationService.cs @@ -3,7 +3,7 @@ using System; using System.Collections.Generic; -using System.Composition; +using System.ComponentModel.Composition; using System.Text.Json; using System.Threading; using System.Threading.Tasks; @@ -14,8 +14,6 @@ namespace Microsoft.VisualStudio.Razor.LanguageClient.Cohost; -#pragma warning disable RS0030 // Do not use banned APIs -[Shared] [Export(typeof(IRazorCohostDynamicRegistrationService))] [method: ImportingConstructor] internal class RazorCohostDynamicRegistrationService( @@ -24,7 +22,6 @@ internal class RazorCohostDynamicRegistrationService( Lazy lazyRazorCohostClientCapabilitiesService) : IRazorCohostDynamicRegistrationService { -#pragma warning restore RS0030 // Do not use banned APIs private readonly DocumentFilter[] _filter = [new DocumentFilter() { Language = Constants.RazorLanguageName, From 37b6f94450ac436ff0875ed04463812ba771ae95 Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Mon, 15 Jul 2024 15:09:41 -0700 Subject: [PATCH 090/176] Further remote logging work --- .../Logging/EmptyLoggerFactory.cs | 17 +++++++++++++++ .../Logging/RemoteLoggerFactory.cs | 18 ++++++---------- .../Logging/SimpleLoggerFactory.cs | 21 ------------------- ....cs => TraceSourceLoggerFactory.Logger.cs} | 4 ++-- ...TraceSourceLoggerFactory.LoggerProvider.cs | 16 ++++++++++++++ ...rovider.cs => TraceSourceLoggerFactory.cs} | 7 ++----- .../RazorBrokeredServiceBase.FactoryBase`1.cs | 21 ++++++++++++++----- .../RazorBrokeredServiceBase.cs | 3 +-- .../ServiceArgs.cs | 2 ++ .../Cohost/TestServiceBroker.cs | 2 +- 10 files changed, 63 insertions(+), 48 deletions(-) create mode 100644 src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Logging/EmptyLoggerFactory.cs delete mode 100644 src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Logging/SimpleLoggerFactory.cs rename src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Logging/{TraceSourceLoggerProvider.Logger.cs => TraceSourceLoggerFactory.Logger.cs} (90%) create mode 100644 src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Logging/TraceSourceLoggerFactory.LoggerProvider.cs rename src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Logging/{TraceSourceLoggerProvider.cs => TraceSourceLoggerFactory.cs} (57%) diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Logging/EmptyLoggerFactory.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Logging/EmptyLoggerFactory.cs new file mode 100644 index 00000000000..d52a222626d --- /dev/null +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Logging/EmptyLoggerFactory.cs @@ -0,0 +1,17 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT license. See License.txt in the project root for license information. + +using System.Collections.Immutable; +using Microsoft.CodeAnalysis.Razor.Logging; + +namespace Microsoft.CodeAnalysis.Remote.Razor.Logging; + +internal sealed class EmptyLoggerFactory : AbstractLoggerFactory +{ + public static ILoggerFactory Instance { get; } = new EmptyLoggerFactory(); + + private EmptyLoggerFactory() + : base(ImmutableArray.Empty) + { + } +} diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Logging/RemoteLoggerFactory.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Logging/RemoteLoggerFactory.cs index 9fc5e90a687..0cfd19b184b 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Logging/RemoteLoggerFactory.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Logging/RemoteLoggerFactory.cs @@ -1,9 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT license. See License.txt in the project root for license information. -using System; using System.Composition; -using Microsoft.AspNetCore.Razor; using Microsoft.CodeAnalysis.Razor.Logging; namespace Microsoft.CodeAnalysis.Remote.Razor.Logging; @@ -13,32 +11,28 @@ namespace Microsoft.CodeAnalysis.Remote.Razor.Logging; [Export(typeof(RemoteLoggerFactory))] internal sealed class RemoteLoggerFactory : ILoggerFactory { - private ILoggerFactory? _targetLoggerFactory; - - private ILoggerFactory TargetLoggerFactory => _targetLoggerFactory.AssumeNotNull(); + private ILoggerFactory _targetLoggerFactory = EmptyLoggerFactory.Instance; internal void SetTargetLoggerFactory(ILoggerFactory loggerFactory) { - if (_targetLoggerFactory is not null) + // We only set the target logger factory if the current factory is empty. + if (_targetLoggerFactory is EmptyLoggerFactory) { - throw new InvalidOperationException($"{nameof(_targetLoggerFactory)} is already set."); + _targetLoggerFactory = loggerFactory; } - - _targetLoggerFactory = loggerFactory; } public void AddLoggerProvider(ILoggerProvider provider) { - TargetLoggerFactory.AddLoggerProvider(provider); + _targetLoggerFactory.AddLoggerProvider(provider); } public ILogger GetOrCreateLogger(string categoryName) { - return TargetLoggerFactory.GetOrCreateLogger(categoryName); + return _targetLoggerFactory.GetOrCreateLogger(categoryName); } public void Dispose() { - // Don't dispose the inner ILoggerFactory because we don't own it. } } diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Logging/SimpleLoggerFactory.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Logging/SimpleLoggerFactory.cs deleted file mode 100644 index 469c1a7991f..00000000000 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Logging/SimpleLoggerFactory.cs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the MIT license. See License.txt in the project root for license information. - -using System.Collections.Immutable; -using System.Diagnostics; -using Microsoft.CodeAnalysis.Razor.Logging; - -namespace Microsoft.CodeAnalysis.Remote.Razor.Logging; - -internal sealed class SimpleLoggerFactory : AbstractLoggerFactory -{ - public static ILoggerFactory Empty { get; } = new SimpleLoggerFactory([]); - - private SimpleLoggerFactory(ImmutableArray loggerProviders) - : base(loggerProviders) - { - } - - public static ILoggerFactory CreateWithTraceSource(TraceSource traceSource) - => new SimpleLoggerFactory([new TraceSourceLoggerProvider(traceSource)]); -} diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Logging/TraceSourceLoggerProvider.Logger.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Logging/TraceSourceLoggerFactory.Logger.cs similarity index 90% rename from src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Logging/TraceSourceLoggerProvider.Logger.cs rename to src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Logging/TraceSourceLoggerFactory.Logger.cs index f19b2ce78b4..e5147d70dd1 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Logging/TraceSourceLoggerProvider.Logger.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Logging/TraceSourceLoggerFactory.Logger.cs @@ -7,9 +7,9 @@ namespace Microsoft.CodeAnalysis.Remote.Razor.Logging; -internal partial class TraceSourceLoggerProvider +internal sealed partial class TraceSourceLoggerFactory { - private class Logger(TraceSource traceSource, string categoryName) : ILogger + private sealed class Logger(TraceSource traceSource, string categoryName) : ILogger { public bool IsEnabled(LogLevel logLevel) => true; diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Logging/TraceSourceLoggerFactory.LoggerProvider.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Logging/TraceSourceLoggerFactory.LoggerProvider.cs new file mode 100644 index 00000000000..0b237ef7f84 --- /dev/null +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Logging/TraceSourceLoggerFactory.LoggerProvider.cs @@ -0,0 +1,16 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT license. See License.txt in the project root for license information. + +using System.Diagnostics; +using Microsoft.CodeAnalysis.Razor.Logging; + +namespace Microsoft.CodeAnalysis.Remote.Razor.Logging; + +internal sealed partial class TraceSourceLoggerFactory +{ + private sealed class LoggerProvider(TraceSource traceSource) : ILoggerProvider + { + public ILogger CreateLogger(string categoryName) + => new Logger(traceSource, categoryName); + } +} diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Logging/TraceSourceLoggerProvider.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Logging/TraceSourceLoggerFactory.cs similarity index 57% rename from src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Logging/TraceSourceLoggerProvider.cs rename to src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Logging/TraceSourceLoggerFactory.cs index 222f79cde29..eafc2a46ca4 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Logging/TraceSourceLoggerProvider.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Logging/TraceSourceLoggerFactory.cs @@ -6,10 +6,7 @@ namespace Microsoft.CodeAnalysis.Remote.Razor.Logging; -internal partial class TraceSourceLoggerProvider(TraceSource traceSource) : ILoggerProvider +internal sealed partial class TraceSourceLoggerFactory(TraceSource traceSource) : AbstractLoggerFactory([new LoggerProvider(traceSource)]) { - public ILogger CreateLogger(string categoryName) - { - return new Logger(traceSource, categoryName); - } + public TraceSource TraceSource { get; } = traceSource; } diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorBrokeredServiceBase.FactoryBase`1.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorBrokeredServiceBase.FactoryBase`1.cs index 7373048b73b..c41d4f74f19 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorBrokeredServiceBase.FactoryBase`1.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorBrokeredServiceBase.FactoryBase`1.cs @@ -22,6 +22,8 @@ internal abstract partial class RazorBrokeredServiceBase internal abstract class FactoryBase : IServiceHubServiceFactory where TService : class { + protected abstract TService CreateService(in ServiceArgs args); + public async Task CreateAsync( Stream stream, IServiceProvider hostProvidedServices, @@ -33,16 +35,27 @@ public async Task CreateAsync( authorizationServiceClient?.Dispose(); var traceSource = (TraceSource?)hostProvidedServices.GetService(typeof(TraceSource)); + + // RazorBrokeredServiceData is a hook that can be provided for different host scenarios, such as testing. var brokeredServiceData = (RazorBrokeredServiceData?)hostProvidedServices.GetService(typeof(RazorBrokeredServiceData)); var exportProvider = brokeredServiceData?.ExportProvider ?? await RemoteMefComposition.GetExportProviderAsync().ConfigureAwait(false); + // There are three logging cases: + // + // 1. We've been provided an ILoggerFactory from the host. + // 2. We've been provided a TraceSource and create an ILoggerFactory for that. + // 3. We don't have anything and just use the empty ILoggerFactory. + var targetLoggerFactory = brokeredServiceData?.LoggerFactory ?? (traceSource is not null - ? SimpleLoggerFactory.CreateWithTraceSource(traceSource) - : SimpleLoggerFactory.Empty); + ? new TraceSourceLoggerFactory(traceSource) + : EmptyLoggerFactory.Instance); + // Update the MEF composition's ILoggerFactory the target ILoggerFactory. + // Note that this means that the first non-empty ILoggerFactory that we use + // will be used for MEF component logging for the lifetime of all services. var remoteLoggerFactory = exportProvider.GetExportedValue(); remoteLoggerFactory.SetTargetLoggerFactory(targetLoggerFactory); @@ -51,7 +64,7 @@ public async Task CreateAsync( var descriptor = RazorServices.Descriptors.GetDescriptorForServiceFactory(typeof(TService)); var serverConnection = descriptor.WithTraceSource(traceSource).ConstructRpcConnection(pipe); - var args = new ServiceArgs(serviceBroker, exportProvider, serverConnection, brokeredServiceData?.Interceptor); + var args = new ServiceArgs(serviceBroker, exportProvider, targetLoggerFactory, serverConnection, brokeredServiceData?.Interceptor); var service = CreateService(in args); @@ -60,7 +73,5 @@ public async Task CreateAsync( return service; } - - protected abstract TService CreateService(in ServiceArgs args); } } diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorBrokeredServiceBase.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorBrokeredServiceBase.cs index a44062833d7..0b5e529b5cd 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorBrokeredServiceBase.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorBrokeredServiceBase.cs @@ -25,8 +25,7 @@ protected RazorBrokeredServiceBase(in ServiceArgs args) _serverConnection = args.ServerConnection; _interceptor = args.Interceptor; - var loggerFactory = args.ExportProvider.GetExportedValue(); - Logger = loggerFactory.GetOrCreateLogger(GetType()); + Logger = args.ServiceLoggerFactory.GetOrCreateLogger(GetType()); } protected ValueTask RunServiceAsync(Func implementation, CancellationToken cancellationToken) diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/ServiceArgs.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/ServiceArgs.cs index d177444e658..aac4bb9aa91 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/ServiceArgs.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/ServiceArgs.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT license. See License.txt in the project root for license information. +using Microsoft.CodeAnalysis.Razor.Logging; using Microsoft.ServiceHub.Framework; using Microsoft.VisualStudio.Composition; @@ -9,5 +10,6 @@ namespace Microsoft.CodeAnalysis.Remote.Razor; internal readonly record struct ServiceArgs( IServiceBroker ServiceBroker, ExportProvider ExportProvider, + ILoggerFactory ServiceLoggerFactory, ServiceRpcDescriptor.RpcConnection? ServerConnection = null, IRazorBrokeredServiceInterceptor? Interceptor = null); diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/TestServiceBroker.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/TestServiceBroker.cs index c543f7d32a3..fd5925588eb 100644 --- a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/TestServiceBroker.cs +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/TestServiceBroker.cs @@ -17,7 +17,7 @@ internal sealed class TestServiceBroker : IServiceBroker, IRazorBrokeredServiceI { private Solution? _solution; - public event EventHandler? AvailabilityChanged; + public event EventHandler? AvailabilityChanged { add { } remove { } } public void UpdateSolution(Solution solution) { From 9e96c3bf2f2510fe678928a2e2d5860e44a8b64a Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Mon, 15 Jul 2024 15:27:31 -0700 Subject: [PATCH 091/176] Remove unused variable --- .../Cohost/TestRemoteServiceInvoker.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/TestRemoteServiceInvoker.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/TestRemoteServiceInvoker.cs index 4ef4a5f4e88..5e4c7f05b47 100644 --- a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/TestRemoteServiceInvoker.cs +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/TestRemoteServiceInvoker.cs @@ -10,7 +10,6 @@ using Microsoft.CodeAnalysis.ExternalAccess.Razor; using Microsoft.CodeAnalysis.Razor.Logging; using Microsoft.CodeAnalysis.Razor.Remote; -using Microsoft.CodeAnalysis.Remote.Razor; using Microsoft.VisualStudio.Composition; using Microsoft.VisualStudio.Threading; @@ -36,7 +35,6 @@ private async Task GetOrCreateServiceAsync() { if (!_services.TryGetValue(typeof(TService), out var service)) { - var args = new ServiceArgs(_serviceBroker, exportProvider); service = await BrokeredServiceFactory.CreateServiceAsync(_serviceBroker, exportProvider, loggerFactory); _services.Add(typeof(TService), service); } From 5579bc04282e3124747ccdd46407f5618eeaf91e Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Mon, 15 Jul 2024 15:40:03 -0700 Subject: [PATCH 092/176] Change WrappedComparer and WrappedComparison to 'Reversed*' --- .../ImmutableArrayExtensions.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/ImmutableArrayExtensions.cs b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/ImmutableArrayExtensions.cs index c6c618123e2..e0d7478cca7 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/ImmutableArrayExtensions.cs +++ b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/ImmutableArrayExtensions.cs @@ -468,23 +468,23 @@ private abstract class DescendingComparer : IComparer { private static IComparer? s_default; - public static IComparer Default => s_default ??= new WrappedComparer(Comparer.Default); + public static IComparer Default => s_default ??= new ReversedComparer(Comparer.Default); public static IComparer Create(IComparer comparer) - => new WrappedComparer(comparer); + => new ReversedComparer(comparer); public static IComparer Create(Comparison comparison) - => new WrappedComparison(comparison); + => new ReversedComparison(comparison); public abstract int Compare(T? x, T? y); - private sealed class WrappedComparer(IComparer comparer) : DescendingComparer + private sealed class ReversedComparer(IComparer comparer) : DescendingComparer { public override int Compare(T? x, T? y) => comparer.Compare(y!, x!); } - private sealed class WrappedComparison(Comparison comparison) : DescendingComparer + private sealed class ReversedComparison(Comparison comparison) : DescendingComparer { public override int Compare(T? x, T? y) => comparison(y!, x!); From 28fbb5952da325326b102c09611c1a497cf4a497 Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Mon, 15 Jul 2024 15:54:03 -0700 Subject: [PATCH 093/176] Add GetPooledArraySpan(...) extension method This change adds a new `GetPooledArraySpan(...)` extension method that returns a pooled array as a `Span` with the expected length. This can help avoid bugs that can occur if a pooled array's `Length` is accidental used. --- .../Utilities/FilePathNormalizer.cs | 39 +++++++++---------- .../BufferExtensions.cs | 7 ++++ .../PooledObjects/PooledArray`1.cs | 4 ++ 3 files changed, 30 insertions(+), 20 deletions(-) diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Utilities/FilePathNormalizer.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Utilities/FilePathNormalizer.cs index 54bd1ac5c91..c9b2a9c2a15 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Utilities/FilePathNormalizer.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Utilities/FilePathNormalizer.cs @@ -28,16 +28,15 @@ public static string NormalizeDirectory(string? directoryFilePath) // Ensure that the array is at least 1 character larger, so that we can add // a trailing space after normalization if necessary. var arrayLength = directoryFilePathSpan.Length + 1; - using var _ = ArrayPool.Shared.GetPooledArray(arrayLength, out var array); - var arraySpan = array.AsSpan(0, arrayLength); - var (start, length) = NormalizeCore(directoryFilePathSpan, arraySpan); - ReadOnlySpan normalizedSpan = arraySpan.Slice(start, length); + using var _ = ArrayPool.Shared.GetPooledArraySpan(arrayLength, out var destination); + var (start, length) = NormalizeCore(directoryFilePathSpan, destination); + ReadOnlySpan normalizedSpan = destination.Slice(start, length); // Add a trailing slash if the normalized span doesn't end in one. if (normalizedSpan is not [.., '/']) { - arraySpan[start + length] = '/'; - normalizedSpan = arraySpan.Slice(start, length + 1); + destination[start + length] = '/'; + normalizedSpan = destination.Slice(start, length + 1); } if (directoryFilePathSpan.Equals(normalizedSpan, StringComparison.Ordinal)) @@ -58,8 +57,8 @@ public static string Normalize(string? filePath) var filePathSpan = filePath.AsSpan(); // Rent a buffer for Normalize to write to. - using var _ = ArrayPool.Shared.GetPooledArray(filePathSpan.Length, out var array); - var normalizedSpan = NormalizeCoreAndGetSpan(filePathSpan, array); + using var _ = ArrayPool.Shared.GetPooledArraySpan(filePathSpan.Length, out var destination); + var normalizedSpan = NormalizeCoreAndGetSpan(filePathSpan, destination); // If we didn't change anything, just return the original string. if (filePathSpan.Equals(normalizedSpan, StringComparison.Ordinal)) @@ -83,8 +82,8 @@ public static string GetNormalizedDirectoryName(string? filePath) var filePathSpan = filePath.AsSpan(); - using var _1 = ArrayPool.Shared.GetPooledArray(filePathSpan.Length, out var array); - var directoryNameSpan = NormalizeDirectoryNameCore(filePathSpan, array); + using var _1 = ArrayPool.Shared.GetPooledArraySpan(filePathSpan.Length, out var destination); + var directoryNameSpan = NormalizeDirectoryNameCore(filePathSpan, destination); if (filePathSpan.Equals(directoryNameSpan, StringComparison.Ordinal)) { @@ -108,11 +107,11 @@ public static bool AreDirectoryPathsEquivalent(string? filePath1, string? filePa return false; } - using var _1 = ArrayPool.Shared.GetPooledArray(filePathSpan1.Length, out var array1); - var normalizedSpan1 = NormalizeDirectoryNameCore(filePathSpan1, array1); + using var _1 = ArrayPool.Shared.GetPooledArraySpan(filePathSpan1.Length, out var destination1); + var normalizedSpan1 = NormalizeDirectoryNameCore(filePathSpan1, destination1); - using var _2 = ArrayPool.Shared.GetPooledArray(filePathSpan2.Length, out var array2); - var normalizedSpan2 = NormalizeDirectoryNameCore(filePathSpan2, array2); + using var _2 = ArrayPool.Shared.GetPooledArraySpan(filePathSpan2.Length, out var destination2); + var normalizedSpan2 = NormalizeDirectoryNameCore(filePathSpan2, destination2); return normalizedSpan1.Equals(normalizedSpan2, FilePathComparison.Instance); } @@ -131,11 +130,11 @@ public static bool AreFilePathsEquivalent(string? filePath1, string? filePath2) return false; } - using var _1 = ArrayPool.Shared.GetPooledArray(filePathSpan1.Length, out var array1); - var normalizedSpan1 = NormalizeCoreAndGetSpan(filePathSpan1, array1); + using var _1 = ArrayPool.Shared.GetPooledArraySpan(filePathSpan1.Length, out var destination1); + var normalizedSpan1 = NormalizeCoreAndGetSpan(filePathSpan1, destination1); - using var _2 = ArrayPool.Shared.GetPooledArray(filePathSpan2.Length, out var array2); - var normalizedSpan2 = NormalizeCoreAndGetSpan(filePathSpan2, array2); + using var _2 = ArrayPool.Shared.GetPooledArraySpan(filePathSpan2.Length, out var destination2); + var normalizedSpan2 = NormalizeCoreAndGetSpan(filePathSpan2, destination2); return normalizedSpan1.Equals(normalizedSpan2, FilePathComparison.Instance); } @@ -149,8 +148,8 @@ public static int GetHashCode(string filePath) var filePathSpan = filePath.AsSpanOrDefault(); - using var _ = ArrayPool.Shared.GetPooledArray(filePathSpan.Length, out var array1); - var normalizedSpan = NormalizeCoreAndGetSpan(filePathSpan, array1); + using var _ = ArrayPool.Shared.GetPooledArraySpan(filePathSpan.Length, out var destination); + var normalizedSpan = NormalizeCoreAndGetSpan(filePathSpan, destination); var hashCombiner = HashCodeCombiner.Start(); diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/BufferExtensions.cs b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/BufferExtensions.cs index ea4e7823eff..8786c059ea4 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/BufferExtensions.cs +++ b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/BufferExtensions.cs @@ -13,4 +13,11 @@ public static PooledArray GetPooledArray(this ArrayPool pool, int minim array = result.Array; return result; } + + public static PooledArray GetPooledArraySpan(this ArrayPool pool, int minimumLength, out Span span) + { + var result = new PooledArray(pool, minimumLength); + span = result.Span; + return result; + } } diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/PooledObjects/PooledArray`1.cs b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/PooledObjects/PooledArray`1.cs index 6bd248baffc..0d78e9183e5 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/PooledObjects/PooledArray`1.cs +++ b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/PooledObjects/PooledArray`1.cs @@ -9,6 +9,7 @@ namespace Microsoft.AspNetCore.Razor.PooledObjects; internal struct PooledArray : IDisposable { private readonly ArrayPool _pool; + private readonly int _minimumLength; private T[]? _array; // Because of how this API is intended to be used, we don't want the consumption code to have @@ -16,10 +17,13 @@ internal struct PooledArray : IDisposable // non-null until this is disposed. public readonly T[] Array => _array!; + public readonly Span Span => _array!.AsSpan(0, _minimumLength); + public PooledArray(ArrayPool pool, int minimumLength) : this() { _pool = pool; + _minimumLength = minimumLength; _array = pool.Rent(minimumLength); } From a42dea49e1bffa3df2f89fb85a5a1bb095ec0d10 Mon Sep 17 00:00:00 2001 From: Andrew Hall Date: Mon, 15 Jul 2024 18:11:21 -0700 Subject: [PATCH 094/176] Fix project info reading (#10623) When reading RazorProjectInfo from a stream the array being used was a pooled array. The code was not correctly trimming that array for the deserializer which meant that unknown bytes were being attempted to be read and were likely wrong. This fixes the code to make sure and trim before deserializing and adds tests. Fixes AB#2137098 --- .../RazorWorkspaceListenerBase.cs | 1 + .../Utilities/StreamExtensions.cs | 37 +++++- .../StreamExtensionTests.cs | 122 ++++++++++++++++++ 3 files changed, 153 insertions(+), 7 deletions(-) create mode 100644 src/Razor/test/Microsoft.AspNetCore.Razor.ProjectEngineHost.Test/StreamExtensionTests.cs diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.ExternalAccess.RoslynWorkspace/RazorWorkspaceListenerBase.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.ExternalAccess.RoslynWorkspace/RazorWorkspaceListenerBase.cs index 1f13f2d9f42..7ab3ecf2a4b 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.ExternalAccess.RoslynWorkspace/RazorWorkspaceListenerBase.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.ExternalAccess.RoslynWorkspace/RazorWorkspaceListenerBase.cs @@ -286,6 +286,7 @@ private static async Task ReportUpdateProjectAsync(Stream stream, Project projec return; } + stream.WriteProjectInfoAction(ProjectInfoAction.Update); await stream.WriteProjectInfoAsync(projectInfo, cancellationToken).ConfigureAwait(false); } diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Utilities/StreamExtensions.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Utilities/StreamExtensions.cs index ff5483df79f..c792e4a25b8 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Utilities/StreamExtensions.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Utilities/StreamExtensions.cs @@ -56,7 +56,8 @@ public static async Task ReadStringAsync(this Stream stream, Encoding? e var length = ReadSize(stream); using var _ = ArrayPool.Shared.GetPooledArray(length, out var encodedBytes); - await stream.ReadAsync(encodedBytes, 0, length, cancellationToken).ConfigureAwait(false); + + await ReadExactlyAsync(stream, encodedBytes, length, cancellationToken).ConfigureAwait(false); return encoding.GetString(encodedBytes, 0, length); } @@ -94,8 +95,6 @@ public static Task ReadProjectInfoRemovalAsync(this Stream stream, Cance public static async Task WriteProjectInfoAsync(this Stream stream, RazorProjectInfo projectInfo, CancellationToken cancellationToken) { - WriteProjectInfoAction(stream, ProjectInfoAction.Update); - var bytes = projectInfo.Serialize(); WriteSize(stream, bytes.Length); await stream.WriteAsync(bytes, 0, bytes.Length, cancellationToken).ConfigureAwait(false); @@ -106,11 +105,15 @@ public static async Task WriteProjectInfoAsync(this Stream stream, RazorProjectI var sizeToRead = ReadSize(stream); using var _ = ArrayPool.Shared.GetPooledArray(sizeToRead, out var projectInfoBytes); - await stream.ReadAsync(projectInfoBytes, 0, projectInfoBytes.Length, cancellationToken).ConfigureAwait(false); - return RazorProjectInfo.DeserializeFrom(projectInfoBytes.AsMemory()); + await ReadExactlyAsync(stream, projectInfoBytes, sizeToRead, cancellationToken).ConfigureAwait(false); + + // The array may be larger than the bytes read so make sure to trim accordingly. + var projectInfoMemory = projectInfoBytes.AsMemory(0, sizeToRead); + + return RazorProjectInfo.DeserializeFrom(projectInfoMemory); } - private static void WriteSize(Stream stream, int length) + public static void WriteSize(this Stream stream, int length) { #if NET Span sizeBytes = stackalloc byte[4]; @@ -125,7 +128,7 @@ private static void WriteSize(Stream stream, int length) } - private unsafe static int ReadSize(Stream stream) + public unsafe static int ReadSize(this Stream stream) { #if NET Span bytes = stackalloc byte[4]; @@ -137,4 +140,24 @@ private unsafe static int ReadSize(Stream stream) return BitConverter.ToInt32(bytes, 0); #endif } + +#if NET + private static ValueTask ReadExactlyAsync(Stream stream, byte[] buffer, int length, CancellationToken cancellationToken) + => stream.ReadExactlyAsync(buffer, 0, length, cancellationToken); +#else + private static async ValueTask ReadExactlyAsync(Stream stream, byte[] buffer, int length, CancellationToken cancellationToken) + { + var bytesRead = 0; + while (bytesRead < length) + { + var read = await stream.ReadAsync(buffer, bytesRead, length - bytesRead, cancellationToken); + if (read == 0) + { + throw new EndOfStreamException(); + } + + bytesRead += read; + } + } +#endif } diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.ProjectEngineHost.Test/StreamExtensionTests.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.ProjectEngineHost.Test/StreamExtensionTests.cs new file mode 100644 index 00000000000..c0f0d50f200 --- /dev/null +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.ProjectEngineHost.Test/StreamExtensionTests.cs @@ -0,0 +1,122 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT license. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Razor.Language; +using Microsoft.AspNetCore.Razor.ProjectSystem; +using Microsoft.AspNetCore.Razor.Serialization; +using Microsoft.AspNetCore.Razor.Utilities; +using Microsoft.CodeAnalysis; +using Xunit; + +namespace Microsoft.AspNetCore.Razor.ProjectEngineHost.Test; + +public class StreamExtensionTests +{ + [Theory] + [InlineData(0)] + [InlineData(int.MaxValue)] + [InlineData(int.MinValue)] + [InlineData(-500)] + [InlineData(500)] + public void SizeFunctions(int size) + { + using var stream = new MemoryStream(); + + stream.WriteSize(size); + stream.Position = 0; + + Assert.Equal(size, stream.ReadSize()); + } + + public static TheoryData StringFunctionData = new TheoryData + { + { "", null }, + { "hello", null }, + { "", Encoding.UTF8 }, + { "hello", Encoding.UTF8 }, + { "", Encoding.ASCII }, + { "hello", Encoding.ASCII }, + { "", Encoding.UTF32 }, + { "hello", Encoding.UTF32 }, + { "", Encoding.Unicode }, + { "hello", Encoding.Unicode }, + { "", Encoding.BigEndianUnicode }, + { "hello", Encoding.BigEndianUnicode }, + }; + + [Theory] + [MemberData(nameof(StringFunctionData))] + public async Task StringFunctions(string expected, Encoding? encoding) + { + using var stream = new MemoryStream(); + + await stream.WriteStringAsync(expected, encoding, default); + stream.Position = 0; + + var actual = await stream.ReadStringAsync(encoding, default); + Assert.Equal(expected, actual); + } + + [Fact] + public async Task SerializeProjectInfo() + { + using var stream = new MemoryStream(); + + var configuration = new RazorConfiguration( + RazorLanguageVersion.Latest, + "TestConfiguration", + ImmutableArray.Empty); + + var tagHelper = TagHelperDescriptorBuilder.Create("TypeName", "AssemblyName") + .TagMatchingRuleDescriptor(rule => rule.RequireTagName("tag-name")) + .Build(); + + var projectWorkspaceState = ProjectWorkspaceState.Create([tagHelper], CodeAnalysis.CSharp.LanguageVersion.Latest); + + var projectInfo = new RazorProjectInfo( + new ProjectKey("TestProject"), + @"C:\test\test.csproj", + configuration, + "TestNamespace", + "Test", + projectWorkspaceState, + [new DocumentSnapshotHandle(@"C:\test\document.razor", @"document.razor", FileKinds.Component)]); + + var bytesToSerialize = projectInfo.Serialize(); + + await stream.WriteProjectInfoAsync(projectInfo, default); + + // WriteProjectInfoAsync prepends the size before writing which is 4 bytes long + Assert.Equal(bytesToSerialize.Length + 4, stream.Position); + + var streamContents = stream.ToArray(); + var expectedSize = BitConverter.GetBytes(bytesToSerialize.Length); + Assert.Equal(expectedSize, streamContents.Take(4).ToArray()); + + Assert.Equal(bytesToSerialize, streamContents.Skip(4).ToArray()); + + stream.Position = 0; + var deserialized = await stream.ReadProjectInfoAsync(default); + + Assert.Equal(projectInfo, deserialized); + } + + [Theory] + [CombinatorialData] + internal void ProjectInfoActionFunctions(ProjectInfoAction infoAction) + { + using var stream = new MemoryStream(); + stream.WriteProjectInfoAction(infoAction); + + stream.Position = 0; + Assert.Equal(infoAction, stream.ReadProjectInfoAction()); + } +} From 401f4f3a4b4a73e2097ef4ce578259aa3c7caa0d Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Mon, 15 Jul 2024 18:18:59 -0700 Subject: [PATCH 095/176] Fix issue with cancelling AsyncBatchingWorkQueue This was simply a mistake on my part. We should not assume that code is unreachable when it is reached because an OperationCanceledException is caught. --- .../Utilities/AsyncBatchingWorkQueue`2.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Utilities/AsyncBatchingWorkQueue`2.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Utilities/AsyncBatchingWorkQueue`2.cs index 2565ce36abc..23fb11979b7 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Utilities/AsyncBatchingWorkQueue`2.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Utilities/AsyncBatchingWorkQueue`2.cs @@ -271,9 +271,8 @@ void AddItemsToBatch(IEnumerable items) catch (OperationCanceledException) { // Silently continue to allow the next batch to be processed. + return default; } - - return Assumed.Unreachable(); } private (ImmutableArray items, CancellationToken batchCancellationToken) GetNextBatchAndResetQueue() From d5a6775d1a6d1c855c187e420f66480bd30bfee2 Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Mon, 15 Jul 2024 18:35:43 -0700 Subject: [PATCH 096/176] Don't force RazorActivityLog onto main thread IVsActivityLog is thread-safe so there's no need to switch to the main thread before using it. --- .../Logging/RazorActivityLog.cs | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/Logging/RazorActivityLog.cs b/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/Logging/RazorActivityLog.cs index a8870a02be1..4352aee3180 100644 --- a/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/Logging/RazorActivityLog.cs +++ b/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/Logging/RazorActivityLog.cs @@ -20,19 +20,15 @@ internal sealed class RazorActivityLog : IDisposable private enum EntryType { Error, Warning, Info } private readonly IAsyncServiceProvider _serviceProvider; - private readonly JoinableTaskFactory _jtf; private readonly CancellationTokenSource _disposeTokenSource; private readonly AsyncBatchingWorkQueue<(EntryType, string)> _loggingQueue; private IVsActivityLog? _vsActivityLog; [ImportingConstructor] - public RazorActivityLog( - [Import(typeof(SAsyncServiceProvider))] IAsyncServiceProvider serviceProvider, - JoinableTaskContext joinableTaskContext) + public RazorActivityLog([Import(typeof(SAsyncServiceProvider))] IAsyncServiceProvider serviceProvider) { _serviceProvider = serviceProvider; - _jtf = joinableTaskContext.Factory; _disposeTokenSource = new(); _loggingQueue = new AsyncBatchingWorkQueue<(EntryType, string)>(TimeSpan.Zero, ProcessBatchAsync, _disposeTokenSource.Token); @@ -51,9 +47,7 @@ public void Dispose() private async ValueTask ProcessBatchAsync(ImmutableArray<(EntryType, string)> items, CancellationToken token) { - await _jtf.SwitchToMainThreadAsync(token); - - _vsActivityLog ??= await _serviceProvider.GetServiceAsync(); + _vsActivityLog ??= await _serviceProvider.GetServiceAsync(token).ConfigureAwait(false); foreach (var (entryType, message) in items) { From 7e7c211f4acd3037ca6e608c8d052af1871189ed Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Mon, 15 Jul 2024 18:36:27 -0700 Subject: [PATCH 097/176] Check CancellationToken in RazorActivityLog when processing batch --- .../Logging/RazorActivityLog.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/Logging/RazorActivityLog.cs b/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/Logging/RazorActivityLog.cs index 4352aee3180..1521bdca194 100644 --- a/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/Logging/RazorActivityLog.cs +++ b/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/Logging/RazorActivityLog.cs @@ -47,10 +47,20 @@ public void Dispose() private async ValueTask ProcessBatchAsync(ImmutableArray<(EntryType, string)> items, CancellationToken token) { + if (token.IsCancellationRequested) + { + return; + } + _vsActivityLog ??= await _serviceProvider.GetServiceAsync(token).ConfigureAwait(false); foreach (var (entryType, message) in items) { + if (token.IsCancellationRequested) + { + return; + } + var vsEntryType = entryType switch { EntryType.Error => __ACTIVITYLOG_ENTRYTYPE.ALE_ERROR, From d6b81be761aabf01c1238b01856ddc0f5bd31116 Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Mon, 15 Jul 2024 18:55:06 -0700 Subject: [PATCH 098/176] Add better mocking for IAsyncServiceProvider Importantly, this includes an implementation of `IAsyncServiceProvider3`, which allows Visual Studios's `IAsyncServiceProvider` extension methods to avoid calling into `ThreadHelper`. --- .../VisualStudio_NetFx/VsMocks.cs | 92 +++++++++++++++---- .../LspEditorFeatureDetectorTest.cs | 9 +- 2 files changed, 76 insertions(+), 25 deletions(-) diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/VisualStudio_NetFx/VsMocks.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/VisualStudio_NetFx/VsMocks.cs index 97c04473b3d..019d422632c 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/VisualStudio_NetFx/VsMocks.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/VisualStudio_NetFx/VsMocks.cs @@ -11,6 +11,7 @@ using Microsoft.VisualStudio.ComponentModelHost; using Microsoft.VisualStudio.Razor; using Microsoft.VisualStudio.Razor.LanguageClient; +using Microsoft.VisualStudio.Shell; using Microsoft.VisualStudio.Text; using Microsoft.VisualStudio.Utilities; using Moq; @@ -79,25 +80,6 @@ public static IServiceProvider CreateServiceProvider(Action CreateVsService(Mock serviceMock) - where TService : class - where TInterface : class - => CreateVsService(serviceMock.Object); - - public static IVsService CreateVsService(TInterface service) - where TService : class - where TInterface : class - { - var mock = new StrictMock>(); - - mock.Setup(x => x.GetValueAsync(It.IsAny())) - .ReturnsAsync(service); - mock.Setup(x => x.GetValueOrNullAsync(It.IsAny())) - .ReturnsAsync(service); - - return mock.Object; - } - public interface IServiceProviderBuilder { void AddService(T? serviceInstance) @@ -160,6 +142,59 @@ public void AddComponentModel(Action? configure = null) } } + public static IAsyncServiceProvider CreateAsyncServiceProvider(Action? configure = null) + { + var builder = new AsyncServiceProviderBuilder(); + configure?.Invoke(builder); + return builder.Mock.Object; + } + + public interface IAsyncServiceProviderBuilder + { + void AddService(TInterface service) + where TInterface : class; + void AddService(Func service) + where TInterface : class; + } + + private class AsyncServiceProviderBuilder : IAsyncServiceProviderBuilder + { + private readonly StrictMock _mock1; + private readonly Mock _mock2; + private readonly Mock _mock3; + + public StrictMock Mock => _mock1; + + public AsyncServiceProviderBuilder() + { + _mock1 = new(); + _mock2 = Mock.As(); + _mock3 = Mock.As(); + } + + public void AddService(TInterface service) + where TInterface : class + { + _mock1.Setup(x => x.GetServiceAsync(typeof(TService))) + .ReturnsAsync(service); + _mock2.Setup(x => x.GetServiceAsync(typeof(TService), /*swallowException*/ false)) + .ReturnsAsync(service); + _mock3.Setup(x => x.GetServiceAsync(/*throwOnFailure*/ true, It.IsAny())) + .ReturnsAsync(service); + } + + public void AddService(Func getServiceCallback) + where TInterface : class + { + _mock1.Setup(x => x.GetServiceAsync(typeof(TService))) + .ReturnsAsync(() => getServiceCallback()); + _mock2.Setup(x => x.GetServiceAsync(typeof(TService), /*swallowException*/ false)) + .ReturnsAsync(() => getServiceCallback()); + _mock3.Setup(x => x.GetServiceAsync(/*throwOnFailure*/ true, It.IsAny())) + .ReturnsAsync(() => getServiceCallback()); + } + } + public static IComponentModel CreateComponentModel(Action? configure = null) { var builder = new ComponentModelBuilder(); @@ -219,4 +254,23 @@ protected override IEnumerable GetExportsCore(ImportDefinition definitio } } } + + public static IVsService CreateVsService(Mock serviceMock) + where TService : class + where TInterface : class + => CreateVsService(serviceMock.Object); + + public static IVsService CreateVsService(TInterface service) + where TService : class + where TInterface : class + { + var mock = new StrictMock>(); + + mock.Setup(x => x.GetValueAsync(It.IsAny())) + .ReturnsAsync(service); + mock.Setup(x => x.GetValueOrNullAsync(It.IsAny())) + .ReturnsAsync(service); + + return mock.Object; + } } diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/LspEditorFeatureDetectorTest.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/LspEditorFeatureDetectorTest.cs index 1764382cc23..d666b5651e3 100644 --- a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/LspEditorFeatureDetectorTest.cs +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/LspEditorFeatureDetectorTest.cs @@ -8,7 +8,6 @@ using Microsoft.Internal.VisualStudio.Shell.Interop; using Microsoft.VisualStudio.Razor.Logging; using Microsoft.VisualStudio.Settings; -using Microsoft.VisualStudio.Shell; using Microsoft.VisualStudio.Shell.Interop; using Moq; using Xunit; @@ -221,12 +220,10 @@ private RazorActivityLog CreateRazorActivityLog() }) .Returns(VSConstants.S_OK); - var serviceProviderMock = new StrictMock(); - serviceProviderMock - .Setup(x => x.GetServiceAsync(typeof(SVsActivityLog))) - .ReturnsAsync(vsActivityLogMock.Object); + var serviceProvider = VsMocks.CreateAsyncServiceProvider(b => + b.AddService(vsActivityLogMock.Object)); - var activityLog = new RazorActivityLog(serviceProviderMock.Object, JoinableTaskContext); + var activityLog = new RazorActivityLog(serviceProvider); AddDisposable(activityLog); From cbe071b93b0646ff9b074d18f0da55d384a1fa71 Mon Sep 17 00:00:00 2001 From: David Wengier Date: Tue, 16 Jul 2024 11:59:04 +1000 Subject: [PATCH 099/176] Remvoe statics from intiailization services --- .../RemoteClientInitializationService.cs | 11 +++++++--- ...emoteClientInitializationServiceFactory.cs | 5 ++++- .../RemoteLanguageServerFeatureOptions.cs | 16 +++++++-------- .../RemoteSemanticTokensLegendService.cs | 20 ++++++++++--------- .../CohostSemanticTokensRangeEndpointTest.cs | 3 ++- .../Cohost/CohostTestBase.cs | 14 ++++++++++--- 6 files changed, 44 insertions(+), 25 deletions(-) diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Initialization/RemoteClientInitializationService.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Initialization/RemoteClientInitializationService.cs index d5d316c971e..464d33a2fd7 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Initialization/RemoteClientInitializationService.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Initialization/RemoteClientInitializationService.cs @@ -9,13 +9,18 @@ namespace Microsoft.CodeAnalysis.Remote.Razor; internal sealed class RemoteClientInitializationService( - IRazorServiceBroker serviceBroker) + IRazorServiceBroker serviceBroker, + RemoteLanguageServerFeatureOptions remoteLanguageServerFeatureOptions, + RemoteSemanticTokensLegendService remoteSemanticTokensLegendService) : RazorServiceBase(serviceBroker), IRemoteClientInitializationService { + private readonly RemoteLanguageServerFeatureOptions _remoteLanguageServerFeatureOptions = remoteLanguageServerFeatureOptions; + private readonly RemoteSemanticTokensLegendService _remoteSemanticTokensLegendService = remoteSemanticTokensLegendService; + public ValueTask InitializeAsync(RemoteClientInitializationOptions options, CancellationToken cancellationToken) => RunServiceAsync(ct => { - RemoteLanguageServerFeatureOptions.SetOptions(options); + _remoteLanguageServerFeatureOptions.SetOptions(options); return default; }, cancellationToken); @@ -23,7 +28,7 @@ public ValueTask InitializeAsync(RemoteClientInitializationOptions options, Canc public ValueTask InitializeLSPAsync(RemoteClientLSPInitializationOptions options, CancellationToken cancellationToken) => RunServiceAsync(ct => { - RemoteSemanticTokensLegendService.SetLegend(options.TokenTypes, options.TokenModifiers); + _remoteSemanticTokensLegendService.SetLegend(options.TokenTypes, options.TokenModifiers); return default; }, cancellationToken); diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Initialization/RemoteClientInitializationServiceFactory.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Initialization/RemoteClientInitializationServiceFactory.cs index c1cb47432a3..f8643fbdeab 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Initialization/RemoteClientInitializationServiceFactory.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Initialization/RemoteClientInitializationServiceFactory.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. See License.txt in the project root for license information. using Microsoft.CodeAnalysis.Razor.Remote; +using Microsoft.CodeAnalysis.Remote.Razor.SemanticTokens; using Microsoft.VisualStudio.Composition; namespace Microsoft.CodeAnalysis.Remote.Razor; @@ -16,6 +17,8 @@ public RemoteClientInitializationServiceFactory() protected override IRemoteClientInitializationService CreateService(IRazorServiceBroker serviceBroker, ExportProvider exportProvider) { - return new RemoteClientInitializationService(serviceBroker); + var languageServerFeatureOptions = exportProvider.GetExportedValue(); + var semanticTokensLegendService = exportProvider.GetExportedValue(); + return new RemoteClientInitializationService(serviceBroker, languageServerFeatureOptions, semanticTokensLegendService); } } diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Initialization/RemoteLanguageServerFeatureOptions.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Initialization/RemoteLanguageServerFeatureOptions.cs index 37286a8c168..45cdae212de 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Initialization/RemoteLanguageServerFeatureOptions.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Initialization/RemoteLanguageServerFeatureOptions.cs @@ -10,24 +10,24 @@ namespace Microsoft.CodeAnalysis.Remote.Razor; [Shared] [Export(typeof(LanguageServerFeatureOptions))] +[Export(typeof(RemoteLanguageServerFeatureOptions))] internal class RemoteLanguageServerFeatureOptions : LanguageServerFeatureOptions { - // It's okay to use default here because we expect the options to be set before the first real OOP call - private static RemoteClientInitializationOptions s_options = default; + private RemoteClientInitializationOptions _options = default; - public static void SetOptions(RemoteClientInitializationOptions options) => s_options = options; + public void SetOptions(RemoteClientInitializationOptions options) => _options = options; public override bool SupportsFileManipulation => throw new InvalidOperationException("This option has not been synced to OOP."); - public override string CSharpVirtualDocumentSuffix => s_options.CSharpVirtualDocumentSuffix; + public override string CSharpVirtualDocumentSuffix => _options.CSharpVirtualDocumentSuffix; - public override string HtmlVirtualDocumentSuffix => s_options.HtmlVirtualDocumentSuffix; + public override string HtmlVirtualDocumentSuffix => _options.HtmlVirtualDocumentSuffix; public override bool SingleServerSupport => throw new InvalidOperationException("This option has not been synced to OOP."); public override bool DelegateToCSharpOnDiagnosticPublish => throw new InvalidOperationException("This option has not been synced to OOP."); - public override bool UsePreciseSemanticTokenRanges => s_options.UsePreciseSemanticTokenRanges; + public override bool UsePreciseSemanticTokenRanges => _options.UsePreciseSemanticTokenRanges; public override bool ShowAllCSharpCodeActions => throw new InvalidOperationException("This option has not been synced to OOP."); @@ -35,9 +35,9 @@ internal class RemoteLanguageServerFeatureOptions : LanguageServerFeatureOptions public override bool ReturnCodeActionAndRenamePathsWithPrefixedSlash => throw new InvalidOperationException("This option has not been synced to OOP."); - public override bool IncludeProjectKeyInGeneratedFilePath => s_options.IncludeProjectKeyInGeneratedFilePath; + public override bool IncludeProjectKeyInGeneratedFilePath => _options.IncludeProjectKeyInGeneratedFilePath; - public override bool UseRazorCohostServer => s_options.UseRazorCohostServer; + public override bool UseRazorCohostServer => _options.UseRazorCohostServer; public override bool DisableRazorLanguageServer => throw new InvalidOperationException("This option has not been synced to OOP."); diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/SemanticTokens/RemoteSemanticTokensLegendService.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/SemanticTokens/RemoteSemanticTokensLegendService.cs index f5175d0ad08..d5c3b6d2f54 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/SemanticTokens/RemoteSemanticTokensLegendService.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/SemanticTokens/RemoteSemanticTokensLegendService.cs @@ -6,22 +6,24 @@ namespace Microsoft.CodeAnalysis.Remote.Razor.SemanticTokens; -[Export(typeof(ISemanticTokensLegendService)), Shared] +[Shared] +[Export(typeof(ISemanticTokensLegendService))] +[Export(typeof(RemoteSemanticTokensLegendService))] internal sealed class RemoteSemanticTokensLegendService : ISemanticTokensLegendService { - private static SemanticTokenModifiers s_tokenModifiers = null!; - private static SemanticTokenTypes s_tokenTypes = null!; + private SemanticTokenModifiers _tokenModifiers = null!; + private SemanticTokenTypes _tokenTypes = null!; - public SemanticTokenModifiers TokenModifiers => s_tokenModifiers; + public SemanticTokenModifiers TokenModifiers => _tokenModifiers; - public SemanticTokenTypes TokenTypes => s_tokenTypes; + public SemanticTokenTypes TokenTypes => _tokenTypes; - public static void SetLegend(string[] tokenTypes, string[] tokenModifiers) + public void SetLegend(string[] tokenTypes, string[] tokenModifiers) { - if (s_tokenTypes is null) + if (_tokenTypes is null) { - s_tokenTypes = new SemanticTokenTypes(tokenTypes); - s_tokenModifiers = new SemanticTokenModifiers(tokenModifiers); + _tokenTypes = new SemanticTokenTypes(tokenTypes); + _tokenModifiers = new SemanticTokenModifiers(tokenModifiers); } } } diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostSemanticTokensRangeEndpointTest.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostSemanticTokensRangeEndpointTest.cs index 55f80474f43..1a5bcfa4cc6 100644 --- a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostSemanticTokensRangeEndpointTest.cs +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostSemanticTokensRangeEndpointTest.cs @@ -97,7 +97,8 @@ private async Task VerifySemanticTokensAsync(string input, bool colorBackground, var legend = TestRazorSemanticTokensLegendService.Instance; // We need to manually initialize the OOP service so we can get semantic token info later - RemoteSemanticTokensLegendService.SetLegend(legend.TokenTypes.All, legend.TokenModifiers.All); + var legendService = OOPExportProvider.GetExportedValue(); + legendService.SetLegend(legend.TokenTypes.All, legend.TokenModifiers.All); var clientSettingsManager = new ClientSettingsManager([], null, null); clientSettingsManager.Update(ClientAdvancedSettings.Default with { ColorBackground = colorBackground }); diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostTestBase.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostTestBase.cs index 614097f847e..505b3565b3d 100644 --- a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostTestBase.cs +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostTestBase.cs @@ -13,6 +13,7 @@ using Microsoft.CodeAnalysis.Razor.Remote; using Microsoft.CodeAnalysis.Remote.Razor; using Microsoft.CodeAnalysis.Text; +using Microsoft.VisualStudio.Composition; using Xunit.Abstractions; namespace Microsoft.VisualStudio.Razor.LanguageClient.Cohost; @@ -21,17 +22,24 @@ public abstract class CohostTestBase(ITestOutputHelper testOutputHelper) : Works { private const string CSharpVirtualDocumentSuffix = ".g.cs"; private IRemoteServiceProvider? _remoteServiceProvider; + private ExportProvider? _exportProvider; private protected IRemoteServiceProvider RemoteServiceProvider => _remoteServiceProvider.AssumeNotNull(); + /// + /// The export provider for Razor OOP services (not Roslyn) + /// + private protected ExportProvider OOPExportProvider => _exportProvider.AssumeNotNull(); + protected override async Task InitializeAsync() { await base.InitializeAsync(); - var exportProvider = AddDisposable(await RemoteMefComposition.CreateExportProviderAsync()); - _remoteServiceProvider = AddDisposable(new TestRemoteServiceProvider(exportProvider)); + _exportProvider = AddDisposable(await RemoteMefComposition.CreateExportProviderAsync()); + _remoteServiceProvider = AddDisposable(new TestRemoteServiceProvider(_exportProvider)); - RemoteLanguageServerFeatureOptions.SetOptions(new() + var featureOptions = OOPExportProvider.GetExportedValue(); + featureOptions.SetOptions(new() { CSharpVirtualDocumentSuffix = CSharpVirtualDocumentSuffix, HtmlVirtualDocumentSuffix = ".g.html", From 734c8a5821a379c1f1da4dd69f774e279e7a2573 Mon Sep 17 00:00:00 2001 From: David Wengier Date: Tue, 16 Jul 2024 12:03:38 +1000 Subject: [PATCH 100/176] Test precise semantic tokens too --- .../CohostSemanticTokensRangeEndpointTest.cs | 14 +++++++++----- .../Cohost/CohostTestBase.cs | 7 +++++-- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostSemanticTokensRangeEndpointTest.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostSemanticTokensRangeEndpointTest.cs index 1a5bcfa4cc6..02d79678d91 100644 --- a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostSemanticTokensRangeEndpointTest.cs +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostSemanticTokensRangeEndpointTest.cs @@ -10,6 +10,7 @@ using Microsoft.AspNetCore.Razor.Telemetry; using Microsoft.CodeAnalysis.Razor.Settings; using Microsoft.CodeAnalysis.Razor.Workspaces; +using Microsoft.CodeAnalysis.Remote.Razor; using Microsoft.CodeAnalysis.Remote.Razor.SemanticTokens; using Microsoft.CodeAnalysis.Text; using Microsoft.VisualStudio.Razor.Settings; @@ -24,7 +25,7 @@ public class CohostSemanticTokensRangeEndpointTest(ITestOutputHelper testOutputH { [Theory] [CombinatorialData] - public async Task Razor(bool colorBackground) + public async Task Razor(bool colorBackground, bool precise) { var input = """ @page "/" @@ -59,12 +60,12 @@ public void M() } """; - await VerifySemanticTokensAsync(input, colorBackground); + await VerifySemanticTokensAsync(input, colorBackground, precise); } [Theory] [CombinatorialData] - public async Task Legacy(bool colorBackground) + public async Task Legacy(bool colorBackground, bool precise) { var input = """ @page "/" @@ -86,10 +87,10 @@ @section MySection { } """; - await VerifySemanticTokensAsync(input, colorBackground, fileKind: FileKinds.Legacy); + await VerifySemanticTokensAsync(input, colorBackground, precise, fileKind: FileKinds.Legacy); } - private async Task VerifySemanticTokensAsync(string input, bool colorBackground, string? fileKind = null, [CallerMemberName] string? testName = null) + private async Task VerifySemanticTokensAsync(string input, bool colorBackground, bool precise, string? fileKind = null, [CallerMemberName] string? testName = null) { var document = CreateProjectAndRazorDocument(input, fileKind); var sourceText = await document.GetTextAsync(DisposalToken); @@ -100,6 +101,9 @@ private async Task VerifySemanticTokensAsync(string input, bool colorBackground, var legendService = OOPExportProvider.GetExportedValue(); legendService.SetLegend(legend.TokenTypes.All, legend.TokenModifiers.All); + var featureOptions = OOPExportProvider.GetExportedValue(); + featureOptions.SetOptions(_clientInitializationOptions with { UsePreciseSemanticTokenRanges = precise }); + var clientSettingsManager = new ClientSettingsManager([], null, null); clientSettingsManager.Update(ClientAdvancedSettings.Default with { ColorBackground = colorBackground }); diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostTestBase.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostTestBase.cs index 505b3565b3d..60dd89e4dc1 100644 --- a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostTestBase.cs +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostTestBase.cs @@ -23,6 +23,7 @@ public abstract class CohostTestBase(ITestOutputHelper testOutputHelper) : Works private const string CSharpVirtualDocumentSuffix = ".g.cs"; private IRemoteServiceProvider? _remoteServiceProvider; private ExportProvider? _exportProvider; + private protected RemoteClientInitializationOptions _clientInitializationOptions; private protected IRemoteServiceProvider RemoteServiceProvider => _remoteServiceProvider.AssumeNotNull(); @@ -39,14 +40,16 @@ protected override async Task InitializeAsync() _remoteServiceProvider = AddDisposable(new TestRemoteServiceProvider(_exportProvider)); var featureOptions = OOPExportProvider.GetExportedValue(); - featureOptions.SetOptions(new() + _clientInitializationOptions = new() { CSharpVirtualDocumentSuffix = CSharpVirtualDocumentSuffix, HtmlVirtualDocumentSuffix = ".g.html", IncludeProjectKeyInGeneratedFilePath = false, UsePreciseSemanticTokenRanges = false, UseRazorCohostServer = true - }); + }; + + featureOptions.SetOptions(_clientInitializationOptions); } protected TextDocument CreateProjectAndRazorDocument(string contents, string? fileKind = null) From 5288d76153bbf69275a52aed082c8b779cc44d6a Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Mon, 15 Jul 2024 19:31:54 -0700 Subject: [PATCH 101/176] Add XML doc comments --- .../BufferExtensions.cs | 12 ++++++++++++ .../PooledObjects/PooledArray`1.cs | 16 +++++++++++++--- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/BufferExtensions.cs b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/BufferExtensions.cs index 8786c059ea4..a897c734fec 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/BufferExtensions.cs +++ b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/BufferExtensions.cs @@ -7,6 +7,13 @@ namespace System.Buffers; internal static class BufferExtensions { + /// + /// Rents an array of the given minimum length from the specified . + /// + /// + /// The array is guaranteed to be at least in length. However, + /// it will likely be larger. + /// public static PooledArray GetPooledArray(this ArrayPool pool, int minimumLength, out T[] array) { var result = new PooledArray(pool, minimumLength); @@ -14,6 +21,11 @@ public static PooledArray GetPooledArray(this ArrayPool pool, int minim return result; } + /// + /// Rents an array of the given minimum length from the specified . + /// The rented array is provided as a representing a portion of the rented array + /// from its start to the minimum length. + /// public static PooledArray GetPooledArraySpan(this ArrayPool pool, int minimumLength, out Span span) { var result = new PooledArray(pool, minimumLength); diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/PooledObjects/PooledArray`1.cs b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/PooledObjects/PooledArray`1.cs index 0d78e9183e5..c2f6ff32c45 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/PooledObjects/PooledArray`1.cs +++ b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/PooledObjects/PooledArray`1.cs @@ -12,11 +12,21 @@ internal struct PooledArray : IDisposable private readonly int _minimumLength; private T[]? _array; - // Because of how this API is intended to be used, we don't want the consumption code to have - // to deal with Array being a nullable reference type. Instead, the guarantee is that this is - // non-null until this is disposed. + /// + /// Returns the array that was rented from . + /// + /// + /// Returns a non-null array until is disposed. + /// public readonly T[] Array => _array!; + /// + /// Returns a representing a portion of the rented array + /// from its start to the minimum length. + /// + /// + /// The array has been returned to the pool. + /// public readonly Span Span => _array!.AsSpan(0, _minimumLength); public PooledArray(ArrayPool pool, int minimumLength) From 72132015f0128ffeac1f7bd5125c0b4f517fac23 Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Mon, 15 Jul 2024 19:39:43 -0700 Subject: [PATCH 102/176] Add GetPooledArray(...) overloads to clear the array when returned --- .../BufferExtensions.cs | 64 ++++++++++++++++++- .../PooledObjects/PooledArray`1.cs | 6 +- 2 files changed, 66 insertions(+), 4 deletions(-) diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/BufferExtensions.cs b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/BufferExtensions.cs index a897c734fec..b3b1f58d087 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/BufferExtensions.cs +++ b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/BufferExtensions.cs @@ -10,13 +10,44 @@ internal static class BufferExtensions /// /// Rents an array of the given minimum length from the specified . /// + /// + /// The to use. + /// + /// + /// The minimum length of the array. + /// + /// + /// The rented array. + /// /// /// The array is guaranteed to be at least in length. However, /// it will likely be larger. /// public static PooledArray GetPooledArray(this ArrayPool pool, int minimumLength, out T[] array) + => pool.GetPooledArray(minimumLength, clearOnReturn: false, out array); + + /// + /// Rents an array of the given minimum length from the specified . + /// + /// + /// The to use. + /// + /// + /// The minimum length of the array. + /// + /// + /// Indicates whether the contents of the array should be cleared before it is returned to the pool. + /// + /// + /// The rented array. + /// + /// + /// The array is guaranteed to be at least in length. However, + /// it will likely be larger. + /// + public static PooledArray GetPooledArray(this ArrayPool pool, int minimumLength, bool clearOnReturn, out T[] array) { - var result = new PooledArray(pool, minimumLength); + var result = new PooledArray(pool, minimumLength, clearOnReturn); array = result.Array; return result; } @@ -26,9 +57,38 @@ public static PooledArray GetPooledArray(this ArrayPool pool, int minim /// The rented array is provided as a representing a portion of the rented array /// from its start to the minimum length. /// + /// + /// The to use. + /// + /// + /// The minimum length of the array. + /// + /// + /// The representing a portion of the rented array from its start to the minimum length. + /// public static PooledArray GetPooledArraySpan(this ArrayPool pool, int minimumLength, out Span span) + => pool.GetPooledArraySpan(minimumLength, clearOnReturn: false, out span); + + /// + /// Rents an array of the given minimum length from the specified . + /// The rented array is provided as a representing a portion of the rented array + /// from its start to the minimum length. + /// + /// + /// The to use. + /// + /// + /// The minimum length of the array. + /// + /// + /// Indicates whether the contents of the array should be cleared before it is returned to the pool. + /// + /// + /// The representing a portion of the rented array from its start to the minimum length. + /// + public static PooledArray GetPooledArraySpan(this ArrayPool pool, int minimumLength, bool clearOnReturn, out Span span) { - var result = new PooledArray(pool, minimumLength); + var result = new PooledArray(pool, minimumLength, clearOnReturn); span = result.Span; return result; } diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/PooledObjects/PooledArray`1.cs b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/PooledObjects/PooledArray`1.cs index c2f6ff32c45..4f6850c092b 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/PooledObjects/PooledArray`1.cs +++ b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/PooledObjects/PooledArray`1.cs @@ -10,6 +10,7 @@ internal struct PooledArray : IDisposable { private readonly ArrayPool _pool; private readonly int _minimumLength; + private readonly bool _clearOnReturn; private T[]? _array; /// @@ -29,11 +30,12 @@ internal struct PooledArray : IDisposable /// public readonly Span Span => _array!.AsSpan(0, _minimumLength); - public PooledArray(ArrayPool pool, int minimumLength) + public PooledArray(ArrayPool pool, int minimumLength, bool clearOnReturn) : this() { _pool = pool; _minimumLength = minimumLength; + _clearOnReturn = clearOnReturn; _array = pool.Rent(minimumLength); } @@ -41,7 +43,7 @@ public void Dispose() { if (_array is T[] array) { - _pool.Return(array); + _pool.Return(array, clearArray: _clearOnReturn); _array = null; } } From 721308d46836ba44fcb08cd000c2648e90f001a0 Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Tue, 16 Jul 2024 08:27:18 -0700 Subject: [PATCH 103/176] Add overloads for string AsSpan(), AsMemory() and *OrDefault() variants - Add overloads for string.AsSpan() and string.AsMemory() that take Razor's Index and Range polyfill types. - Add overloads for string.AsSpanOrDefault() and string.AsMemoryOrDefault() that take start, start+length, and Razor Index and Range polyfill types. Note: If compiling for .NET, these forward to the relevant runtime methods. --- .../StringExtensions.cs | 152 ++++++++++++++++++ .../Utilities/ThrowHelper.cs | 28 ++++ 2 files changed, 180 insertions(+) diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/StringExtensions.cs b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/StringExtensions.cs index f649b756075..fb0b34d9b3b 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/StringExtensions.cs +++ b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/StringExtensions.cs @@ -3,6 +3,10 @@ using System.Diagnostics.CodeAnalysis; +#if !NET +using ThrowHelper = Microsoft.AspNetCore.Razor.Utilities.ThrowHelper; +#endif + namespace System; internal static class StringExtensions @@ -13,12 +17,160 @@ public static bool IsNullOrEmpty([NotNullWhen(false)] this string? s) public static bool IsNullOrWhiteSpace([NotNullWhen(false)] this string? s) => string.IsNullOrWhiteSpace(s); + public static ReadOnlySpan AsSpan(this string? s, Index startIndex) + { +#if NET + return MemoryExtensions.AsSpan(s, startIndex); +#else + if (s is null) + { + if (!startIndex.Equals(Index.Start)) + { + ThrowHelper.ThrowArgumentOutOfRange(nameof(startIndex)); + } + + return default; + } + + return s.AsSpan(startIndex.GetOffset(s.Length)); +#endif + } + + public static ReadOnlySpan AsSpan(this string? s, Range range) + { +#if NET + return MemoryExtensions.AsSpan(s, range); +#else + if (s is null) + { + if (!range.Start.Equals(Index.Start) || !range.End.Equals(Index.Start)) + { + ThrowHelper.ThrowArgumentNull(nameof(s)); + } + + return default; + } + + var (start, length) = range.GetOffsetAndLength(s.Length); + return s.AsSpan(start, length); +#endif + } + public static ReadOnlySpan AsSpanOrDefault(this string? s) => s is not null ? s.AsSpan() : default; + public static ReadOnlySpan AsSpanOrDefault(this string? s, int start) + => s is not null ? s.AsSpan(start) : default; + + public static ReadOnlySpan AsSpanOrDefault(this string? s, int start, int length) + => s is not null ? s.AsSpan(start, length) : default; + + public static ReadOnlySpan AsSpanOrDefault(this string? s, Index startIndex) + { + if (s is null) + { + return default; + } + +#if NET + return MemoryExtensions.AsSpan(s, startIndex); +#else + return s.AsSpan(startIndex.GetOffset(s.Length)); +#endif + } + + public static ReadOnlySpan AsSpanOrDefault(this string? s, Range range) + { + if (s is null) + { + return default; + } + +#if NET + return MemoryExtensions.AsSpan(s, range); +#else + var (start, length) = range.GetOffsetAndLength(s.Length); + return s.AsSpan(start, length); +#endif + } + + public static ReadOnlyMemory AsMemory(this string? s, Index startIndex) + { +#if NET + return MemoryExtensions.AsMemory(s, startIndex); +#else + if (s is null) + { + if (!startIndex.Equals(Index.Start)) + { + ThrowHelper.ThrowArgumentOutOfRange(nameof(startIndex)); + } + + return default; + } + + return s.AsMemory(startIndex.GetOffset(s.Length)); +#endif + } + + public static ReadOnlyMemory AsMemory(this string? s, Range range) + { +#if NET + return MemoryExtensions.AsMemory(s, range); +#else + if (s is null) + { + if (!range.Start.Equals(Index.Start) || !range.End.Equals(Index.Start)) + { + ThrowHelper.ThrowArgumentNull(nameof(s)); + } + + return default; + } + + var (start, length) = range.GetOffsetAndLength(s.Length); + return s.AsMemory(start, length); +#endif + } + public static ReadOnlyMemory AsMemoryOrDefault(this string? s) => s is not null ? s.AsMemory() : default; + public static ReadOnlyMemory AsMemoryOrDefault(this string? s, int start) + => s is not null ? s.AsMemory(start) : default; + + public static ReadOnlyMemory AsMemoryOrDefault(this string? s, int start, int length) + => s is not null ? s.AsMemory(start, length) : default; + + public static ReadOnlyMemory AsMemoryOrDefault(this string? s, Index startIndex) + { + if (s is null) + { + return default; + } + +#if NET + return MemoryExtensions.AsMemory(s, startIndex); +#else + return s.AsMemory(startIndex.GetOffset(s.Length)); +#endif + } + + public static ReadOnlyMemory AsMemoryOrDefault(this string? s, Range range) + { + if (s is null) + { + return default; + } + +#if NET + return MemoryExtensions.AsMemory(s, range); +#else + var (start, length) = range.GetOffsetAndLength(s.Length); + return s.AsMemory(start, length); +#endif + } + // This method doesn't exist on .NET Framework, but it does on .NET Core. public static bool Contains(this string s, char ch) => s.IndexOf(ch) >= 0; diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Utilities/ThrowHelper.cs b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Utilities/ThrowHelper.cs index 1a78ee3a3d2..168871c0218 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Utilities/ThrowHelper.cs +++ b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/Utilities/ThrowHelper.cs @@ -8,6 +8,34 @@ namespace Microsoft.AspNetCore.Razor.Utilities; internal static class ThrowHelper { + /// + /// This is present to help the JIT inline methods that need to throw an . + /// + [DoesNotReturn] + public static void ThrowArgumentNull(string paramName) + => throw new ArgumentNullException(paramName); + + /// + /// This is present to help the JIT inline methods that need to throw an . + /// + [DoesNotReturn] + public static T ThrowArgumentNull(string paramName) + => throw new ArgumentNullException(paramName); + + /// + /// This is present to help the JIT inline methods that need to throw an . + /// + [DoesNotReturn] + public static void ThrowArgumentOutOfRange(string paramName) + => throw new ArgumentOutOfRangeException(paramName); + + /// + /// This is present to help the JIT inline methods that need to throw an . + /// + [DoesNotReturn] + public static T ThrowArgumentOutOfRange(string paramName) + => throw new ArgumentOutOfRangeException(paramName); + /// /// This is present to help the JIT inline methods that need to throw an . /// From 2e994ba3adf7ad65410739ebfa848a0dbfba5957 Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Tue, 16 Jul 2024 09:01:04 -0700 Subject: [PATCH 104/176] Add overloads for string.Contains(), IndexOf, StartsWith, and EndsWith Add overloads for string.Contains(), IndexOf(), StartsWith, and EndsWith() extensions methods that exist on .NET Core but not on .NET Framework or .NET Standard 2.0 --- .../StringExtensions.cs | 155 +++++++++++++++++- 1 file changed, 149 insertions(+), 6 deletions(-) diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/StringExtensions.cs b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/StringExtensions.cs index fb0b34d9b3b..59e7f106e6b 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/StringExtensions.cs +++ b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/StringExtensions.cs @@ -171,11 +171,154 @@ public static ReadOnlyMemory AsMemoryOrDefault(this string? s, Range range #endif } - // This method doesn't exist on .NET Framework, but it does on .NET Core. - public static bool Contains(this string s, char ch) - => s.IndexOf(ch) >= 0; + /// + /// Returns a value indicating whether a specified character occurs within a string instance. + /// + /// + /// The string instance. + /// + /// + /// The character to seek. + /// + /// + /// if the value parameter occurs within the string; otherwise, . + /// + /// + /// This method exists on .NET Core, but doesn't on .NET Framework or .NET Standard 2.0. + /// + public static bool Contains(this string text, char value) + { +#if NET + return text.Contains(value); +#else + return text.IndexOf(value) >= 0; +#endif + } + + /// + /// Returns a value indicating whether a specified character occurs within a string instance, + /// using the specified comparison rules. + /// + /// + /// The string instance. + /// + /// + /// The character to seek. + /// + /// + /// One of the enumeration values that specifies the rules to use in the comparison. + /// + /// + /// if the value parameter occurs within the string; otherwise, . + /// + /// + /// This method exists on .NET Core, but doesn't on .NET Framework or .NET Standard 2.0. + /// + public static bool Contains(this string text, char value, StringComparison comparisonType) + { +#if NET + return text.Contains(value, comparisonType); +#else + return text.IndexOf(value, comparisonType) != 0; +#endif + } + + /// + /// Reports the zero-based index of the first occurrence of the specified Unicode character in a string instance. + /// A parameter specifies the type of search to use for the specified character. + /// + /// + /// The string instance. + /// + /// + /// The character to compare to the character at the start of this string. + /// + /// + /// An enumeration value that specifies the rules for the search. + /// + /// + /// The zero-based index of if that character is found, or -1 if it is not. + /// + /// + /// + /// Index numbering starts from zero. + /// + /// + /// The parameter is a enumeration member + /// that specifies whether the search for the argument uses the current or invariant culture, + /// is case-sensitive or case-insensitive, or uses word or ordinal comparison rules. + /// + /// + /// This method exists on .NET Core, but doesn't on .NET Framework or .NET Standard 2.0. + /// + /// + public static int IndexOf(this string text, char value, StringComparison comparisonType) + { +#if NET + return text.IndexOf(value, comparisonType); +#else + // [ch] produces a ReadOnlySpan using a ref to ch. + return text.AsSpan().IndexOf([value], comparisonType); +#endif + } + + /// + /// Determines whether a string instance starts with the specified character. + /// + /// + /// The string instance. + /// + /// + /// The character to compare to the character at the start of this string. + /// + /// + /// if matches the start of the string; + /// otherwise, . + /// + /// + /// + /// This method performs an ordinal (case-sensitive and culture-insensitive) comparison. + /// + /// + /// This method exists on .NET Core, but doesn't on .NET Framework or .NET Standard 2.0. + /// + /// + public static bool StartsWith(this string text, char value) + { +#if NET + return text.StartsWith(value); +#else + return text.Length > 0 && text[0] == value; +#endif + } - // This method doesn't exist on .NET Framework, but it does on .NET Core. - public static bool EndsWith(this string s, char ch) - => s.Length > 0 && s[^1] == ch; + /// + /// Determines whether the end of a string instance matches the specified character. + /// + /// + /// The string instance. + /// + /// + /// The character to compare to the character at the end of this string. + /// + /// + /// if matches the end of this string; + /// otherwise, . + /// + /// + /// + /// This method performs an ordinal (case-sensitive and culture-insensitive) comparison. + /// + /// + /// This method exists on .NET Core, but doesn't on .NET Framework or .NET Standard 2.0. + /// + /// + public static bool EndsWith(this string text, char value) + { +#if NET + return text.EndsWith(value); +#else + return text.Length > 0 && text[^1] == value; +#endif + } } From 59362df65df63901c1aaf32d7377603c42483266 Mon Sep 17 00:00:00 2001 From: Todd Grunke Date: Tue, 16 Jul 2024 09:23:44 -0700 Subject: [PATCH 105/176] Pool CodeWriter ReadOnlyMemory pages (#10585) * Pool CodeWriter ReadOnlyMemory pages These allocations are present in a customer trace I'm looking at, accounting for 1.4% of allocations in the VS process (around 100 MB). The owner of the CodeWriter is already disposable, so making the CodeWriter disposable is trivial, and allows for all ReadOnlyMemory pages added to _pages to be released back to a pool. --- .../CodeGeneration/CSharpCodeWriterTest.cs | 42 +++++++++---------- .../DesignTimeNodeWriterTest.cs | 4 +- .../src/Language/CodeGeneration/CodeWriter.cs | 33 ++++++++++++--- .../DefaultCodeRenderingContext.cs | 17 ++------ .../CodeGeneration/DefaultDocumentWriter.cs | 1 - .../src/Language/RazorHtmlWriter.cs | 1 + .../TestCodeRenderingContext.cs | 6 +-- 7 files changed, 57 insertions(+), 47 deletions(-) diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/CodeGeneration/CSharpCodeWriterTest.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/CodeGeneration/CSharpCodeWriterTest.cs index 2c503f89f8f..8d7c6ff83c3 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/CodeGeneration/CSharpCodeWriterTest.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/CodeGeneration/CSharpCodeWriterTest.cs @@ -32,7 +32,7 @@ public static IEnumerable NewLines public void CSharpCodeWriter_TracksPosition_WithWrite() { // Arrange - var writer = new CodeWriter(); + using var writer = new CodeWriter(); // Act writer.Write("1234"); @@ -48,7 +48,7 @@ public void CSharpCodeWriter_TracksPosition_WithWrite() public void CSharpCodeWriter_TracksPosition_WithIndent() { // Arrange - var writer = new CodeWriter(); + using var writer = new CodeWriter(); // Act writer.WriteLine(); @@ -65,7 +65,7 @@ public void CSharpCodeWriter_TracksPosition_WithIndent() public void CSharpCodeWriter_TracksPosition_WithWriteLine() { // Arrange - var writer = new CodeWriter(); + using var writer = new CodeWriter(); // Act writer.WriteLine("1234"); @@ -83,7 +83,7 @@ public void CSharpCodeWriter_TracksPosition_WithWriteLine() public void CSharpCodeWriter_TracksPosition_WithWriteLine_WithNewLineInContent(string newLine) { // Arrange - var writer = new CodeWriter(); + using var writer = new CodeWriter(); // Act writer.WriteLine("1234" + newLine + "12"); @@ -104,7 +104,7 @@ public void CSharpCodeWriter_TracksPosition_WithWriteLine_WithNewLineInContent(s public void CSharpCodeWriter_TracksPosition_WithWrite_WithNewlineInContent(string newLine) { // Arrange - var writer = new CodeWriter(); + using var writer = new CodeWriter(); // Act writer.Write("1234" + newLine + "123" + newLine + "12"); @@ -124,7 +124,7 @@ public void CSharpCodeWriter_TracksPosition_WithWrite_WithNewlineInContent(strin public void CSharpCodeWriter_TracksPosition_WithWrite_WithNewlineInContent_RepeatedN() { // Arrange - var writer = new CodeWriter(); + using var writer = new CodeWriter(); // Act writer.Write("1234\n\n123"); @@ -144,7 +144,7 @@ public void CSharpCodeWriter_TracksPosition_WithWrite_WithNewlineInContent_Repea public void CSharpCodeWriter_TracksPosition_WithWrite_WithMixedNewlineInContent() { // Arrange - var writer = new CodeWriter(); + using var writer = new CodeWriter(); // Act writer.Write("1234\r123\r\n12\n1"); @@ -164,7 +164,7 @@ public void CSharpCodeWriter_TracksPosition_WithWrite_WithMixedNewlineInContent( public void CSharpCodeWriter_TracksPosition_WithNewline_SplitAcrossWrites() { // Arrange - var writer = new CodeWriter(); + using var writer = new CodeWriter(); // Act writer.Write("1234\r"); @@ -185,7 +185,7 @@ public void CSharpCodeWriter_TracksPosition_WithNewline_SplitAcrossWrites() public void CSharpCodeWriter_TracksPosition_WithTwoNewline_SplitAcrossWrites_R() { // Arrange - var writer = new CodeWriter(); + using var writer = new CodeWriter(); // Act writer.Write("1234\r"); @@ -206,7 +206,7 @@ public void CSharpCodeWriter_TracksPosition_WithTwoNewline_SplitAcrossWrites_R() public void CSharpCodeWriter_TracksPosition_WithTwoNewline_SplitAcrossWrites_N() { // Arrange - var writer = new CodeWriter(); + using var writer = new CodeWriter(); // Act writer.Write("1234\n"); @@ -227,7 +227,7 @@ public void CSharpCodeWriter_TracksPosition_WithTwoNewline_SplitAcrossWrites_N() public void CSharpCodeWriter_TracksPosition_WithTwoNewline_SplitAcrossWrites_Reversed() { // Arrange - var writer = new CodeWriter(); + using var writer = new CodeWriter(); // Act writer.Write("1234\n"); @@ -248,7 +248,7 @@ public void CSharpCodeWriter_TracksPosition_WithTwoNewline_SplitAcrossWrites_Rev public void CSharpCodeWriter_TracksPosition_WithNewline_SplitAcrossWrites_AtBeginning() { // Arrange - var writer = new CodeWriter(); + using var writer = new CodeWriter(); // Act writer.Write("\r"); @@ -269,7 +269,7 @@ public void CSharpCodeWriter_TracksPosition_WithNewline_SplitAcrossWrites_AtBegi public void CSharpCodeWriter_LinesBreaksOutsideOfContentAreNotCounted() { // Arrange - var writer = new CodeWriter(); + using var writer = new CodeWriter(); // Act writer.Write("\r\nHello\r\nWorld\r\n", startIndex: 2, count: 12); @@ -287,7 +287,7 @@ public void WriteLineNumberDirective_UsesFilePath_FromSourceLocation() var filePath = "some-path"; var mappingLocation = new SourceSpan(filePath, 10, 4, 3, 9); - var writer = new CodeWriter(); + using var writer = new CodeWriter(); var expected = $"#line 5 \"{filePath}\"" + writer.NewLine; // Act @@ -302,7 +302,7 @@ public void WriteLineNumberDirective_UsesFilePath_FromSourceLocation() public void WriteField_WritesFieldDeclaration() { // Arrange - var writer = new CodeWriter(); + using var writer = new CodeWriter(); // Act writer.WriteField(Array.Empty(), new[] { "private" }, "global::System.String", "_myString"); @@ -319,7 +319,7 @@ public void WriteField_WritesFieldDeclaration() public void WriteField_WithModifiers_WritesFieldDeclaration() { // Arrange - var writer = new CodeWriter(); + using var writer = new CodeWriter(); // Act writer.WriteField(Array.Empty(), new[] { "private", "readonly", "static" }, "global::System.String", "_myString"); @@ -336,7 +336,7 @@ public void WriteField_WithModifiers_WritesFieldDeclaration() public void WriteField_WithModifiersAndSupressions_WritesFieldDeclaration() { // Arrange - var writer = new CodeWriter(); + using var writer = new CodeWriter(); // Act writer.WriteField( @@ -362,7 +362,7 @@ public void WriteField_WithModifiersAndSupressions_WritesFieldDeclaration() public void WriteAutoPropertyDeclaration_WritesPropertyDeclaration() { // Arrange - var writer = new CodeWriter(); + using var writer = new CodeWriter(); // Act writer.WriteAutoPropertyDeclaration(new[] { "public" }, "global::System.String", "MyString"); @@ -379,7 +379,7 @@ public void WriteAutoPropertyDeclaration_WritesPropertyDeclaration() public void WriteAutoPropertyDeclaration_WithModifiers_WritesPropertyDeclaration() { // Arrange - var writer = new CodeWriter(); + using var writer = new CodeWriter(); // Act writer.WriteAutoPropertyDeclaration(new[] { "public", "static" }, "global::System.String", "MyString"); @@ -402,7 +402,7 @@ public void CSharpCodeWriter_RespectTabSetting() o.IndentSize = 4; }); - var writer = new CodeWriter(Environment.NewLine, options); + using var writer = new CodeWriter(Environment.NewLine, options); // Act writer.BuildClassDeclaration(Array.Empty(), "C", "", Array.Empty(), Array.Empty(), context: null); @@ -428,7 +428,7 @@ public void CSharpCodeWriter_RespectSpaceSetting() o.IndentSize = 4; }); - var writer = new CodeWriter(Environment.NewLine, options); + using var writer = new CodeWriter(Environment.NewLine, options); // Act writer.BuildClassDeclaration(Array.Empty(), "C", "", Array.Empty(), Array.Empty(), context: null); diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/CodeGeneration/DesignTimeNodeWriterTest.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/CodeGeneration/DesignTimeNodeWriterTest.cs index b5f5aa95765..1724a5ad318 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/CodeGeneration/DesignTimeNodeWriterTest.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/CodeGeneration/DesignTimeNodeWriterTest.cs @@ -506,7 +506,7 @@ Render Children public void LinePragma_Is_Adjusted_On_Windows(string fileName, string expectedFileName) { var writer = new DesignTimeNodeWriter(); - var context = TestCodeRenderingContext.CreateDesignTime(); + using var context = TestCodeRenderingContext.CreateDesignTime(); Assert.True(context.Options.RemapLinePragmaPathsOnWindows); @@ -553,7 +553,7 @@ public void LinePragma_Is_Adjusted_On_Windows(string fileName, string expectedFi public void LinePragma_Enhanced_Is_Adjusted_On_Windows(string fileName, string expectedFileName) { var writer = new RuntimeNodeWriter(); - var context = TestCodeRenderingContext.CreateDesignTime(source: RazorSourceDocument.Create("", fileName)); + using var context = TestCodeRenderingContext.CreateDesignTime(source: RazorSourceDocument.Create("", fileName)); Assert.True(context.Options.RemapLinePragmaPathsOnWindows); Assert.True(context.Options.UseEnhancedLinePragma); diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/CodeWriter.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/CodeWriter.cs index 6f850bd120b..b0d4dcae50a 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/CodeWriter.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/CodeWriter.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Buffers; using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; @@ -10,13 +11,13 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration; -public sealed partial class CodeWriter +public sealed partial class CodeWriter : IDisposable { // This is the size of each "page", which are arrays of ReadOnlyMemory. // This number was chosen arbitrarily as a "best guess". If changed, care should be // taken to ensure that pages are not allocated on the LOH. ReadOnlyMemory // takes up 16 bytes, so a page size of 1000 is 16k. - private const int PageSize = 1000; + private const int MinimumPageSize = 1000; // Rather than using a StringBuilder, we maintain a linked list of pages, which are arrays // of "chunks of text", represented by ReadOnlyMemory. This avoids copying strings @@ -65,9 +66,17 @@ private void AddTextChunk(ReadOnlyMemory value) } // If we're at the start of a page, we need to add the page first. - var lastPage = _pageOffset == 0 - ? _pages.AddLast(new ReadOnlyMemory[PageSize]).Value - : _pages.Last!.Value; + ReadOnlyMemory[] lastPage; + + if (_pageOffset == 0) + { + lastPage = ArrayPool>.Shared.Rent(MinimumPageSize); + _pages.AddLast(lastPage); + } + else + { + lastPage = _pages.Last!.Value; + } // Add our chunk of text (the ReadOnlyMemory) and increment the offset. lastPage[_pageOffset] = value; @@ -75,7 +84,9 @@ private void AddTextChunk(ReadOnlyMemory value) // We've reached the end of a page, so we reset the offset to 0. // This will cause a new page to be added next time. - if (_pageOffset == PageSize) + // _pageOffset is checked against the lastPage.Length as the Rent call that + // return that array may return an array longer that MinimumPageSize. + if (_pageOffset == lastPage.Length) { _pageOffset = 0; } @@ -370,4 +381,14 @@ public string GenerateCode() return result; } } + + public void Dispose() + { + foreach (var page in _pages) + { + ArrayPool>.Shared.Return(page, clearArray: true); + } + + _pages.Clear(); + } } diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/DefaultCodeRenderingContext.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/DefaultCodeRenderingContext.cs index 60fb31990bd..109ab30dd6f 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/DefaultCodeRenderingContext.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/DefaultCodeRenderingContext.cs @@ -21,17 +21,11 @@ internal class DefaultCodeRenderingContext : CodeRenderingContext private readonly PooledObject.Builder> _sourceMappingsBuilder; public DefaultCodeRenderingContext( - CodeWriter codeWriter, IntermediateNodeWriter nodeWriter, RazorCodeDocument codeDocument, DocumentIntermediateNode documentNode, RazorCodeGenerationOptions options) { - if (codeWriter == null) - { - throw new ArgumentNullException(nameof(codeWriter)); - } - if (nodeWriter == null) { throw new ArgumentNullException(nameof(nodeWriter)); @@ -52,7 +46,6 @@ public DefaultCodeRenderingContext( throw new ArgumentNullException(nameof(options)); } - CodeWriter = codeWriter; _codeDocument = codeDocument; _documentNode = documentNode; Options = options; @@ -69,12 +62,9 @@ public DefaultCodeRenderingContext( Diagnostics.Add(diagnostics[i]); } - var newLineString = codeDocument.Items[NewLineString]; - if (newLineString != null) - { - // Set new line character to a specific string regardless of platform, for testing purposes. - codeWriter.NewLine = (string)newLineString; - } + // Set new line character to a specific string regardless of platform, for testing purposes. + var newLineString = codeDocument.Items[NewLineString] as string ?? Environment.NewLine; + CodeWriter = new CodeWriter(newLineString, options); Items[NewLineString] = codeDocument.Items[NewLineString]; Items[SuppressUniqueIds] = codeDocument.Items[SuppressUniqueIds] ?? options.SuppressUniqueIds; @@ -220,6 +210,7 @@ public override void AddLinePragma(LinePragma linePragma) public override void Dispose() { _sourceMappingsBuilder.Dispose(); + CodeWriter.Dispose(); } private struct ScopeInternal diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/DefaultDocumentWriter.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/DefaultDocumentWriter.cs index 3b976d4ea4c..72c3b39d0f1 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/DefaultDocumentWriter.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/DefaultDocumentWriter.cs @@ -34,7 +34,6 @@ public override RazorCSharpDocument WriteDocument(RazorCodeDocument codeDocument } using var context = new DefaultCodeRenderingContext( - new CodeWriter(Environment.NewLine, _options), _codeTarget.CreateNodeWriter(), codeDocument, documentNode, diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/RazorHtmlWriter.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/RazorHtmlWriter.cs index aa062c94ca0..39586c97e5f 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/RazorHtmlWriter.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/RazorHtmlWriter.cs @@ -276,5 +276,6 @@ private void WriteNode(TNode node, bool isHtml, Action handler) wh public void Dispose() { _sourceMappingsBuilder.Dispose(); + Builder.Dispose(); } } diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Test.Common/Language/CodeGeneration/TestCodeRenderingContext.cs b/src/Shared/Microsoft.AspNetCore.Razor.Test.Common/Language/CodeGeneration/TestCodeRenderingContext.cs index 28c534b3234..e4f695cc133 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Test.Common/Language/CodeGeneration/TestCodeRenderingContext.cs +++ b/src/Shared/Microsoft.AspNetCore.Razor.Test.Common/Language/CodeGeneration/TestCodeRenderingContext.cs @@ -15,7 +15,6 @@ public static CodeRenderingContext CreateDesignTime( RazorSourceDocument source = null, IntermediateNodeWriter nodeWriter = null) { - var codeWriter = new CodeWriter(); var documentNode = new DocumentIntermediateNode(); var options = RazorCodeGenerationOptions.CreateDesignTimeDefault(); @@ -40,7 +39,7 @@ public static CodeRenderingContext CreateDesignTime( nodeWriter = new DesignTimeNodeWriter(); } - var context = new DefaultCodeRenderingContext(codeWriter, nodeWriter, codeDocument, documentNode, options); + var context = new DefaultCodeRenderingContext(nodeWriter, codeDocument, documentNode, options); context.Visitor = new RenderChildrenVisitor(context); return context; @@ -52,7 +51,6 @@ public static CodeRenderingContext CreateRuntime( RazorSourceDocument source = null, IntermediateNodeWriter nodeWriter = null) { - var codeWriter = new CodeWriter(); var documentNode = new DocumentIntermediateNode(); var options = RazorCodeGenerationOptions.CreateDefault(); @@ -77,7 +75,7 @@ public static CodeRenderingContext CreateRuntime( nodeWriter = new RuntimeNodeWriter(); } - var context = new DefaultCodeRenderingContext(codeWriter, nodeWriter, codeDocument, documentNode, options); + var context = new DefaultCodeRenderingContext(nodeWriter, codeDocument, documentNode, options); context.Visitor = new RenderChildrenVisitor(context); return context; From 55aeabb88bcbcd5b76ddc58e8634a97781847ed1 Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Tue, 16 Jul 2024 10:00:14 -0700 Subject: [PATCH 106/176] Add more XML doc comments --- .../StringExtensions.cs | 341 +++++++++++++++--- 1 file changed, 287 insertions(+), 54 deletions(-) diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/StringExtensions.cs b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/StringExtensions.cs index 59e7f106e6b..9dde4e4b539 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/StringExtensions.cs +++ b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/StringExtensions.cs @@ -11,18 +11,64 @@ namespace System; internal static class StringExtensions { - public static bool IsNullOrEmpty([NotNullWhen(false)] this string? s) - => string.IsNullOrEmpty(s); + /// + /// Indicates whether the specified string is or an empty string (""). + /// + /// + /// The string to test. + /// + /// + /// if the parameter is + /// or an empty string (""); otherwise, . + /// + /// + /// This extension method is useful on .NET Framework and .NET Standard 2.0 where + /// is not annotated for nullability. + /// + public static bool IsNullOrEmpty([NotNullWhen(false)] this string? value) + => string.IsNullOrEmpty(value); - public static bool IsNullOrWhiteSpace([NotNullWhen(false)] this string? s) - => string.IsNullOrWhiteSpace(s); + /// + /// Indicates whether a specified string is , empty, or consists only + /// of white-space characters. + /// + /// + /// The string to test. + /// + /// + /// if the parameter is + /// or , or if consists exclusively of + /// white-space characters. + /// + /// + /// This extension method is useful on .NET Framework and .NET Standard 2.0 where + /// is not annotated for nullability. + /// + public static bool IsNullOrWhiteSpace([NotNullWhen(false)] this string? value) + => string.IsNullOrWhiteSpace(value); - public static ReadOnlySpan AsSpan(this string? s, Index startIndex) + /// + /// Creates a new over a portion of the target string from + /// a specified position to the end of the string. + /// + /// + /// The target string. + /// + /// + /// The index at which to begin this slice. + /// + /// + /// This uses Razor's type, which is type-forwarded on .NET. + /// + /// + /// is less than 0 or greater than .Length. + /// + public static ReadOnlySpan AsSpan(this string? text, Index startIndex) { #if NET - return MemoryExtensions.AsSpan(s, startIndex); + return MemoryExtensions.AsSpan(text, startIndex); #else - if (s is null) + if (text is null) { if (!startIndex.Equals(Index.Start)) { @@ -32,74 +78,175 @@ public static ReadOnlySpan AsSpan(this string? s, Index startIndex) return default; } - return s.AsSpan(startIndex.GetOffset(s.Length)); + return text.AsSpan(startIndex.GetOffset(text.Length)); #endif } - public static ReadOnlySpan AsSpan(this string? s, Range range) + /// + /// Creates a new over a portion of a target string using + /// the range start and end indexes. + /// + /// + /// The target string. + /// + /// + /// The range that has start and end indexes to use for slicing the string. + /// + /// + /// This uses Razor's type, which is type-forwarded on .NET. + /// + /// + /// 's start or end index is not within the bounds of the string. + /// + /// + /// 's start index is greater than its end index. + /// + public static ReadOnlySpan AsSpan(this string? text, Range range) { #if NET - return MemoryExtensions.AsSpan(s, range); + return MemoryExtensions.AsSpan(text, range); #else - if (s is null) + if (text is null) { if (!range.Start.Equals(Index.Start) || !range.End.Equals(Index.Start)) { - ThrowHelper.ThrowArgumentNull(nameof(s)); + ThrowHelper.ThrowArgumentNull(nameof(text)); } return default; } - var (start, length) = range.GetOffsetAndLength(s.Length); - return s.AsSpan(start, length); + var (start, length) = range.GetOffsetAndLength(text.Length); + return text.AsSpan(start, length); #endif } - public static ReadOnlySpan AsSpanOrDefault(this string? s) - => s is not null ? s.AsSpan() : default; + /// + /// Creates a new over a string. If the target string + /// is a () is returned. + /// + /// + /// The target string. + /// + public static ReadOnlySpan AsSpanOrDefault(this string? text) + => text is not null ? text.AsSpan() : default; - public static ReadOnlySpan AsSpanOrDefault(this string? s, int start) - => s is not null ? s.AsSpan(start) : default; + /// + /// Creates a new over a portion of the target string from + /// a specified position to the end of the string. If the target string is + /// a () is returned. + /// + /// + /// The target string. + /// + /// + /// The index at which to begin this slice. + /// + /// + /// is less than 0 or greater than .Length. + /// + public static ReadOnlySpan AsSpanOrDefault(this string? text, int start) + => text is not null ? text.AsSpan(start) : default; - public static ReadOnlySpan AsSpanOrDefault(this string? s, int start, int length) - => s is not null ? s.AsSpan(start, length) : default; + /// + /// Creates a new over a portion of the target string from + /// a specified position for a specified number of characters. If the target string is + /// a () is returned. + /// + /// + /// The target string. + /// + /// + /// The index at which to begin this slice. + /// + /// + /// The desired length for the slice. + /// + /// + /// , , or + + /// is not in the range of . + /// + public static ReadOnlySpan AsSpanOrDefault(this string? text, int start, int length) + => text is not null ? text.AsSpan(start, length) : default; - public static ReadOnlySpan AsSpanOrDefault(this string? s, Index startIndex) + /// + /// Creates a new over a portion of the target string from + /// a specified position to the end of the string. If the target string is + /// a () is returned. + /// + /// + /// The target string. + /// + /// + /// The index at which to begin this slice. + /// + public static ReadOnlySpan AsSpanOrDefault(this string? text, Index startIndex) { - if (s is null) + if (text is null) { return default; } #if NET - return MemoryExtensions.AsSpan(s, startIndex); + return MemoryExtensions.AsSpan(text, startIndex); #else - return s.AsSpan(startIndex.GetOffset(s.Length)); + return text.AsSpan(startIndex.GetOffset(text.Length)); #endif } - public static ReadOnlySpan AsSpanOrDefault(this string? s, Range range) + /// + /// Creates a new over a portion of the target string using the range + /// start and end indexes. If the target string is a + /// () is returned. + /// + /// + /// The target string. + /// + /// + /// The range that has start and end indexes to use for slicing the string. + /// + /// + /// 's start or end index is not within the bounds of the string. + /// + /// + /// 's start index is greater than its end index. + /// + public static ReadOnlySpan AsSpanOrDefault(this string? text, Range range) { - if (s is null) + if (text is null) { return default; } #if NET - return MemoryExtensions.AsSpan(s, range); + return MemoryExtensions.AsSpan(text, range); #else - var (start, length) = range.GetOffsetAndLength(s.Length); - return s.AsSpan(start, length); + var (start, length) = range.GetOffsetAndLength(text.Length); + return text.AsSpan(start, length); #endif } - public static ReadOnlyMemory AsMemory(this string? s, Index startIndex) + /// + /// Creates a new over a portion of a target string starting at a specified index. + /// + /// + /// The target string. + /// + /// + /// The index at which to begin this slice. + /// + /// + /// This uses Razor's type, which is type-forwarded on .NET. + /// + /// + /// is less than 0 or greater than .Length. + /// + public static ReadOnlyMemory AsMemory(this string? text, Index startIndex) { #if NET - return MemoryExtensions.AsMemory(s, startIndex); + return MemoryExtensions.AsMemory(text, startIndex); #else - if (s is null) + if (text is null) { if (!startIndex.Equals(Index.Start)) { @@ -109,65 +256,151 @@ public static ReadOnlyMemory AsMemory(this string? s, Index startIndex) return default; } - return s.AsMemory(startIndex.GetOffset(s.Length)); + return text.AsMemory(startIndex.GetOffset(text.Length)); #endif } - public static ReadOnlyMemory AsMemory(this string? s, Range range) + /// + /// Creates a new over a portion of a target string using + /// the range start and end indexes. + /// + /// + /// The target string. + /// + /// + /// The range that has start and end indexes to use for slicing the string. + /// + /// + /// This uses Razor's type, which is type-forwarded on .NET. + /// + /// + /// 's start or end index is not within the bounds of the string. + /// + /// + /// 's start index is greater than its end index. + /// + public static ReadOnlyMemory AsMemory(this string? text, Range range) { #if NET - return MemoryExtensions.AsMemory(s, range); + return MemoryExtensions.AsMemory(text, range); #else - if (s is null) + if (text is null) { if (!range.Start.Equals(Index.Start) || !range.End.Equals(Index.Start)) { - ThrowHelper.ThrowArgumentNull(nameof(s)); + ThrowHelper.ThrowArgumentNull(nameof(text)); } return default; } - var (start, length) = range.GetOffsetAndLength(s.Length); - return s.AsMemory(start, length); + var (start, length) = range.GetOffsetAndLength(text.Length); + return text.AsMemory(start, length); #endif } - public static ReadOnlyMemory AsMemoryOrDefault(this string? s) - => s is not null ? s.AsMemory() : default; + /// + /// Creates a new over a string. If the target string + /// is a () is returned. + /// + /// + /// The target string. + /// + public static ReadOnlyMemory AsMemoryOrDefault(this string? text) + => text is not null ? text.AsMemory() : default; - public static ReadOnlyMemory AsMemoryOrDefault(this string? s, int start) - => s is not null ? s.AsMemory(start) : default; + /// + /// Creates a new over a portion of the target string from + /// a specified position to the end of the string. If the target string is + /// a () is returned. + /// + /// + /// The target string. + /// + /// + /// The index at which to begin this slice. + /// + /// + /// is less than 0 or greater than .Length. + /// + public static ReadOnlyMemory AsMemoryOrDefault(this string? text, int start) + => text is not null ? text.AsMemory(start) : default; - public static ReadOnlyMemory AsMemoryOrDefault(this string? s, int start, int length) - => s is not null ? s.AsMemory(start, length) : default; + /// + /// Creates a new over a portion of the target string from + /// a specified position for a specified number of characters. If the target string is + /// a () is returned. + /// + /// + /// The target string. + /// + /// + /// The index at which to begin this slice. + /// + /// + /// The desired length for the slice. + /// + /// + /// , , or + + /// is not in the range of . + /// + public static ReadOnlyMemory AsMemoryOrDefault(this string? text, int start, int length) + => text is not null ? text.AsMemory(start, length) : default; - public static ReadOnlyMemory AsMemoryOrDefault(this string? s, Index startIndex) + /// + /// Creates a new over a portion of the target string from + /// a specified position to the end of the string. If the target string is + /// a () is returned. + /// + /// + /// The target string. + /// + /// + /// The index at which to begin this slice. + /// + public static ReadOnlyMemory AsMemoryOrDefault(this string? text, Index startIndex) { - if (s is null) + if (text is null) { return default; } #if NET - return MemoryExtensions.AsMemory(s, startIndex); + return MemoryExtensions.AsMemory(text, startIndex); #else - return s.AsMemory(startIndex.GetOffset(s.Length)); + return text.AsMemory(startIndex.GetOffset(text.Length)); #endif } - public static ReadOnlyMemory AsMemoryOrDefault(this string? s, Range range) + /// + /// Creates a new over a portion of the target string using the range + /// start and end indexes. If the target string is a + /// () is returned. + /// + /// + /// The target string. + /// + /// + /// The range that has start and end indexes to use for slicing the string. + /// + /// + /// 's start or end index is not within the bounds of the string. + /// + /// + /// 's start index is greater than its end index. + /// + public static ReadOnlyMemory AsMemoryOrDefault(this string? text, Range range) { - if (s is null) + if (text is null) { return default; } #if NET - return MemoryExtensions.AsMemory(s, range); + return MemoryExtensions.AsMemory(text, range); #else - var (start, length) = range.GetOffsetAndLength(s.Length); - return s.AsMemory(start, length); + var (start, length) = range.GetOffsetAndLength(text.Length); + return text.AsMemory(start, length); #endif } From 19f2f7fe0d222367a7193833406c34eacd58d263 Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Tue, 16 Jul 2024 10:23:08 -0700 Subject: [PATCH 107/176] Add array AsSpan and AsMemory extensions that use Razor's polyfill types --- .../ArrayExtensions.cs | 175 ++++++++++++++++++ 1 file changed, 175 insertions(+) diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/ArrayExtensions.cs b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/ArrayExtensions.cs index 2663e636bd7..f09b4c8176e 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/ArrayExtensions.cs +++ b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/ArrayExtensions.cs @@ -1,13 +1,188 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT license. See License.txt in the project root for license information. +using System; using System.Collections.Generic; using System.Collections.Immutable; +#if !NET +using ThrowHelper = Microsoft.AspNetCore.Razor.Utilities.ThrowHelper; +#endif + namespace Microsoft.AspNetCore.Razor; internal static class ArrayExtensions { + /// + /// Creates a new span over the portion of the target array defined by an value. + /// + /// + /// The array to convert. + /// + /// + /// The starting index. + /// + /// + /// This uses Razor's type, which is type-forwarded on .NET. + /// + /// + /// is . + /// + /// + /// is less than 0 or greater than .Length. + /// + /// + /// is covariant, and the array's type is not exactly []. + /// + public static ReadOnlySpan AsSpan(this T[]? array, Index startIndex) + { +#if NET + return MemoryExtensions.AsSpan(array, startIndex); +#else + if (array is null) + { + if (!startIndex.Equals(Index.Start)) + { + ThrowHelper.ThrowArgumentOutOfRange(nameof(startIndex)); + } + + return default; + } + + return MemoryExtensions.AsSpan(array, startIndex.GetOffset(array.Length)); +#endif + } + + /// + /// Creates a new span over the portion of the target array defined by a value. + /// + /// + /// The array to convert. + /// + /// + /// The range of the array to convert. + /// + /// + /// This uses Razor's type, which is type-forwarded on .NET. + /// + /// + /// is . + /// + /// + /// 's start or end index is not within the bounds of the string. + /// + /// + /// 's start index is greater than its end index. + /// + /// + /// is covariant, and the array's type is not exactly []. + /// + public static ReadOnlySpan AsSpan(this T[]? array, Range range) + { +#if NET + return MemoryExtensions.AsSpan(array, range); +#else + if (array is null) + { + if (!range.Start.Equals(Index.Start) || !range.End.Equals(Index.Start)) + { + ThrowHelper.ThrowArgumentNull(nameof(array)); + } + + return default; + } + + var (start, length) = range.GetOffsetAndLength(array.Length); + return MemoryExtensions.AsSpan(array, start, length); +#endif + } + + /// + /// Creates a new memory region over the portion of the target starting at the specified index + /// to the end of the array. + /// + /// + /// The array to convert. + /// + /// + /// The first position of the array. + /// + /// + /// This uses Razor's type, which is type-forwarded on .NET. + /// + /// + /// is . + /// + /// + /// is less than 0 or greater than .Length. + /// + /// + /// is covariant, and the array's type is not exactly []. + /// + public static ReadOnlyMemory AsMemory(this T[]? array, Index startIndex) + { +#if NET + return MemoryExtensions.AsMemory(array, startIndex); +#else + if (array is null) + { + if (!startIndex.Equals(Index.Start)) + { + ThrowHelper.ThrowArgumentOutOfRange(nameof(startIndex)); + } + + return default; + } + + return MemoryExtensions.AsMemory(array, startIndex.GetOffset(array.Length)); +#endif + } + + /// + /// Creates a new memory region over the portion of the target array beginning at + /// inclusive start index of the range and ending at the exclusive end index of the range. + /// + /// + /// The array to convert. + /// + /// + /// The range of the array to convert. + /// + /// + /// This uses Razor's type, which is type-forwarded on .NET. + /// + /// + /// is . + /// + /// + /// 's start or end index is not within the bounds of the string. + /// + /// + /// 's start index is greater than its end index. + /// + /// + /// is covariant, and the array's type is not exactly []. + /// + public static ReadOnlyMemory AsMemory(this T[]? array, Range range) + { +#if NET + return MemoryExtensions.AsMemory(array, range); +#else + if (array is null) + { + if (!range.Start.Equals(Index.Start) || !range.End.Equals(Index.Start)) + { + ThrowHelper.ThrowArgumentNull(nameof(array)); + } + + return default; + } + + var (start, length) = range.GetOffsetAndLength(array.Length); + return MemoryExtensions.AsMemory(array, start, length); +#endif + } + public static ImmutableDictionary ToImmutableDictionary( this (TKey key, TValue value)[] array, IEqualityComparer keyComparer) where TKey : notnull From 90cbe54474deca5d2844e6714d69fb484858c8c5 Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Tue, 16 Jul 2024 10:28:25 -0700 Subject: [PATCH 108/176] Remote DrainToImmutable() extension method Since moving to System.Collections.Immutable 8.0, this extension method is no longer needed. --- .../ImmutableArrayExtensions.cs | 33 ------------------- 1 file changed, 33 deletions(-) diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/ImmutableArrayExtensions.cs b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/ImmutableArrayExtensions.cs index e0d7478cca7..3107a833101 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/ImmutableArrayExtensions.cs +++ b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/ImmutableArrayExtensions.cs @@ -29,39 +29,6 @@ public static void SetCapacityIfLarger(this ImmutableArray.Builder builder } } - /// - /// Returns the current contents as an and sets - /// the collection to a zero length array. - /// - /// - /// If equals - /// , the internal array will be extracted - /// as an without copying the contents. Otherwise, the - /// contents will be copied into a new array. The collection will then be set to a - /// zero-length array. - /// - /// An immutable array. - public static ImmutableArray DrainToImmutable(this ImmutableArray.Builder builder) - { -#if NET8_0_OR_GREATER - return builder.DrainToImmutable(); -#else - if (builder.Count == 0) - { - return []; - } - - if (builder.Count == builder.Capacity) - { - return builder.MoveToImmutable(); - } - - var result = builder.ToImmutable(); - builder.Clear(); - return result; -#endif - } - public static ImmutableArray SelectAsArray(this ImmutableArray source, Func selector) { return source switch From fd837e1f2df38690099059b0a315ed6eadd6d472 Mon Sep 17 00:00:00 2001 From: Chris Sienkiewicz Date: Tue, 16 Jul 2024 10:35:33 -0700 Subject: [PATCH 109/176] [FUSE] Component attribute nameof() (#10581) * Track the containing type of bound attributes for components * Write out the attribute name as a nameof when we have a containingtype. * Use the concrete containing type if we rewrote the parent component. * nameof support for type inferred components * Add line and source span mappings - Special case the synthesized bind entries that don't have a runtime representation - Update spanmapping writing to handle cases where identifiers are escaped * Add nameof test - Adds a test the demonstrates what happens if you declare a function called nameof in a component * Update baselines --- .../ComponentCodeGenerationTestBase.cs | 247 +++++++++++++++++- .../TestComponent.codegen.cs | 53 ++++ .../TestComponent.ir.txt | 20 ++ .../TestComponent.mappings.txt | 5 + .../TestComponent.codegen.cs | 53 ++++ .../TestComponent.ir.txt | 20 ++ .../TestComponent.mappings.txt | 5 + .../TestComponent.codegen.cs | 53 ++++ .../TestComponent.ir.txt | 20 ++ .../TestComponent.mappings.txt | 5 + .../TestComponent.codegen.cs | 61 +++++ .../TestComponent.ir.txt | 24 ++ .../TestComponent.mappings.txt | 14 + .../TestComponent.codegen.cs | 71 +++++ .../TestComponent.ir.txt | 27 ++ .../TestComponent.mappings.txt | 19 ++ .../TestComponent.codegen.cs | 71 +++++ .../TestComponent.ir.txt | 27 ++ .../TestComponent.mappings.txt | 19 ++ .../TestComponent.codegen.cs | 73 ++++++ .../TestComponent.ir.txt | 27 ++ .../TestComponent.mappings.txt | 23 ++ .../TestComponent.codegen.cs | 20 +- .../TestComponent.mappings.txt | 10 + .../TestComponent.codegen.cs | 52 +++- .../TestComponent.mappings.txt | 25 ++ .../TestComponent.codegen.cs | 60 ++++- .../TestComponent.mappings.txt | 30 +++ .../TestComponent.codegen.cs | 50 +++- .../TestComponent.mappings.txt | 25 ++ .../TestComponent.codegen.cs | 35 +++ .../TestComponent.ir.txt | 13 + .../TestComponent.mappings.txt | 5 + .../TestComponent.codegen.cs | 35 +++ .../TestComponent.ir.txt | 13 + .../TestComponent.mappings.txt | 5 + .../TestComponent.codegen.cs | 35 +++ .../TestComponent.ir.txt | 13 + .../TestComponent.mappings.txt | 5 + .../TestComponent.codegen.cs | 44 ++++ .../TestComponent.ir.txt | 15 ++ .../TestComponent.mappings.txt | 14 + .../TestComponent.codegen.cs | 14 +- .../TestComponent.mappings.txt | 11 +- .../TestComponent.codegen.cs | 14 +- .../TestComponent.mappings.txt | 5 + .../TestComponent.codegen.cs | 14 +- .../TestComponent.mappings.txt | 5 + .../TestComponent.codegen.cs | 12 +- .../TestComponent.mappings.txt | 11 +- .../TestComponent.codegen.cs | 12 +- .../TestComponent.mappings.txt | 11 +- .../TestComponent.codegen.cs | 12 +- .../TestComponent.mappings.txt | 11 +- .../TestComponent.codegen.cs | 14 +- .../TestComponent.mappings.txt | 11 +- .../TestComponent.codegen.cs | 14 +- .../TestComponent.mappings.txt | 5 + .../TestComponent.codegen.cs | 12 +- .../TestComponent.mappings.txt | 11 +- .../TestComponent.codegen.cs | 53 ++++ .../TestComponent.ir.txt | 18 ++ .../TestComponent.mappings.txt | 19 ++ .../TestComponent.codegen.cs | 53 ++++ .../TestComponent.ir.txt | 18 ++ .../TestComponent.mappings.txt | 19 ++ .../TestComponent.codegen.cs | 55 ++++ .../TestComponent.ir.txt | 18 ++ .../TestComponent.mappings.txt | 23 ++ .../TestComponent.codegen.cs | 12 +- .../TestComponent.mappings.txt | 11 +- .../TestComponent.codegen.cs | 12 +- .../TestComponent.mappings.txt | 13 +- .../TestComponent.codegen.cs | 12 +- .../TestComponent.mappings.txt | 13 +- .../TestComponent.codegen.cs | 12 +- .../TestComponent.mappings.txt | 13 +- .../TestComponent.codegen.cs | 12 +- .../TestComponent.mappings.txt | 13 +- .../TestComponent.codegen.cs | 12 +- .../TestComponent.mappings.txt | 13 +- .../TestComponent.codegen.cs | 12 +- .../TestComponent.mappings.txt | 13 +- .../TestComponent.codegen.cs | 12 +- .../TestComponent.mappings.txt | 13 +- .../TestComponent.codegen.cs | 12 +- .../TestComponent.mappings.txt | 13 +- .../TestComponent.codegen.cs | 12 +- .../TestComponent.mappings.txt | 13 +- .../TestComponent.codegen.cs | 12 +- .../TestComponent.mappings.txt | 13 +- .../TestComponent.codegen.cs | 12 +- .../TestComponent.mappings.txt | 13 +- .../TestComponent.codegen.cs | 12 +- .../TestComponent.mappings.txt | 13 +- .../TestComponent.codegen.cs | 12 +- .../TestComponent.mappings.txt | 13 +- .../TestComponent.codegen.cs | 12 +- .../TestComponent.mappings.txt | 13 +- .../TestComponent.codegen.cs | 12 +- .../TestComponent.mappings.txt | 13 +- .../TestComponent.codegen.cs | 12 +- .../TestComponent.mappings.txt | 13 +- .../TestComponent.codegen.cs | 12 +- .../TestComponent.mappings.txt | 11 +- .../TestComponent.codegen.cs | 12 +- .../TestComponent.mappings.txt | 13 +- .../TestComponent.codegen.cs | 12 +- .../TestComponent.mappings.txt | 13 +- .../TestComponent.codegen.cs | 12 +- .../TestComponent.mappings.txt | 13 +- .../TestComponent.codegen.cs | 12 +- .../TestComponent.mappings.txt | 13 +- .../TestComponent.codegen.cs | 12 +- .../TestComponent.mappings.txt | 5 + .../TestComponent.codegen.cs | 12 +- .../TestComponent.mappings.txt | 5 + .../TestComponent.codegen.cs | 12 +- .../TestComponent.mappings.txt | 5 + .../TestComponent.codegen.cs | 12 +- .../TestComponent.mappings.txt | 5 + .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 7 +- .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 7 +- .../TestComponent.codegen.cs | 20 +- .../TestComponent.mappings.txt | 10 + .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 9 +- .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 9 +- .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 5 + .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 5 + .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 5 + .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 5 + .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 5 + .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 5 + .../TestComponent.codegen.cs | 20 +- .../TestComponent.mappings.txt | 10 + .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 5 + .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 5 + .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 5 + .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 5 + .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 5 + .../TestComponent.codegen.cs | 30 ++- .../TestComponent.mappings.txt | 15 ++ .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 5 + .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 9 +- .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 5 + .../TestComponent.codegen.cs | 20 +- .../TestComponent.mappings.txt | 10 + .../TestComponent.codegen.cs | 20 +- .../TestComponent.mappings.txt | 10 + .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 5 + .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 5 + .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 5 + .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 5 + .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 5 + .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 9 +- .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 9 +- .../TestComponent.codegen.cs | 12 +- .../TestComponent.mappings.txt | 11 +- .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 5 + .../TestComponent.codegen.cs | 24 +- .../TestComponent.mappings.txt | 10 + .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 11 +- .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 5 + .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 11 +- .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 5 + .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 5 + .../TestComponent.codegen.cs | 30 ++- .../TestComponent.mappings.txt | 15 ++ .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 13 +- .../TestComponent.codegen.cs | 20 +- .../TestComponent.mappings.txt | 10 + .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 5 + .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 5 + .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 11 +- .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 9 +- .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 9 +- .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 9 +- .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 9 +- .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 11 +- .../TestComponent.codegen.cs | 40 ++- .../TestComponent.mappings.txt | 28 +- .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 9 +- .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 9 +- .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 7 +- .../UseTestComponent.codegen.cs | 30 ++- .../UseTestComponent.mappings.txt | 15 ++ .../UseTestComponent.codegen.cs | 30 ++- .../UseTestComponent.mappings.txt | 15 ++ .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 9 +- .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 9 +- .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 11 +- .../UseTestComponent.codegen.cs | 30 ++- .../UseTestComponent.mappings.txt | 15 ++ .../UseTestComponent.codegen.cs | 20 +- .../UseTestComponent.mappings.txt | 10 + .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 5 + .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 9 +- .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 11 +- .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 11 +- .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 13 +- .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 9 +- .../TestComponent.codegen.cs | 20 +- .../TestComponent.mappings.txt | 16 +- .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 5 + .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 11 +- .../TestComponent.codegen.cs | 20 +- .../TestComponent.mappings.txt | 16 +- .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 9 +- .../TestComponent.codegen.cs | 20 +- .../TestComponent.mappings.txt | 10 + .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 11 +- .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 11 +- .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 5 + .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 5 + .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 9 +- .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 5 + .../TestComponent.codegen.cs | 24 +- .../TestComponent.mappings.txt | 18 +- .../TestComponent.codegen.cs | 24 +- .../TestComponent.mappings.txt | 18 +- .../TestComponent.codegen.cs | 24 +- .../TestComponent.mappings.txt | 18 +- .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 5 + .../TestComponent.codegen.cs | 14 +- .../TestComponent.mappings.txt | 5 + .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 11 +- .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 11 +- .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 5 + .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 9 +- .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 11 +- .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 9 +- .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 9 +- .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 11 +- .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 9 +- .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 11 +- .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 11 +- .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 11 +- .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 11 +- .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 11 +- .../TestComponent.codegen.cs | 20 +- .../TestComponent.mappings.txt | 10 + .../TestComponent.codegen.cs | 20 +- .../TestComponent.mappings.txt | 10 + .../TestComponent.codegen.cs | 12 +- .../TestComponent.mappings.txt | 11 +- .../TestComponent.codegen.cs | 12 +- .../TestComponent.mappings.txt | 11 +- .../TestComponent.codegen.cs | 12 +- .../TestComponent.mappings.txt | 11 +- .../TestComponent.codegen.cs | 12 +- .../TestComponent.mappings.txt | 11 +- .../TestComponent.codegen.cs | 12 +- .../TestComponent.mappings.txt | 5 + .../TestComponent.codegen.cs | 12 +- .../TestComponent.mappings.txt | 5 + .../TestComponent.codegen.cs | 12 +- .../TestComponent.mappings.txt | 5 + .../TestComponent.codegen.cs | 12 +- .../TestComponent.mappings.txt | 5 + .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 7 +- .../TestComponent.codegen.cs | 20 +- .../TestComponent.mappings.txt | 10 + .../TestComponent.codegen.cs | 20 +- .../TestComponent.mappings.txt | 10 + .../TestComponent.codegen.cs | 20 +- .../TestComponent.mappings.txt | 10 + .../TestComponent.codegen.cs | 20 +- .../TestComponent.mappings.txt | 10 + .../TestComponent.codegen.cs | 20 +- .../TestComponent.mappings.txt | 10 + .../TestComponent.codegen.cs | 20 +- .../TestComponent.mappings.txt | 10 + .../TestComponent.codegen.cs | 20 +- .../TestComponent.mappings.txt | 10 + .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 9 +- .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 5 + .../TestComponent.codegen.cs | 24 +- .../TestComponent.mappings.txt | 18 +- .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 5 + .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 13 +- .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 5 + .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 5 + .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 13 +- .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 5 + .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 9 +- .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 7 +- .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 11 +- .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 13 +- .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 7 +- .../Regression_772/TestComponent.codegen.cs | 10 +- .../Regression_772/TestComponent.mappings.txt | 5 + .../Regression_773/TestComponent.codegen.cs | 10 +- .../Regression_773/TestComponent.mappings.txt | 5 + .../TestComponent.codegen.cs | 20 +- .../TestComponent.mappings.txt | 16 +- .../TestComponent.codegen.cs | 10 +- .../TestComponent.mappings.txt | 5 + .../ComponentTagHelperDescriptorProvider.cs | 5 +- .../src/Language/BoundAttributeDescriptor.cs | 4 + .../BoundAttributeDescriptorBuilder.cs | 3 + ...BoundAttributeDescriptorBuilder_Pooling.cs | 1 + .../CodeGeneration/CodeRenderingContext.cs | 2 +- .../CodeGeneration/CodeWriterExtensions.cs | 22 +- .../DefaultCodeRenderingContext.cs | 6 +- .../Components/ComponentBindLoweringPass.cs | 23 ++ .../ComponentDesignTimeNodeWriter.cs | 9 +- .../Components/ComponentGenericTypePass.cs | 2 + .../Language/Components/ComponentMetadata.cs | 24 ++ .../Components/ComponentNodeWriter.cs | 52 +++- .../Components/ComponentRuntimeNodeWriter.cs | 10 +- .../Kendo.Mvc.Examples.project.razor.json | 2 +- .../Resources/project.razor.bin | Bin 163752 -> 164158 bytes .../Resources/project.razor.json | 2 +- .../TagHelpers/BoundAttributeFormatter.cs | 13 +- .../MessagePack/SerializationFormat.cs | 2 +- .../ObjectReaders.cs | 5 +- .../ObjectWriters.cs | 1 + .../SerializationFormat.cs | 2 +- 408 files changed, 5048 insertions(+), 616 deletions(-) create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/AddComponentParameter_DynamicComponentName/TestComponent.codegen.cs create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/AddComponentParameter_DynamicComponentName/TestComponent.ir.txt create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/AddComponentParameter_DynamicComponentName/TestComponent.mappings.txt create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/AddComponentParameter_EscapedComponentName/TestComponent.codegen.cs create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/AddComponentParameter_EscapedComponentName/TestComponent.ir.txt create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/AddComponentParameter_EscapedComponentName/TestComponent.mappings.txt create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/AddComponentParameter_GlobalNamespace/TestComponent.codegen.cs create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/AddComponentParameter_GlobalNamespace/TestComponent.ir.txt create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/AddComponentParameter_GlobalNamespace/TestComponent.mappings.txt create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/AddComponentParameter_WithNameof/TestComponent.codegen.cs create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/AddComponentParameter_WithNameof/TestComponent.ir.txt create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/AddComponentParameter_WithNameof/TestComponent.mappings.txt create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/BindToComponent_SpecifiesValue_WithMatchingProperties_DynamicComponentName/TestComponent.codegen.cs create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/BindToComponent_SpecifiesValue_WithMatchingProperties_DynamicComponentName/TestComponent.ir.txt create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/BindToComponent_SpecifiesValue_WithMatchingProperties_DynamicComponentName/TestComponent.mappings.txt create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/BindToComponent_SpecifiesValue_WithMatchingProperties_EscapedComponentName/TestComponent.codegen.cs create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/BindToComponent_SpecifiesValue_WithMatchingProperties_EscapedComponentName/TestComponent.ir.txt create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/BindToComponent_SpecifiesValue_WithMatchingProperties_EscapedComponentName/TestComponent.mappings.txt create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/BindToComponent_SpecifiesValue_WithMatchingProperties_WithNameof/TestComponent.codegen.cs create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/BindToComponent_SpecifiesValue_WithMatchingProperties_WithNameof/TestComponent.ir.txt create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/BindToComponent_SpecifiesValue_WithMatchingProperties_WithNameof/TestComponent.mappings.txt create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AddComponentParameter_DynamicComponentName/TestComponent.codegen.cs create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AddComponentParameter_DynamicComponentName/TestComponent.ir.txt create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AddComponentParameter_DynamicComponentName/TestComponent.mappings.txt create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AddComponentParameter_EscapedComponentName/TestComponent.codegen.cs create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AddComponentParameter_EscapedComponentName/TestComponent.ir.txt create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AddComponentParameter_EscapedComponentName/TestComponent.mappings.txt create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AddComponentParameter_GlobalNamespace/TestComponent.codegen.cs create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AddComponentParameter_GlobalNamespace/TestComponent.ir.txt create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AddComponentParameter_GlobalNamespace/TestComponent.mappings.txt create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AddComponentParameter_WithNameof/TestComponent.codegen.cs create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AddComponentParameter_WithNameof/TestComponent.ir.txt create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AddComponentParameter_WithNameof/TestComponent.mappings.txt create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_SpecifiesValue_WithMatchingProperties_DynamicComponentName/TestComponent.codegen.cs create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_SpecifiesValue_WithMatchingProperties_DynamicComponentName/TestComponent.ir.txt create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_SpecifiesValue_WithMatchingProperties_DynamicComponentName/TestComponent.mappings.txt create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_SpecifiesValue_WithMatchingProperties_EscapedComponentName/TestComponent.codegen.cs create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_SpecifiesValue_WithMatchingProperties_EscapedComponentName/TestComponent.ir.txt create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_SpecifiesValue_WithMatchingProperties_EscapedComponentName/TestComponent.mappings.txt create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_SpecifiesValue_WithMatchingProperties_WithNameof/TestComponent.codegen.cs create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_SpecifiesValue_WithMatchingProperties_WithNameof/TestComponent.ir.txt create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_SpecifiesValue_WithMatchingProperties_WithNameof/TestComponent.mappings.txt create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_WithChildContent/TestComponent.mappings.txt create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithEditorRequiredParameter_ValueSpecified/TestComponent.mappings.txt create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/DuplicateComponentParameters_IsAnError/TestComponent.mappings.txt create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/DuplicateComponentParameters_IsAnError_Multiple/TestComponent.mappings.txt diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/IntegrationTests/ComponentCodeGenerationTestBase.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/IntegrationTests/ComponentCodeGenerationTestBase.cs index 8c948743a59..364e9b87341 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/IntegrationTests/ComponentCodeGenerationTestBase.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/IntegrationTests/ComponentCodeGenerationTestBase.cs @@ -1672,6 +1672,115 @@ @typeparam T } } + [IntegrationTestFact] + public void AddComponentParameter_GlobalNamespace() + { + // Arrange + AdditionalSyntaxTrees.Add(Parse(@" +using System; +using Microsoft.AspNetCore.Components; + +public class MyComponent : ComponentBase +{ + [Parameter] + public string Value { get; set; } +}")); + + // Act + var generated = CompileToCSharp(@""); + + // Assert + AssertDocumentNodeMatchesBaseline(generated.CodeDocument); + AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); + CompileToAssembly(generated); + } + + [IntegrationTestFact] + public void AddComponentParameter_WithNameof() + { + // Arrange + AdditionalSyntaxTrees.Add(Parse(@" +using System; +using Microsoft.AspNetCore.Components; + +namespace Test +{ + public class MyComponent : ComponentBase + { + [Parameter] + public string Value { get; set; } + } +}")); + + // Act + var generated = CompileToCSharp(@" + +@code { + public string nameof(string s) => string.Empty; +}"); + + // Assert + AssertDocumentNodeMatchesBaseline(generated.CodeDocument); + AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); + CompileToAssembly(generated, designTime ? [] : [ + // (21,55): error CS0120: An object reference is required for the non-static field, method, or property 'MyComponent.Value' + // __builder.AddComponentParameter(1, nameof(global::Test.MyComponent. + Diagnostic(ErrorCode.ERR_ObjectRequired, "global::Test.MyComponent.\r\n#nullable restore\r\n#line (1,14)-(1,19) \"x:\\dir\\subdir\\Test\\TestComponent.cshtml\"\r\nValue").WithArguments("Test.MyComponent.Value").WithLocation(21, 55) + ]); + } + + [IntegrationTestFact] + public void AddComponentParameter_EscapedComponentName() + { + // Arrange + AdditionalSyntaxTrees.Add(Parse(@" +using System; +using Microsoft.AspNetCore.Components; + +namespace Test +{ + public class @int : ComponentBase + { + [Parameter] + public string Value { get; set; } + } +}")); + + // Act + var generated = CompileToCSharp(@""); + + // Assert + AssertDocumentNodeMatchesBaseline(generated.CodeDocument); + AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); + CompileToAssembly(generated); + } + + [IntegrationTestFact] + public void AddComponentParameter_DynamicComponentName() + { + // Arrange + AdditionalSyntaxTrees.Add(Parse(@" +using System; +using Microsoft.AspNetCore.Components; + +namespace Test +{ + public class dynamic : ComponentBase + { + [Parameter] + public string Value { get; set; } + } +}")); + + // Act + var generated = CompileToCSharp(@""); + + // Assert + AssertDocumentNodeMatchesBaseline(generated.CodeDocument); + AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); + CompileToAssembly(generated); + } + #endregion #region Bind @@ -1709,6 +1818,114 @@ public class MyComponent : ComponentBase CompileToAssembly(generated); } + [IntegrationTestFact] + public void BindToComponent_SpecifiesValue_WithMatchingProperties_WithNameof() + { + // Arrange + AdditionalSyntaxTrees.Add(Parse(@" +using System; +using Microsoft.AspNetCore.Components; + +namespace Test +{ + public class MyComponent : ComponentBase + { + [Parameter] + public int Value { get; set; } + + [Parameter] + public Action ValueChanged { get; set; } + } +}")); + + // Act + var generated = CompileToCSharp(@" + +@code { + public int ParentValue { get; set; } = 42; + + public string nameof(string s) => string.Empty; +}"); + + // Assert + AssertDocumentNodeMatchesBaseline(generated.CodeDocument); + AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); + CompileToAssembly(generated, designTime ? [] : [ + // (21,55): error CS0120: An object reference is required for the non-static field, method, or property 'MyComponent.Value' + // __builder.AddComponentParameter(1, nameof(global::Test.MyComponent. + Diagnostic(ErrorCode.ERR_ObjectRequired, "global::Test.MyComponent.\r\n#nullable restore\r\n#line (1,20)-(1,25) \"x:\\dir\\subdir\\Test\\TestComponent.cshtml\"\r\nValue").WithArguments("Test.MyComponent.Value").WithLocation(21, 55), + // (38,55): error CS0120: An object reference is required for the non-static field, method, or property 'MyComponent.ValueChanged' + // __builder.AddComponentParameter(2, nameof(global::Test.MyComponent.ValueChanged), (global::System.Action)(__value => ParentValue = __value)); + Diagnostic(ErrorCode.ERR_ObjectRequired, "global::Test.MyComponent.ValueChanged").WithArguments("Test.MyComponent.ValueChanged").WithLocation(38, 55) + ]); + } + + [IntegrationTestFact] + public void BindToComponent_SpecifiesValue_WithMatchingProperties_EscapedComponentName() + { + // Arrange + AdditionalSyntaxTrees.Add(Parse(@" +using System; +using Microsoft.AspNetCore.Components; + +namespace Test +{ + public class @int : ComponentBase + { + [Parameter] + public int Value { get; set; } + + [Parameter] + public Action ValueChanged { get; set; } + } +}")); + + // Act + var generated = CompileToCSharp(@" + +@code { + public int ParentValue { get; set; } = 42; +}"); + + // Assert + AssertDocumentNodeMatchesBaseline(generated.CodeDocument); + AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); + CompileToAssembly(generated); + } + + [IntegrationTestFact] + public void BindToComponent_SpecifiesValue_WithMatchingProperties_DynamicComponentName() + { + // Arrange + AdditionalSyntaxTrees.Add(Parse(@" +using System; +using Microsoft.AspNetCore.Components; + +namespace Test +{ + public class dynamic : ComponentBase + { + [Parameter] + public int Value { get; set; } + + [Parameter] + public Action ValueChanged { get; set; } + } +}")); + + // Act + var generated = CompileToCSharp(@" + +@code { + public int ParentValue { get; set; } = 42; +}"); + + // Assert + AssertDocumentNodeMatchesBaseline(generated.CodeDocument); + AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); + CompileToAssembly(generated); + } + [IntegrationTestFact] public void BindToComponent_WithStringAttribute_DoesNotUseStringSyntax() { @@ -1791,15 +2008,15 @@ public class MyComponent : ComponentBase ? [// x:\dir\subdir\Test\TestComponent.cshtml(1,27): error CS1503: Argument 1: cannot convert from 'string' to 'int' // ParentValue Diagnostic(ErrorCode.ERR_BadArgType, "ParentValue").WithArguments("1", "string", "int").WithLocation(1, 27), - // (30,127): error CS0029: Cannot implicitly convert type 'int' to 'string' + // (37,38): error CS0029: Cannot implicitly convert type 'int' to 'string' // __builder.AddComponentParameter(2, "ValueChanged", (global::System.Action)(__value => ParentValue = __value)); Diagnostic(ErrorCode.ERR_NoImplicitConv, "__value").WithArguments("int", "string").WithLocation(37, 38)] : [// x:\dir\subdir\Test\TestComponent.cshtml(1,27): error CS1503: Argument 1: cannot convert from 'string' to 'int' // ParentValue Diagnostic(ErrorCode.ERR_BadArgType, "ParentValue").WithArguments("1", "string", "int").WithLocation(1, 27), - // (30,127): error CS0029: Cannot implicitly convert type 'int' to 'string' + // (38,158): error CS0029: Cannot implicitly convert type 'int' to 'string' // __builder.AddComponentParameter(2, "ValueChanged", (global::System.Action)(__value => ParentValue = __value)); - Diagnostic(ErrorCode.ERR_NoImplicitConv, "__value").WithArguments("int", "string").WithLocation(30, 127)]); + Diagnostic(ErrorCode.ERR_NoImplicitConv, "__value").WithArguments("int", "string").WithLocation(38, 158)]); } [IntegrationTestFact] @@ -1876,9 +2093,9 @@ public class MyComponent : ComponentBase : [// x:\dir\subdir\Test\TestComponent.cshtml(1,27): error CS1503: Argument 1: cannot convert from 'string' to 'int' // ParentValue Diagnostic(ErrorCode.ERR_BadArgType, "ParentValue").WithArguments("1", "string", "int").WithLocation(1, 27), - // (37,13): error CS1503: Argument 2: cannot convert from 'Microsoft.AspNetCore.Components.EventCallback' to 'Microsoft.AspNetCore.Components.EventCallback' + // (38,351): error CS1503: Argument 2: cannot convert from 'Microsoft.AspNetCore.Components.EventCallback' to 'Microsoft.AspNetCore.Components.EventCallback' // global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.CreateInferredEventCallback(this, __value => ParentValue = __value, ParentValue))); - Diagnostic(ErrorCode.ERR_BadArgType, "global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.CreateInferredEventCallback(this, __value => ParentValue = __value, ParentValue)").WithArguments("2", "Microsoft.AspNetCore.Components.EventCallback", "Microsoft.AspNetCore.Components.EventCallback").WithLocation(30, 320) + Diagnostic(ErrorCode.ERR_BadArgType, "global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.CreateInferredEventCallback(this, __value => ParentValue = __value, ParentValue)").WithArguments("2", "Microsoft.AspNetCore.Components.EventCallback", "Microsoft.AspNetCore.Components.EventCallback").WithLocation(38, 351) ] ); } @@ -2077,18 +2294,18 @@ public class MyComponent : ComponentBase CompileToAssembly(generated, DesignTime - ? [// (31,227): error CS0029: Cannot implicitly convert type 'int' to 'string' + ? [// (31,179): error CS0029: Cannot implicitly convert type 'int' to 'string' // __builder.AddComponentParameter(3, "ValueExpression", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck>>(() => ParentValue)); Diagnostic(ErrorCode.ERR_NoImplicitConv, "ParentValue").WithArguments("int", "string").WithLocation(38, 179), - // (31,227): error CS1662: Cannot convert lambda expression to intended delegate type because some of the return types in the block are not implicitly convertible to the delegate return type + // (31,179): error CS1662: Cannot convert lambda expression to intended delegate type because some of the return types in the block are not implicitly convertible to the delegate return type // __builder.AddComponentParameter(3, "ValueExpression", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck>>(() => ParentValue)); Diagnostic(ErrorCode.ERR_CantConvAnonMethReturns, "ParentValue").WithArguments("lambda expression").WithLocation(38, 179)] - : [// (31,227): error CS0029: Cannot implicitly convert type 'int' to 'string' + : [// (39,258): error CS0029: Cannot implicitly convert type 'int' to 'string' // __builder.AddComponentParameter(3, "ValueExpression", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck>>(() => ParentValue)); - Diagnostic(ErrorCode.ERR_NoImplicitConv, "ParentValue").WithArguments("int", "string").WithLocation(31, 227), - // (31,227): error CS1662: Cannot convert lambda expression to intended delegate type because some of the return types in the block are not implicitly convertible to the delegate return type + Diagnostic(ErrorCode.ERR_NoImplicitConv, "ParentValue").WithArguments("int", "string").WithLocation(39, 258), + // (39,258): error CS1662: Cannot convert lambda expression to intended delegate type because some of the return types in the block are not implicitly convertible to the delegate return type // __builder.AddComponentParameter(3, "ValueExpression", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck>>(() => ParentValue)); - Diagnostic(ErrorCode.ERR_CantConvAnonMethReturns, "ParentValue").WithArguments("lambda expression").WithLocation(31, 227) + Diagnostic(ErrorCode.ERR_CantConvAnonMethReturns, "ParentValue").WithArguments("lambda expression").WithLocation(39, 258) ]); } @@ -10364,9 +10581,9 @@ public class MyComponent : ComponentBase : [// x:\dir\subdir\Test\TestComponent.cshtml(1,32): error CS1003: Syntax error, ',' expected // x Diagnostic(ErrorCode.ERR_SyntaxError, "").WithArguments(",").WithLocation(1, 32), - // (27,91): error CS1501: No overload for method 'TypeCheck' takes 2 arguments + // (29,88): error CS1501: No overload for method 'TypeCheck' takes 2 arguments // __o = global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( - Diagnostic(ErrorCode.ERR_BadArgCount, "TypeCheck").WithArguments("TypeCheck", "2").WithLocation(21, 138)] + Diagnostic(ErrorCode.ERR_BadArgCount, "TypeCheck").WithArguments("TypeCheck", "2").WithLocation(29, 88)] ); Assert.NotEmpty(generated.RazorDiagnostics); } @@ -11132,6 +11349,7 @@ @using Microsoft.AspNetCore.Components.Web // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); + CompileToAssembly(generated); } [IntegrationTestFact, WorkItem("https://github.com/dotnet/razor/issues/9077")] @@ -11178,6 +11396,7 @@ @using Microsoft.AspNetCore.Components.Web // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); + CompileToAssembly(generated); } [IntegrationTestFact, WorkItem("https://github.com/dotnet/razor/issues/9077")] @@ -11193,6 +11412,7 @@ @using Microsoft.AspNetCore.Components.Web // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); + CompileToAssembly(generated); } [IntegrationTestFact, WorkItem("https://github.com/dotnet/razor/issues/9077")] @@ -11208,6 +11428,7 @@ @using Microsoft.AspNetCore.Components.Web // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); + CompileToAssembly(generated); } [IntegrationTestFact, WorkItem("https://github.com/dotnet/razor/issues/9077")] diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/AddComponentParameter_DynamicComponentName/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/AddComponentParameter_DynamicComponentName/TestComponent.codegen.cs new file mode 100644 index 00000000000..02ce2dd5757 --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/AddComponentParameter_DynamicComponentName/TestComponent.codegen.cs @@ -0,0 +1,53 @@ +// +#pragma warning disable 1591 +namespace Test +{ + #line default + using global::System; + using global::System.Collections.Generic; + using global::System.Linq; + using global::System.Threading.Tasks; + using global::Microsoft.AspNetCore.Components; + #line default + #line hidden + #nullable restore + public partial class TestComponent : global::Microsoft.AspNetCore.Components.ComponentBase + #nullable disable + { + #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) + { + __o = ""; + __builder.AddAttribute(-1, "ChildContent", (global::Microsoft.AspNetCore.Components.RenderFragment)((__builder2) => { + } + )); + #pragma warning disable BL0005 + ((global::Test.dynamic)default). +#nullable restore +#line 1 "x:\dir\subdir\Test\TestComponent.cshtml" + Value + +#line default +#line hidden +#nullable disable + = default; + #pragma warning restore BL0005 +#nullable restore +#line 1 "x:\dir\subdir\Test\TestComponent.cshtml" +__o = typeof(global::Test.dynamic); + +#line default +#line hidden +#nullable disable + } + #pragma warning restore 1998 + } +} +#pragma warning restore 1591 diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/AddComponentParameter_DynamicComponentName/TestComponent.ir.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/AddComponentParameter_DynamicComponentName/TestComponent.ir.txt new file mode 100644 index 00000000000..60b1f3c07a7 --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/AddComponentParameter_DynamicComponentName/TestComponent.ir.txt @@ -0,0 +1,20 @@ +Document - + NamespaceDeclaration - - Test + UsingDirective - (3:1,1 [20] ) - global::System + UsingDirective - (26:2,1 [40] ) - global::System.Collections.Generic + UsingDirective - (69:3,1 [25] ) - global::System.Linq + UsingDirective - (97:4,1 [36] ) - global::System.Threading.Tasks + UsingDirective - (136:5,1 [45] ) - global::Microsoft.AspNetCore.Components + ClassDeclaration - - public partial - TestComponent - global::Microsoft.AspNetCore.Components.ComponentBase - + DesignTimeDirective - + CSharpCode - + IntermediateToken - - CSharp - #pragma warning disable 0414 + CSharpCode - + IntermediateToken - - CSharp - private static object __o = null; + CSharpCode - + IntermediateToken - - CSharp - #pragma warning restore 0414 + MethodDeclaration - - protected override - void - BuildRenderTree + Component - (0:0,0 [25] x:\dir\subdir\Test\TestComponent.cshtml) - dynamic + ComponentAttribute - (16:0,16 [5] x:\dir\subdir\Test\TestComponent.cshtml) - Value - Value - AttributeStructure.DoubleQuotes + HtmlContent - (16:0,16 [5] x:\dir\subdir\Test\TestComponent.cshtml) + LazyIntermediateToken - (16:0,16 [5] x:\dir\subdir\Test\TestComponent.cshtml) - Html - Hello diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/AddComponentParameter_DynamicComponentName/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/AddComponentParameter_DynamicComponentName/TestComponent.mappings.txt new file mode 100644 index 00000000000..cbc7aa2c47c --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/AddComponentParameter_DynamicComponentName/TestComponent.mappings.txt @@ -0,0 +1,5 @@ +Source Location: (9:0,9 [5] x:\dir\subdir\Test\TestComponent.cshtml) +|Value| +Generated Location: (1270:34,9 [5] ) +|Value| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/AddComponentParameter_EscapedComponentName/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/AddComponentParameter_EscapedComponentName/TestComponent.codegen.cs new file mode 100644 index 00000000000..aee2f59ec3f --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/AddComponentParameter_EscapedComponentName/TestComponent.codegen.cs @@ -0,0 +1,53 @@ +// +#pragma warning disable 1591 +namespace Test +{ + #line default + using global::System; + using global::System.Collections.Generic; + using global::System.Linq; + using global::System.Threading.Tasks; + using global::Microsoft.AspNetCore.Components; + #line default + #line hidden + #nullable restore + public partial class TestComponent : global::Microsoft.AspNetCore.Components.ComponentBase + #nullable disable + { + #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) + { + __o = ""; + __builder.AddAttribute(-1, "ChildContent", (global::Microsoft.AspNetCore.Components.RenderFragment)((__builder2) => { + } + )); + #pragma warning disable BL0005 + ((global::Test.@int)default). +#nullable restore +#line 1 "x:\dir\subdir\Test\TestComponent.cshtml" + Value + +#line default +#line hidden +#nullable disable + = default; + #pragma warning restore BL0005 +#nullable restore +#line 1 "x:\dir\subdir\Test\TestComponent.cshtml" +__o = typeof(global::Test.@int); + +#line default +#line hidden +#nullable disable + } + #pragma warning restore 1998 + } +} +#pragma warning restore 1591 diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/AddComponentParameter_EscapedComponentName/TestComponent.ir.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/AddComponentParameter_EscapedComponentName/TestComponent.ir.txt new file mode 100644 index 00000000000..bb161f0c34d --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/AddComponentParameter_EscapedComponentName/TestComponent.ir.txt @@ -0,0 +1,20 @@ +Document - + NamespaceDeclaration - - Test + UsingDirective - (3:1,1 [20] ) - global::System + UsingDirective - (26:2,1 [40] ) - global::System.Collections.Generic + UsingDirective - (69:3,1 [25] ) - global::System.Linq + UsingDirective - (97:4,1 [36] ) - global::System.Threading.Tasks + UsingDirective - (136:5,1 [45] ) - global::Microsoft.AspNetCore.Components + ClassDeclaration - - public partial - TestComponent - global::Microsoft.AspNetCore.Components.ComponentBase - + DesignTimeDirective - + CSharpCode - + IntermediateToken - - CSharp - #pragma warning disable 0414 + CSharpCode - + IntermediateToken - - CSharp - private static object __o = null; + CSharpCode - + IntermediateToken - - CSharp - #pragma warning restore 0414 + MethodDeclaration - - protected override - void - BuildRenderTree + Component - (0:0,0 [21] x:\dir\subdir\Test\TestComponent.cshtml) - int + ComponentAttribute - (12:0,12 [5] x:\dir\subdir\Test\TestComponent.cshtml) - Value - Value - AttributeStructure.DoubleQuotes + HtmlContent - (12:0,12 [5] x:\dir\subdir\Test\TestComponent.cshtml) + LazyIntermediateToken - (12:0,12 [5] x:\dir\subdir\Test\TestComponent.cshtml) - Html - Hello diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/AddComponentParameter_EscapedComponentName/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/AddComponentParameter_EscapedComponentName/TestComponent.mappings.txt new file mode 100644 index 00000000000..b4be9151384 --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/AddComponentParameter_EscapedComponentName/TestComponent.mappings.txt @@ -0,0 +1,5 @@ +Source Location: (5:0,5 [5] x:\dir\subdir\Test\TestComponent.cshtml) +|Value| +Generated Location: (1263:34,5 [5] ) +|Value| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/AddComponentParameter_GlobalNamespace/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/AddComponentParameter_GlobalNamespace/TestComponent.codegen.cs new file mode 100644 index 00000000000..56737446afc --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/AddComponentParameter_GlobalNamespace/TestComponent.codegen.cs @@ -0,0 +1,53 @@ +// +#pragma warning disable 1591 +namespace Test +{ + #line default + using global::System; + using global::System.Collections.Generic; + using global::System.Linq; + using global::System.Threading.Tasks; + using global::Microsoft.AspNetCore.Components; + #line default + #line hidden + #nullable restore + public partial class TestComponent : global::Microsoft.AspNetCore.Components.ComponentBase + #nullable disable + { + #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) + { + __o = ""; + __builder.AddAttribute(-1, "ChildContent", (global::Microsoft.AspNetCore.Components.RenderFragment)((__builder2) => { + } + )); + #pragma warning disable BL0005 + ((global::MyComponent)default). +#nullable restore +#line 1 "x:\dir\subdir\Test\TestComponent.cshtml" + Value + +#line default +#line hidden +#nullable disable + = default; + #pragma warning restore BL0005 +#nullable restore +#line 1 "x:\dir\subdir\Test\TestComponent.cshtml" +__o = typeof(global::MyComponent); + +#line default +#line hidden +#nullable disable + } + #pragma warning restore 1998 + } +} +#pragma warning restore 1591 diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/AddComponentParameter_GlobalNamespace/TestComponent.ir.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/AddComponentParameter_GlobalNamespace/TestComponent.ir.txt new file mode 100644 index 00000000000..a95300fdde0 --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/AddComponentParameter_GlobalNamespace/TestComponent.ir.txt @@ -0,0 +1,20 @@ +Document - + NamespaceDeclaration - - Test + UsingDirective - (3:1,1 [20] ) - global::System + UsingDirective - (26:2,1 [40] ) - global::System.Collections.Generic + UsingDirective - (69:3,1 [25] ) - global::System.Linq + UsingDirective - (97:4,1 [36] ) - global::System.Threading.Tasks + UsingDirective - (136:5,1 [45] ) - global::Microsoft.AspNetCore.Components + ClassDeclaration - - public partial - TestComponent - global::Microsoft.AspNetCore.Components.ComponentBase - + DesignTimeDirective - + CSharpCode - + IntermediateToken - - CSharp - #pragma warning disable 0414 + CSharpCode - + IntermediateToken - - CSharp - private static object __o = null; + CSharpCode - + IntermediateToken - - CSharp - #pragma warning restore 0414 + MethodDeclaration - - protected override - void - BuildRenderTree + Component - (0:0,0 [29] x:\dir\subdir\Test\TestComponent.cshtml) - MyComponent + ComponentAttribute - (20:0,20 [5] x:\dir\subdir\Test\TestComponent.cshtml) - Value - Value - AttributeStructure.DoubleQuotes + HtmlContent - (20:0,20 [5] x:\dir\subdir\Test\TestComponent.cshtml) + LazyIntermediateToken - (20:0,20 [5] x:\dir\subdir\Test\TestComponent.cshtml) - Html - Hello diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/AddComponentParameter_GlobalNamespace/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/AddComponentParameter_GlobalNamespace/TestComponent.mappings.txt new file mode 100644 index 00000000000..b0ae7fe7aeb --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/AddComponentParameter_GlobalNamespace/TestComponent.mappings.txt @@ -0,0 +1,5 @@ +Source Location: (13:0,13 [5] x:\dir\subdir\Test\TestComponent.cshtml) +|Value| +Generated Location: (1273:34,13 [5] ) +|Value| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/AddComponentParameter_WithNameof/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/AddComponentParameter_WithNameof/TestComponent.codegen.cs new file mode 100644 index 00000000000..efd1997cfb0 --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/AddComponentParameter_WithNameof/TestComponent.codegen.cs @@ -0,0 +1,61 @@ +// +#pragma warning disable 1591 +namespace Test +{ + #line default + using global::System; + using global::System.Collections.Generic; + using global::System.Linq; + using global::System.Threading.Tasks; + using global::Microsoft.AspNetCore.Components; + #line default + #line hidden + #nullable restore + public partial class TestComponent : global::Microsoft.AspNetCore.Components.ComponentBase + #nullable disable + { + #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) + { + __o = ""; + __builder.AddAttribute(-1, "ChildContent", (global::Microsoft.AspNetCore.Components.RenderFragment)((__builder2) => { + } + )); + #pragma warning disable BL0005 + ((global::Test.MyComponent)default). +#nullable restore +#line 1 "x:\dir\subdir\Test\TestComponent.cshtml" + Value + +#line default +#line hidden +#nullable disable + = default; + #pragma warning restore BL0005 +#nullable restore +#line 1 "x:\dir\subdir\Test\TestComponent.cshtml" +__o = typeof(global::Test.MyComponent); + +#line default +#line hidden +#nullable disable + } + #pragma warning restore 1998 +#nullable restore +#line 2 "x:\dir\subdir\Test\TestComponent.cshtml" + + public string nameof(string s) => string.Empty; + +#line default +#line hidden +#nullable disable + } +} +#pragma warning restore 1591 diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/AddComponentParameter_WithNameof/TestComponent.ir.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/AddComponentParameter_WithNameof/TestComponent.ir.txt new file mode 100644 index 00000000000..ebe44efdb7f --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/AddComponentParameter_WithNameof/TestComponent.ir.txt @@ -0,0 +1,24 @@ +Document - + NamespaceDeclaration - - Test + UsingDirective - (3:1,1 [20] ) - global::System + UsingDirective - (26:2,1 [40] ) - global::System.Collections.Generic + UsingDirective - (69:3,1 [25] ) - global::System.Linq + UsingDirective - (97:4,1 [36] ) - global::System.Threading.Tasks + UsingDirective - (136:5,1 [45] ) - global::Microsoft.AspNetCore.Components + ClassDeclaration - - public partial - TestComponent - global::Microsoft.AspNetCore.Components.ComponentBase - + DesignTimeDirective - + CSharpCode - + IntermediateToken - - CSharp - #pragma warning disable 0414 + CSharpCode - + IntermediateToken - - CSharp - private static object __o = null; + CSharpCode - + IntermediateToken - - CSharp - #pragma warning restore 0414 + MethodDeclaration - - protected override - void - BuildRenderTree + Component - (0:0,0 [29] x:\dir\subdir\Test\TestComponent.cshtml) - MyComponent + ComponentAttribute - (20:0,20 [5] x:\dir\subdir\Test\TestComponent.cshtml) - Value - Value - AttributeStructure.DoubleQuotes + HtmlContent - (20:0,20 [5] x:\dir\subdir\Test\TestComponent.cshtml) + LazyIntermediateToken - (20:0,20 [5] x:\dir\subdir\Test\TestComponent.cshtml) - Html - Hello + HtmlContent - (29:0,29 [2] x:\dir\subdir\Test\TestComponent.cshtml) + LazyIntermediateToken - (29:0,29 [2] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n + CSharpCode - (38:1,7 [55] x:\dir\subdir\Test\TestComponent.cshtml) + LazyIntermediateToken - (38:1,7 [55] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - \n public string nameof(string s) => string.Empty;\n diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/AddComponentParameter_WithNameof/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/AddComponentParameter_WithNameof/TestComponent.mappings.txt new file mode 100644 index 00000000000..45e16d127eb --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/AddComponentParameter_WithNameof/TestComponent.mappings.txt @@ -0,0 +1,14 @@ +Source Location: (13:0,13 [5] x:\dir\subdir\Test\TestComponent.cshtml) +|Value| +Generated Location: (1278:34,13 [5] ) +|Value| + +Source Location: (38:1,7 [55] x:\dir\subdir\Test\TestComponent.cshtml) +| + public string nameof(string s) => string.Empty; +| +Generated Location: (1691:52,7 [55] ) +| + public string nameof(string s) => string.Empty; +| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/BindToComponent_SpecifiesValue_WithMatchingProperties_DynamicComponentName/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/BindToComponent_SpecifiesValue_WithMatchingProperties_DynamicComponentName/TestComponent.codegen.cs new file mode 100644 index 00000000000..da7e74a7844 --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/BindToComponent_SpecifiesValue_WithMatchingProperties_DynamicComponentName/TestComponent.codegen.cs @@ -0,0 +1,71 @@ +// +#pragma warning disable 1591 +namespace Test +{ + #line default + using global::System; + using global::System.Collections.Generic; + using global::System.Linq; + using global::System.Threading.Tasks; + using global::Microsoft.AspNetCore.Components; + #line default + #line hidden + #nullable restore + public partial class TestComponent : global::Microsoft.AspNetCore.Components.ComponentBase + #nullable disable + { + #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) + { + __o = global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( +#nullable restore +#line 1 "x:\dir\subdir\Test\TestComponent.cshtml" + ParentValue + +#line default +#line hidden +#nullable disable + ); + __o = new global::System.Action( + __value => ParentValue = __value); + __builder.AddAttribute(-1, "ChildContent", (global::Microsoft.AspNetCore.Components.RenderFragment)((__builder2) => { + } + )); + #pragma warning disable BL0005 + ((global::Test.dynamic)default). +#nullable restore +#line 1 "x:\dir\subdir\Test\TestComponent.cshtml" + Value + +#line default +#line hidden +#nullable disable + = default; + #pragma warning restore BL0005 +#nullable restore +#line 1 "x:\dir\subdir\Test\TestComponent.cshtml" +__o = typeof(global::Test.dynamic); + +#line default +#line hidden +#nullable disable + } + #pragma warning restore 1998 +#nullable restore +#line 2 "x:\dir\subdir\Test\TestComponent.cshtml" + + public int ParentValue { get; set; } = 42; + +#line default +#line hidden +#nullable disable + } +} +#pragma warning restore 1591 diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/BindToComponent_SpecifiesValue_WithMatchingProperties_DynamicComponentName/TestComponent.ir.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/BindToComponent_SpecifiesValue_WithMatchingProperties_DynamicComponentName/TestComponent.ir.txt new file mode 100644 index 00000000000..cbe14e69938 --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/BindToComponent_SpecifiesValue_WithMatchingProperties_DynamicComponentName/TestComponent.ir.txt @@ -0,0 +1,27 @@ +Document - + NamespaceDeclaration - - Test + UsingDirective - (3:1,1 [20] ) - global::System + UsingDirective - (26:2,1 [40] ) - global::System.Collections.Generic + UsingDirective - (69:3,1 [25] ) - global::System.Linq + UsingDirective - (97:4,1 [36] ) - global::System.Threading.Tasks + UsingDirective - (136:5,1 [45] ) - global::Microsoft.AspNetCore.Components + ClassDeclaration - - public partial - TestComponent - global::Microsoft.AspNetCore.Components.ComponentBase - + DesignTimeDirective - + CSharpCode - + IntermediateToken - - CSharp - #pragma warning disable 0414 + CSharpCode - + IntermediateToken - - CSharp - private static object __o = null; + CSharpCode - + IntermediateToken - - CSharp - #pragma warning restore 0414 + MethodDeclaration - - protected override - void - BuildRenderTree + Component - (0:0,0 [37] x:\dir\subdir\Test\TestComponent.cshtml) - dynamic + ComponentAttribute - (22:0,22 [11] x:\dir\subdir\Test\TestComponent.cshtml) - Value - Value - AttributeStructure.DoubleQuotes + CSharpExpression - + LazyIntermediateToken - (22:0,22 [11] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - ParentValue + ComponentAttribute - (22:0,22 [11] x:\dir\subdir\Test\TestComponent.cshtml) - ValueChanged - ValueChanged - AttributeStructure.DoubleQuotes + CSharpExpression - + IntermediateToken - - CSharp - __value => ParentValue = __value + HtmlContent - (37:0,37 [2] x:\dir\subdir\Test\TestComponent.cshtml) + LazyIntermediateToken - (37:0,37 [2] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n + CSharpCode - (46:1,7 [50] x:\dir\subdir\Test\TestComponent.cshtml) + LazyIntermediateToken - (46:1,7 [50] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - \n public int ParentValue { get; set; } = 42;\n diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/BindToComponent_SpecifiesValue_WithMatchingProperties_DynamicComponentName/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/BindToComponent_SpecifiesValue_WithMatchingProperties_DynamicComponentName/TestComponent.mappings.txt new file mode 100644 index 00000000000..bebd4144eb5 --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/BindToComponent_SpecifiesValue_WithMatchingProperties_DynamicComponentName/TestComponent.mappings.txt @@ -0,0 +1,19 @@ +Source Location: (22:0,22 [11] x:\dir\subdir\Test\TestComponent.cshtml) +|ParentValue| +Generated Location: (1131:29,22 [11] ) +|ParentValue| + +Source Location: (15:0,15 [5] x:\dir\subdir\Test\TestComponent.cshtml) +|Value| +Generated Location: (1656:44,15 [5] ) +|Value| + +Source Location: (46:1,7 [50] x:\dir\subdir\Test\TestComponent.cshtml) +| + public int ParentValue { get; set; } = 42; +| +Generated Location: (2065:62,7 [50] ) +| + public int ParentValue { get; set; } = 42; +| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/BindToComponent_SpecifiesValue_WithMatchingProperties_EscapedComponentName/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/BindToComponent_SpecifiesValue_WithMatchingProperties_EscapedComponentName/TestComponent.codegen.cs new file mode 100644 index 00000000000..02317b1f280 --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/BindToComponent_SpecifiesValue_WithMatchingProperties_EscapedComponentName/TestComponent.codegen.cs @@ -0,0 +1,71 @@ +// +#pragma warning disable 1591 +namespace Test +{ + #line default + using global::System; + using global::System.Collections.Generic; + using global::System.Linq; + using global::System.Threading.Tasks; + using global::Microsoft.AspNetCore.Components; + #line default + #line hidden + #nullable restore + public partial class TestComponent : global::Microsoft.AspNetCore.Components.ComponentBase + #nullable disable + { + #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) + { + __o = global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( +#nullable restore +#line 1 "x:\dir\subdir\Test\TestComponent.cshtml" + ParentValue + +#line default +#line hidden +#nullable disable + ); + __o = new global::System.Action( + __value => ParentValue = __value); + __builder.AddAttribute(-1, "ChildContent", (global::Microsoft.AspNetCore.Components.RenderFragment)((__builder2) => { + } + )); + #pragma warning disable BL0005 + ((global::Test.@int)default). +#nullable restore +#line 1 "x:\dir\subdir\Test\TestComponent.cshtml" + Value + +#line default +#line hidden +#nullable disable + = default; + #pragma warning restore BL0005 +#nullable restore +#line 1 "x:\dir\subdir\Test\TestComponent.cshtml" +__o = typeof(global::Test.@int); + +#line default +#line hidden +#nullable disable + } + #pragma warning restore 1998 +#nullable restore +#line 2 "x:\dir\subdir\Test\TestComponent.cshtml" + + public int ParentValue { get; set; } = 42; + +#line default +#line hidden +#nullable disable + } +} +#pragma warning restore 1591 diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/BindToComponent_SpecifiesValue_WithMatchingProperties_EscapedComponentName/TestComponent.ir.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/BindToComponent_SpecifiesValue_WithMatchingProperties_EscapedComponentName/TestComponent.ir.txt new file mode 100644 index 00000000000..86f71e2c92e --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/BindToComponent_SpecifiesValue_WithMatchingProperties_EscapedComponentName/TestComponent.ir.txt @@ -0,0 +1,27 @@ +Document - + NamespaceDeclaration - - Test + UsingDirective - (3:1,1 [20] ) - global::System + UsingDirective - (26:2,1 [40] ) - global::System.Collections.Generic + UsingDirective - (69:3,1 [25] ) - global::System.Linq + UsingDirective - (97:4,1 [36] ) - global::System.Threading.Tasks + UsingDirective - (136:5,1 [45] ) - global::Microsoft.AspNetCore.Components + ClassDeclaration - - public partial - TestComponent - global::Microsoft.AspNetCore.Components.ComponentBase - + DesignTimeDirective - + CSharpCode - + IntermediateToken - - CSharp - #pragma warning disable 0414 + CSharpCode - + IntermediateToken - - CSharp - private static object __o = null; + CSharpCode - + IntermediateToken - - CSharp - #pragma warning restore 0414 + MethodDeclaration - - protected override - void - BuildRenderTree + Component - (0:0,0 [33] x:\dir\subdir\Test\TestComponent.cshtml) - int + ComponentAttribute - (18:0,18 [11] x:\dir\subdir\Test\TestComponent.cshtml) - Value - Value - AttributeStructure.DoubleQuotes + CSharpExpression - + LazyIntermediateToken - (18:0,18 [11] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - ParentValue + ComponentAttribute - (18:0,18 [11] x:\dir\subdir\Test\TestComponent.cshtml) - ValueChanged - ValueChanged - AttributeStructure.DoubleQuotes + CSharpExpression - + IntermediateToken - - CSharp - __value => ParentValue = __value + HtmlContent - (33:0,33 [2] x:\dir\subdir\Test\TestComponent.cshtml) + LazyIntermediateToken - (33:0,33 [2] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n + CSharpCode - (42:1,7 [50] x:\dir\subdir\Test\TestComponent.cshtml) + LazyIntermediateToken - (42:1,7 [50] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - \n public int ParentValue { get; set; } = 42;\n diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/BindToComponent_SpecifiesValue_WithMatchingProperties_EscapedComponentName/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/BindToComponent_SpecifiesValue_WithMatchingProperties_EscapedComponentName/TestComponent.mappings.txt new file mode 100644 index 00000000000..c0b3b29ac6b --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/BindToComponent_SpecifiesValue_WithMatchingProperties_EscapedComponentName/TestComponent.mappings.txt @@ -0,0 +1,19 @@ +Source Location: (18:0,18 [11] x:\dir\subdir\Test\TestComponent.cshtml) +|ParentValue| +Generated Location: (1127:29,18 [11] ) +|ParentValue| + +Source Location: (11:0,11 [5] x:\dir\subdir\Test\TestComponent.cshtml) +|Value| +Generated Location: (1645:44,11 [5] ) +|Value| + +Source Location: (42:1,7 [50] x:\dir\subdir\Test\TestComponent.cshtml) +| + public int ParentValue { get; set; } = 42; +| +Generated Location: (2051:62,7 [50] ) +| + public int ParentValue { get; set; } = 42; +| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/BindToComponent_SpecifiesValue_WithMatchingProperties_WithNameof/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/BindToComponent_SpecifiesValue_WithMatchingProperties_WithNameof/TestComponent.codegen.cs new file mode 100644 index 00000000000..2d38b170952 --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/BindToComponent_SpecifiesValue_WithMatchingProperties_WithNameof/TestComponent.codegen.cs @@ -0,0 +1,73 @@ +// +#pragma warning disable 1591 +namespace Test +{ + #line default + using global::System; + using global::System.Collections.Generic; + using global::System.Linq; + using global::System.Threading.Tasks; + using global::Microsoft.AspNetCore.Components; + #line default + #line hidden + #nullable restore + public partial class TestComponent : global::Microsoft.AspNetCore.Components.ComponentBase + #nullable disable + { + #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) + { + __o = global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( +#nullable restore +#line 1 "x:\dir\subdir\Test\TestComponent.cshtml" + ParentValue + +#line default +#line hidden +#nullable disable + ); + __o = new global::System.Action( + __value => ParentValue = __value); + __builder.AddAttribute(-1, "ChildContent", (global::Microsoft.AspNetCore.Components.RenderFragment)((__builder2) => { + } + )); + #pragma warning disable BL0005 + ((global::Test.MyComponent)default). +#nullable restore +#line 1 "x:\dir\subdir\Test\TestComponent.cshtml" + Value + +#line default +#line hidden +#nullable disable + = default; + #pragma warning restore BL0005 +#nullable restore +#line 1 "x:\dir\subdir\Test\TestComponent.cshtml" +__o = typeof(global::Test.MyComponent); + +#line default +#line hidden +#nullable disable + } + #pragma warning restore 1998 +#nullable restore +#line 2 "x:\dir\subdir\Test\TestComponent.cshtml" + + public int ParentValue { get; set; } = 42; + + public string nameof(string s) => string.Empty; + +#line default +#line hidden +#nullable disable + } +} +#pragma warning restore 1591 diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/BindToComponent_SpecifiesValue_WithMatchingProperties_WithNameof/TestComponent.ir.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/BindToComponent_SpecifiesValue_WithMatchingProperties_WithNameof/TestComponent.ir.txt new file mode 100644 index 00000000000..145083af87a --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/BindToComponent_SpecifiesValue_WithMatchingProperties_WithNameof/TestComponent.ir.txt @@ -0,0 +1,27 @@ +Document - + NamespaceDeclaration - - Test + UsingDirective - (3:1,1 [20] ) - global::System + UsingDirective - (26:2,1 [40] ) - global::System.Collections.Generic + UsingDirective - (69:3,1 [25] ) - global::System.Linq + UsingDirective - (97:4,1 [36] ) - global::System.Threading.Tasks + UsingDirective - (136:5,1 [45] ) - global::Microsoft.AspNetCore.Components + ClassDeclaration - - public partial - TestComponent - global::Microsoft.AspNetCore.Components.ComponentBase - + DesignTimeDirective - + CSharpCode - + IntermediateToken - - CSharp - #pragma warning disable 0414 + CSharpCode - + IntermediateToken - - CSharp - private static object __o = null; + CSharpCode - + IntermediateToken - - CSharp - #pragma warning restore 0414 + MethodDeclaration - - protected override - void - BuildRenderTree + Component - (0:0,0 [41] x:\dir\subdir\Test\TestComponent.cshtml) - MyComponent + ComponentAttribute - (26:0,26 [11] x:\dir\subdir\Test\TestComponent.cshtml) - Value - Value - AttributeStructure.DoubleQuotes + CSharpExpression - + LazyIntermediateToken - (26:0,26 [11] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - ParentValue + ComponentAttribute - (26:0,26 [11] x:\dir\subdir\Test\TestComponent.cshtml) - ValueChanged - ValueChanged - AttributeStructure.DoubleQuotes + CSharpExpression - + IntermediateToken - - CSharp - __value => ParentValue = __value + HtmlContent - (41:0,41 [2] x:\dir\subdir\Test\TestComponent.cshtml) + LazyIntermediateToken - (41:0,41 [2] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n + CSharpCode - (50:1,7 [105] x:\dir\subdir\Test\TestComponent.cshtml) + LazyIntermediateToken - (50:1,7 [105] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - \n public int ParentValue { get; set; } = 42;\n\n public string nameof(string s) => string.Empty;\n diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/BindToComponent_SpecifiesValue_WithMatchingProperties_WithNameof/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/BindToComponent_SpecifiesValue_WithMatchingProperties_WithNameof/TestComponent.mappings.txt new file mode 100644 index 00000000000..39e1027589c --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/BindToComponent_SpecifiesValue_WithMatchingProperties_WithNameof/TestComponent.mappings.txt @@ -0,0 +1,23 @@ +Source Location: (26:0,26 [11] x:\dir\subdir\Test\TestComponent.cshtml) +|ParentValue| +Generated Location: (1135:29,26 [11] ) +|ParentValue| + +Source Location: (19:0,19 [5] x:\dir\subdir\Test\TestComponent.cshtml) +|Value| +Generated Location: (1668:44,19 [5] ) +|Value| + +Source Location: (50:1,7 [105] x:\dir\subdir\Test\TestComponent.cshtml) +| + public int ParentValue { get; set; } = 42; + + public string nameof(string s) => string.Empty; +| +Generated Location: (2081:62,7 [105] ) +| + public int ParentValue { get; set; } = 42; + + public string nameof(string s) => string.Empty; +| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AddAttribute_ImplicitBooleanConversion/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AddAttribute_ImplicitBooleanConversion/TestComponent.codegen.cs index 1625ad96f01..243edfeb727 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AddAttribute_ImplicitBooleanConversion/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AddAttribute_ImplicitBooleanConversion/TestComponent.codegen.cs @@ -55,8 +55,24 @@ internal static class TypeInference public static void CreateMyComponent_0(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder, int seq, int __seq0, global::Test.MyClass __arg0, int __seq1, global::System.Boolean __arg1) { __builder.OpenComponent>(seq); - __builder.AddAttribute(__seq0, "MyParameter", (object)__arg0); - __builder.AddAttribute(__seq1, "BoolParameter", (object)__arg1); + __builder.AddAttribute(__seq0, nameof(global::Test.MyComponent. +#nullable restore +#line (1,14)-(1,25) "x:\dir\subdir\Test\TestComponent.cshtml" +MyParameter + +#line default +#line hidden +#nullable disable + ), (object)__arg0); + __builder.AddAttribute(__seq1, nameof(global::Test.MyComponent. +#nullable restore +#line (1,30)-(1,43) "x:\dir\subdir\Test\TestComponent.cshtml" +BoolParameter + +#line default +#line hidden +#nullable disable + ), (object)__arg1); __builder.CloseComponent(); } } diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AddAttribute_ImplicitBooleanConversion/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AddAttribute_ImplicitBooleanConversion/TestComponent.mappings.txt index 6d5c6c03f7a..fc326d08245 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AddAttribute_ImplicitBooleanConversion/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AddAttribute_ImplicitBooleanConversion/TestComponent.mappings.txt @@ -17,3 +17,13 @@ Generated Location: (1189:40,0 [42] ) private MyClass c = new(); | +Source Location: (13:0,13 [11] x:\dir\subdir\Test\TestComponent.cshtml) +|MyParameter| +Generated Location: (1864:60,0 [11] ) +|MyParameter| + +Source Location: (29:0,29 [13] x:\dir\subdir\Test\TestComponent.cshtml) +|BoolParameter| +Generated Location: (2114:69,0 [13] ) +|BoolParameter| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AddAttribute_ImplicitStringConversion_Bind/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AddAttribute_ImplicitStringConversion_Bind/TestComponent.codegen.cs index 7ffa3cda5e2..afb7c37a782 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AddAttribute_ImplicitStringConversion_Bind/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AddAttribute_ImplicitStringConversion_Bind/TestComponent.codegen.cs @@ -71,12 +71,52 @@ internal static class TypeInference public static void CreateMyComponent_0(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder, int seq, int __seq0, global::System.Boolean __arg0, int __seq1, global::System.String __arg1, int __seq2, global::System.Delegate __arg2, int __seq3, global::System.Object __arg3, int __seq4, global::Test.MyClass __arg4, int __seq5, global::Microsoft.AspNetCore.Components.EventCallback> __arg5) { __builder.OpenComponent>(seq); - __builder.AddAttribute(__seq0, "BoolParameter", (object)__arg0); - __builder.AddAttribute(__seq1, "StringParameter", (object)__arg1); - __builder.AddAttribute(__seq2, "DelegateParameter", (object)__arg2); - __builder.AddAttribute(__seq3, "ObjectParameter", (object)__arg3); - __builder.AddAttribute(__seq4, "MyParameter", (object)__arg4); - __builder.AddAttribute(__seq5, "MyParameterChanged", (object)__arg5); + __builder.AddAttribute(__seq0, nameof(global::Test.MyComponent. +#nullable restore +#line (2,5)-(2,18) "x:\dir\subdir\Test\TestComponent.cshtml" +BoolParameter + +#line default +#line hidden +#nullable disable + ), (object)__arg0); + __builder.AddAttribute(__seq1, nameof(global::Test.MyComponent. +#nullable restore +#line (3,5)-(3,20) "x:\dir\subdir\Test\TestComponent.cshtml" +StringParameter + +#line default +#line hidden +#nullable disable + ), (object)__arg1); + __builder.AddAttribute(__seq2, nameof(global::Test.MyComponent. +#nullable restore +#line (4,5)-(4,22) "x:\dir\subdir\Test\TestComponent.cshtml" +DelegateParameter + +#line default +#line hidden +#nullable disable + ), (object)__arg2); + __builder.AddAttribute(__seq3, nameof(global::Test.MyComponent. +#nullable restore +#line (5,5)-(5,20) "x:\dir\subdir\Test\TestComponent.cshtml" +ObjectParameter + +#line default +#line hidden +#nullable disable + ), (object)__arg3); + __builder.AddAttribute(__seq4, nameof(global::Test.MyComponent. +#nullable restore +#line (1,20)-(1,31) "x:\dir\subdir\Test\TestComponent.cshtml" +MyParameter + +#line default +#line hidden +#nullable disable + ), (object)__arg4); + __builder.AddAttribute(__seq5, nameof(global::Test.MyComponent.MyParameterChanged), (object)__arg5); __builder.CloseComponent(); } } diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AddAttribute_ImplicitStringConversion_Bind/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AddAttribute_ImplicitStringConversion_Bind/TestComponent.mappings.txt index e4c8710b765..b2cf70f9ed8 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AddAttribute_ImplicitStringConversion_Bind/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AddAttribute_ImplicitStringConversion_Bind/TestComponent.mappings.txt @@ -27,3 +27,28 @@ Generated Location: (1731:56,0 [42] ) private MyClass c = new(); | +Source Location: (40:1,4 [13] x:\dir\subdir\Test\TestComponent.cshtml) +|BoolParameter| +Generated Location: (2632:76,0 [13] ) +|BoolParameter| + +Source Location: (66:2,4 [15] x:\dir\subdir\Test\TestComponent.cshtml) +|StringParameter| +Generated Location: (2883:85,0 [15] ) +|StringParameter| + +Source Location: (93:3,4 [17] x:\dir\subdir\Test\TestComponent.cshtml) +|DelegateParameter| +Generated Location: (3136:94,0 [17] ) +|DelegateParameter| + +Source Location: (128:4,4 [15] x:\dir\subdir\Test\TestComponent.cshtml) +|ObjectParameter| +Generated Location: (3391:103,0 [15] ) +|ObjectParameter| + +Source Location: (19:0,19 [11] x:\dir\subdir\Test\TestComponent.cshtml) +|MyParameter| +Generated Location: (3645:112,0 [11] ) +|MyParameter| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AddAttribute_ImplicitStringConversion_CustomEvent/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AddAttribute_ImplicitStringConversion_CustomEvent/TestComponent.codegen.cs index 7f530015628..f1e507ec56a 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AddAttribute_ImplicitStringConversion_CustomEvent/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AddAttribute_ImplicitStringConversion_CustomEvent/TestComponent.codegen.cs @@ -79,12 +79,60 @@ internal static class TypeInference public static void CreateMyComponent_0(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder, int seq, int __seq0, global::Test.MyClass __arg0, int __seq1, global::Microsoft.AspNetCore.Components.EventCallback __arg1, int __seq2, global::System.Boolean __arg2, int __seq3, global::System.String __arg3, int __seq4, global::System.Delegate __arg4, int __seq5, global::System.Object __arg5) { __builder.OpenComponent>(seq); - __builder.AddAttribute(__seq0, "MyParameter", (object)__arg0); - __builder.AddAttribute(__seq1, "MyEvent", (object)__arg1); - __builder.AddAttribute(__seq2, "BoolParameter", (object)__arg2); - __builder.AddAttribute(__seq3, "StringParameter", (object)__arg3); - __builder.AddAttribute(__seq4, "DelegateParameter", (object)__arg4); - __builder.AddAttribute(__seq5, "ObjectParameter", (object)__arg5); + __builder.AddAttribute(__seq0, nameof(global::Test.MyComponent. +#nullable restore +#line (1,14)-(1,25) "x:\dir\subdir\Test\TestComponent.cshtml" +MyParameter + +#line default +#line hidden +#nullable disable + ), (object)__arg0); + __builder.AddAttribute(__seq1, nameof(global::Test.MyComponent. +#nullable restore +#line (2,5)-(2,12) "x:\dir\subdir\Test\TestComponent.cshtml" +MyEvent + +#line default +#line hidden +#nullable disable + ), (object)__arg1); + __builder.AddAttribute(__seq2, nameof(global::Test.MyComponent. +#nullable restore +#line (3,5)-(3,18) "x:\dir\subdir\Test\TestComponent.cshtml" +BoolParameter + +#line default +#line hidden +#nullable disable + ), (object)__arg2); + __builder.AddAttribute(__seq3, nameof(global::Test.MyComponent. +#nullable restore +#line (4,5)-(4,20) "x:\dir\subdir\Test\TestComponent.cshtml" +StringParameter + +#line default +#line hidden +#nullable disable + ), (object)__arg3); + __builder.AddAttribute(__seq4, nameof(global::Test.MyComponent. +#nullable restore +#line (5,5)-(5,22) "x:\dir\subdir\Test\TestComponent.cshtml" +DelegateParameter + +#line default +#line hidden +#nullable disable + ), (object)__arg4); + __builder.AddAttribute(__seq5, nameof(global::Test.MyComponent. +#nullable restore +#line (6,5)-(6,20) "x:\dir\subdir\Test\TestComponent.cshtml" +ObjectParameter + +#line default +#line hidden +#nullable disable + ), (object)__arg5); __builder.CloseComponent(); } } diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AddAttribute_ImplicitStringConversion_CustomEvent/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AddAttribute_ImplicitStringConversion_CustomEvent/TestComponent.mappings.txt index 5be8f216d12..8c97113d5e1 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AddAttribute_ImplicitStringConversion_CustomEvent/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AddAttribute_ImplicitStringConversion_CustomEvent/TestComponent.mappings.txt @@ -32,3 +32,33 @@ Generated Location: (1757:64,0 [42] ) private MyClass c = new(); | +Source Location: (13:0,13 [11] x:\dir\subdir\Test\TestComponent.cshtml) +|MyParameter| +Generated Location: (2634:84,0 [11] ) +|MyParameter| + +Source Location: (34:1,4 [7] x:\dir\subdir\Test\TestComponent.cshtml) +|MyEvent| +Generated Location: (2883:93,0 [7] ) +|MyEvent| + +Source Location: (59:2,4 [13] x:\dir\subdir\Test\TestComponent.cshtml) +|BoolParameter| +Generated Location: (3128:102,0 [13] ) +|BoolParameter| + +Source Location: (85:3,4 [15] x:\dir\subdir\Test\TestComponent.cshtml) +|StringParameter| +Generated Location: (3379:111,0 [15] ) +|StringParameter| + +Source Location: (112:4,4 [17] x:\dir\subdir\Test\TestComponent.cshtml) +|DelegateParameter| +Generated Location: (3632:120,0 [17] ) +|DelegateParameter| + +Source Location: (147:5,4 [15] x:\dir\subdir\Test\TestComponent.cshtml) +|ObjectParameter| +Generated Location: (3887:129,0 [15] ) +|ObjectParameter| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AddAttribute_ImplicitStringConversion_TypeInference/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AddAttribute_ImplicitStringConversion_TypeInference/TestComponent.codegen.cs index 8a5289cead7..ed7f51f3b98 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AddAttribute_ImplicitStringConversion_TypeInference/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AddAttribute_ImplicitStringConversion_TypeInference/TestComponent.codegen.cs @@ -71,11 +71,51 @@ internal static class TypeInference public static void CreateMyComponent_0(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder, int seq, int __seq0, global::Test.MyClass __arg0, int __seq1, global::System.Boolean __arg1, int __seq2, global::System.String __arg2, int __seq3, global::System.Delegate __arg3, int __seq4, global::System.Object __arg4) { __builder.OpenComponent>(seq); - __builder.AddAttribute(__seq0, "MyParameter", (object)__arg0); - __builder.AddAttribute(__seq1, "BoolParameter", (object)__arg1); - __builder.AddAttribute(__seq2, "StringParameter", (object)__arg2); - __builder.AddAttribute(__seq3, "DelegateParameter", (object)__arg3); - __builder.AddAttribute(__seq4, "ObjectParameter", (object)__arg4); + __builder.AddAttribute(__seq0, nameof(global::Test.MyComponent. +#nullable restore +#line (1,14)-(1,25) "x:\dir\subdir\Test\TestComponent.cshtml" +MyParameter + +#line default +#line hidden +#nullable disable + ), (object)__arg0); + __builder.AddAttribute(__seq1, nameof(global::Test.MyComponent. +#nullable restore +#line (2,5)-(2,18) "x:\dir\subdir\Test\TestComponent.cshtml" +BoolParameter + +#line default +#line hidden +#nullable disable + ), (object)__arg1); + __builder.AddAttribute(__seq2, nameof(global::Test.MyComponent. +#nullable restore +#line (3,5)-(3,20) "x:\dir\subdir\Test\TestComponent.cshtml" +StringParameter + +#line default +#line hidden +#nullable disable + ), (object)__arg2); + __builder.AddAttribute(__seq3, nameof(global::Test.MyComponent. +#nullable restore +#line (4,5)-(4,22) "x:\dir\subdir\Test\TestComponent.cshtml" +DelegateParameter + +#line default +#line hidden +#nullable disable + ), (object)__arg3); + __builder.AddAttribute(__seq4, nameof(global::Test.MyComponent. +#nullable restore +#line (5,5)-(5,20) "x:\dir\subdir\Test\TestComponent.cshtml" +ObjectParameter + +#line default +#line hidden +#nullable disable + ), (object)__arg4); __builder.CloseComponent(); } } diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AddAttribute_ImplicitStringConversion_TypeInference/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AddAttribute_ImplicitStringConversion_TypeInference/TestComponent.mappings.txt index f79751dcce9..f3d9ba6e18b 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AddAttribute_ImplicitStringConversion_TypeInference/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AddAttribute_ImplicitStringConversion_TypeInference/TestComponent.mappings.txt @@ -27,3 +27,28 @@ Generated Location: (1518:56,0 [51] ) private readonly MyClass c = new(); | +Source Location: (13:0,13 [11] x:\dir\subdir\Test\TestComponent.cshtml) +|MyParameter| +Generated Location: (2330:76,0 [11] ) +|MyParameter| + +Source Location: (34:1,4 [13] x:\dir\subdir\Test\TestComponent.cshtml) +|BoolParameter| +Generated Location: (2579:85,0 [13] ) +|BoolParameter| + +Source Location: (60:2,4 [15] x:\dir\subdir\Test\TestComponent.cshtml) +|StringParameter| +Generated Location: (2830:94,0 [15] ) +|StringParameter| + +Source Location: (87:3,4 [17] x:\dir\subdir\Test\TestComponent.cshtml) +|DelegateParameter| +Generated Location: (3083:103,0 [17] ) +|DelegateParameter| + +Source Location: (122:4,4 [15] x:\dir\subdir\Test\TestComponent.cshtml) +|ObjectParameter| +Generated Location: (3338:112,0 [15] ) +|ObjectParameter| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AddComponentParameter_DynamicComponentName/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AddComponentParameter_DynamicComponentName/TestComponent.codegen.cs new file mode 100644 index 00000000000..6e511a0601b --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AddComponentParameter_DynamicComponentName/TestComponent.codegen.cs @@ -0,0 +1,35 @@ +// +#pragma warning disable 1591 +namespace Test +{ + #line default + using global::System; + using global::System.Collections.Generic; + using global::System.Linq; + using global::System.Threading.Tasks; + using global::Microsoft.AspNetCore.Components; + #line default + #line hidden + #nullable restore + public partial class TestComponent : global::Microsoft.AspNetCore.Components.ComponentBase + #nullable disable + { + #pragma warning disable 1998 + protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) + { + __builder.OpenComponent(0); + __builder.AddComponentParameter(1, nameof(global::Test.dynamic. +#nullable restore +#line (1,10)-(1,15) "x:\dir\subdir\Test\TestComponent.cshtml" +Value + +#line default +#line hidden +#nullable disable + ), "Hello"); + __builder.CloseComponent(); + } + #pragma warning restore 1998 + } +} +#pragma warning restore 1591 diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AddComponentParameter_DynamicComponentName/TestComponent.ir.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AddComponentParameter_DynamicComponentName/TestComponent.ir.txt new file mode 100644 index 00000000000..719f326d9a1 --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AddComponentParameter_DynamicComponentName/TestComponent.ir.txt @@ -0,0 +1,13 @@ +Document - + NamespaceDeclaration - - Test + UsingDirective - (3:1,1 [22] ) - global::System + UsingDirective - (26:2,1 [42] ) - global::System.Collections.Generic + UsingDirective - (69:3,1 [27] ) - global::System.Linq + UsingDirective - (97:4,1 [38] ) - global::System.Threading.Tasks + UsingDirective - (136:5,1 [47] ) - global::Microsoft.AspNetCore.Components + ClassDeclaration - - public partial - TestComponent - global::Microsoft.AspNetCore.Components.ComponentBase - + MethodDeclaration - - protected override - void - BuildRenderTree + Component - (0:0,0 [25] x:\dir\subdir\Test\TestComponent.cshtml) - dynamic + ComponentAttribute - (16:0,16 [5] x:\dir\subdir\Test\TestComponent.cshtml) - Value - Value - AttributeStructure.DoubleQuotes + HtmlContent - (16:0,16 [5] x:\dir\subdir\Test\TestComponent.cshtml) + LazyIntermediateToken - (16:0,16 [5] x:\dir\subdir\Test\TestComponent.cshtml) - Html - Hello diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AddComponentParameter_DynamicComponentName/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AddComponentParameter_DynamicComponentName/TestComponent.mappings.txt new file mode 100644 index 00000000000..c376d5fa3d5 --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AddComponentParameter_DynamicComponentName/TestComponent.mappings.txt @@ -0,0 +1,5 @@ +Source Location: (9:0,9 [5] x:\dir\subdir\Test\TestComponent.cshtml) +|Value| +Generated Location: (876:23,0 [5] ) +|Value| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AddComponentParameter_EscapedComponentName/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AddComponentParameter_EscapedComponentName/TestComponent.codegen.cs new file mode 100644 index 00000000000..32792a48ac9 --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AddComponentParameter_EscapedComponentName/TestComponent.codegen.cs @@ -0,0 +1,35 @@ +// +#pragma warning disable 1591 +namespace Test +{ + #line default + using global::System; + using global::System.Collections.Generic; + using global::System.Linq; + using global::System.Threading.Tasks; + using global::Microsoft.AspNetCore.Components; + #line default + #line hidden + #nullable restore + public partial class TestComponent : global::Microsoft.AspNetCore.Components.ComponentBase + #nullable disable + { + #pragma warning disable 1998 + protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) + { + __builder.OpenComponent(0); + __builder.AddComponentParameter(1, nameof(global::Test.@int. +#nullable restore +#line (1,6)-(1,11) "x:\dir\subdir\Test\TestComponent.cshtml" +Value + +#line default +#line hidden +#nullable disable + ), "Hello"); + __builder.CloseComponent(); + } + #pragma warning restore 1998 + } +} +#pragma warning restore 1591 diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AddComponentParameter_EscapedComponentName/TestComponent.ir.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AddComponentParameter_EscapedComponentName/TestComponent.ir.txt new file mode 100644 index 00000000000..296377e97da --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AddComponentParameter_EscapedComponentName/TestComponent.ir.txt @@ -0,0 +1,13 @@ +Document - + NamespaceDeclaration - - Test + UsingDirective - (3:1,1 [22] ) - global::System + UsingDirective - (26:2,1 [42] ) - global::System.Collections.Generic + UsingDirective - (69:3,1 [27] ) - global::System.Linq + UsingDirective - (97:4,1 [38] ) - global::System.Threading.Tasks + UsingDirective - (136:5,1 [47] ) - global::Microsoft.AspNetCore.Components + ClassDeclaration - - public partial - TestComponent - global::Microsoft.AspNetCore.Components.ComponentBase - + MethodDeclaration - - protected override - void - BuildRenderTree + Component - (0:0,0 [21] x:\dir\subdir\Test\TestComponent.cshtml) - int + ComponentAttribute - (12:0,12 [5] x:\dir\subdir\Test\TestComponent.cshtml) - Value - Value - AttributeStructure.DoubleQuotes + HtmlContent - (12:0,12 [5] x:\dir\subdir\Test\TestComponent.cshtml) + LazyIntermediateToken - (12:0,12 [5] x:\dir\subdir\Test\TestComponent.cshtml) - Html - Hello diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AddComponentParameter_EscapedComponentName/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AddComponentParameter_EscapedComponentName/TestComponent.mappings.txt new file mode 100644 index 00000000000..fc636663a76 --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AddComponentParameter_EscapedComponentName/TestComponent.mappings.txt @@ -0,0 +1,5 @@ +Source Location: (5:0,5 [5] x:\dir\subdir\Test\TestComponent.cshtml) +|Value| +Generated Location: (869:23,0 [5] ) +|Value| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AddComponentParameter_GlobalNamespace/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AddComponentParameter_GlobalNamespace/TestComponent.codegen.cs new file mode 100644 index 00000000000..3eec6001c86 --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AddComponentParameter_GlobalNamespace/TestComponent.codegen.cs @@ -0,0 +1,35 @@ +// +#pragma warning disable 1591 +namespace Test +{ + #line default + using global::System; + using global::System.Collections.Generic; + using global::System.Linq; + using global::System.Threading.Tasks; + using global::Microsoft.AspNetCore.Components; + #line default + #line hidden + #nullable restore + public partial class TestComponent : global::Microsoft.AspNetCore.Components.ComponentBase + #nullable disable + { + #pragma warning disable 1998 + protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) + { + __builder.OpenComponent(0); + __builder.AddComponentParameter(1, nameof(global::MyComponent. +#nullable restore +#line (1,14)-(1,19) "x:\dir\subdir\Test\TestComponent.cshtml" +Value + +#line default +#line hidden +#nullable disable + ), "Hello"); + __builder.CloseComponent(); + } + #pragma warning restore 1998 + } +} +#pragma warning restore 1591 diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AddComponentParameter_GlobalNamespace/TestComponent.ir.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AddComponentParameter_GlobalNamespace/TestComponent.ir.txt new file mode 100644 index 00000000000..ff610dabd93 --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AddComponentParameter_GlobalNamespace/TestComponent.ir.txt @@ -0,0 +1,13 @@ +Document - + NamespaceDeclaration - - Test + UsingDirective - (3:1,1 [22] ) - global::System + UsingDirective - (26:2,1 [42] ) - global::System.Collections.Generic + UsingDirective - (69:3,1 [27] ) - global::System.Linq + UsingDirective - (97:4,1 [38] ) - global::System.Threading.Tasks + UsingDirective - (136:5,1 [47] ) - global::Microsoft.AspNetCore.Components + ClassDeclaration - - public partial - TestComponent - global::Microsoft.AspNetCore.Components.ComponentBase - + MethodDeclaration - - protected override - void - BuildRenderTree + Component - (0:0,0 [29] x:\dir\subdir\Test\TestComponent.cshtml) - MyComponent + ComponentAttribute - (20:0,20 [5] x:\dir\subdir\Test\TestComponent.cshtml) - Value - Value - AttributeStructure.DoubleQuotes + HtmlContent - (20:0,20 [5] x:\dir\subdir\Test\TestComponent.cshtml) + LazyIntermediateToken - (20:0,20 [5] x:\dir\subdir\Test\TestComponent.cshtml) - Html - Hello diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AddComponentParameter_GlobalNamespace/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AddComponentParameter_GlobalNamespace/TestComponent.mappings.txt new file mode 100644 index 00000000000..64f9a0c51f9 --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AddComponentParameter_GlobalNamespace/TestComponent.mappings.txt @@ -0,0 +1,5 @@ +Source Location: (13:0,13 [5] x:\dir\subdir\Test\TestComponent.cshtml) +|Value| +Generated Location: (874:23,0 [5] ) +|Value| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AddComponentParameter_WithNameof/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AddComponentParameter_WithNameof/TestComponent.codegen.cs new file mode 100644 index 00000000000..ddc5424c599 --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AddComponentParameter_WithNameof/TestComponent.codegen.cs @@ -0,0 +1,44 @@ +// +#pragma warning disable 1591 +namespace Test +{ + #line default + using global::System; + using global::System.Collections.Generic; + using global::System.Linq; + using global::System.Threading.Tasks; + using global::Microsoft.AspNetCore.Components; + #line default + #line hidden + #nullable restore + public partial class TestComponent : global::Microsoft.AspNetCore.Components.ComponentBase + #nullable disable + { + #pragma warning disable 1998 + protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) + { + __builder.OpenComponent(0); + __builder.AddComponentParameter(1, nameof(global::Test.MyComponent. +#nullable restore +#line (1,14)-(1,19) "x:\dir\subdir\Test\TestComponent.cshtml" +Value + +#line default +#line hidden +#nullable disable + ), "Hello"); + __builder.CloseComponent(); + } + #pragma warning restore 1998 +#nullable restore +#line (2,8)-(4,1) "x:\dir\subdir\Test\TestComponent.cshtml" + + public string nameof(string s) => string.Empty; + +#line default +#line hidden +#nullable disable + + } +} +#pragma warning restore 1591 diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AddComponentParameter_WithNameof/TestComponent.ir.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AddComponentParameter_WithNameof/TestComponent.ir.txt new file mode 100644 index 00000000000..34f78e4f708 --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AddComponentParameter_WithNameof/TestComponent.ir.txt @@ -0,0 +1,15 @@ +Document - + NamespaceDeclaration - - Test + UsingDirective - (3:1,1 [22] ) - global::System + UsingDirective - (26:2,1 [42] ) - global::System.Collections.Generic + UsingDirective - (69:3,1 [27] ) - global::System.Linq + UsingDirective - (97:4,1 [38] ) - global::System.Threading.Tasks + UsingDirective - (136:5,1 [47] ) - global::Microsoft.AspNetCore.Components + ClassDeclaration - - public partial - TestComponent - global::Microsoft.AspNetCore.Components.ComponentBase - + MethodDeclaration - - protected override - void - BuildRenderTree + Component - (0:0,0 [29] x:\dir\subdir\Test\TestComponent.cshtml) - MyComponent + ComponentAttribute - (20:0,20 [5] x:\dir\subdir\Test\TestComponent.cshtml) - Value - Value - AttributeStructure.DoubleQuotes + HtmlContent - (20:0,20 [5] x:\dir\subdir\Test\TestComponent.cshtml) + LazyIntermediateToken - (20:0,20 [5] x:\dir\subdir\Test\TestComponent.cshtml) - Html - Hello + CSharpCode - (38:1,7 [55] x:\dir\subdir\Test\TestComponent.cshtml) + LazyIntermediateToken - (38:1,7 [55] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - \n public string nameof(string s) => string.Empty;\n diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AddComponentParameter_WithNameof/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AddComponentParameter_WithNameof/TestComponent.mappings.txt new file mode 100644 index 00000000000..0e6b43d7c3a --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/AddComponentParameter_WithNameof/TestComponent.mappings.txt @@ -0,0 +1,14 @@ +Source Location: (13:0,13 [5] x:\dir\subdir\Test\TestComponent.cshtml) +|Value| +Generated Location: (884:23,0 [5] ) +|Value| + +Source Location: (38:1,7 [55] x:\dir\subdir\Test\TestComponent.cshtml) +| + public string nameof(string s) => string.Empty; +| +Generated Location: (1137:34,0 [55] ) +| + public string nameof(string s) => string.Empty; +| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_EventCallback_SpecifiesValueAndExpression/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_EventCallback_SpecifiesValueAndExpression/TestComponent.codegen.cs index f4942789e77..abd3ceb0635 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_EventCallback_SpecifiesValueAndExpression/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_EventCallback_SpecifiesValueAndExpression/TestComponent.codegen.cs @@ -18,7 +18,15 @@ public partial class TestComponent : global::Microsoft.AspNetCore.Components.Com protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { __builder.OpenComponent(0); - __builder.AddComponentParameter(1, "Value", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( + __builder.AddComponentParameter(1, nameof(global::Test.MyComponent. +#nullable restore +#line (1,20)-(1,25) "x:\dir\subdir\Test\TestComponent.cshtml" +Value + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( #nullable restore #line (1,27)-(1,38) "x:\dir\subdir\Test\TestComponent.cshtml" ParentValue @@ -27,8 +35,8 @@ protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components. #line hidden #nullable disable )); - __builder.AddComponentParameter(2, "ValueChanged", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck>(global::Microsoft.AspNetCore.Components.EventCallback.Factory.Create(this, global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.CreateInferredEventCallback(this, __value => ParentValue = __value, ParentValue)))); - __builder.AddComponentParameter(3, "ValueExpression", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck>>(() => ParentValue)); + __builder.AddComponentParameter(2, nameof(global::Test.MyComponent.ValueChanged), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck>(global::Microsoft.AspNetCore.Components.EventCallback.Factory.Create(this, global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.CreateInferredEventCallback(this, __value => ParentValue = __value, ParentValue)))); + __builder.AddComponentParameter(3, nameof(global::Test.MyComponent.ValueExpression), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck>>(() => ParentValue)); __builder.CloseComponent(); } #pragma warning restore 1998 diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_EventCallback_SpecifiesValueAndExpression/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_EventCallback_SpecifiesValueAndExpression/TestComponent.mappings.txt index 7264da26a45..6a68a34f37a 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_EventCallback_SpecifiesValueAndExpression/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_EventCallback_SpecifiesValueAndExpression/TestComponent.mappings.txt @@ -1,13 +1,18 @@ -Source Location: (26:0,26 [11] x:\dir\subdir\Test\TestComponent.cshtml) +Source Location: (19:0,19 [5] x:\dir\subdir\Test\TestComponent.cshtml) +|Value| +Generated Location: (884:23,0 [5] ) +|Value| + +Source Location: (26:0,26 [11] x:\dir\subdir\Test\TestComponent.cshtml) |ParentValue| -Generated Location: (965:23,0 [11] ) +Generated Location: (1144:31,0 [11] ) |ParentValue| Source Location: (50:1,7 [50] x:\dir\subdir\Test\TestComponent.cshtml) | public int ParentValue { get; set; } = 42; | -Generated Location: (1933:36,0 [50] ) +Generated Location: (2174:44,0 [50] ) | public int ParentValue { get; set; } = 42; | diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_EventCallback_SpecifiesValueAndExpression_Generic/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_EventCallback_SpecifiesValueAndExpression_Generic/TestComponent.codegen.cs index d47703890d8..c90d7acc6f0 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_EventCallback_SpecifiesValueAndExpression_Generic/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_EventCallback_SpecifiesValueAndExpression_Generic/TestComponent.codegen.cs @@ -47,9 +47,17 @@ internal static class TypeInference public static void CreateMyComponent_0(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder, int seq, int __seq0, T __arg0, int __seq1, global::Microsoft.AspNetCore.Components.EventCallback __arg1, int __seq2, global::System.Linq.Expressions.Expression> __arg2) { __builder.OpenComponent>(seq); - __builder.AddComponentParameter(__seq0, "SomeParam", __arg0); - __builder.AddComponentParameter(__seq1, "SomeParamChanged", __arg1); - __builder.AddComponentParameter(__seq2, "SomeParamExpression", __arg2); + __builder.AddComponentParameter(__seq0, nameof(global::Test.MyComponent. +#nullable restore +#line (1,20)-(1,29) "x:\dir\subdir\Test\TestComponent.cshtml" +SomeParam + +#line default +#line hidden +#nullable disable + ), __arg0); + __builder.AddComponentParameter(__seq1, nameof(global::Test.MyComponent.SomeParamChanged), __arg1); + __builder.AddComponentParameter(__seq2, nameof(global::Test.MyComponent.SomeParamExpression), __arg2); __builder.CloseComponent(); } } diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_EventCallback_SpecifiesValueAndExpression_Generic/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_EventCallback_SpecifiesValueAndExpression_Generic/TestComponent.mappings.txt index 6bd03c4ef4f..ac9f7fad38c 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_EventCallback_SpecifiesValueAndExpression_Generic/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_EventCallback_SpecifiesValueAndExpression_Generic/TestComponent.mappings.txt @@ -12,3 +12,8 @@ Generated Location: (1300:32,0 [65] ) public DateTime ParentValue { get; set; } = DateTime.Now; | +Source Location: (19:0,19 [9] x:\dir\subdir\Test\TestComponent.cshtml) +|SomeParam| +Generated Location: (2106:52,0 [9] ) +|SomeParam| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_EventCallback_SpecifiesValueAndExpression_NestedGeneric/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_EventCallback_SpecifiesValueAndExpression_NestedGeneric/TestComponent.codegen.cs index 5699df325a1..1d68a8a1316 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_EventCallback_SpecifiesValueAndExpression_NestedGeneric/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_EventCallback_SpecifiesValueAndExpression_NestedGeneric/TestComponent.codegen.cs @@ -47,9 +47,17 @@ internal static class TypeInference public static void CreateMyComponent_0(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder, int seq, int __seq0, global::System.Collections.Generic.IEnumerable __arg0, int __seq1, global::Microsoft.AspNetCore.Components.EventCallback> __arg1, int __seq2, global::System.Linq.Expressions.Expression>> __arg2) { __builder.OpenComponent>(seq); - __builder.AddComponentParameter(__seq0, "SomeParam", __arg0); - __builder.AddComponentParameter(__seq1, "SomeParamChanged", __arg1); - __builder.AddComponentParameter(__seq2, "SomeParamExpression", __arg2); + __builder.AddComponentParameter(__seq0, nameof(global::Test.MyComponent. +#nullable restore +#line (1,20)-(1,29) "x:\dir\subdir\Test\TestComponent.cshtml" +SomeParam + +#line default +#line hidden +#nullable disable + ), __arg0); + __builder.AddComponentParameter(__seq1, nameof(global::Test.MyComponent.SomeParamChanged), __arg1); + __builder.AddComponentParameter(__seq2, nameof(global::Test.MyComponent.SomeParamExpression), __arg2); __builder.CloseComponent(); } } diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_EventCallback_SpecifiesValueAndExpression_NestedGeneric/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_EventCallback_SpecifiesValueAndExpression_NestedGeneric/TestComponent.mappings.txt index 37857d147d7..98be953f456 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_EventCallback_SpecifiesValueAndExpression_NestedGeneric/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_EventCallback_SpecifiesValueAndExpression_NestedGeneric/TestComponent.mappings.txt @@ -12,3 +12,8 @@ Generated Location: (1300:32,0 [89] ) public IEnumerable ParentValue { get; set; } = new [] { DateTime.Now }; | +Source Location: (19:0,19 [9] x:\dir\subdir\Test\TestComponent.cshtml) +|SomeParam| +Generated Location: (2274:52,0 [9] ) +|SomeParam| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_EventCallback_SpecifiesValue_WithMatchingProperties/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_EventCallback_SpecifiesValue_WithMatchingProperties/TestComponent.codegen.cs index b533eb2ab01..d241bc5e721 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_EventCallback_SpecifiesValue_WithMatchingProperties/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_EventCallback_SpecifiesValue_WithMatchingProperties/TestComponent.codegen.cs @@ -18,7 +18,15 @@ public partial class TestComponent : global::Microsoft.AspNetCore.Components.Com protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { __builder.OpenComponent(0); - __builder.AddComponentParameter(1, "Value", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( + __builder.AddComponentParameter(1, nameof(global::Test.MyComponent. +#nullable restore +#line (1,20)-(1,25) "x:\dir\subdir\Test\TestComponent.cshtml" +Value + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( #nullable restore #line (1,27)-(1,38) "x:\dir\subdir\Test\TestComponent.cshtml" ParentValue @@ -27,7 +35,7 @@ protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components. #line hidden #nullable disable )); - __builder.AddComponentParameter(2, "ValueChanged", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck>(global::Microsoft.AspNetCore.Components.EventCallback.Factory.Create(this, global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.CreateInferredEventCallback(this, __value => ParentValue = __value, ParentValue)))); + __builder.AddComponentParameter(2, nameof(global::Test.MyComponent.ValueChanged), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck>(global::Microsoft.AspNetCore.Components.EventCallback.Factory.Create(this, global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.CreateInferredEventCallback(this, __value => ParentValue = __value, ParentValue)))); __builder.CloseComponent(); } #pragma warning restore 1998 diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_EventCallback_SpecifiesValue_WithMatchingProperties/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_EventCallback_SpecifiesValue_WithMatchingProperties/TestComponent.mappings.txt index 57384d1e879..1fe81884eca 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_EventCallback_SpecifiesValue_WithMatchingProperties/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_EventCallback_SpecifiesValue_WithMatchingProperties/TestComponent.mappings.txt @@ -1,13 +1,18 @@ -Source Location: (26:0,26 [11] x:\dir\subdir\Test\TestComponent.cshtml) +Source Location: (19:0,19 [5] x:\dir\subdir\Test\TestComponent.cshtml) +|Value| +Generated Location: (884:23,0 [5] ) +|Value| + +Source Location: (26:0,26 [11] x:\dir\subdir\Test\TestComponent.cshtml) |ParentValue| -Generated Location: (965:23,0 [11] ) +Generated Location: (1144:31,0 [11] ) |ParentValue| Source Location: (50:1,7 [50] x:\dir\subdir\Test\TestComponent.cshtml) | public int ParentValue { get; set; } = 42; | -Generated Location: (1692:35,0 [50] ) +Generated Location: (1902:43,0 [50] ) | public int ParentValue { get; set; } = 42; | diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_EventCallback_TypeChecked_WithMatchingProperties/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_EventCallback_TypeChecked_WithMatchingProperties/TestComponent.codegen.cs index bff4fabbf56..3544a73b777 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_EventCallback_TypeChecked_WithMatchingProperties/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_EventCallback_TypeChecked_WithMatchingProperties/TestComponent.codegen.cs @@ -18,7 +18,15 @@ public partial class TestComponent : global::Microsoft.AspNetCore.Components.Com protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { __builder.OpenComponent(0); - __builder.AddComponentParameter(1, "Value", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( + __builder.AddComponentParameter(1, nameof(global::Test.MyComponent. +#nullable restore +#line (1,20)-(1,25) "x:\dir\subdir\Test\TestComponent.cshtml" +Value + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( #nullable restore #line (1,27)-(1,38) "x:\dir\subdir\Test\TestComponent.cshtml" ParentValue @@ -27,7 +35,7 @@ protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components. #line hidden #nullable disable )); - __builder.AddComponentParameter(2, "ValueChanged", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck>(global::Microsoft.AspNetCore.Components.EventCallback.Factory.Create(this, global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.CreateInferredEventCallback(this, __value => ParentValue = __value, ParentValue)))); + __builder.AddComponentParameter(2, nameof(global::Test.MyComponent.ValueChanged), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck>(global::Microsoft.AspNetCore.Components.EventCallback.Factory.Create(this, global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.CreateInferredEventCallback(this, __value => ParentValue = __value, ParentValue)))); __builder.CloseComponent(); } #pragma warning restore 1998 diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_EventCallback_TypeChecked_WithMatchingProperties/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_EventCallback_TypeChecked_WithMatchingProperties/TestComponent.mappings.txt index f5331101822..eb4a7854781 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_EventCallback_TypeChecked_WithMatchingProperties/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_EventCallback_TypeChecked_WithMatchingProperties/TestComponent.mappings.txt @@ -1,13 +1,18 @@ -Source Location: (26:0,26 [11] x:\dir\subdir\Test\TestComponent.cshtml) +Source Location: (19:0,19 [5] x:\dir\subdir\Test\TestComponent.cshtml) +|Value| +Generated Location: (884:23,0 [5] ) +|Value| + +Source Location: (26:0,26 [11] x:\dir\subdir\Test\TestComponent.cshtml) |ParentValue| -Generated Location: (965:23,0 [11] ) +Generated Location: (1144:31,0 [11] ) |ParentValue| Source Location: (50:1,7 [55] x:\dir\subdir\Test\TestComponent.cshtml) | public string ParentValue { get; set; } = "42"; | -Generated Location: (1692:35,0 [55] ) +Generated Location: (1902:43,0 [55] ) | public string ParentValue { get; set; } = "42"; | diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_SpecifiesValueAndChangeEvent_WithMatchingProperties/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_SpecifiesValueAndChangeEvent_WithMatchingProperties/TestComponent.codegen.cs index 46dc4dd69cb..6c85c6edbb8 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_SpecifiesValueAndChangeEvent_WithMatchingProperties/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_SpecifiesValueAndChangeEvent_WithMatchingProperties/TestComponent.codegen.cs @@ -18,7 +18,15 @@ public partial class TestComponent : global::Microsoft.AspNetCore.Components.Com protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { __builder.OpenComponent(0); - __builder.AddComponentParameter(1, "Value", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( + __builder.AddComponentParameter(1, nameof(global::Test.MyComponent. +#nullable restore +#line (1,20)-(1,25) "x:\dir\subdir\Test\TestComponent.cshtml" +Value + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( #nullable restore #line (1,27)-(1,38) "x:\dir\subdir\Test\TestComponent.cshtml" ParentValue @@ -27,7 +35,7 @@ protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components. #line hidden #nullable disable )); - __builder.AddComponentParameter(2, "OnChanged", (global::System.Action)(__value => ParentValue = __value)); + __builder.AddComponentParameter(2, nameof(global::Test.MyComponent.OnChanged), (global::System.Action)(__value => ParentValue = __value)); __builder.CloseComponent(); } #pragma warning restore 1998 diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_SpecifiesValueAndChangeEvent_WithMatchingProperties/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_SpecifiesValueAndChangeEvent_WithMatchingProperties/TestComponent.mappings.txt index bb8f679ea55..7f3dc1ced28 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_SpecifiesValueAndChangeEvent_WithMatchingProperties/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_SpecifiesValueAndChangeEvent_WithMatchingProperties/TestComponent.mappings.txt @@ -1,13 +1,18 @@ -Source Location: (26:0,26 [11] x:\dir\subdir\Test\TestComponent.cshtml) +Source Location: (19:0,19 [5] x:\dir\subdir\Test\TestComponent.cshtml) +|Value| +Generated Location: (884:23,0 [5] ) +|Value| + +Source Location: (26:0,26 [11] x:\dir\subdir\Test\TestComponent.cshtml) |ParentValue| -Generated Location: (965:23,0 [11] ) +Generated Location: (1144:31,0 [11] ) |ParentValue| Source Location: (80:1,7 [50] x:\dir\subdir\Test\TestComponent.cshtml) | public int ParentValue { get; set; } = 42; | -Generated Location: (1350:35,0 [50] ) +Generated Location: (1560:43,0 [50] ) | public int ParentValue { get; set; } = 42; | diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_SpecifiesValueAndExpression/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_SpecifiesValueAndExpression/TestComponent.codegen.cs index ca68500d75e..3167bd4ea2d 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_SpecifiesValueAndExpression/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_SpecifiesValueAndExpression/TestComponent.codegen.cs @@ -18,7 +18,15 @@ public partial class TestComponent : global::Microsoft.AspNetCore.Components.Com protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { __builder.OpenComponent(0); - __builder.AddComponentParameter(1, "Value", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( + __builder.AddComponentParameter(1, nameof(global::Test.MyComponent. +#nullable restore +#line (1,20)-(1,25) "x:\dir\subdir\Test\TestComponent.cshtml" +Value + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( #nullable restore #line (1,27)-(1,38) "x:\dir\subdir\Test\TestComponent.cshtml" ParentValue @@ -27,8 +35,8 @@ protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components. #line hidden #nullable disable )); - __builder.AddComponentParameter(2, "ValueChanged", (global::System.Action)(__value => ParentValue = __value)); - __builder.AddComponentParameter(3, "ValueExpression", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck>>(() => ParentValue)); + __builder.AddComponentParameter(2, nameof(global::Test.MyComponent.ValueChanged), (global::System.Action)(__value => ParentValue = __value)); + __builder.AddComponentParameter(3, nameof(global::Test.MyComponent.ValueExpression), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck>>(() => ParentValue)); __builder.CloseComponent(); } #pragma warning restore 1998 diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_SpecifiesValueAndExpression/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_SpecifiesValueAndExpression/TestComponent.mappings.txt index 7395ac15d31..01f8dac4026 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_SpecifiesValueAndExpression/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_SpecifiesValueAndExpression/TestComponent.mappings.txt @@ -1,13 +1,18 @@ -Source Location: (26:0,26 [11] x:\dir\subdir\Test\TestComponent.cshtml) +Source Location: (19:0,19 [5] x:\dir\subdir\Test\TestComponent.cshtml) +|Value| +Generated Location: (884:23,0 [5] ) +|Value| + +Source Location: (26:0,26 [11] x:\dir\subdir\Test\TestComponent.cshtml) |ParentValue| -Generated Location: (965:23,0 [11] ) +Generated Location: (1144:31,0 [11] ) |ParentValue| Source Location: (50:1,7 [50] x:\dir\subdir\Test\TestComponent.cshtml) | public int ParentValue { get; set; } = 42; | -Generated Location: (1594:36,0 [50] ) +Generated Location: (1835:44,0 [50] ) | public int ParentValue { get; set; } = 42; | diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_SpecifiesValueAndExpression_Generic/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_SpecifiesValueAndExpression_Generic/TestComponent.codegen.cs index bc076d97ea4..6c68f3115f8 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_SpecifiesValueAndExpression_Generic/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_SpecifiesValueAndExpression_Generic/TestComponent.codegen.cs @@ -47,9 +47,17 @@ internal static class TypeInference public static void CreateMyComponent_0(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder, int seq, int __seq0, T __arg0, int __seq1, global::System.Action __arg1, int __seq2, global::System.Linq.Expressions.Expression> __arg2) { __builder.OpenComponent>(seq); - __builder.AddComponentParameter(__seq0, "SomeParam", __arg0); - __builder.AddComponentParameter(__seq1, "SomeParamChanged", __arg1); - __builder.AddComponentParameter(__seq2, "SomeParamExpression", __arg2); + __builder.AddComponentParameter(__seq0, nameof(global::Test.MyComponent. +#nullable restore +#line (1,20)-(1,29) "x:\dir\subdir\Test\TestComponent.cshtml" +SomeParam + +#line default +#line hidden +#nullable disable + ), __arg0); + __builder.AddComponentParameter(__seq1, nameof(global::Test.MyComponent.SomeParamChanged), __arg1); + __builder.AddComponentParameter(__seq2, nameof(global::Test.MyComponent.SomeParamExpression), __arg2); __builder.CloseComponent(); } } diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_SpecifiesValueAndExpression_Generic/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_SpecifiesValueAndExpression_Generic/TestComponent.mappings.txt index dffa9cd4cdb..e2a1b1b1b27 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_SpecifiesValueAndExpression_Generic/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_SpecifiesValueAndExpression_Generic/TestComponent.mappings.txt @@ -12,3 +12,8 @@ Generated Location: (1104:32,0 [65] ) public DateTime ParentValue { get; set; } = DateTime.Now; | +Source Location: (19:0,19 [9] x:\dir\subdir\Test\TestComponent.cshtml) +|SomeParam| +Generated Location: (1878:52,0 [9] ) +|SomeParam| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_SpecifiesValue_WithMatchingProperties/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_SpecifiesValue_WithMatchingProperties/TestComponent.codegen.cs index 2786816bc69..e36578b746f 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_SpecifiesValue_WithMatchingProperties/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_SpecifiesValue_WithMatchingProperties/TestComponent.codegen.cs @@ -18,7 +18,15 @@ public partial class TestComponent : global::Microsoft.AspNetCore.Components.Com protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { __builder.OpenComponent(0); - __builder.AddComponentParameter(1, "Value", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( + __builder.AddComponentParameter(1, nameof(global::Test.MyComponent. +#nullable restore +#line (1,20)-(1,25) "x:\dir\subdir\Test\TestComponent.cshtml" +Value + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( #nullable restore #line (1,27)-(1,38) "x:\dir\subdir\Test\TestComponent.cshtml" ParentValue @@ -27,7 +35,7 @@ protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components. #line hidden #nullable disable )); - __builder.AddComponentParameter(2, "ValueChanged", (global::System.Action)(__value => ParentValue = __value)); + __builder.AddComponentParameter(2, nameof(global::Test.MyComponent.ValueChanged), (global::System.Action)(__value => ParentValue = __value)); __builder.CloseComponent(); } #pragma warning restore 1998 diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_SpecifiesValue_WithMatchingProperties/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_SpecifiesValue_WithMatchingProperties/TestComponent.mappings.txt index 53651bf267e..d192ffede1f 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_SpecifiesValue_WithMatchingProperties/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_SpecifiesValue_WithMatchingProperties/TestComponent.mappings.txt @@ -1,13 +1,18 @@ -Source Location: (26:0,26 [11] x:\dir\subdir\Test\TestComponent.cshtml) +Source Location: (19:0,19 [5] x:\dir\subdir\Test\TestComponent.cshtml) +|Value| +Generated Location: (884:23,0 [5] ) +|Value| + +Source Location: (26:0,26 [11] x:\dir\subdir\Test\TestComponent.cshtml) |ParentValue| -Generated Location: (965:23,0 [11] ) +Generated Location: (1144:31,0 [11] ) |ParentValue| Source Location: (50:1,7 [50] x:\dir\subdir\Test\TestComponent.cshtml) | public int ParentValue { get; set; } = 42; | -Generated Location: (1353:35,0 [50] ) +Generated Location: (1563:43,0 [50] ) | public int ParentValue { get; set; } = 42; | diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_SpecifiesValue_WithMatchingProperties_DynamicComponentName/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_SpecifiesValue_WithMatchingProperties_DynamicComponentName/TestComponent.codegen.cs new file mode 100644 index 00000000000..df3153b6eaf --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_SpecifiesValue_WithMatchingProperties_DynamicComponentName/TestComponent.codegen.cs @@ -0,0 +1,53 @@ +// +#pragma warning disable 1591 +namespace Test +{ + #line default + using global::System; + using global::System.Collections.Generic; + using global::System.Linq; + using global::System.Threading.Tasks; + using global::Microsoft.AspNetCore.Components; + #line default + #line hidden + #nullable restore + public partial class TestComponent : global::Microsoft.AspNetCore.Components.ComponentBase + #nullable disable + { + #pragma warning disable 1998 + protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) + { + __builder.OpenComponent(0); + __builder.AddComponentParameter(1, nameof(global::Test.dynamic. +#nullable restore +#line (1,16)-(1,21) "x:\dir\subdir\Test\TestComponent.cshtml" +Value + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( +#nullable restore +#line (1,23)-(1,34) "x:\dir\subdir\Test\TestComponent.cshtml" +ParentValue + +#line default +#line hidden +#nullable disable + )); + __builder.AddComponentParameter(2, nameof(global::Test.dynamic.ValueChanged), (global::System.Action)(__value => ParentValue = __value)); + __builder.CloseComponent(); + } + #pragma warning restore 1998 +#nullable restore +#line (2,8)-(4,1) "x:\dir\subdir\Test\TestComponent.cshtml" + + public int ParentValue { get; set; } = 42; + +#line default +#line hidden +#nullable disable + + } +} +#pragma warning restore 1591 diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_SpecifiesValue_WithMatchingProperties_DynamicComponentName/TestComponent.ir.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_SpecifiesValue_WithMatchingProperties_DynamicComponentName/TestComponent.ir.txt new file mode 100644 index 00000000000..1439dd67f21 --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_SpecifiesValue_WithMatchingProperties_DynamicComponentName/TestComponent.ir.txt @@ -0,0 +1,18 @@ +Document - + NamespaceDeclaration - - Test + UsingDirective - (3:1,1 [22] ) - global::System + UsingDirective - (26:2,1 [42] ) - global::System.Collections.Generic + UsingDirective - (69:3,1 [27] ) - global::System.Linq + UsingDirective - (97:4,1 [38] ) - global::System.Threading.Tasks + UsingDirective - (136:5,1 [47] ) - global::Microsoft.AspNetCore.Components + ClassDeclaration - - public partial - TestComponent - global::Microsoft.AspNetCore.Components.ComponentBase - + MethodDeclaration - - protected override - void - BuildRenderTree + Component - (0:0,0 [37] x:\dir\subdir\Test\TestComponent.cshtml) - dynamic + ComponentAttribute - (22:0,22 [11] x:\dir\subdir\Test\TestComponent.cshtml) - Value - Value - AttributeStructure.DoubleQuotes + CSharpExpression - + LazyIntermediateToken - (22:0,22 [11] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - ParentValue + ComponentAttribute - (22:0,22 [11] x:\dir\subdir\Test\TestComponent.cshtml) - ValueChanged - ValueChanged - AttributeStructure.DoubleQuotes + CSharpExpression - + IntermediateToken - - CSharp - __value => ParentValue = __value + CSharpCode - (46:1,7 [50] x:\dir\subdir\Test\TestComponent.cshtml) + LazyIntermediateToken - (46:1,7 [50] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - \n public int ParentValue { get; set; } = 42;\n diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_SpecifiesValue_WithMatchingProperties_DynamicComponentName/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_SpecifiesValue_WithMatchingProperties_DynamicComponentName/TestComponent.mappings.txt new file mode 100644 index 00000000000..dbef272501e --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_SpecifiesValue_WithMatchingProperties_DynamicComponentName/TestComponent.mappings.txt @@ -0,0 +1,19 @@ +Source Location: (15:0,15 [5] x:\dir\subdir\Test\TestComponent.cshtml) +|Value| +Generated Location: (876:23,0 [5] ) +|Value| + +Source Location: (22:0,22 [11] x:\dir\subdir\Test\TestComponent.cshtml) +|ParentValue| +Generated Location: (1136:31,0 [11] ) +|ParentValue| + +Source Location: (46:1,7 [50] x:\dir\subdir\Test\TestComponent.cshtml) +| + public int ParentValue { get; set; } = 42; +| +Generated Location: (1551:43,0 [50] ) +| + public int ParentValue { get; set; } = 42; +| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_SpecifiesValue_WithMatchingProperties_EscapedComponentName/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_SpecifiesValue_WithMatchingProperties_EscapedComponentName/TestComponent.codegen.cs new file mode 100644 index 00000000000..983865f9dd9 --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_SpecifiesValue_WithMatchingProperties_EscapedComponentName/TestComponent.codegen.cs @@ -0,0 +1,53 @@ +// +#pragma warning disable 1591 +namespace Test +{ + #line default + using global::System; + using global::System.Collections.Generic; + using global::System.Linq; + using global::System.Threading.Tasks; + using global::Microsoft.AspNetCore.Components; + #line default + #line hidden + #nullable restore + public partial class TestComponent : global::Microsoft.AspNetCore.Components.ComponentBase + #nullable disable + { + #pragma warning disable 1998 + protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) + { + __builder.OpenComponent(0); + __builder.AddComponentParameter(1, nameof(global::Test.@int. +#nullable restore +#line (1,12)-(1,17) "x:\dir\subdir\Test\TestComponent.cshtml" +Value + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( +#nullable restore +#line (1,19)-(1,30) "x:\dir\subdir\Test\TestComponent.cshtml" +ParentValue + +#line default +#line hidden +#nullable disable + )); + __builder.AddComponentParameter(2, nameof(global::Test.@int.ValueChanged), (global::System.Action)(__value => ParentValue = __value)); + __builder.CloseComponent(); + } + #pragma warning restore 1998 +#nullable restore +#line (2,8)-(4,1) "x:\dir\subdir\Test\TestComponent.cshtml" + + public int ParentValue { get; set; } = 42; + +#line default +#line hidden +#nullable disable + + } +} +#pragma warning restore 1591 diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_SpecifiesValue_WithMatchingProperties_EscapedComponentName/TestComponent.ir.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_SpecifiesValue_WithMatchingProperties_EscapedComponentName/TestComponent.ir.txt new file mode 100644 index 00000000000..851174b1718 --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_SpecifiesValue_WithMatchingProperties_EscapedComponentName/TestComponent.ir.txt @@ -0,0 +1,18 @@ +Document - + NamespaceDeclaration - - Test + UsingDirective - (3:1,1 [22] ) - global::System + UsingDirective - (26:2,1 [42] ) - global::System.Collections.Generic + UsingDirective - (69:3,1 [27] ) - global::System.Linq + UsingDirective - (97:4,1 [38] ) - global::System.Threading.Tasks + UsingDirective - (136:5,1 [47] ) - global::Microsoft.AspNetCore.Components + ClassDeclaration - - public partial - TestComponent - global::Microsoft.AspNetCore.Components.ComponentBase - + MethodDeclaration - - protected override - void - BuildRenderTree + Component - (0:0,0 [33] x:\dir\subdir\Test\TestComponent.cshtml) - int + ComponentAttribute - (18:0,18 [11] x:\dir\subdir\Test\TestComponent.cshtml) - Value - Value - AttributeStructure.DoubleQuotes + CSharpExpression - + LazyIntermediateToken - (18:0,18 [11] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - ParentValue + ComponentAttribute - (18:0,18 [11] x:\dir\subdir\Test\TestComponent.cshtml) - ValueChanged - ValueChanged - AttributeStructure.DoubleQuotes + CSharpExpression - + IntermediateToken - - CSharp - __value => ParentValue = __value + CSharpCode - (42:1,7 [50] x:\dir\subdir\Test\TestComponent.cshtml) + LazyIntermediateToken - (42:1,7 [50] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - \n public int ParentValue { get; set; } = 42;\n diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_SpecifiesValue_WithMatchingProperties_EscapedComponentName/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_SpecifiesValue_WithMatchingProperties_EscapedComponentName/TestComponent.mappings.txt new file mode 100644 index 00000000000..776acdd1ae4 --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_SpecifiesValue_WithMatchingProperties_EscapedComponentName/TestComponent.mappings.txt @@ -0,0 +1,19 @@ +Source Location: (11:0,11 [5] x:\dir\subdir\Test\TestComponent.cshtml) +|Value| +Generated Location: (870:23,0 [5] ) +|Value| + +Source Location: (18:0,18 [11] x:\dir\subdir\Test\TestComponent.cshtml) +|ParentValue| +Generated Location: (1130:31,0 [11] ) +|ParentValue| + +Source Location: (42:1,7 [50] x:\dir\subdir\Test\TestComponent.cshtml) +| + public int ParentValue { get; set; } = 42; +| +Generated Location: (1542:43,0 [50] ) +| + public int ParentValue { get; set; } = 42; +| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_SpecifiesValue_WithMatchingProperties_WithNameof/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_SpecifiesValue_WithMatchingProperties_WithNameof/TestComponent.codegen.cs new file mode 100644 index 00000000000..2748c8c3cfe --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_SpecifiesValue_WithMatchingProperties_WithNameof/TestComponent.codegen.cs @@ -0,0 +1,55 @@ +// +#pragma warning disable 1591 +namespace Test +{ + #line default + using global::System; + using global::System.Collections.Generic; + using global::System.Linq; + using global::System.Threading.Tasks; + using global::Microsoft.AspNetCore.Components; + #line default + #line hidden + #nullable restore + public partial class TestComponent : global::Microsoft.AspNetCore.Components.ComponentBase + #nullable disable + { + #pragma warning disable 1998 + protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) + { + __builder.OpenComponent(0); + __builder.AddComponentParameter(1, nameof(global::Test.MyComponent. +#nullable restore +#line (1,20)-(1,25) "x:\dir\subdir\Test\TestComponent.cshtml" +Value + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( +#nullable restore +#line (1,27)-(1,38) "x:\dir\subdir\Test\TestComponent.cshtml" +ParentValue + +#line default +#line hidden +#nullable disable + )); + __builder.AddComponentParameter(2, nameof(global::Test.MyComponent.ValueChanged), (global::System.Action)(__value => ParentValue = __value)); + __builder.CloseComponent(); + } + #pragma warning restore 1998 +#nullable restore +#line (2,8)-(6,1) "x:\dir\subdir\Test\TestComponent.cshtml" + + public int ParentValue { get; set; } = 42; + + public string nameof(string s) => string.Empty; + +#line default +#line hidden +#nullable disable + + } +} +#pragma warning restore 1591 diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_SpecifiesValue_WithMatchingProperties_WithNameof/TestComponent.ir.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_SpecifiesValue_WithMatchingProperties_WithNameof/TestComponent.ir.txt new file mode 100644 index 00000000000..8f477332011 --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_SpecifiesValue_WithMatchingProperties_WithNameof/TestComponent.ir.txt @@ -0,0 +1,18 @@ +Document - + NamespaceDeclaration - - Test + UsingDirective - (3:1,1 [22] ) - global::System + UsingDirective - (26:2,1 [42] ) - global::System.Collections.Generic + UsingDirective - (69:3,1 [27] ) - global::System.Linq + UsingDirective - (97:4,1 [38] ) - global::System.Threading.Tasks + UsingDirective - (136:5,1 [47] ) - global::Microsoft.AspNetCore.Components + ClassDeclaration - - public partial - TestComponent - global::Microsoft.AspNetCore.Components.ComponentBase - + MethodDeclaration - - protected override - void - BuildRenderTree + Component - (0:0,0 [41] x:\dir\subdir\Test\TestComponent.cshtml) - MyComponent + ComponentAttribute - (26:0,26 [11] x:\dir\subdir\Test\TestComponent.cshtml) - Value - Value - AttributeStructure.DoubleQuotes + CSharpExpression - + LazyIntermediateToken - (26:0,26 [11] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - ParentValue + ComponentAttribute - (26:0,26 [11] x:\dir\subdir\Test\TestComponent.cshtml) - ValueChanged - ValueChanged - AttributeStructure.DoubleQuotes + CSharpExpression - + IntermediateToken - - CSharp - __value => ParentValue = __value + CSharpCode - (50:1,7 [105] x:\dir\subdir\Test\TestComponent.cshtml) + LazyIntermediateToken - (50:1,7 [105] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - \n public int ParentValue { get; set; } = 42;\n\n public string nameof(string s) => string.Empty;\n diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_SpecifiesValue_WithMatchingProperties_WithNameof/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_SpecifiesValue_WithMatchingProperties_WithNameof/TestComponent.mappings.txt new file mode 100644 index 00000000000..022089c5023 --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_SpecifiesValue_WithMatchingProperties_WithNameof/TestComponent.mappings.txt @@ -0,0 +1,23 @@ +Source Location: (19:0,19 [5] x:\dir\subdir\Test\TestComponent.cshtml) +|Value| +Generated Location: (884:23,0 [5] ) +|Value| + +Source Location: (26:0,26 [11] x:\dir\subdir\Test\TestComponent.cshtml) +|ParentValue| +Generated Location: (1144:31,0 [11] ) +|ParentValue| + +Source Location: (50:1,7 [105] x:\dir\subdir\Test\TestComponent.cshtml) +| + public int ParentValue { get; set; } = 42; + + public string nameof(string s) => string.Empty; +| +Generated Location: (1563:43,0 [105] ) +| + public int ParentValue { get; set; } = 42; + + public string nameof(string s) => string.Empty; +| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_TypeChecked_WithMatchingProperties/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_TypeChecked_WithMatchingProperties/TestComponent.codegen.cs index f03ba6c9000..cade82dcb2c 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_TypeChecked_WithMatchingProperties/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_TypeChecked_WithMatchingProperties/TestComponent.codegen.cs @@ -18,7 +18,15 @@ public partial class TestComponent : global::Microsoft.AspNetCore.Components.Com protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { __builder.OpenComponent(0); - __builder.AddComponentParameter(1, "Value", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( + __builder.AddComponentParameter(1, nameof(global::Test.MyComponent. +#nullable restore +#line (1,20)-(1,25) "x:\dir\subdir\Test\TestComponent.cshtml" +Value + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( #nullable restore #line (1,27)-(1,38) "x:\dir\subdir\Test\TestComponent.cshtml" ParentValue @@ -27,7 +35,7 @@ protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components. #line hidden #nullable disable )); - __builder.AddComponentParameter(2, "ValueChanged", (global::System.Action)(__value => ParentValue = __value)); + __builder.AddComponentParameter(2, nameof(global::Test.MyComponent.ValueChanged), (global::System.Action)(__value => ParentValue = __value)); __builder.CloseComponent(); } #pragma warning restore 1998 diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_TypeChecked_WithMatchingProperties/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_TypeChecked_WithMatchingProperties/TestComponent.mappings.txt index 4d239eb1895..01a2b30ddea 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_TypeChecked_WithMatchingProperties/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_TypeChecked_WithMatchingProperties/TestComponent.mappings.txt @@ -1,13 +1,18 @@ -Source Location: (26:0,26 [11] x:\dir\subdir\Test\TestComponent.cshtml) +Source Location: (19:0,19 [5] x:\dir\subdir\Test\TestComponent.cshtml) +|Value| +Generated Location: (884:23,0 [5] ) +|Value| + +Source Location: (26:0,26 [11] x:\dir\subdir\Test\TestComponent.cshtml) |ParentValue| -Generated Location: (965:23,0 [11] ) +Generated Location: (1144:31,0 [11] ) |ParentValue| Source Location: (50:1,7 [55] x:\dir\subdir\Test\TestComponent.cshtml) | public string ParentValue { get; set; } = "42"; | -Generated Location: (1353:35,0 [55] ) +Generated Location: (1563:43,0 [55] ) | public string ParentValue { get; set; } = "42"; | diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithAfter_Action/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithAfter_Action/TestComponent.codegen.cs index ff41b2bf913..e7f7c74e2fe 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithAfter_Action/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithAfter_Action/TestComponent.codegen.cs @@ -18,7 +18,15 @@ public partial class TestComponent : global::Microsoft.AspNetCore.Components.Com protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { __builder.OpenComponent(0); - __builder.AddComponentParameter(1, "Value", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( + __builder.AddComponentParameter(1, nameof(global::Test.MyComponent. +#nullable restore +#line (1,20)-(1,25) "x:\dir\subdir\Test\TestComponent.cshtml" +Value + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( #nullable restore #line (1,31)-(1,42) "x:\dir\subdir\Test\TestComponent.cshtml" ParentValue @@ -27,7 +35,7 @@ protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components. #line hidden #nullable disable )); - __builder.AddComponentParameter(2, "ValueChanged", (global::System.Action)( __value => { ParentValue = __value; global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.InvokeSynchronousDelegate( + __builder.AddComponentParameter(2, nameof(global::Test.MyComponent.ValueChanged), (global::System.Action)( __value => { ParentValue = __value; global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.InvokeSynchronousDelegate( #nullable restore #line (1,63)-(1,69) "x:\dir\subdir\Test\TestComponent.cshtml" Update diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithAfter_Action/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithAfter_Action/TestComponent.mappings.txt index e674b1a6c04..52094507c13 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithAfter_Action/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithAfter_Action/TestComponent.mappings.txt @@ -1,11 +1,16 @@ -Source Location: (30:0,30 [11] x:\dir\subdir\Test\TestComponent.cshtml) +Source Location: (19:0,19 [5] x:\dir\subdir\Test\TestComponent.cshtml) +|Value| +Generated Location: (884:23,0 [5] ) +|Value| + +Source Location: (30:0,30 [11] x:\dir\subdir\Test\TestComponent.cshtml) |ParentValue| -Generated Location: (965:23,0 [11] ) +Generated Location: (1144:31,0 [11] ) |ParentValue| Source Location: (62:0,62 [6] x:\dir\subdir\Test\TestComponent.cshtml) |Update| -Generated Location: (1365:32,0 [6] ) +Generated Location: (1575:40,0 [6] ) |Update| Source Location: (81:1,7 [82] x:\dir\subdir\Test\TestComponent.cshtml) @@ -14,7 +19,7 @@ Source Location: (81:1,7 [82] x:\dir\subdir\Test\TestComponent.cshtml) public void Update() { } | -Generated Location: (1614:43,0 [82] ) +Generated Location: (1824:51,0 [82] ) | public int ParentValue { get; set; } = 42; diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithAfter_ActionLambda/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithAfter_ActionLambda/TestComponent.codegen.cs index e6a8e06950a..5f96b9aa07a 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithAfter_ActionLambda/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithAfter_ActionLambda/TestComponent.codegen.cs @@ -18,7 +18,15 @@ public partial class TestComponent : global::Microsoft.AspNetCore.Components.Com protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { __builder.OpenComponent(0); - __builder.AddComponentParameter(1, "Value", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( + __builder.AddComponentParameter(1, nameof(global::Test.MyComponent. +#nullable restore +#line (1,20)-(1,25) "x:\dir\subdir\Test\TestComponent.cshtml" +Value + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( #nullable restore #line (1,31)-(1,42) "x:\dir\subdir\Test\TestComponent.cshtml" ParentValue @@ -27,7 +35,7 @@ protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components. #line hidden #nullable disable )); - __builder.AddComponentParameter(2, "ValueChanged", (global::System.Action)( __value => { ParentValue = __value; global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.InvokeSynchronousDelegate( + __builder.AddComponentParameter(2, nameof(global::Test.MyComponent.ValueChanged), (global::System.Action)( __value => { ParentValue = __value; global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.InvokeSynchronousDelegate( #nullable restore #line (1,63)-(1,72) "x:\dir\subdir\Test\TestComponent.cshtml" () => { } diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithAfter_ActionLambda/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithAfter_ActionLambda/TestComponent.mappings.txt index 21bd402c806..7f2679c6167 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithAfter_ActionLambda/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithAfter_ActionLambda/TestComponent.mappings.txt @@ -1,18 +1,23 @@ -Source Location: (30:0,30 [11] x:\dir\subdir\Test\TestComponent.cshtml) +Source Location: (19:0,19 [5] x:\dir\subdir\Test\TestComponent.cshtml) +|Value| +Generated Location: (884:23,0 [5] ) +|Value| + +Source Location: (30:0,30 [11] x:\dir\subdir\Test\TestComponent.cshtml) |ParentValue| -Generated Location: (965:23,0 [11] ) +Generated Location: (1144:31,0 [11] ) |ParentValue| Source Location: (62:0,62 [9] x:\dir\subdir\Test\TestComponent.cshtml) |() => { }| -Generated Location: (1365:32,0 [9] ) +Generated Location: (1575:40,0 [9] ) |() => { }| Source Location: (84:1,7 [50] x:\dir\subdir\Test\TestComponent.cshtml) | public int ParentValue { get; set; } = 42; | -Generated Location: (1617:43,0 [50] ) +Generated Location: (1827:51,0 [50] ) | public int ParentValue { get; set; } = 42; | diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithAfter_AsyncLambdaProducesError/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithAfter_AsyncLambdaProducesError/TestComponent.codegen.cs index a5ee16df9a4..a673f7ff341 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithAfter_AsyncLambdaProducesError/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithAfter_AsyncLambdaProducesError/TestComponent.codegen.cs @@ -18,7 +18,15 @@ public partial class TestComponent : global::Microsoft.AspNetCore.Components.Com protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { __builder.OpenComponent(0); - __builder.AddComponentParameter(1, "Value", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( + __builder.AddComponentParameter(1, nameof(global::Test.MyComponent. +#nullable restore +#line (1,20)-(1,25) "x:\dir\subdir\Test\TestComponent.cshtml" +Value + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( #nullable restore #line (1,31)-(1,42) "x:\dir\subdir\Test\TestComponent.cshtml" ParentValue @@ -27,7 +35,7 @@ protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components. #line hidden #nullable disable )); - __builder.AddComponentParameter(2, "ValueChanged", (global::System.Action)( + __builder.AddComponentParameter(2, nameof(global::Test.MyComponent.ValueChanged), (global::System.Action)( #nullable restore #line (1,61)-(1,123) "x:\dir\subdir\Test\TestComponent.cshtml" (value => { ParentValue = value; return Task.CompletedTask; }) diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithAfter_AsyncLambdaProducesError/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithAfter_AsyncLambdaProducesError/TestComponent.mappings.txt index 9a43ac5634b..f8a444575ca 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithAfter_AsyncLambdaProducesError/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithAfter_AsyncLambdaProducesError/TestComponent.mappings.txt @@ -1,18 +1,23 @@ -Source Location: (30:0,30 [11] x:\dir\subdir\Test\TestComponent.cshtml) +Source Location: (19:0,19 [5] x:\dir\subdir\Test\TestComponent.cshtml) +|Value| +Generated Location: (884:23,0 [5] ) +|Value| + +Source Location: (30:0,30 [11] x:\dir\subdir\Test\TestComponent.cshtml) |ParentValue| -Generated Location: (965:23,0 [11] ) +Generated Location: (1144:31,0 [11] ) |ParentValue| Source Location: (60:0,60 [62] x:\dir\subdir\Test\TestComponent.cshtml) |(value => { ParentValue = value; return Task.CompletedTask; })| -Generated Location: (1231:32,0 [62] ) +Generated Location: (1441:40,0 [62] ) |(value => { ParentValue = value; return Task.CompletedTask; })| Source Location: (135:1,7 [50] x:\dir\subdir\Test\TestComponent.cshtml) | public int ParentValue { get; set; } = 42; | -Generated Location: (1532:43,0 [50] ) +Generated Location: (1742:51,0 [50] ) | public int ParentValue { get; set; } = 42; | diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithAfter_EventCallback/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithAfter_EventCallback/TestComponent.codegen.cs index 600210d1437..1c11101a1ab 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithAfter_EventCallback/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithAfter_EventCallback/TestComponent.codegen.cs @@ -18,7 +18,15 @@ public partial class TestComponent : global::Microsoft.AspNetCore.Components.Com protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { __builder.OpenComponent(0); - __builder.AddComponentParameter(1, "Value", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( + __builder.AddComponentParameter(1, nameof(global::Test.MyComponent. +#nullable restore +#line (1,20)-(1,25) "x:\dir\subdir\Test\TestComponent.cshtml" +Value + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( #nullable restore #line (1,31)-(1,42) "x:\dir\subdir\Test\TestComponent.cshtml" ParentValue @@ -27,7 +35,7 @@ protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components. #line hidden #nullable disable )); - __builder.AddComponentParameter(2, "ValueChanged", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck>(global::Microsoft.AspNetCore.Components.EventCallback.Factory.Create(this, global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.CreateInferredEventCallback(this, global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.CreateInferredBindSetter(callback: __value => { ParentValue = __value; return global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.InvokeAsynchronousDelegate(callback: + __builder.AddComponentParameter(2, nameof(global::Test.MyComponent.ValueChanged), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck>(global::Microsoft.AspNetCore.Components.EventCallback.Factory.Create(this, global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.CreateInferredEventCallback(this, global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.CreateInferredBindSetter(callback: __value => { ParentValue = __value; return global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.InvokeAsynchronousDelegate(callback: #nullable restore #line (1,63)-(1,74) "x:\dir\subdir\Test\TestComponent.cshtml" UpdateValue diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithAfter_EventCallback/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithAfter_EventCallback/TestComponent.mappings.txt index e8fdb1b6835..0ebff81e87b 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithAfter_EventCallback/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithAfter_EventCallback/TestComponent.mappings.txt @@ -1,11 +1,16 @@ -Source Location: (30:0,30 [11] x:\dir\subdir\Test\TestComponent.cshtml) +Source Location: (19:0,19 [5] x:\dir\subdir\Test\TestComponent.cshtml) +|Value| +Generated Location: (884:23,0 [5] ) +|Value| + +Source Location: (30:0,30 [11] x:\dir\subdir\Test\TestComponent.cshtml) |ParentValue| -Generated Location: (965:23,0 [11] ) +Generated Location: (1144:31,0 [11] ) |ParentValue| Source Location: (62:0,62 [11] x:\dir\subdir\Test\TestComponent.cshtml) |UpdateValue| -Generated Location: (1813:32,0 [11] ) +Generated Location: (2023:40,0 [11] ) |UpdateValue| Source Location: (86:1,7 [102] x:\dir\subdir\Test\TestComponent.cshtml) @@ -13,7 +18,7 @@ Source Location: (86:1,7 [102] x:\dir\subdir\Test\TestComponent.cshtml) public int ParentValue { get; set; } = 42; public EventCallback UpdateValue { get; set; } | -Generated Location: (2103:43,0 [102] ) +Generated Location: (2313:51,0 [102] ) | public int ParentValue { get; set; } = 42; public EventCallback UpdateValue { get; set; } diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithAfter_EventCallback_ReceivesAction/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithAfter_EventCallback_ReceivesAction/TestComponent.codegen.cs index 2482163d169..7aa10176bf4 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithAfter_EventCallback_ReceivesAction/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithAfter_EventCallback_ReceivesAction/TestComponent.codegen.cs @@ -18,7 +18,15 @@ public partial class TestComponent : global::Microsoft.AspNetCore.Components.Com protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { __builder.OpenComponent(0); - __builder.AddComponentParameter(1, "Value", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( + __builder.AddComponentParameter(1, nameof(global::Test.MyComponent. +#nullable restore +#line (1,20)-(1,25) "x:\dir\subdir\Test\TestComponent.cshtml" +Value + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( #nullable restore #line (1,31)-(1,42) "x:\dir\subdir\Test\TestComponent.cshtml" ParentValue @@ -27,7 +35,7 @@ protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components. #line hidden #nullable disable )); - __builder.AddComponentParameter(2, "ValueChanged", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck>(global::Microsoft.AspNetCore.Components.EventCallback.Factory.Create(this, global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.CreateInferredEventCallback(this, global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.CreateInferredBindSetter(callback: __value => { ParentValue = __value; return global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.InvokeAsynchronousDelegate(callback: + __builder.AddComponentParameter(2, nameof(global::Test.MyComponent.ValueChanged), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck>(global::Microsoft.AspNetCore.Components.EventCallback.Factory.Create(this, global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.CreateInferredEventCallback(this, global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.CreateInferredBindSetter(callback: __value => { ParentValue = __value; return global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.InvokeAsynchronousDelegate(callback: #nullable restore #line (1,63)-(1,72) "x:\dir\subdir\Test\TestComponent.cshtml" () => { } diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithAfter_EventCallback_ReceivesAction/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithAfter_EventCallback_ReceivesAction/TestComponent.mappings.txt index 821bdbb84cd..209c01f92d6 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithAfter_EventCallback_ReceivesAction/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithAfter_EventCallback_ReceivesAction/TestComponent.mappings.txt @@ -1,18 +1,23 @@ -Source Location: (30:0,30 [11] x:\dir\subdir\Test\TestComponent.cshtml) +Source Location: (19:0,19 [5] x:\dir\subdir\Test\TestComponent.cshtml) +|Value| +Generated Location: (884:23,0 [5] ) +|Value| + +Source Location: (30:0,30 [11] x:\dir\subdir\Test\TestComponent.cshtml) |ParentValue| -Generated Location: (965:23,0 [11] ) +Generated Location: (1144:31,0 [11] ) |ParentValue| Source Location: (62:0,62 [9] x:\dir\subdir\Test\TestComponent.cshtml) |() => { }| -Generated Location: (1813:32,0 [9] ) +Generated Location: (2023:40,0 [9] ) |() => { }| Source Location: (84:1,7 [50] x:\dir\subdir\Test\TestComponent.cshtml) | public int ParentValue { get; set; } = 42; | -Generated Location: (2101:43,0 [50] ) +Generated Location: (2311:51,0 [50] ) | public int ParentValue { get; set; } = 42; | diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithAfter_EventCallback_ReceivesFunction/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithAfter_EventCallback_ReceivesFunction/TestComponent.codegen.cs index 76c7ec87bb5..40880f13c2d 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithAfter_EventCallback_ReceivesFunction/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithAfter_EventCallback_ReceivesFunction/TestComponent.codegen.cs @@ -18,7 +18,15 @@ public partial class TestComponent : global::Microsoft.AspNetCore.Components.Com protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { __builder.OpenComponent(0); - __builder.AddComponentParameter(1, "Value", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( + __builder.AddComponentParameter(1, nameof(global::Test.MyComponent. +#nullable restore +#line (1,20)-(1,25) "x:\dir\subdir\Test\TestComponent.cshtml" +Value + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( #nullable restore #line (1,31)-(1,42) "x:\dir\subdir\Test\TestComponent.cshtml" ParentValue @@ -27,7 +35,7 @@ protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components. #line hidden #nullable disable )); - __builder.AddComponentParameter(2, "ValueChanged", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck>(global::Microsoft.AspNetCore.Components.EventCallback.Factory.Create(this, global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.CreateInferredEventCallback(this, global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.CreateInferredBindSetter(callback: __value => { ParentValue = __value; return global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.InvokeAsynchronousDelegate(callback: + __builder.AddComponentParameter(2, nameof(global::Test.MyComponent.ValueChanged), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck>(global::Microsoft.AspNetCore.Components.EventCallback.Factory.Create(this, global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.CreateInferredEventCallback(this, global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.CreateInferredBindSetter(callback: __value => { ParentValue = __value; return global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.InvokeAsynchronousDelegate(callback: #nullable restore #line (1,63)-(1,74) "x:\dir\subdir\Test\TestComponent.cshtml" UpdateValue diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithAfter_EventCallback_ReceivesFunction/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithAfter_EventCallback_ReceivesFunction/TestComponent.mappings.txt index 4627cfb292a..41bd0f9bb1e 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithAfter_EventCallback_ReceivesFunction/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithAfter_EventCallback_ReceivesFunction/TestComponent.mappings.txt @@ -1,11 +1,16 @@ -Source Location: (30:0,30 [11] x:\dir\subdir\Test\TestComponent.cshtml) +Source Location: (19:0,19 [5] x:\dir\subdir\Test\TestComponent.cshtml) +|Value| +Generated Location: (884:23,0 [5] ) +|Value| + +Source Location: (30:0,30 [11] x:\dir\subdir\Test\TestComponent.cshtml) |ParentValue| -Generated Location: (965:23,0 [11] ) +Generated Location: (1144:31,0 [11] ) |ParentValue| Source Location: (62:0,62 [11] x:\dir\subdir\Test\TestComponent.cshtml) |UpdateValue| -Generated Location: (1813:32,0 [11] ) +Generated Location: (2023:40,0 [11] ) |UpdateValue| Source Location: (86:1,7 [106] x:\dir\subdir\Test\TestComponent.cshtml) @@ -14,7 +19,7 @@ Source Location: (86:1,7 [106] x:\dir\subdir\Test\TestComponent.cshtml) public Task UpdateValue() => Task.CompletedTask; | -Generated Location: (2103:43,0 [106] ) +Generated Location: (2313:51,0 [106] ) | public int ParentValue { get; set; } = 42; diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithAfter_TaskReturningDelegate/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithAfter_TaskReturningDelegate/TestComponent.codegen.cs index f7ad2f045b1..f3e042efa30 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithAfter_TaskReturningDelegate/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithAfter_TaskReturningDelegate/TestComponent.codegen.cs @@ -18,7 +18,15 @@ public partial class TestComponent : global::Microsoft.AspNetCore.Components.Com protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { __builder.OpenComponent(0); - __builder.AddComponentParameter(1, "Value", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( + __builder.AddComponentParameter(1, nameof(global::Test.MyComponent. +#nullable restore +#line (1,20)-(1,25) "x:\dir\subdir\Test\TestComponent.cshtml" +Value + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( #nullable restore #line (1,31)-(1,42) "x:\dir\subdir\Test\TestComponent.cshtml" ParentValue @@ -27,7 +35,7 @@ protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components. #line hidden #nullable disable )); - __builder.AddComponentParameter(2, "ValueChanged", (global::System.Func)(async __value => { ParentValue = __value; await global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.InvokeAsynchronousDelegate( + __builder.AddComponentParameter(2, nameof(global::Test.MyComponent.ValueChanged), (global::System.Func)(async __value => { ParentValue = __value; await global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.InvokeAsynchronousDelegate( #nullable restore #line (1,63)-(1,69) "x:\dir\subdir\Test\TestComponent.cshtml" Update diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithAfter_TaskReturningDelegate/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithAfter_TaskReturningDelegate/TestComponent.mappings.txt index fbafac43ed7..196efd4fa84 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithAfter_TaskReturningDelegate/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithAfter_TaskReturningDelegate/TestComponent.mappings.txt @@ -1,11 +1,16 @@ -Source Location: (30:0,30 [11] x:\dir\subdir\Test\TestComponent.cshtml) +Source Location: (19:0,19 [5] x:\dir\subdir\Test\TestComponent.cshtml) +|Value| +Generated Location: (884:23,0 [5] ) +|Value| + +Source Location: (30:0,30 [11] x:\dir\subdir\Test\TestComponent.cshtml) |ParentValue| -Generated Location: (965:23,0 [11] ) +Generated Location: (1144:31,0 [11] ) |ParentValue| Source Location: (62:0,62 [6] x:\dir\subdir\Test\TestComponent.cshtml) |Update| -Generated Location: (1405:32,0 [6] ) +Generated Location: (1615:40,0 [6] ) |Update| Source Location: (81:1,7 [101] x:\dir\subdir\Test\TestComponent.cshtml) @@ -14,7 +19,7 @@ Source Location: (81:1,7 [101] x:\dir\subdir\Test\TestComponent.cshtml) public Task Update() => Task.CompletedTask; | -Generated Location: (1654:43,0 [101] ) +Generated Location: (1864:51,0 [101] ) | public int ParentValue { get; set; } = 42; diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithAfter_TaskReturningLambda/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithAfter_TaskReturningLambda/TestComponent.codegen.cs index ea3567329ff..49e65646f4e 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithAfter_TaskReturningLambda/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithAfter_TaskReturningLambda/TestComponent.codegen.cs @@ -18,7 +18,15 @@ public partial class TestComponent : global::Microsoft.AspNetCore.Components.Com protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { __builder.OpenComponent(0); - __builder.AddComponentParameter(1, "Value", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( + __builder.AddComponentParameter(1, nameof(global::Test.MyComponent. +#nullable restore +#line (1,20)-(1,25) "x:\dir\subdir\Test\TestComponent.cshtml" +Value + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( #nullable restore #line (1,31)-(1,42) "x:\dir\subdir\Test\TestComponent.cshtml" ParentValue @@ -27,7 +35,7 @@ protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components. #line hidden #nullable disable )); - __builder.AddComponentParameter(2, "ValueChanged", (global::System.Func)(async __value => { ParentValue = __value; await global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.InvokeAsynchronousDelegate( + __builder.AddComponentParameter(2, nameof(global::Test.MyComponent.ValueChanged), (global::System.Func)(async __value => { ParentValue = __value; await global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.InvokeAsynchronousDelegate( #nullable restore #line (1,63)-(1,99) "x:\dir\subdir\Test\TestComponent.cshtml" () => { return Task.CompletedTask; } diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithAfter_TaskReturningLambda/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithAfter_TaskReturningLambda/TestComponent.mappings.txt index 45057d7826b..7a0348f8e2d 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithAfter_TaskReturningLambda/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithAfter_TaskReturningLambda/TestComponent.mappings.txt @@ -1,18 +1,23 @@ -Source Location: (30:0,30 [11] x:\dir\subdir\Test\TestComponent.cshtml) +Source Location: (19:0,19 [5] x:\dir\subdir\Test\TestComponent.cshtml) +|Value| +Generated Location: (884:23,0 [5] ) +|Value| + +Source Location: (30:0,30 [11] x:\dir\subdir\Test\TestComponent.cshtml) |ParentValue| -Generated Location: (965:23,0 [11] ) +Generated Location: (1144:31,0 [11] ) |ParentValue| Source Location: (62:0,62 [36] x:\dir\subdir\Test\TestComponent.cshtml) |() => { return Task.CompletedTask; }| -Generated Location: (1405:32,0 [36] ) +Generated Location: (1615:40,0 [36] ) |() => { return Task.CompletedTask; }| Source Location: (111:1,7 [50] x:\dir\subdir\Test\TestComponent.cshtml) | public int ParentValue { get; set; } = 42; | -Generated Location: (1684:43,0 [50] ) +Generated Location: (1894:51,0 [50] ) | public int ParentValue { get; set; } = 42; | diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithGetSet_Action/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithGetSet_Action/TestComponent.codegen.cs index ba8976982b9..bfb36b475d7 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithGetSet_Action/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithGetSet_Action/TestComponent.codegen.cs @@ -18,7 +18,15 @@ public partial class TestComponent : global::Microsoft.AspNetCore.Components.Com protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { __builder.OpenComponent(0); - __builder.AddComponentParameter(1, "Value", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( + __builder.AddComponentParameter(1, nameof(global::Test.MyComponent. +#nullable restore +#line (1,20)-(1,25) "x:\dir\subdir\Test\TestComponent.cshtml" +Value + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( #nullable restore #line (1,31)-(1,42) "x:\dir\subdir\Test\TestComponent.cshtml" ParentValue @@ -27,7 +35,7 @@ protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components. #line hidden #nullable disable )); - __builder.AddComponentParameter(2, "ValueChanged", (global::System.Action)( + __builder.AddComponentParameter(2, nameof(global::Test.MyComponent.ValueChanged), (global::System.Action)( #nullable restore #line (1,61)-(1,72) "x:\dir\subdir\Test\TestComponent.cshtml" UpdateValue diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithGetSet_Action/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithGetSet_Action/TestComponent.mappings.txt index 5e51e7ee889..94d87a1d84d 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithGetSet_Action/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithGetSet_Action/TestComponent.mappings.txt @@ -1,11 +1,16 @@ -Source Location: (30:0,30 [11] x:\dir\subdir\Test\TestComponent.cshtml) +Source Location: (19:0,19 [5] x:\dir\subdir\Test\TestComponent.cshtml) +|Value| +Generated Location: (884:23,0 [5] ) +|Value| + +Source Location: (30:0,30 [11] x:\dir\subdir\Test\TestComponent.cshtml) |ParentValue| -Generated Location: (965:23,0 [11] ) +Generated Location: (1144:31,0 [11] ) |ParentValue| Source Location: (60:0,60 [11] x:\dir\subdir\Test\TestComponent.cshtml) |UpdateValue| -Generated Location: (1230:32,0 [11] ) +Generated Location: (1440:40,0 [11] ) |UpdateValue| Source Location: (84:1,7 [116] x:\dir\subdir\Test\TestComponent.cshtml) @@ -14,7 +19,7 @@ Source Location: (84:1,7 [116] x:\dir\subdir\Test\TestComponent.cshtml) public void UpdateValue(int value) => ParentValue = value; | -Generated Location: (1480:43,0 [116] ) +Generated Location: (1690:51,0 [116] ) | public int ParentValue { get; set; } = 42; diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithGetSet_ActionLambda/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithGetSet_ActionLambda/TestComponent.codegen.cs index c15091b1ff5..21f622ba370 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithGetSet_ActionLambda/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithGetSet_ActionLambda/TestComponent.codegen.cs @@ -18,7 +18,15 @@ public partial class TestComponent : global::Microsoft.AspNetCore.Components.Com protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { __builder.OpenComponent(0); - __builder.AddComponentParameter(1, "Value", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( + __builder.AddComponentParameter(1, nameof(global::Test.MyComponent. +#nullable restore +#line (1,20)-(1,25) "x:\dir\subdir\Test\TestComponent.cshtml" +Value + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( #nullable restore #line (1,31)-(1,42) "x:\dir\subdir\Test\TestComponent.cshtml" ParentValue @@ -27,7 +35,7 @@ protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components. #line hidden #nullable disable )); - __builder.AddComponentParameter(2, "ValueChanged", (global::System.Action)( + __builder.AddComponentParameter(2, nameof(global::Test.MyComponent.ValueChanged), (global::System.Action)( #nullable restore #line (1,61)-(1,89) "x:\dir\subdir\Test\TestComponent.cshtml" value => ParentValue = value diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithGetSet_ActionLambda/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithGetSet_ActionLambda/TestComponent.mappings.txt index edff65e803d..dfbb63429bc 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithGetSet_ActionLambda/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithGetSet_ActionLambda/TestComponent.mappings.txt @@ -1,18 +1,23 @@ -Source Location: (30:0,30 [11] x:\dir\subdir\Test\TestComponent.cshtml) +Source Location: (19:0,19 [5] x:\dir\subdir\Test\TestComponent.cshtml) +|Value| +Generated Location: (884:23,0 [5] ) +|Value| + +Source Location: (30:0,30 [11] x:\dir\subdir\Test\TestComponent.cshtml) |ParentValue| -Generated Location: (965:23,0 [11] ) +Generated Location: (1144:31,0 [11] ) |ParentValue| Source Location: (60:0,60 [28] x:\dir\subdir\Test\TestComponent.cshtml) |value => ParentValue = value| -Generated Location: (1230:32,0 [28] ) +Generated Location: (1440:40,0 [28] ) |value => ParentValue = value| Source Location: (101:1,7 [50] x:\dir\subdir\Test\TestComponent.cshtml) | public int ParentValue { get; set; } = 42; | -Generated Location: (1497:43,0 [50] ) +Generated Location: (1707:51,0 [50] ) | public int ParentValue { get; set; } = 42; | diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithGetSet_EventCallback/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithGetSet_EventCallback/TestComponent.codegen.cs index f5a46602235..f38e790ecc9 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithGetSet_EventCallback/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithGetSet_EventCallback/TestComponent.codegen.cs @@ -18,7 +18,15 @@ public partial class TestComponent : global::Microsoft.AspNetCore.Components.Com protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { __builder.OpenComponent(0); - __builder.AddComponentParameter(1, "Value", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( + __builder.AddComponentParameter(1, nameof(global::Test.MyComponent. +#nullable restore +#line (1,20)-(1,25) "x:\dir\subdir\Test\TestComponent.cshtml" +Value + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( #nullable restore #line (1,31)-(1,42) "x:\dir\subdir\Test\TestComponent.cshtml" ParentValue @@ -27,7 +35,7 @@ protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components. #line hidden #nullable disable )); - __builder.AddComponentParameter(2, "ValueChanged", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck>(global::Microsoft.AspNetCore.Components.EventCallback.Factory.Create(this, global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.CreateInferredEventCallback(this, + __builder.AddComponentParameter(2, nameof(global::Test.MyComponent.ValueChanged), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck>(global::Microsoft.AspNetCore.Components.EventCallback.Factory.Create(this, global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.CreateInferredEventCallback(this, #nullable restore #line (1,61)-(1,72) "x:\dir\subdir\Test\TestComponent.cshtml" UpdateValue diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithGetSet_EventCallback/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithGetSet_EventCallback/TestComponent.mappings.txt index 563ad383af4..b413cf157c5 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithGetSet_EventCallback/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithGetSet_EventCallback/TestComponent.mappings.txt @@ -1,11 +1,16 @@ -Source Location: (30:0,30 [11] x:\dir\subdir\Test\TestComponent.cshtml) +Source Location: (19:0,19 [5] x:\dir\subdir\Test\TestComponent.cshtml) +|Value| +Generated Location: (884:23,0 [5] ) +|Value| + +Source Location: (30:0,30 [11] x:\dir\subdir\Test\TestComponent.cshtml) |ParentValue| -Generated Location: (965:23,0 [11] ) +Generated Location: (1144:31,0 [11] ) |ParentValue| Source Location: (60:0,60 [11] x:\dir\subdir\Test\TestComponent.cshtml) |UpdateValue| -Generated Location: (1554:32,0 [11] ) +Generated Location: (1764:40,0 [11] ) |UpdateValue| Source Location: (84:1,7 [107] x:\dir\subdir\Test\TestComponent.cshtml) @@ -13,7 +18,7 @@ Source Location: (84:1,7 [107] x:\dir\subdir\Test\TestComponent.cshtml) public int ParentValue { get; set; } = 42; public EventCallback UpdateValue { get; set; } | -Generated Location: (1819:43,0 [107] ) +Generated Location: (2029:51,0 [107] ) | public int ParentValue { get; set; } = 42; public EventCallback UpdateValue { get; set; } diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithGetSet_EventCallback_ReceivesAction/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithGetSet_EventCallback_ReceivesAction/TestComponent.codegen.cs index f28903fc39d..8613bc60122 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithGetSet_EventCallback_ReceivesAction/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithGetSet_EventCallback_ReceivesAction/TestComponent.codegen.cs @@ -18,7 +18,15 @@ public partial class TestComponent : global::Microsoft.AspNetCore.Components.Com protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { __builder.OpenComponent(0); - __builder.AddComponentParameter(1, "Value", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( + __builder.AddComponentParameter(1, nameof(global::Test.MyComponent. +#nullable restore +#line (1,20)-(1,25) "x:\dir\subdir\Test\TestComponent.cshtml" +Value + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( #nullable restore #line (1,31)-(1,42) "x:\dir\subdir\Test\TestComponent.cshtml" ParentValue @@ -27,7 +35,7 @@ protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components. #line hidden #nullable disable )); - __builder.AddComponentParameter(2, "ValueChanged", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck>(global::Microsoft.AspNetCore.Components.EventCallback.Factory.Create(this, global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.CreateInferredEventCallback(this, + __builder.AddComponentParameter(2, nameof(global::Test.MyComponent.ValueChanged), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck>(global::Microsoft.AspNetCore.Components.EventCallback.Factory.Create(this, global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.CreateInferredEventCallback(this, #nullable restore #line (1,61)-(1,89) "x:\dir\subdir\Test\TestComponent.cshtml" value => ParentValue = value diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithGetSet_EventCallback_ReceivesAction/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithGetSet_EventCallback_ReceivesAction/TestComponent.mappings.txt index d33d86e4836..d257b6e5d75 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithGetSet_EventCallback_ReceivesAction/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithGetSet_EventCallback_ReceivesAction/TestComponent.mappings.txt @@ -1,18 +1,23 @@ -Source Location: (30:0,30 [11] x:\dir\subdir\Test\TestComponent.cshtml) +Source Location: (19:0,19 [5] x:\dir\subdir\Test\TestComponent.cshtml) +|Value| +Generated Location: (884:23,0 [5] ) +|Value| + +Source Location: (30:0,30 [11] x:\dir\subdir\Test\TestComponent.cshtml) |ParentValue| -Generated Location: (965:23,0 [11] ) +Generated Location: (1144:31,0 [11] ) |ParentValue| Source Location: (60:0,60 [28] x:\dir\subdir\Test\TestComponent.cshtml) |value => ParentValue = value| -Generated Location: (1554:32,0 [28] ) +Generated Location: (1764:40,0 [28] ) |value => ParentValue = value| Source Location: (101:1,7 [50] x:\dir\subdir\Test\TestComponent.cshtml) | public int ParentValue { get; set; } = 42; | -Generated Location: (1836:43,0 [50] ) +Generated Location: (2046:51,0 [50] ) | public int ParentValue { get; set; } = 42; | diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithGetSet_EventCallback_ReceivesFunction/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithGetSet_EventCallback_ReceivesFunction/TestComponent.codegen.cs index 016d6ed6f62..704445d77e2 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithGetSet_EventCallback_ReceivesFunction/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithGetSet_EventCallback_ReceivesFunction/TestComponent.codegen.cs @@ -18,7 +18,15 @@ public partial class TestComponent : global::Microsoft.AspNetCore.Components.Com protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { __builder.OpenComponent(0); - __builder.AddComponentParameter(1, "Value", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( + __builder.AddComponentParameter(1, nameof(global::Test.MyComponent. +#nullable restore +#line (1,20)-(1,25) "x:\dir\subdir\Test\TestComponent.cshtml" +Value + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( #nullable restore #line (1,31)-(1,42) "x:\dir\subdir\Test\TestComponent.cshtml" ParentValue @@ -27,7 +35,7 @@ protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components. #line hidden #nullable disable )); - __builder.AddComponentParameter(2, "ValueChanged", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck>(global::Microsoft.AspNetCore.Components.EventCallback.Factory.Create(this, global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.CreateInferredEventCallback(this, + __builder.AddComponentParameter(2, nameof(global::Test.MyComponent.ValueChanged), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck>(global::Microsoft.AspNetCore.Components.EventCallback.Factory.Create(this, global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.CreateInferredEventCallback(this, #nullable restore #line (1,61)-(1,72) "x:\dir\subdir\Test\TestComponent.cshtml" UpdateValue diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithGetSet_EventCallback_ReceivesFunction/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithGetSet_EventCallback_ReceivesFunction/TestComponent.mappings.txt index 237ce5908ef..b2213b40f24 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithGetSet_EventCallback_ReceivesFunction/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithGetSet_EventCallback_ReceivesFunction/TestComponent.mappings.txt @@ -1,11 +1,16 @@ -Source Location: (30:0,30 [11] x:\dir\subdir\Test\TestComponent.cshtml) +Source Location: (19:0,19 [5] x:\dir\subdir\Test\TestComponent.cshtml) +|Value| +Generated Location: (884:23,0 [5] ) +|Value| + +Source Location: (30:0,30 [11] x:\dir\subdir\Test\TestComponent.cshtml) |ParentValue| -Generated Location: (965:23,0 [11] ) +Generated Location: (1144:31,0 [11] ) |ParentValue| Source Location: (60:0,60 [11] x:\dir\subdir\Test\TestComponent.cshtml) |UpdateValue| -Generated Location: (1554:32,0 [11] ) +Generated Location: (1764:40,0 [11] ) |UpdateValue| Source Location: (84:1,7 [144] x:\dir\subdir\Test\TestComponent.cshtml) @@ -14,7 +19,7 @@ Source Location: (84:1,7 [144] x:\dir\subdir\Test\TestComponent.cshtml) public Task UpdateValue(int value) { ParentValue = value; return Task.CompletedTask; } | -Generated Location: (1819:43,0 [144] ) +Generated Location: (2029:51,0 [144] ) | public int ParentValue { get; set; } = 42; diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithGetSet_ProducesErrorOnOlderLanguageVersions/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithGetSet_ProducesErrorOnOlderLanguageVersions/TestComponent.codegen.cs index 43973157a01..361d55a95a8 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithGetSet_ProducesErrorOnOlderLanguageVersions/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithGetSet_ProducesErrorOnOlderLanguageVersions/TestComponent.codegen.cs @@ -18,7 +18,15 @@ public partial class TestComponent : global::Microsoft.AspNetCore.Components.Com protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { __builder.OpenComponent(0); - __builder.AddAttribute(1, "Value", (object)(global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( + __builder.AddAttribute(1, nameof(global::Test.MyComponent. +#nullable restore +#line (1,20)-(1,25) "x:\dir\subdir\Test\TestComponent.cshtml" +Value + +#line default +#line hidden +#nullable disable + ), (object)(global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( #nullable restore #line (1,31)-(1,42) "x:\dir\subdir\Test\TestComponent.cshtml" ParentValue @@ -27,7 +35,7 @@ protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components. #line hidden #nullable disable ))); - __builder.AddAttribute(2, "ValueChanged", (object)((global::System.Action)( + __builder.AddAttribute(2, nameof(global::Test.MyComponent.ValueChanged), (object)((global::System.Action)( #nullable restore #line (1,61)-(1,72) "x:\dir\subdir\Test\TestComponent.cshtml" UpdateValue diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithGetSet_ProducesErrorOnOlderLanguageVersions/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithGetSet_ProducesErrorOnOlderLanguageVersions/TestComponent.mappings.txt index 2ca22229e79..0e4155e0284 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithGetSet_ProducesErrorOnOlderLanguageVersions/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithGetSet_ProducesErrorOnOlderLanguageVersions/TestComponent.mappings.txt @@ -1,11 +1,16 @@ -Source Location: (30:0,30 [11] x:\dir\subdir\Test\TestComponent.cshtml) +Source Location: (19:0,19 [5] x:\dir\subdir\Test\TestComponent.cshtml) +|Value| +Generated Location: (875:23,0 [5] ) +|Value| + +Source Location: (30:0,30 [11] x:\dir\subdir\Test\TestComponent.cshtml) |ParentValue| -Generated Location: (965:23,0 [11] ) +Generated Location: (1144:31,0 [11] ) |ParentValue| Source Location: (60:0,60 [11] x:\dir\subdir\Test\TestComponent.cshtml) |UpdateValue| -Generated Location: (1231:32,0 [11] ) +Generated Location: (1441:40,0 [11] ) |UpdateValue| Source Location: (84:1,7 [116] x:\dir\subdir\Test\TestComponent.cshtml) @@ -14,7 +19,7 @@ Source Location: (84:1,7 [116] x:\dir\subdir\Test\TestComponent.cshtml) public void UpdateValue(int value) => ParentValue = value; | -Generated Location: (1482:43,0 [116] ) +Generated Location: (1692:51,0 [116] ) | public int ParentValue { get; set; } = 42; diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithGetSet_TaskReturningDelegate/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithGetSet_TaskReturningDelegate/TestComponent.codegen.cs index 31d30a215c0..a43e5220dc5 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithGetSet_TaskReturningDelegate/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithGetSet_TaskReturningDelegate/TestComponent.codegen.cs @@ -18,7 +18,15 @@ public partial class TestComponent : global::Microsoft.AspNetCore.Components.Com protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { __builder.OpenComponent(0); - __builder.AddComponentParameter(1, "Value", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( + __builder.AddComponentParameter(1, nameof(global::Test.MyComponent. +#nullable restore +#line (1,20)-(1,25) "x:\dir\subdir\Test\TestComponent.cshtml" +Value + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( #nullable restore #line (1,31)-(1,42) "x:\dir\subdir\Test\TestComponent.cshtml" ParentValue @@ -27,7 +35,7 @@ protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components. #line hidden #nullable disable )); - __builder.AddComponentParameter(2, "ValueChanged", (global::System.Func)( + __builder.AddComponentParameter(2, nameof(global::Test.MyComponent.ValueChanged), (global::System.Func)( #nullable restore #line (1,61)-(1,72) "x:\dir\subdir\Test\TestComponent.cshtml" UpdateValue diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithGetSet_TaskReturningDelegate/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithGetSet_TaskReturningDelegate/TestComponent.mappings.txt index 1453f1998e2..e2045b99fdd 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithGetSet_TaskReturningDelegate/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithGetSet_TaskReturningDelegate/TestComponent.mappings.txt @@ -1,11 +1,16 @@ -Source Location: (30:0,30 [11] x:\dir\subdir\Test\TestComponent.cshtml) +Source Location: (19:0,19 [5] x:\dir\subdir\Test\TestComponent.cshtml) +|Value| +Generated Location: (884:23,0 [5] ) +|Value| + +Source Location: (30:0,30 [11] x:\dir\subdir\Test\TestComponent.cshtml) |ParentValue| -Generated Location: (965:23,0 [11] ) +Generated Location: (1144:31,0 [11] ) |ParentValue| Source Location: (60:0,60 [11] x:\dir\subdir\Test\TestComponent.cshtml) |UpdateValue| -Generated Location: (1257:32,0 [11] ) +Generated Location: (1467:40,0 [11] ) |UpdateValue| Source Location: (84:1,7 [144] x:\dir\subdir\Test\TestComponent.cshtml) @@ -14,7 +19,7 @@ Source Location: (84:1,7 [144] x:\dir\subdir\Test\TestComponent.cshtml) public Task UpdateValue(int value) { ParentValue = value; return Task.CompletedTask; } | -Generated Location: (1507:43,0 [144] ) +Generated Location: (1717:51,0 [144] ) | public int ParentValue { get; set; } = 42; diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithGetSet_TaskReturningLambda/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithGetSet_TaskReturningLambda/TestComponent.codegen.cs index eb923b7a9c1..358e53a3b9a 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithGetSet_TaskReturningLambda/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithGetSet_TaskReturningLambda/TestComponent.codegen.cs @@ -18,7 +18,15 @@ public partial class TestComponent : global::Microsoft.AspNetCore.Components.Com protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { __builder.OpenComponent(0); - __builder.AddComponentParameter(1, "Value", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( + __builder.AddComponentParameter(1, nameof(global::Test.MyComponent. +#nullable restore +#line (1,20)-(1,25) "x:\dir\subdir\Test\TestComponent.cshtml" +Value + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( #nullable restore #line (1,31)-(1,42) "x:\dir\subdir\Test\TestComponent.cshtml" ParentValue @@ -27,7 +35,7 @@ protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components. #line hidden #nullable disable )); - __builder.AddComponentParameter(2, "ValueChanged", (global::System.Func)( + __builder.AddComponentParameter(2, nameof(global::Test.MyComponent.ValueChanged), (global::System.Func)( #nullable restore #line (1,61)-(1,121) "x:\dir\subdir\Test\TestComponent.cshtml" value => { ParentValue = value; return Task.CompletedTask; } diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithGetSet_TaskReturningLambda/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithGetSet_TaskReturningLambda/TestComponent.mappings.txt index 2ba16c1979d..70a99a8556f 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithGetSet_TaskReturningLambda/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithGetSet_TaskReturningLambda/TestComponent.mappings.txt @@ -1,18 +1,23 @@ -Source Location: (30:0,30 [11] x:\dir\subdir\Test\TestComponent.cshtml) +Source Location: (19:0,19 [5] x:\dir\subdir\Test\TestComponent.cshtml) +|Value| +Generated Location: (884:23,0 [5] ) +|Value| + +Source Location: (30:0,30 [11] x:\dir\subdir\Test\TestComponent.cshtml) |ParentValue| -Generated Location: (965:23,0 [11] ) +Generated Location: (1144:31,0 [11] ) |ParentValue| Source Location: (60:0,60 [60] x:\dir\subdir\Test\TestComponent.cshtml) |value => { ParentValue = value; return Task.CompletedTask; }| -Generated Location: (1258:32,0 [60] ) +Generated Location: (1468:40,0 [60] ) |value => { ParentValue = value; return Task.CompletedTask; }| Source Location: (133:1,7 [50] x:\dir\subdir\Test\TestComponent.cshtml) | public int ParentValue { get; set; } = 42; | -Generated Location: (1557:43,0 [50] ) +Generated Location: (1767:51,0 [50] ) | public int ParentValue { get; set; } = 42; | diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithStringAttribute_DoesNotUseStringSyntax/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithStringAttribute_DoesNotUseStringSyntax/TestComponent.codegen.cs index e64eac198fe..c72983ec8e4 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithStringAttribute_DoesNotUseStringSyntax/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithStringAttribute_DoesNotUseStringSyntax/TestComponent.codegen.cs @@ -18,7 +18,15 @@ public partial class TestComponent : global::Microsoft.AspNetCore.Components.Com protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { __builder.OpenComponent(0); - __builder.AddComponentParameter(1, "Value", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( + __builder.AddComponentParameter(1, nameof(global::Test.InputText. +#nullable restore +#line (1,18)-(1,23) "x:\dir\subdir\Test\TestComponent.cshtml" +Value + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( #nullable restore #line (1,25)-(1,36) "x:\dir\subdir\Test\TestComponent.cshtml" person.Name @@ -27,7 +35,7 @@ protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components. #line hidden #nullable disable )); - __builder.AddComponentParameter(2, "ValueChanged", (global::System.Action)(__value => person.Name = __value)); + __builder.AddComponentParameter(2, nameof(global::Test.InputText.ValueChanged), (global::System.Action)(__value => person.Name = __value)); __builder.CloseComponent(); } #pragma warning restore 1998 diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithStringAttribute_DoesNotUseStringSyntax/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithStringAttribute_DoesNotUseStringSyntax/TestComponent.mappings.txt index a34cc991a7d..3db547b9f8f 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithStringAttribute_DoesNotUseStringSyntax/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToComponent_WithStringAttribute_DoesNotUseStringSyntax/TestComponent.mappings.txt @@ -1,13 +1,18 @@ -Source Location: (24:0,24 [11] x:\dir\subdir\Test\TestComponent.cshtml) +Source Location: (17:0,17 [5] x:\dir\subdir\Test\TestComponent.cshtml) +|Value| +Generated Location: (880:23,0 [5] ) +|Value| + +Source Location: (24:0,24 [11] x:\dir\subdir\Test\TestComponent.cshtml) |person.Name| -Generated Location: (964:23,0 [11] ) +Generated Location: (1141:31,0 [11] ) |person.Name| Source Location: (56:3,1 [37] x:\dir\subdir\Test\TestComponent.cshtml) | Person person = new Person(); | -Generated Location: (1353:35,0 [37] ) +Generated Location: (1559:43,0 [37] ) | Person person = new Person(); | diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToGenericComponent_ExplicitType_WithAfter_Action/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToGenericComponent_ExplicitType_WithAfter_Action/TestComponent.codegen.cs index 3923e98656a..b7ff3201d11 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToGenericComponent_ExplicitType_WithAfter_Action/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToGenericComponent_ExplicitType_WithAfter_Action/TestComponent.codegen.cs @@ -18,7 +18,15 @@ public partial class TestComponent : global::Microsoft.AspNetCore.Components.Com protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { __builder.OpenComponent>(0); - __builder.AddComponentParameter(1, "Value", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( + __builder.AddComponentParameter(1, nameof(global::Test.MyComponent. +#nullable restore +#line (1,33)-(1,38) "x:\dir\subdir\Test\TestComponent.cshtml" +Value + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( #nullable restore #line (1,44)-(1,55) "x:\dir\subdir\Test\TestComponent.cshtml" ParentValue @@ -27,7 +35,7 @@ protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components. #line hidden #nullable disable )); - __builder.AddComponentParameter(2, "ValueChanged", (global::System.Action)( __value => { ParentValue = __value; global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.InvokeSynchronousDelegate( + __builder.AddComponentParameter(2, nameof(global::Test.MyComponent.ValueChanged), (global::System.Action)( __value => { ParentValue = __value; global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.InvokeSynchronousDelegate( #nullable restore #line (1,76)-(1,82) "x:\dir\subdir\Test\TestComponent.cshtml" Update diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToGenericComponent_ExplicitType_WithAfter_Action/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToGenericComponent_ExplicitType_WithAfter_Action/TestComponent.mappings.txt index 96a2c968b65..f0784640e1a 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToGenericComponent_ExplicitType_WithAfter_Action/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToGenericComponent_ExplicitType_WithAfter_Action/TestComponent.mappings.txt @@ -1,11 +1,16 @@ -Source Location: (43:0,43 [11] x:\dir\subdir\Test\TestComponent.cshtml) +Source Location: (32:0,32 [5] x:\dir\subdir\Test\TestComponent.cshtml) +|Value| +Generated Location: (894:23,0 [5] ) +|Value| + +Source Location: (43:0,43 [11] x:\dir\subdir\Test\TestComponent.cshtml) |ParentValue| -Generated Location: (953:23,0 [11] ) +Generated Location: (1137:31,0 [11] ) |ParentValue| Source Location: (75:0,75 [6] x:\dir\subdir\Test\TestComponent.cshtml) |Update| -Generated Location: (1344:32,0 [6] ) +Generated Location: (1564:40,0 [6] ) |Update| Source Location: (94:1,7 [82] x:\dir\subdir\Test\TestComponent.cshtml) @@ -14,7 +19,7 @@ Source Location: (94:1,7 [82] x:\dir\subdir\Test\TestComponent.cshtml) public void Update() { } | -Generated Location: (1593:43,0 [82] ) +Generated Location: (1813:51,0 [82] ) | public int ParentValue { get; set; } = 42; diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToGenericComponent_ExplicitType_WithGetSet_Action/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToGenericComponent_ExplicitType_WithGetSet_Action/TestComponent.codegen.cs index 5356d258260..8a4db3328d6 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToGenericComponent_ExplicitType_WithGetSet_Action/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToGenericComponent_ExplicitType_WithGetSet_Action/TestComponent.codegen.cs @@ -18,7 +18,15 @@ public partial class TestComponent : global::Microsoft.AspNetCore.Components.Com protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { __builder.OpenComponent>(0); - __builder.AddComponentParameter(1, "Value", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( + __builder.AddComponentParameter(1, nameof(global::Test.MyComponent. +#nullable restore +#line (1,41)-(1,46) "x:\dir\subdir\Test\TestComponent.cshtml" +Value + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( #nullable restore #line (1,52)-(1,63) "x:\dir\subdir\Test\TestComponent.cshtml" ParentValue @@ -27,7 +35,7 @@ protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components. #line hidden #nullable disable )); - __builder.AddComponentParameter(2, "ValueChanged", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck>(global::Microsoft.AspNetCore.Components.EventCallback.Factory.Create(this, global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.CreateInferredEventCallback(this, + __builder.AddComponentParameter(2, nameof(global::Test.MyComponent.ValueChanged), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck>(global::Microsoft.AspNetCore.Components.EventCallback.Factory.Create(this, global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.CreateInferredEventCallback(this, #nullable restore #line (1,82)-(1,93) "x:\dir\subdir\Test\TestComponent.cshtml" UpdateValue diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToGenericComponent_ExplicitType_WithGetSet_Action/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToGenericComponent_ExplicitType_WithGetSet_Action/TestComponent.mappings.txt index c37d97b04ea..84d48326884 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToGenericComponent_ExplicitType_WithGetSet_Action/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToGenericComponent_ExplicitType_WithGetSet_Action/TestComponent.mappings.txt @@ -1,11 +1,16 @@ -Source Location: (51:0,51 [11] x:\dir\subdir\Test\TestComponent.cshtml) +Source Location: (40:0,40 [5] x:\dir\subdir\Test\TestComponent.cshtml) +|Value| +Generated Location: (910:23,0 [5] ) +|Value| + +Source Location: (51:0,51 [11] x:\dir\subdir\Test\TestComponent.cshtml) |ParentValue| -Generated Location: (969:23,0 [11] ) +Generated Location: (1161:31,0 [11] ) |ParentValue| Source Location: (81:0,81 [11] x:\dir\subdir\Test\TestComponent.cshtml) |UpdateValue| -Generated Location: (1540:32,0 [11] ) +Generated Location: (1776:40,0 [11] ) |UpdateValue| Source Location: (105:1,7 [147] x:\dir\subdir\Test\TestComponent.cshtml) @@ -14,7 +19,7 @@ Source Location: (105:1,7 [147] x:\dir\subdir\Test\TestComponent.cshtml) public void UpdateValue(CustomValue value) => ParentValue = value; | -Generated Location: (1805:43,0 [147] ) +Generated Location: (2041:51,0 [147] ) | public CustomValue ParentValue { get; set; } = new CustomValue(); diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToGenericComponent_ExplicitType_WithGetSet_EventCallback/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToGenericComponent_ExplicitType_WithGetSet_EventCallback/TestComponent.codegen.cs index 9bfaa8c7102..1083ea60026 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToGenericComponent_ExplicitType_WithGetSet_EventCallback/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToGenericComponent_ExplicitType_WithGetSet_EventCallback/TestComponent.codegen.cs @@ -18,7 +18,15 @@ public partial class TestComponent : global::Microsoft.AspNetCore.Components.Com protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { __builder.OpenComponent>(0); - __builder.AddComponentParameter(1, "Value", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( + __builder.AddComponentParameter(1, nameof(global::Test.MyComponent. +#nullable restore +#line (1,41)-(1,46) "x:\dir\subdir\Test\TestComponent.cshtml" +Value + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( #nullable restore #line (1,52)-(1,63) "x:\dir\subdir\Test\TestComponent.cshtml" ParentValue @@ -27,7 +35,7 @@ protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components. #line hidden #nullable disable )); - __builder.AddComponentParameter(2, "ValueChanged", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck>(global::Microsoft.AspNetCore.Components.EventCallback.Factory.Create(this, global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.CreateInferredEventCallback(this, + __builder.AddComponentParameter(2, nameof(global::Test.MyComponent.ValueChanged), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck>(global::Microsoft.AspNetCore.Components.EventCallback.Factory.Create(this, global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.CreateInferredEventCallback(this, #nullable restore #line (1,82)-(1,93) "x:\dir\subdir\Test\TestComponent.cshtml" UpdateValue diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToGenericComponent_ExplicitType_WithGetSet_EventCallback/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToGenericComponent_ExplicitType_WithGetSet_EventCallback/TestComponent.mappings.txt index 5904ae0837d..681432f05f9 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToGenericComponent_ExplicitType_WithGetSet_EventCallback/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToGenericComponent_ExplicitType_WithGetSet_EventCallback/TestComponent.mappings.txt @@ -1,11 +1,16 @@ -Source Location: (51:0,51 [11] x:\dir\subdir\Test\TestComponent.cshtml) +Source Location: (40:0,40 [5] x:\dir\subdir\Test\TestComponent.cshtml) +|Value| +Generated Location: (910:23,0 [5] ) +|Value| + +Source Location: (51:0,51 [11] x:\dir\subdir\Test\TestComponent.cshtml) |ParentValue| -Generated Location: (969:23,0 [11] ) +Generated Location: (1161:31,0 [11] ) |ParentValue| Source Location: (81:0,81 [11] x:\dir\subdir\Test\TestComponent.cshtml) |UpdateValue| -Generated Location: (1540:32,0 [11] ) +Generated Location: (1776:40,0 [11] ) |UpdateValue| Source Location: (105:1,7 [138] x:\dir\subdir\Test\TestComponent.cshtml) @@ -13,7 +18,7 @@ Source Location: (105:1,7 [138] x:\dir\subdir\Test\TestComponent.cshtml) public CustomValue ParentValue { get; set; } = new CustomValue(); public EventCallback UpdateValue { get; set; } | -Generated Location: (1805:43,0 [138] ) +Generated Location: (2041:51,0 [138] ) | public CustomValue ParentValue { get; set; } = new CustomValue(); public EventCallback UpdateValue { get; set; } diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToGenericComponent_ExplicitType_WithGetSet_Function/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToGenericComponent_ExplicitType_WithGetSet_Function/TestComponent.codegen.cs index 1091e7ad76a..160f3a0c69e 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToGenericComponent_ExplicitType_WithGetSet_Function/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToGenericComponent_ExplicitType_WithGetSet_Function/TestComponent.codegen.cs @@ -18,7 +18,15 @@ public partial class TestComponent : global::Microsoft.AspNetCore.Components.Com protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { __builder.OpenComponent>(0); - __builder.AddComponentParameter(1, "Value", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( + __builder.AddComponentParameter(1, nameof(global::Test.MyComponent. +#nullable restore +#line (1,41)-(1,46) "x:\dir\subdir\Test\TestComponent.cshtml" +Value + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( #nullable restore #line (1,52)-(1,63) "x:\dir\subdir\Test\TestComponent.cshtml" ParentValue @@ -27,7 +35,7 @@ protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components. #line hidden #nullable disable )); - __builder.AddComponentParameter(2, "ValueChanged", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck>(global::Microsoft.AspNetCore.Components.EventCallback.Factory.Create(this, global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.CreateInferredEventCallback(this, + __builder.AddComponentParameter(2, nameof(global::Test.MyComponent.ValueChanged), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck>(global::Microsoft.AspNetCore.Components.EventCallback.Factory.Create(this, global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.CreateInferredEventCallback(this, #nullable restore #line (1,82)-(1,93) "x:\dir\subdir\Test\TestComponent.cshtml" UpdateValue diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToGenericComponent_ExplicitType_WithGetSet_Function/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToGenericComponent_ExplicitType_WithGetSet_Function/TestComponent.mappings.txt index ddf9a56de64..eb5779adab1 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToGenericComponent_ExplicitType_WithGetSet_Function/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToGenericComponent_ExplicitType_WithGetSet_Function/TestComponent.mappings.txt @@ -1,11 +1,16 @@ -Source Location: (51:0,51 [11] x:\dir\subdir\Test\TestComponent.cshtml) +Source Location: (40:0,40 [5] x:\dir\subdir\Test\TestComponent.cshtml) +|Value| +Generated Location: (910:23,0 [5] ) +|Value| + +Source Location: (51:0,51 [11] x:\dir\subdir\Test\TestComponent.cshtml) |ParentValue| -Generated Location: (969:23,0 [11] ) +Generated Location: (1161:31,0 [11] ) |ParentValue| Source Location: (81:0,81 [11] x:\dir\subdir\Test\TestComponent.cshtml) |UpdateValue| -Generated Location: (1540:32,0 [11] ) +Generated Location: (1776:40,0 [11] ) |UpdateValue| Source Location: (105:1,7 [179] x:\dir\subdir\Test\TestComponent.cshtml) @@ -14,7 +19,7 @@ Source Location: (105:1,7 [179] x:\dir\subdir\Test\TestComponent.cshtml) public Task UpdateValue(CustomValue value) { ParentValue = value; return Task.CompletedTask; } | -Generated Location: (1805:43,0 [179] ) +Generated Location: (2041:51,0 [179] ) | public CustomValue ParentValue { get; set; } = new CustomValue(); diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToGenericComponent_InferredType_WithAfter_Action/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToGenericComponent_InferredType_WithAfter_Action/TestComponent.codegen.cs index f87134d851a..51819242001 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToGenericComponent_InferredType_WithAfter_Action/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToGenericComponent_InferredType_WithAfter_Action/TestComponent.codegen.cs @@ -57,8 +57,16 @@ internal static class TypeInference public static void CreateMyComponent_0(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder, int seq, int __seq0, TValue __arg0, int __seq1, global::System.Action __arg1) { __builder.OpenComponent>(seq); - __builder.AddComponentParameter(__seq0, "Value", __arg0); - __builder.AddComponentParameter(__seq1, "ValueChanged", __arg1); + __builder.AddComponentParameter(__seq0, nameof(global::Test.MyComponent. +#nullable restore +#line (1,20)-(1,25) "x:\dir\subdir\Test\TestComponent.cshtml" +Value + +#line default +#line hidden +#nullable disable + ), __arg0); + __builder.AddComponentParameter(__seq1, nameof(global::Test.MyComponent.ValueChanged), __arg1); __builder.CloseComponent(); } } diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToGenericComponent_InferredType_WithAfter_Action/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToGenericComponent_InferredType_WithAfter_Action/TestComponent.mappings.txt index f3e32bd8916..8958c2be569 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToGenericComponent_InferredType_WithAfter_Action/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToGenericComponent_InferredType_WithAfter_Action/TestComponent.mappings.txt @@ -21,3 +21,8 @@ Generated Location: (1343:40,0 [82] ) public void Update() { } | +Source Location: (19:0,19 [5] x:\dir\subdir\Test\TestComponent.cshtml) +|Value| +Generated Location: (2072:62,0 [5] ) +|Value| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToGenericComponent_InferredType_WithGetSet_Action/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToGenericComponent_InferredType_WithGetSet_Action/TestComponent.codegen.cs index 9d4cd28f3df..8dff4a138c7 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToGenericComponent_InferredType_WithGetSet_Action/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToGenericComponent_InferredType_WithGetSet_Action/TestComponent.codegen.cs @@ -57,8 +57,16 @@ internal static class TypeInference public static void CreateMyComponent_0(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder, int seq, int __seq0, TValue __arg0, int __seq1, global::Microsoft.AspNetCore.Components.EventCallback __arg1) { __builder.OpenComponent>(seq); - __builder.AddComponentParameter(__seq0, "Value", __arg0); - __builder.AddComponentParameter(__seq1, "ValueChanged", __arg1); + __builder.AddComponentParameter(__seq0, nameof(global::Test.MyComponent. +#nullable restore +#line (1,20)-(1,25) "x:\dir\subdir\Test\TestComponent.cshtml" +Value + +#line default +#line hidden +#nullable disable + ), __arg0); + __builder.AddComponentParameter(__seq1, nameof(global::Test.MyComponent.ValueChanged), __arg1); __builder.CloseComponent(); } } diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToGenericComponent_InferredType_WithGetSet_Action/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToGenericComponent_InferredType_WithGetSet_Action/TestComponent.mappings.txt index 507a42b9e0e..b68e8e7fd34 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToGenericComponent_InferredType_WithGetSet_Action/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToGenericComponent_InferredType_WithGetSet_Action/TestComponent.mappings.txt @@ -21,3 +21,8 @@ Generated Location: (1405:40,0 [147] ) public void UpdateValue(CustomValue value) => ParentValue = value; | +Source Location: (19:0,19 [5] x:\dir\subdir\Test\TestComponent.cshtml) +|Value| +Generated Location: (2231:62,0 [5] ) +|Value| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToGenericComponent_InferredType_WithGetSet_EventCallback/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToGenericComponent_InferredType_WithGetSet_EventCallback/TestComponent.codegen.cs index fc535e36c1d..fcd7e5615cf 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToGenericComponent_InferredType_WithGetSet_EventCallback/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToGenericComponent_InferredType_WithGetSet_EventCallback/TestComponent.codegen.cs @@ -56,8 +56,16 @@ internal static class TypeInference public static void CreateMyComponent_0(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder, int seq, int __seq0, TValue __arg0, int __seq1, global::Microsoft.AspNetCore.Components.EventCallback __arg1) { __builder.OpenComponent>(seq); - __builder.AddComponentParameter(__seq0, "Value", __arg0); - __builder.AddComponentParameter(__seq1, "ValueChanged", __arg1); + __builder.AddComponentParameter(__seq0, nameof(global::Test.MyComponent. +#nullable restore +#line (1,20)-(1,25) "x:\dir\subdir\Test\TestComponent.cshtml" +Value + +#line default +#line hidden +#nullable disable + ), __arg0); + __builder.AddComponentParameter(__seq1, nameof(global::Test.MyComponent.ValueChanged), __arg1); __builder.CloseComponent(); } } diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToGenericComponent_InferredType_WithGetSet_EventCallback/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToGenericComponent_InferredType_WithGetSet_EventCallback/TestComponent.mappings.txt index b839444310e..df7365e58d2 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToGenericComponent_InferredType_WithGetSet_EventCallback/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToGenericComponent_InferredType_WithGetSet_EventCallback/TestComponent.mappings.txt @@ -19,3 +19,8 @@ Generated Location: (1405:40,0 [138] ) public EventCallback UpdateValue { get; set; } | +Source Location: (19:0,19 [5] x:\dir\subdir\Test\TestComponent.cshtml) +|Value| +Generated Location: (2222:61,0 [5] ) +|Value| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToGenericComponent_InferredType_WithGetSet_Function/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToGenericComponent_InferredType_WithGetSet_Function/TestComponent.codegen.cs index 4727368f380..933a7f320d2 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToGenericComponent_InferredType_WithGetSet_Function/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToGenericComponent_InferredType_WithGetSet_Function/TestComponent.codegen.cs @@ -57,8 +57,16 @@ internal static class TypeInference public static void CreateMyComponent_0(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder, int seq, int __seq0, TValue __arg0, int __seq1, global::Microsoft.AspNetCore.Components.EventCallback __arg1) { __builder.OpenComponent>(seq); - __builder.AddComponentParameter(__seq0, "Value", __arg0); - __builder.AddComponentParameter(__seq1, "ValueChanged", __arg1); + __builder.AddComponentParameter(__seq0, nameof(global::Test.MyComponent. +#nullable restore +#line (1,20)-(1,25) "x:\dir\subdir\Test\TestComponent.cshtml" +Value + +#line default +#line hidden +#nullable disable + ), __arg0); + __builder.AddComponentParameter(__seq1, nameof(global::Test.MyComponent.ValueChanged), __arg1); __builder.CloseComponent(); } } diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToGenericComponent_InferredType_WithGetSet_Function/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToGenericComponent_InferredType_WithGetSet_Function/TestComponent.mappings.txt index e74906c50f6..598bda4ebc5 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToGenericComponent_InferredType_WithGetSet_Function/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToGenericComponent_InferredType_WithGetSet_Function/TestComponent.mappings.txt @@ -21,3 +21,8 @@ Generated Location: (1405:40,0 [175] ) public Task UpdateValue(CustomValue value) { ParentValue = value; return Task.CompletedTask; } | +Source Location: (19:0,19 [5] x:\dir\subdir\Test\TestComponent.cshtml) +|Value| +Generated Location: (2259:62,0 [5] ) +|Value| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BodyAndAttributeChildContent/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BodyAndAttributeChildContent/TestComponent.codegen.cs index abb5003d72f..d79cfac0416 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BodyAndAttributeChildContent/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BodyAndAttributeChildContent/TestComponent.codegen.cs @@ -47,7 +47,15 @@ protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components. #nullable disable __builder.OpenComponent(2); - __builder.AddComponentParameter(3, "Header", (global::Microsoft.AspNetCore.Components.RenderFragment)( + __builder.AddComponentParameter(3, nameof(global::Test.MyComponent. +#nullable restore +#line (2,14)-(2,20) "x:\dir\subdir\Test\TestComponent.cshtml" +Header + +#line default +#line hidden +#nullable disable + ), (global::Microsoft.AspNetCore.Components.RenderFragment)( #nullable restore #line (2,22)-(2,28) "x:\dir\subdir\Test\TestComponent.cshtml" header diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BodyAndAttributeChildContent/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BodyAndAttributeChildContent/TestComponent.mappings.txt index bbec970f3fb..21b82df25e8 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BodyAndAttributeChildContent/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BodyAndAttributeChildContent/TestComponent.mappings.txt @@ -13,8 +13,13 @@ Source Location: (87:0,87 [2] x:\dir\subdir\Test\TestComponent.cshtml) Generated Location: (1281:42,0 [2] ) |; | +Source Location: (105:1,13 [6] x:\dir\subdir\Test\TestComponent.cshtml) +|Header| +Generated Location: (1567:52,0 [6] ) +|Header| + Source Location: (113:1,21 [6] x:\dir\subdir\Test\TestComponent.cshtml) |header| -Generated Location: (1617:52,0 [6] ) +Generated Location: (1796:60,0 [6] ) |header| diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BodyAndExplicitChildContent/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BodyAndExplicitChildContent/TestComponent.codegen.cs index 1ba4bb73072..2a4aab4d08f 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BodyAndExplicitChildContent/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BodyAndExplicitChildContent/TestComponent.codegen.cs @@ -47,7 +47,15 @@ protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components. #nullable disable __builder.OpenComponent(2); - __builder.AddComponentParameter(3, "Header", (global::Microsoft.AspNetCore.Components.RenderFragment)( + __builder.AddComponentParameter(3, nameof(global::Test.MyComponent. +#nullable restore +#line (2,14)-(2,20) "x:\dir\subdir\Test\TestComponent.cshtml" +Header + +#line default +#line hidden +#nullable disable + ), (global::Microsoft.AspNetCore.Components.RenderFragment)( #nullable restore #line (2,22)-(2,28) "x:\dir\subdir\Test\TestComponent.cshtml" header diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BodyAndExplicitChildContent/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BodyAndExplicitChildContent/TestComponent.mappings.txt index bbec970f3fb..21b82df25e8 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BodyAndExplicitChildContent/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BodyAndExplicitChildContent/TestComponent.mappings.txt @@ -13,8 +13,13 @@ Source Location: (87:0,87 [2] x:\dir\subdir\Test\TestComponent.cshtml) Generated Location: (1281:42,0 [2] ) |; | +Source Location: (105:1,13 [6] x:\dir\subdir\Test\TestComponent.cshtml) +|Header| +Generated Location: (1567:52,0 [6] ) +|Header| + Source Location: (113:1,21 [6] x:\dir\subdir\Test\TestComponent.cshtml) |header| -Generated Location: (1617:52,0 [6] ) +Generated Location: (1796:60,0 [6] ) |header| diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_CombiningMultipleAncestors/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_CombiningMultipleAncestors/TestComponent.codegen.cs index dd3caade802..00c150b61ee 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_CombiningMultipleAncestors/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_CombiningMultipleAncestors/TestComponent.codegen.cs @@ -60,7 +60,15 @@ internal static class TypeInference public static void CreateParentOne_0(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder, int seq, int __seq0, TOne __arg0, int __seq1, global::Microsoft.AspNetCore.Components.RenderFragment __arg1) { __builder.OpenComponent>(seq); - __builder.AddComponentParameter(__seq0, "Value", __arg0); + __builder.AddComponentParameter(__seq0, nameof(global::Test.ParentOne. +#nullable restore +#line (1,12)-(1,17) "x:\dir\subdir\Test\TestComponent.cshtml" +Value + +#line default +#line hidden +#nullable disable + ), __arg0); __builder.AddComponentParameter(__seq1, "ChildContent", __arg1); __builder.CloseComponent(); } @@ -72,7 +80,15 @@ public static void CreateParentOne_0_CaptureParameters(TOne __arg0, out TO public static void CreateParentTwo_1(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder, int seq, int __seq0, TTwo __arg0, int __seq1, global::Microsoft.AspNetCore.Components.RenderFragment __arg1) { __builder.OpenComponent>(seq); - __builder.AddComponentParameter(__seq0, "Value", __arg0); + __builder.AddComponentParameter(__seq0, nameof(global::Test.ParentTwo. +#nullable restore +#line (2,16)-(2,21) "x:\dir\subdir\Test\TestComponent.cshtml" +Value + +#line default +#line hidden +#nullable disable + ), __arg0); __builder.AddComponentParameter(__seq1, "ChildContent", __arg1); __builder.CloseComponent(); } diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_CombiningMultipleAncestors/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_CombiningMultipleAncestors/TestComponent.mappings.txt index 3d120f644ea..2f6201059bb 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_CombiningMultipleAncestors/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_CombiningMultipleAncestors/TestComponent.mappings.txt @@ -8,3 +8,13 @@ Source Location: (59:1,24 [7] x:\dir\subdir\Test\TestComponent.cshtml) Generated Location: (1345:34,0 [7] ) |"Hello"| +Source Location: (11:0,11 [5] x:\dir\subdir\Test\TestComponent.cshtml) +|Value| +Generated Location: (2704:65,0 [5] ) +|Value| + +Source Location: (50:1,15 [5] x:\dir\subdir\Test\TestComponent.cshtml) +|Value| +Generated Location: (3554:85,0 [5] ) +|Value| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_Explicit/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_Explicit/TestComponent.codegen.cs index 108d3f777a1..a56a42d9764 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_Explicit/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_Explicit/TestComponent.codegen.cs @@ -18,7 +18,15 @@ public partial class TestComponent : global::Microsoft.AspNetCore.Components.Com protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { __builder.OpenComponent>(0); - __builder.AddComponentParameter(1, "Items", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck>( + __builder.AddComponentParameter(1, nameof(global::Test.Grid. +#nullable restore +#line (1,24)-(1,29) "x:\dir\subdir\Test\TestComponent.cshtml" +Items + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck>( #nullable restore #line (1,33)-(1,56) "x:\dir\subdir\Test\TestComponent.cshtml" Array.Empty() diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_Explicit/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_Explicit/TestComponent.mappings.txt index 89995bc7197..84bf77a9101 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_Explicit/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_Explicit/TestComponent.mappings.txt @@ -1,5 +1,10 @@ -Source Location: (32:0,32 [23] x:\dir\subdir\Test\TestComponent.cshtml) +Source Location: (23:0,23 [5] x:\dir\subdir\Test\TestComponent.cshtml) +|Items| +Generated Location: (890:23,0 [5] ) +|Items| + +Source Location: (32:0,32 [23] x:\dir\subdir\Test\TestComponent.cshtml) |Array.Empty()| -Generated Location: (1004:23,0 [23] ) +Generated Location: (1186:31,0 [23] ) |Array.Empty()| diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_ExplicitOverride/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_ExplicitOverride/TestComponent.codegen.cs index d3b7e2cd7bf..895c9ff49d8 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_ExplicitOverride/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_ExplicitOverride/TestComponent.codegen.cs @@ -18,7 +18,15 @@ public partial class TestComponent : global::Microsoft.AspNetCore.Components.Com protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { __builder.OpenComponent>(0); - __builder.AddComponentParameter(1, "Items", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck>( + __builder.AddComponentParameter(1, nameof(global::Test.Grid. +#nullable restore +#line (1,24)-(1,29) "x:\dir\subdir\Test\TestComponent.cshtml" +Items + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck>( #nullable restore #line (1,33)-(1,56) "x:\dir\subdir\Test\TestComponent.cshtml" Array.Empty() diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_ExplicitOverride/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_ExplicitOverride/TestComponent.mappings.txt index 89995bc7197..84bf77a9101 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_ExplicitOverride/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_ExplicitOverride/TestComponent.mappings.txt @@ -1,5 +1,10 @@ -Source Location: (32:0,32 [23] x:\dir\subdir\Test\TestComponent.cshtml) +Source Location: (23:0,23 [5] x:\dir\subdir\Test\TestComponent.cshtml) +|Items| +Generated Location: (890:23,0 [5] ) +|Items| + +Source Location: (32:0,32 [23] x:\dir\subdir\Test\TestComponent.cshtml) |Array.Empty()| -Generated Location: (1004:23,0 [23] ) +Generated Location: (1186:31,0 [23] ) |Array.Empty()| diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_GenericArgumentNested/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_GenericArgumentNested/TestComponent.codegen.cs index a4f0721bf9c..a17522443d6 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_GenericArgumentNested/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_GenericArgumentNested/TestComponent.codegen.cs @@ -45,7 +45,15 @@ internal static class TypeInference public static void CreateGrid_0(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder, int seq, int __seq0, global::System.Func> __arg0, int __seq1, Microsoft.AspNetCore.Components.RenderFragment __arg1) { __builder.OpenComponent>(seq); - __builder.AddComponentParameter(__seq0, "Data", __arg0); + __builder.AddComponentParameter(__seq0, nameof(global::Test.Grid. +#nullable restore +#line (1,7)-(1,11) "x:\dir\subdir\Test\TestComponent.cshtml" +Data + +#line default +#line hidden +#nullable disable + ), __arg0); __builder.AddComponentParameter(__seq1, "ChildContent", __arg1); __builder.CloseComponent(); } diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_GenericArgumentNested/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_GenericArgumentNested/TestComponent.mappings.txt index 4f44c655e05..fb2c73260a9 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_GenericArgumentNested/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_GenericArgumentNested/TestComponent.mappings.txt @@ -3,3 +3,8 @@ Generated Location: (850:23,0 [24] ) |() => new List()| +Source Location: (6:0,6 [4] x:\dir\subdir\Test\TestComponent.cshtml) +|Data| +Generated Location: (2056:50,0 [4] ) +|Data| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_GenericArgumentNested_Dictionary/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_GenericArgumentNested_Dictionary/TestComponent.codegen.cs index ab27441ef86..232dfc10220 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_GenericArgumentNested_Dictionary/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_GenericArgumentNested_Dictionary/TestComponent.codegen.cs @@ -45,7 +45,15 @@ internal static class TypeInference public static void CreateGrid_0(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder, int seq, int __seq0, global::System.Func> __arg0, int __seq1, Microsoft.AspNetCore.Components.RenderFragment __arg1) { __builder.OpenComponent>(seq); - __builder.AddComponentParameter(__seq0, "Data", __arg0); + __builder.AddComponentParameter(__seq0, nameof(global::Test.Grid. +#nullable restore +#line (1,7)-(1,11) "x:\dir\subdir\Test\TestComponent.cshtml" +Data + +#line default +#line hidden +#nullable disable + ), __arg0); __builder.AddComponentParameter(__seq1, "ChildContent", __arg1); __builder.CloseComponent(); } diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_GenericArgumentNested_Dictionary/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_GenericArgumentNested_Dictionary/TestComponent.mappings.txt index 6d7138c34ea..610bc45b6fd 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_GenericArgumentNested_Dictionary/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_GenericArgumentNested_Dictionary/TestComponent.mappings.txt @@ -3,3 +3,8 @@ Generated Location: (850:23,0 [33] ) |() => new Dictionary()| +Source Location: (6:0,6 [4] x:\dir\subdir\Test\TestComponent.cshtml) +|Data| +Generated Location: (2082:50,0 [4] ) +|Data| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_GenericArgumentNested_Dictionary_02/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_GenericArgumentNested_Dictionary_02/TestComponent.codegen.cs index b082bccca5c..ff6c0195ccb 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_GenericArgumentNested_Dictionary_02/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_GenericArgumentNested_Dictionary_02/TestComponent.codegen.cs @@ -45,7 +45,15 @@ internal static class TypeInference public static void CreateGrid_0(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder, int seq, int __seq0, global::System.Func> __arg0, int __seq1, Microsoft.AspNetCore.Components.RenderFragment __arg1) { __builder.OpenComponent>(seq); - __builder.AddComponentParameter(__seq0, "Data", __arg0); + __builder.AddComponentParameter(__seq0, nameof(global::Test.Grid. +#nullable restore +#line (1,7)-(1,11) "x:\dir\subdir\Test\TestComponent.cshtml" +Data + +#line default +#line hidden +#nullable disable + ), __arg0); __builder.AddComponentParameter(__seq1, "ChildContent", __arg1); __builder.CloseComponent(); } diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_GenericArgumentNested_Dictionary_02/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_GenericArgumentNested_Dictionary_02/TestComponent.mappings.txt index 6d7138c34ea..3059d1b3ceb 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_GenericArgumentNested_Dictionary_02/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_GenericArgumentNested_Dictionary_02/TestComponent.mappings.txt @@ -3,3 +3,8 @@ Generated Location: (850:23,0 [33] ) |() => new Dictionary()| +Source Location: (6:0,6 [4] x:\dir\subdir\Test\TestComponent.cshtml) +|Data| +Generated Location: (2087:50,0 [4] ) +|Data| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_GenericArgumentNested_Dictionary_03/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_GenericArgumentNested_Dictionary_03/TestComponent.codegen.cs index 0c693e719e1..9dc2ccb960c 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_GenericArgumentNested_Dictionary_03/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_GenericArgumentNested_Dictionary_03/TestComponent.codegen.cs @@ -45,7 +45,15 @@ internal static class TypeInference public static void CreateGrid_0(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder, int seq, int __seq0, global::System.Collections.Generic.Dictionary __arg0, int __seq1, Microsoft.AspNetCore.Components.RenderFragment __arg1) { __builder.OpenComponent>(seq); - __builder.AddComponentParameter(__seq0, "Data", __arg0); + __builder.AddComponentParameter(__seq0, nameof(global::Test.Grid. +#nullable restore +#line (1,7)-(1,11) "x:\dir\subdir\Test\TestComponent.cshtml" +Data + +#line default +#line hidden +#nullable disable + ), __arg0); __builder.AddComponentParameter(__seq1, "ChildContent", __arg1); __builder.CloseComponent(); } diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_GenericArgumentNested_Dictionary_03/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_GenericArgumentNested_Dictionary_03/TestComponent.mappings.txt index 1905c6d3fd1..d7d695c3c25 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_GenericArgumentNested_Dictionary_03/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_GenericArgumentNested_Dictionary_03/TestComponent.mappings.txt @@ -3,3 +3,8 @@ Generated Location: (850:23,0 [27] ) |new Dictionary()| +Source Location: (6:0,6 [4] x:\dir\subdir\Test\TestComponent.cshtml) +|Data| +Generated Location: (2055:50,0 [4] ) +|Data| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_GenericArgumentNested_Dictionary_Dynamic/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_GenericArgumentNested_Dictionary_Dynamic/TestComponent.codegen.cs index e576793a3cf..748ef5de42d 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_GenericArgumentNested_Dictionary_Dynamic/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_GenericArgumentNested_Dictionary_Dynamic/TestComponent.codegen.cs @@ -45,7 +45,15 @@ internal static class TypeInference public static void CreateGrid_0(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder, int seq, int __seq0, global::System.Collections.Generic.Dictionary __arg0, int __seq1, Microsoft.AspNetCore.Components.RenderFragment __arg1) { __builder.OpenComponent>(seq); - __builder.AddComponentParameter(__seq0, "Data", __arg0); + __builder.AddComponentParameter(__seq0, nameof(global::Test.Grid. +#nullable restore +#line (1,7)-(1,11) "x:\dir\subdir\Test\TestComponent.cshtml" +Data + +#line default +#line hidden +#nullable disable + ), __arg0); __builder.AddComponentParameter(__seq1, "ChildContent", __arg1); __builder.CloseComponent(); } diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_GenericArgumentNested_Dictionary_Dynamic/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_GenericArgumentNested_Dictionary_Dynamic/TestComponent.mappings.txt index 207d7614aab..843b5a3441d 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_GenericArgumentNested_Dictionary_Dynamic/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_GenericArgumentNested_Dictionary_Dynamic/TestComponent.mappings.txt @@ -3,3 +3,8 @@ Generated Location: (850:23,0 [33] ) |new Dictionary()| +Source Location: (6:0,6 [4] x:\dir\subdir\Test\TestComponent.cshtml) +|Data| +Generated Location: (2059:50,0 [4] ) +|Data| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_GenericChildContent/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_GenericChildContent/TestComponent.codegen.cs index 744db39584f..8cafb636218 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_GenericChildContent/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_GenericChildContent/TestComponent.codegen.cs @@ -56,7 +56,15 @@ internal static class TypeInference public static void CreateGrid_0(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder, int seq, int __seq0, global::System.Collections.Generic.IEnumerable __arg0, int __seq1, global::Microsoft.AspNetCore.Components.RenderFragment __arg1) { __builder.OpenComponent>(seq); - __builder.AddComponentParameter(__seq0, "Items", __arg0); + __builder.AddComponentParameter(__seq0, nameof(global::Test.Grid. +#nullable restore +#line (1,7)-(1,12) "x:\dir\subdir\Test\TestComponent.cshtml" +Items + +#line default +#line hidden +#nullable disable + ), __arg0); __builder.AddComponentParameter(__seq1, "ChildContent", __arg1); __builder.CloseComponent(); } diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_GenericChildContent/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_GenericChildContent/TestComponent.mappings.txt index 72da1980ae7..1733803b963 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_GenericChildContent/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_GenericChildContent/TestComponent.mappings.txt @@ -8,3 +8,8 @@ Source Location: (50:0,50 [12] x:\dir\subdir\Test\TestComponent.cshtml) Generated Location: (1426:34,0 [12] ) |context.Year| +Source Location: (6:0,6 [5] x:\dir\subdir\Test\TestComponent.cshtml) +|Items| +Generated Location: (2366:61,0 [5] ) +|Items| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_GenericLambda/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_GenericLambda/TestComponent.codegen.cs index cbe2379768c..41f894b4a47 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_GenericLambda/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_GenericLambda/TestComponent.codegen.cs @@ -53,7 +53,15 @@ internal static class TypeInference public static void CreateGrid_0(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder, int seq, int __seq0, global::System.Collections.Generic.IEnumerable __arg0, int __seq1, global::Microsoft.AspNetCore.Components.RenderFragment __arg1) { __builder.OpenComponent>(seq); - __builder.AddComponentParameter(__seq0, "Items", __arg0); + __builder.AddComponentParameter(__seq0, nameof(global::Test.Grid. +#nullable restore +#line (1,7)-(1,12) "x:\dir\subdir\Test\TestComponent.cshtml" +Items + +#line default +#line hidden +#nullable disable + ), __arg0); __builder.AddComponentParameter(__seq1, "ChildContent", __arg1); __builder.CloseComponent(); } @@ -65,7 +73,15 @@ public static void CreateGrid_0_CaptureParameters(global::System.Collecti public static void CreateColumn_1(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder, int seq, global::System.Collections.Generic.IEnumerable __syntheticArg0, int __seq0, global::System.Func __arg0) { __builder.OpenComponent>(seq); - __builder.AddComponentParameter(__seq0, "SomeLambda", __arg0); + __builder.AddComponentParameter(__seq0, nameof(global::Test.Column. +#nullable restore +#line (1,50)-(1,60) "x:\dir\subdir\Test\TestComponent.cshtml" +SomeLambda + +#line default +#line hidden +#nullable disable + ), __arg0); __builder.CloseComponent(); } } diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_GenericLambda/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_GenericLambda/TestComponent.mappings.txt index 904bf649d2e..5c8e99104a8 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_GenericLambda/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_GenericLambda/TestComponent.mappings.txt @@ -8,3 +8,13 @@ Source Location: (63:0,63 [11] x:\dir\subdir\Test\TestComponent.cshtml) Generated Location: (1345:33,0 [11] ) |x => x.Year| +Source Location: (6:0,6 [5] x:\dir\subdir\Test\TestComponent.cshtml) +|Items| +Generated Location: (2233:58,0 [5] ) +|Items| + +Source Location: (49:0,49 [10] x:\dir\subdir\Test\TestComponent.cshtml) +|SomeLambda| +Generated Location: (3225:78,0 [10] ) +|SomeLambda| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_Inferred_MultipleConstraints/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_Inferred_MultipleConstraints/TestComponent.codegen.cs index f6cd5940eb4..ebb1672e215 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_Inferred_MultipleConstraints/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_Inferred_MultipleConstraints/TestComponent.codegen.cs @@ -46,7 +46,15 @@ public static void CreateColumn_0(global::Microsoft.AspNetCore.Components { __builder.OpenComponent>(seq); __builder.AddComponentParameter(__seq0, "Title", __arg0); - __builder.AddComponentParameter(__seq1, "FieldName", __arg1); + __builder.AddComponentParameter(__seq1, nameof(global::Test.Column. +#nullable restore +#line (3,30)-(3,39) "x:\dir\subdir\Test\TestComponent.cshtml" +FieldName + +#line default +#line hidden +#nullable disable + ), __arg1); __builder.AddComponentParameter(__seq2, "Format", __arg2); __builder.AddComponentParameter(__seq3, "Width", __arg3); __builder.CloseComponent(); diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_Inferred_MultipleConstraints/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_Inferred_MultipleConstraints/TestComponent.mappings.txt index 239a3f6e201..407c9ab593b 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_Inferred_MultipleConstraints/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_Inferred_MultipleConstraints/TestComponent.mappings.txt @@ -3,3 +3,8 @@ Generated Location: (871:23,0 [30] ) |Array.Empty()| +Source Location: (126:2,29 [9] x:\dir\subdir\Test\TestComponent.cshtml) +|FieldName| +Generated Location: (2189:51,0 [9] ) +|FieldName| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_Inferred_MultipleConstraints_ClassesAndInterfaces/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_Inferred_MultipleConstraints_ClassesAndInterfaces/TestComponent.codegen.cs index c75bfaf7169..9ab4d99531d 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_Inferred_MultipleConstraints_ClassesAndInterfaces/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_Inferred_MultipleConstraints_ClassesAndInterfaces/TestComponent.codegen.cs @@ -51,7 +51,15 @@ public static void CreateColumn_0(global::Microsoft.AspNetCore.Components { __builder.OpenComponent>(seq); __builder.AddComponentParameter(__seq0, "Title", __arg0); - __builder.AddComponentParameter(__seq1, "FieldName", __arg1); + __builder.AddComponentParameter(__seq1, nameof(global::Test.Column. +#nullable restore +#line (5,30)-(5,39) "x:\dir\subdir\Test\TestComponent.cshtml" +FieldName + +#line default +#line hidden +#nullable disable + ), __arg1); __builder.AddComponentParameter(__seq2, "Format", __arg2); __builder.AddComponentParameter(__seq3, "Width", __arg3); __builder.CloseComponent(); diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_Inferred_MultipleConstraints_ClassesAndInterfaces/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_Inferred_MultipleConstraints_ClassesAndInterfaces/TestComponent.mappings.txt index 760a78d03ab..9a055201ede 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_Inferred_MultipleConstraints_ClassesAndInterfaces/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_Inferred_MultipleConstraints_ClassesAndInterfaces/TestComponent.mappings.txt @@ -10,3 +10,8 @@ Source Location: (57:2,39 [30] x:\dir\subdir\Test\TestComponent.cshtml) Generated Location: (979:28,0 [30] ) |Array.Empty()| +Source Location: (144:4,29 [9] x:\dir\subdir\Test\TestComponent.cshtml) +|FieldName| +Generated Location: (2322:56,0 [9] ) +|FieldName| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_Inferred_MultipleConstraints_GenericClassConstraints/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_Inferred_MultipleConstraints_GenericClassConstraints/TestComponent.codegen.cs index 8c93fb7247d..47ab73941ea 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_Inferred_MultipleConstraints_GenericClassConstraints/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_Inferred_MultipleConstraints_GenericClassConstraints/TestComponent.codegen.cs @@ -51,7 +51,15 @@ public static void CreateColumn_0(global::Microsoft.AspNetCore.Components { __builder.OpenComponent>(seq); __builder.AddComponentParameter(__seq0, "Title", __arg0); - __builder.AddComponentParameter(__seq1, "FieldName", __arg1); + __builder.AddComponentParameter(__seq1, nameof(global::Test.Column. +#nullable restore +#line (4,30)-(4,39) "x:\dir\subdir\Test\TestComponent.cshtml" +FieldName + +#line default +#line hidden +#nullable disable + ), __arg1); __builder.AddComponentParameter(__seq2, "Format", __arg2); __builder.AddComponentParameter(__seq3, "Width", __arg3); __builder.CloseComponent(); diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_Inferred_MultipleConstraints_GenericClassConstraints/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_Inferred_MultipleConstraints_GenericClassConstraints/TestComponent.mappings.txt index dcaa9ab609e..33ba752f4ab 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_Inferred_MultipleConstraints_GenericClassConstraints/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_Inferred_MultipleConstraints_GenericClassConstraints/TestComponent.mappings.txt @@ -10,3 +10,8 @@ Source Location: (55:1,39 [30] x:\dir\subdir\Test\TestComponent.cshtml) Generated Location: (979:28,0 [30] ) |Array.Empty()| +Source Location: (142:3,29 [9] x:\dir\subdir\Test\TestComponent.cshtml) +|FieldName| +Generated Location: (2338:56,0 [9] ) +|FieldName| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_Inferred_WithConstraints/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_Inferred_WithConstraints/TestComponent.codegen.cs index 66d193c0156..995c34b1652 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_Inferred_WithConstraints/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_Inferred_WithConstraints/TestComponent.codegen.cs @@ -46,7 +46,15 @@ public static void CreateColumn_0(global::Microsoft.AspNetCore.Components { __builder.OpenComponent>(seq); __builder.AddComponentParameter(__seq0, "Title", __arg0); - __builder.AddComponentParameter(__seq1, "FieldName", __arg1); + __builder.AddComponentParameter(__seq1, nameof(global::Test.Column. +#nullable restore +#line (3,30)-(3,39) "x:\dir\subdir\Test\TestComponent.cshtml" +FieldName + +#line default +#line hidden +#nullable disable + ), __arg1); __builder.AddComponentParameter(__seq2, "Format", __arg2); __builder.AddComponentParameter(__seq3, "Width", __arg3); __builder.CloseComponent(); diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_Inferred_WithConstraints/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_Inferred_WithConstraints/TestComponent.mappings.txt index 239a3f6e201..37f5e5d7d26 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_Inferred_WithConstraints/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_Inferred_WithConstraints/TestComponent.mappings.txt @@ -3,3 +3,8 @@ Generated Location: (871:23,0 [30] ) |Array.Empty()| +Source Location: (126:2,29 [9] x:\dir\subdir\Test\TestComponent.cshtml) +|FieldName| +Generated Location: (2182:51,0 [9] ) +|FieldName| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_Multilayer/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_Multilayer/TestComponent.codegen.cs index e19de176316..98ecd97969c 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_Multilayer/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_Multilayer/TestComponent.codegen.cs @@ -50,7 +50,15 @@ internal static class TypeInference public static void CreateAncestor_0(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder, int seq, int __seq0, global::System.Collections.Generic.IEnumerable __arg0, int __seq1, global::Microsoft.AspNetCore.Components.RenderFragment __arg1) { __builder.OpenComponent>(seq); - __builder.AddComponentParameter(__seq0, "Items", __arg0); + __builder.AddComponentParameter(__seq0, nameof(global::Test.Ancestor. +#nullable restore +#line (1,11)-(1,16) "x:\dir\subdir\Test\TestComponent.cshtml" +Items + +#line default +#line hidden +#nullable disable + ), __arg0); __builder.AddComponentParameter(__seq1, "ChildContent", __arg1); __builder.CloseComponent(); } diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_Multilayer/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_Multilayer/TestComponent.mappings.txt index c97f4d1e28d..7b46f15e11a 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_Multilayer/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_Multilayer/TestComponent.mappings.txt @@ -3,3 +3,8 @@ Generated Location: (854:23,0 [23] ) |Array.Empty()| +Source Location: (10:0,10 [5] x:\dir\subdir\Test\TestComponent.cshtml) +|Items| +Generated Location: (2398:55,0 [5] ) +|Items| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_MultipleTypes/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_MultipleTypes/TestComponent.codegen.cs index 57a5af64663..6ce87c69202 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_MultipleTypes/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_MultipleTypes/TestComponent.codegen.cs @@ -62,8 +62,24 @@ internal static class TypeInference public static void CreateParent_0(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder, int seq, int __seq0, global::System.Collections.Generic.Dictionary __arg0, int __seq1, TOther __arg1, int __seq2, global::Microsoft.AspNetCore.Components.RenderFragment __arg2) { __builder.OpenComponent>(seq); - __builder.AddComponentParameter(__seq0, "Data", __arg0); - __builder.AddComponentParameter(__seq1, "Other", __arg1); + __builder.AddComponentParameter(__seq0, nameof(global::Test.Parent. +#nullable restore +#line (1,9)-(1,13) "x:\dir\subdir\Test\TestComponent.cshtml" +Data + +#line default +#line hidden +#nullable disable + ), __arg0); + __builder.AddComponentParameter(__seq1, nameof(global::Test.Parent. +#nullable restore +#line (1,76)-(1,81) "x:\dir\subdir\Test\TestComponent.cshtml" +Other + +#line default +#line hidden +#nullable disable + ), __arg1); __builder.AddComponentParameter(__seq2, "ChildContent", __arg2); __builder.CloseComponent(); } @@ -76,7 +92,15 @@ public static void CreateParent_0_CaptureParameters(global public static void CreateChild_1(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder, int seq, TOther __syntheticArg0, global::System.Collections.Generic.Dictionary __syntheticArg1, global::System.Collections.Generic.Dictionary __syntheticArg2, int __seq0, global::System.Collections.Generic.ICollection __arg0) { __builder.OpenComponent>(seq); - __builder.AddComponentParameter(__seq0, "ChildOnlyItems", __arg0); + __builder.AddComponentParameter(__seq0, nameof(global::Test.Child. +#nullable restore +#line (2,12)-(2,26) "x:\dir\subdir\Test\TestComponent.cshtml" +ChildOnlyItems + +#line default +#line hidden +#nullable disable + ), __arg0); __builder.CloseComponent(); } } diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_MultipleTypes/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_MultipleTypes/TestComponent.mappings.txt index be2423480f7..cc45c286efa 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_MultipleTypes/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_MultipleTypes/TestComponent.mappings.txt @@ -13,3 +13,18 @@ Source Location: (133:1,29 [23] x:\dir\subdir\Test\TestComponent.cshtml) Generated Location: (1680:41,0 [23] ) |new[] { 'a', 'b', 'c' }| +Source Location: (8:0,8 [4] x:\dir\subdir\Test\TestComponent.cshtml) +|Data| +Generated Location: (2720:67,0 [4] ) +|Data| + +Source Location: (75:0,75 [5] x:\dir\subdir\Test\TestComponent.cshtml) +|Other| +Generated Location: (2978:76,0 [5] ) +|Other| + +Source Location: (115:1,11 [14] x:\dir\subdir\Test\TestComponent.cshtml) +|ChildOnlyItems| +Generated Location: (4252:97,0 [14] ) +|ChildOnlyItems| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_NotCascaded_CreatesError/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_NotCascaded_CreatesError/TestComponent.codegen.cs index 2307182429b..b7ed7efc056 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_NotCascaded_CreatesError/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_NotCascaded_CreatesError/TestComponent.codegen.cs @@ -40,7 +40,15 @@ internal static class TypeInference public static void CreateGrid_0(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder, int seq, int __seq0, global::System.Collections.Generic.IEnumerable __arg0, int __seq1, global::Microsoft.AspNetCore.Components.RenderFragment __arg1) { __builder.OpenComponent>(seq); - __builder.AddComponentParameter(__seq0, "Items", __arg0); + __builder.AddComponentParameter(__seq0, nameof(global::Test.Grid. +#nullable restore +#line (1,7)-(1,12) "x:\dir\subdir\Test\TestComponent.cshtml" +Items + +#line default +#line hidden +#nullable disable + ), __arg0); __builder.AddComponentParameter(__seq1, "ChildContent", __arg1); __builder.CloseComponent(); } diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_NotCascaded_CreatesError/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_NotCascaded_CreatesError/TestComponent.mappings.txt index b503c1677a9..6e56cf0909c 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_NotCascaded_CreatesError/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_NotCascaded_CreatesError/TestComponent.mappings.txt @@ -3,3 +3,8 @@ Generated Location: (830:22,0 [23] ) |Array.Empty()| +Source Location: (6:0,6 [5] x:\dir\subdir\Test\TestComponent.cshtml) +|Items| +Generated Location: (1663:45,0 [5] ) +|Items| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_NotCascaded_Explicit/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_NotCascaded_Explicit/TestComponent.codegen.cs index 865abfb98dd..737e0c9e22c 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_NotCascaded_Explicit/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_NotCascaded_Explicit/TestComponent.codegen.cs @@ -18,7 +18,15 @@ public partial class TestComponent : global::Microsoft.AspNetCore.Components.Com protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { __builder.OpenComponent>(0); - __builder.AddComponentParameter(1, "Items", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck>( + __builder.AddComponentParameter(1, nameof(global::Test.Grid. +#nullable restore +#line (1,24)-(1,29) "x:\dir\subdir\Test\TestComponent.cshtml" +Items + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck>( #nullable restore #line (1,33)-(1,56) "x:\dir\subdir\Test\TestComponent.cshtml" Array.Empty() diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_NotCascaded_Explicit/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_NotCascaded_Explicit/TestComponent.mappings.txt index 89995bc7197..84bf77a9101 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_NotCascaded_Explicit/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_NotCascaded_Explicit/TestComponent.mappings.txt @@ -1,5 +1,10 @@ -Source Location: (32:0,32 [23] x:\dir\subdir\Test\TestComponent.cshtml) +Source Location: (23:0,23 [5] x:\dir\subdir\Test\TestComponent.cshtml) +|Items| +Generated Location: (890:23,0 [5] ) +|Items| + +Source Location: (32:0,32 [23] x:\dir\subdir\Test\TestComponent.cshtml) |Array.Empty()| -Generated Location: (1004:23,0 [23] ) +Generated Location: (1186:31,0 [23] ) |Array.Empty()| diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_NotCascaded_Inferred/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_NotCascaded_Inferred/TestComponent.codegen.cs index 0186029f22e..c287f3224ae 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_NotCascaded_Inferred/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_NotCascaded_Inferred/TestComponent.codegen.cs @@ -46,7 +46,15 @@ internal static class TypeInference public static void CreateGrid_0(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder, int seq, int __seq0, global::System.Collections.Generic.IEnumerable __arg0, int __seq1, global::Microsoft.AspNetCore.Components.RenderFragment __arg1) { __builder.OpenComponent>(seq); - __builder.AddComponentParameter(__seq0, "Items", __arg0); + __builder.AddComponentParameter(__seq0, nameof(global::Test.Grid. +#nullable restore +#line (1,7)-(1,12) "x:\dir\subdir\Test\TestComponent.cshtml" +Items + +#line default +#line hidden +#nullable disable + ), __arg0); __builder.AddComponentParameter(__seq1, "ChildContent", __arg1); __builder.CloseComponent(); } diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_NotCascaded_Inferred/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_NotCascaded_Inferred/TestComponent.mappings.txt index 65c881a3b87..07e6f873093 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_NotCascaded_Inferred/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_NotCascaded_Inferred/TestComponent.mappings.txt @@ -3,3 +3,8 @@ Generated Location: (850:23,0 [23] ) |Array.Empty()| +Source Location: (6:0,6 [5] x:\dir\subdir\Test\TestComponent.cshtml) +|Items| +Generated Location: (2192:51,0 [5] ) +|Items| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_Override/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_Override/TestComponent.codegen.cs index f3aec34ac7e..281c40351b4 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_Override/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_Override/TestComponent.codegen.cs @@ -53,7 +53,15 @@ internal static class TypeInference public static void CreateGrid_0(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder, int seq, int __seq0, global::System.Collections.Generic.IEnumerable __arg0, int __seq1, global::Microsoft.AspNetCore.Components.RenderFragment __arg1) { __builder.OpenComponent>(seq); - __builder.AddComponentParameter(__seq0, "Items", __arg0); + __builder.AddComponentParameter(__seq0, nameof(global::Test.Grid. +#nullable restore +#line (1,7)-(1,12) "x:\dir\subdir\Test\TestComponent.cshtml" +Items + +#line default +#line hidden +#nullable disable + ), __arg0); __builder.AddComponentParameter(__seq1, "ChildContent", __arg1); __builder.CloseComponent(); } @@ -65,7 +73,15 @@ public static void CreateGrid_0_CaptureParameters(global::System.Collecti public static void CreateColumn_1(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder, int seq, int __seq0, TItem __arg0) { __builder.OpenComponent>(seq); - __builder.AddComponentParameter(__seq0, "OverrideParam", __arg0); + __builder.AddComponentParameter(__seq0, nameof(global::Test.Column. +#nullable restore +#line (1,50)-(1,63) "x:\dir\subdir\Test\TestComponent.cshtml" +OverrideParam + +#line default +#line hidden +#nullable disable + ), __arg0); __builder.CloseComponent(); } } diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_Override/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_Override/TestComponent.mappings.txt index 9a26ea7354a..a64b450019f 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_Override/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_Override/TestComponent.mappings.txt @@ -8,3 +8,13 @@ Source Location: (66:0,66 [13] x:\dir\subdir\Test\TestComponent.cshtml) Generated Location: (1316:33,0 [13] ) |"Some string"| +Source Location: (6:0,6 [5] x:\dir\subdir\Test\TestComponent.cshtml) +|Items| +Generated Location: (2206:58,0 [5] ) +|Items| + +Source Location: (49:0,49 [13] x:\dir\subdir\Test\TestComponent.cshtml) +|OverrideParam| +Generated Location: (3070:78,0 [13] ) +|OverrideParam| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_Override_Multilayer/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_Override_Multilayer/TestComponent.codegen.cs index 51c95e3733c..9dd6f9f88a0 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_Override_Multilayer/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_Override_Multilayer/TestComponent.codegen.cs @@ -77,7 +77,15 @@ internal static class TypeInference public static void CreateTreeNode_0(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder, int seq, int __seq0, TItem __arg0, int __seq1, global::Microsoft.AspNetCore.Components.RenderFragment __arg1) { __builder.OpenComponent>(seq); - __builder.AddComponentParameter(__seq0, "Item", __arg0); + __builder.AddComponentParameter(__seq0, nameof(global::Test.TreeNode. +#nullable restore +#line (1,11)-(1,15) "x:\dir\subdir\Test\TestComponent.cshtml" +Item + +#line default +#line hidden +#nullable disable + ), __arg0); __builder.AddComponentParameter(__seq1, "ChildContent", __arg1); __builder.CloseComponent(); } @@ -89,7 +97,15 @@ public static void CreateTreeNode_0_CaptureParameters(TItem __arg0, out T public static void CreateTreeNode_1(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder, int seq, int __seq0, TItem __arg0, int __seq1, global::Microsoft.AspNetCore.Components.RenderFragment __arg1) { __builder.OpenComponent>(seq); - __builder.AddComponentParameter(__seq0, "Item", __arg0); + __builder.AddComponentParameter(__seq0, nameof(global::Test.TreeNode. +#nullable restore +#line (2,15)-(2,19) "x:\dir\subdir\Test\TestComponent.cshtml" +Item + +#line default +#line hidden +#nullable disable + ), __arg0); __builder.AddComponentParameter(__seq1, "ChildContent", __arg1); __builder.CloseComponent(); } diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_Override_Multilayer/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_Override_Multilayer/TestComponent.mappings.txt index 85991e0e03f..8d731b4cf42 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_Override_Multilayer/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_Override_Multilayer/TestComponent.mappings.txt @@ -8,3 +8,13 @@ Source Location: (54:1,21 [37] x:\dir\subdir\Test\TestComponent.cshtml) Generated Location: (1342:34,0 [37] ) |System.Threading.Thread.CurrentThread| +Source Location: (10:0,10 [4] x:\dir\subdir\Test\TestComponent.cshtml) +|Item| +Generated Location: (4194:82,0 [4] ) +|Item| + +Source Location: (47:1,14 [4] x:\dir\subdir\Test\TestComponent.cshtml) +|Item| +Generated Location: (5046:102,0 [4] ) +|Item| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_ParameterInNamespace/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_ParameterInNamespace/TestComponent.codegen.cs index 6e6c123693c..d1caa8a27ce 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_ParameterInNamespace/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_ParameterInNamespace/TestComponent.codegen.cs @@ -52,7 +52,15 @@ internal static class TypeInference public static void CreateParentComponent_0(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder, int seq, int __seq0, global::MyApp.MyClass __arg0, int __seq1, Microsoft.AspNetCore.Components.RenderFragment __arg1) { __builder.OpenComponent>(seq); - __builder.AddComponentParameter(__seq0, "Parameter", __arg0); + __builder.AddComponentParameter(__seq0, nameof(global::MyApp.Components.ParentComponent. +#nullable restore +#line (3,18)-(3,27) "x:\dir\subdir\Test\TestComponent.cshtml" +Parameter + +#line default +#line hidden +#nullable disable + ), __arg0); __builder.AddComponentParameter(__seq1, "ChildContent", __arg1); __builder.CloseComponent(); } diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_ParameterInNamespace/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_ParameterInNamespace/TestComponent.mappings.txt index 113df549f07..d77abcf4c27 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_ParameterInNamespace/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_ParameterInNamespace/TestComponent.mappings.txt @@ -8,3 +8,8 @@ Source Location: (59:2,28 [21] x:\dir\subdir\Test\TestComponent.cshtml) Generated Location: (1019:30,0 [21] ) |new MyClass()| +Source Location: (48:2,17 [9] x:\dir\subdir\Test\TestComponent.cshtml) +|Parameter| +Generated Location: (2292:57,0 [9] ) +|Parameter| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_Partial_CreatesError/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_Partial_CreatesError/TestComponent.codegen.cs index c48f4cb5a9e..072a1eca680 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_Partial_CreatesError/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_Partial_CreatesError/TestComponent.codegen.cs @@ -46,7 +46,15 @@ internal static class TypeInference public static void CreateGrid_0(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder, int seq, int __seq0, global::System.Collections.Generic.IEnumerable __arg0, int __seq1, global::Microsoft.AspNetCore.Components.RenderFragment __arg1) { __builder.OpenComponent>(seq); - __builder.AddComponentParameter(__seq0, "Items", __arg0); + __builder.AddComponentParameter(__seq0, nameof(global::Test.Grid. +#nullable restore +#line (1,7)-(1,12) "x:\dir\subdir\Test\TestComponent.cshtml" +Items + +#line default +#line hidden +#nullable disable + ), __arg0); __builder.AddComponentParameter(__seq1, "ChildContent", __arg1); __builder.CloseComponent(); } diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_Partial_CreatesError/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_Partial_CreatesError/TestComponent.mappings.txt index 65c881a3b87..6a36ebc1e74 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_Partial_CreatesError/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_Partial_CreatesError/TestComponent.mappings.txt @@ -3,3 +3,8 @@ Generated Location: (850:23,0 [23] ) |Array.Empty()| +Source Location: (6:0,6 [5] x:\dir\subdir\Test\TestComponent.cshtml) +|Items| +Generated Location: (2071:51,0 [5] ) +|Items| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_Tuple/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_Tuple/TestComponent.codegen.cs index 1f65a70ca4f..ce7ec937614 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_Tuple/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_Tuple/TestComponent.codegen.cs @@ -45,7 +45,15 @@ internal static class TypeInference public static void CreateParentComponent_0(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder, int seq, int __seq0, (T, T) __arg0, int __seq1, Microsoft.AspNetCore.Components.RenderFragment __arg1) { __builder.OpenComponent>(seq); - __builder.AddComponentParameter(__seq0, "Parameter", __arg0); + __builder.AddComponentParameter(__seq0, nameof(global::Test.ParentComponent. +#nullable restore +#line (1,18)-(1,27) "x:\dir\subdir\Test\TestComponent.cshtml" +Parameter + +#line default +#line hidden +#nullable disable + ), __arg0); __builder.AddComponentParameter(__seq1, "ChildContent", __arg1); __builder.CloseComponent(); } diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_Tuple/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_Tuple/TestComponent.mappings.txt index 35719cf5f6a..08399705f57 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_Tuple/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_Tuple/TestComponent.mappings.txt @@ -3,3 +3,8 @@ Generated Location: (861:23,0 [6] ) |(1, 2)| +Source Location: (17:0,17 [9] x:\dir\subdir\Test\TestComponent.cshtml) +|Parameter| +Generated Location: (2041:50,0 [9] ) +|Parameter| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_WithSplatAndKey/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_WithSplatAndKey/TestComponent.codegen.cs index 28d7c6e3b55..90effdc4f65 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_WithSplatAndKey/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_WithSplatAndKey/TestComponent.codegen.cs @@ -79,7 +79,15 @@ internal static class TypeInference public static void CreateGrid_0(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder, int seq, int __seq0, global::System.Collections.Generic.IEnumerable __arg0, int __seq1, global::Microsoft.AspNetCore.Components.RenderFragment __arg1, int __seq2, object __arg2) { __builder.OpenComponent>(seq); - __builder.AddComponentParameter(__seq0, "Items", __arg0); + __builder.AddComponentParameter(__seq0, nameof(global::Test.Grid. +#nullable restore +#line (2,25)-(2,30) "x:\dir\subdir\Test\TestComponent.cshtml" +Items + +#line default +#line hidden +#nullable disable + ), __arg0); __builder.AddComponentParameter(__seq1, "ChildContent", __arg1); __builder.SetKey(__arg2); __builder.CloseComponent(); diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_WithSplatAndKey/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_WithSplatAndKey/TestComponent.mappings.txt index d71e0776a0d..70722389f90 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_WithSplatAndKey/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_WithSplatAndKey/TestComponent.mappings.txt @@ -23,3 +23,8 @@ Source Location: (78:1,13 [9] x:\dir\subdir\Test\TestComponent.cshtml) Generated Location: (1940:60,0 [9] ) |parentKey| +Source Location: (89:1,24 [5] x:\dir\subdir\Test\TestComponent.cshtml) +|Items| +Generated Location: (2813:84,0 [5] ) +|Items| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_WithUnrelatedType_CreatesError/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_WithUnrelatedType_CreatesError/TestComponent.codegen.cs index efac7c31c9a..4b5fb42d02c 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_WithUnrelatedType_CreatesError/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_WithUnrelatedType_CreatesError/TestComponent.codegen.cs @@ -44,7 +44,15 @@ internal static class TypeInference public static void CreateGrid_0(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder, int seq, int __seq0, global::System.Collections.Generic.Dictionary __arg0, int __seq1, global::Microsoft.AspNetCore.Components.RenderFragment __arg1) { __builder.OpenComponent>(seq); - __builder.AddComponentParameter(__seq0, "Items", __arg0); + __builder.AddComponentParameter(__seq0, nameof(global::Test.Grid. +#nullable restore +#line (1,7)-(1,12) "x:\dir\subdir\Test\TestComponent.cshtml" +Items + +#line default +#line hidden +#nullable disable + ), __arg0); __builder.AddComponentParameter(__seq1, "ChildContent", __arg1); __builder.CloseComponent(); } diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_WithUnrelatedType_CreatesError/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_WithUnrelatedType_CreatesError/TestComponent.mappings.txt index b235bdae2a2..1d8f7b98b58 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_WithUnrelatedType_CreatesError/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CascadingGenericInference_WithUnrelatedType_CreatesError/TestComponent.mappings.txt @@ -3,3 +3,8 @@ Generated Location: (850:23,0 [29] ) |new Dictionary()| +Source Location: (6:0,6 [5] x:\dir\subdir\Test\TestComponent.cshtml) +|Items| +Generated Location: (1983:49,0 [5] ) +|Items| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_AtSpecifiedInRazorFileForTypeParameter/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_AtSpecifiedInRazorFileForTypeParameter/TestComponent.codegen.cs index 095f390c943..a97ea92e8c6 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_AtSpecifiedInRazorFileForTypeParameter/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_AtSpecifiedInRazorFileForTypeParameter/TestComponent.codegen.cs @@ -18,7 +18,15 @@ public partial class TestComponent : global::Microsoft.AspNetCore.Components.Com protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { __builder.OpenComponent>(0); - __builder.AddComponentParameter(1, "Item", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( + __builder.AddComponentParameter(1, nameof(global::Test.C. +#nullable restore +#line (1,16)-(1,20) "x:\dir\subdir\Test\TestComponent.cshtml" +Item + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( #nullable restore #line (1,22)-(1,23) "x:\dir\subdir\Test\TestComponent.cshtml" 1 diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_AtSpecifiedInRazorFileForTypeParameter/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_AtSpecifiedInRazorFileForTypeParameter/TestComponent.mappings.txt index 96fd752fc3d..f00071fcaaa 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_AtSpecifiedInRazorFileForTypeParameter/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_AtSpecifiedInRazorFileForTypeParameter/TestComponent.mappings.txt @@ -1,5 +1,10 @@ -Source Location: (21:0,21 [1] x:\dir\subdir\Test\TestComponent.cshtml) +Source Location: (15:0,15 [4] x:\dir\subdir\Test\TestComponent.cshtml) +|Item| +Generated Location: (880:23,0 [4] ) +|Item| + +Source Location: (21:0,21 [1] x:\dir\subdir\Test\TestComponent.cshtml) |1| -Generated Location: (962:23,0 [1] ) +Generated Location: (1139:31,0 [1] ) |1| diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_Generic/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_Generic/TestComponent.codegen.cs index b2b543bc8d9..f7750986ac7 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_Generic/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_Generic/TestComponent.codegen.cs @@ -18,7 +18,15 @@ public partial class TestComponent : global::Microsoft.AspNetCore.Components.Com protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { __builder.OpenComponent>(0); - __builder.AddComponentParameter(1, "Item", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( + __builder.AddComponentParameter(1, nameof(global::Test.MyComponent. +#nullable restore +#line (1,27)-(1,31) "x:\dir\subdir\Test\TestComponent.cshtml" +Item + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( #nullable restore #line (1,35)-(1,39) "x:\dir\subdir\Test\TestComponent.cshtml" "hi" diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_Generic/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_Generic/TestComponent.mappings.txt index fb4caed6ff4..4d40cb44f40 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_Generic/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_Generic/TestComponent.mappings.txt @@ -1,5 +1,10 @@ -Source Location: (34:0,34 [4] x:\dir\subdir\Test\TestComponent.cshtml) +Source Location: (26:0,26 [4] x:\dir\subdir\Test\TestComponent.cshtml) +|Item| +Generated Location: (900:23,0 [4] ) +|Item| + +Source Location: (34:0,34 [4] x:\dir\subdir\Test\TestComponent.cshtml) |"hi"| -Generated Location: (958:23,0 [4] ) +Generated Location: (1145:31,0 [4] ) |"hi"| diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_GenericBind/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_GenericBind/TestComponent.codegen.cs index 49ff066d944..920d60a7bcf 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_GenericBind/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_GenericBind/TestComponent.codegen.cs @@ -18,7 +18,15 @@ public partial class TestComponent : global::Microsoft.AspNetCore.Components.Com protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { __builder.OpenComponent>(0); - __builder.AddComponentParameter(1, "Item", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( + __builder.AddComponentParameter(1, nameof(global::Test.MyComponent. +#nullable restore +#line (1,33)-(1,37) "x:\dir\subdir\Test\TestComponent.cshtml" +Item + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( #nullable restore #line (1,38)-(1,43) "x:\dir\subdir\Test\TestComponent.cshtml" Value @@ -27,7 +35,7 @@ protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components. #line hidden #nullable disable )); - __builder.AddComponentParameter(2, "ItemChanged", (global::System.Action)(__value => Value = __value)); + __builder.AddComponentParameter(2, nameof(global::Test.MyComponent.ItemChanged), (global::System.Action)(__value => Value = __value)); __builder.CloseComponent(); } #pragma warning restore 1998 diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_GenericBind/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_GenericBind/TestComponent.mappings.txt index 4805e65e8a6..291fee4e476 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_GenericBind/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_GenericBind/TestComponent.mappings.txt @@ -1,13 +1,18 @@ -Source Location: (37:0,37 [5] x:\dir\subdir\Test\TestComponent.cshtml) +Source Location: (32:0,32 [4] x:\dir\subdir\Test\TestComponent.cshtml) +|Item| +Generated Location: (900:23,0 [4] ) +|Item| + +Source Location: (37:0,37 [5] x:\dir\subdir\Test\TestComponent.cshtml) |Value| -Generated Location: (958:23,0 [5] ) +Generated Location: (1145:31,0 [5] ) |Value| Source Location: (53:1,7 [21] x:\dir\subdir\Test\TestComponent.cshtml) | string Value; | -Generated Location: (1327:35,0 [21] ) +Generated Location: (1553:43,0 [21] ) | string Value; | diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_GenericBindWeaklyTyped_TypeInference/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_GenericBindWeaklyTyped_TypeInference/TestComponent.codegen.cs index 20459e64e20..c991536c002 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_GenericBindWeaklyTyped_TypeInference/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_GenericBindWeaklyTyped_TypeInference/TestComponent.codegen.cs @@ -55,7 +55,15 @@ internal static class TypeInference public static void CreateMyComponent_0(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder, int seq, int __seq0, TItem __arg0, int __seq1, global::System.Object __arg1, int __seq2, global::System.Object __arg2) { __builder.OpenComponent>(seq); - __builder.AddComponentParameter(__seq0, "Value", __arg0); + __builder.AddComponentParameter(__seq0, nameof(global::Test.MyComponent. +#nullable restore +#line (1,31)-(1,36) "x:\dir\subdir\Test\TestComponent.cshtml" +Value + +#line default +#line hidden +#nullable disable + ), __arg0); __builder.AddComponentParameter(__seq1, "Item", __arg1); __builder.AddComponentParameter(__seq2, "ItemChanged", __arg2); __builder.CloseComponent(); diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_GenericBindWeaklyTyped_TypeInference/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_GenericBindWeaklyTyped_TypeInference/TestComponent.mappings.txt index d25b10a150e..271c7e1e1e2 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_GenericBindWeaklyTyped_TypeInference/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_GenericBindWeaklyTyped_TypeInference/TestComponent.mappings.txt @@ -17,3 +17,8 @@ Generated Location: (1339:40,0 [21] ) string Value; | +Source Location: (30:0,30 [5] x:\dir\subdir\Test\TestComponent.cshtml) +|Value| +Generated Location: (2037:60,0 [5] ) +|Value| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_GenericBind_TypeInference/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_GenericBind_TypeInference/TestComponent.codegen.cs index 4b3c3f6499d..b674d13fe66 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_GenericBind_TypeInference/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_GenericBind_TypeInference/TestComponent.codegen.cs @@ -57,15 +57,31 @@ internal static class TypeInference public static void CreateMyComponent_0(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder, int seq, int __seq0, TItem __arg0, int __seq1, global::System.Action __arg1) { __builder.OpenComponent>(seq); - __builder.AddComponentParameter(__seq0, "Item", __arg0); - __builder.AddComponentParameter(__seq1, "ItemChanged", __arg1); + __builder.AddComponentParameter(__seq0, nameof(global::Test.MyComponent. +#nullable restore +#line (1,20)-(1,24) "x:\dir\subdir\Test\TestComponent.cshtml" +Item + +#line default +#line hidden +#nullable disable + ), __arg0); + __builder.AddComponentParameter(__seq1, nameof(global::Test.MyComponent.ItemChanged), __arg1); __builder.CloseComponent(); } public static void CreateMyComponent_1(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder, int seq, int __seq0, TItem __arg0, int __seq1, global::System.Action __arg1) { __builder.OpenComponent>(seq); - __builder.AddComponentParameter(__seq0, "Item", __arg0); - __builder.AddComponentParameter(__seq1, "ItemChanged", __arg1); + __builder.AddComponentParameter(__seq0, nameof(global::Test.MyComponent. +#nullable restore +#line (2,20)-(2,24) "x:\dir\subdir\Test\TestComponent.cshtml" +Item + +#line default +#line hidden +#nullable disable + ), __arg0); + __builder.AddComponentParameter(__seq1, nameof(global::Test.MyComponent.ItemChanged), __arg1); __builder.CloseComponent(); } } diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_GenericBind_TypeInference/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_GenericBind_TypeInference/TestComponent.mappings.txt index 867d3f1c854..984477a5083 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_GenericBind_TypeInference/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_GenericBind_TypeInference/TestComponent.mappings.txt @@ -17,3 +17,13 @@ Generated Location: (1409:42,0 [21] ) string Value; | +Source Location: (19:0,19 [4] x:\dir\subdir\Test\TestComponent.cshtml) +|Item| +Generated Location: (2072:62,0 [4] ) +|Item| + +Source Location: (52:1,19 [4] x:\dir\subdir\Test\TestComponent.cshtml) +|Item| +Generated Location: (2780:77,0 [4] ) +|Item| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_GenericChildContent/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_GenericChildContent/TestComponent.codegen.cs index b1cc1dc9388..7cfe1d4f6f6 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_GenericChildContent/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_GenericChildContent/TestComponent.codegen.cs @@ -18,7 +18,15 @@ public partial class TestComponent : global::Microsoft.AspNetCore.Components.Com protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { __builder.OpenComponent>(0); - __builder.AddComponentParameter(1, "Item", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( + __builder.AddComponentParameter(1, nameof(global::Test.MyComponent. +#nullable restore +#line (1,27)-(1,31) "x:\dir\subdir\Test\TestComponent.cshtml" +Item + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( #nullable restore #line (1,35)-(1,39) "x:\dir\subdir\Test\TestComponent.cshtml" "hi" diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_GenericChildContent/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_GenericChildContent/TestComponent.mappings.txt index 2f1085d2040..af55d28d24a 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_GenericChildContent/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_GenericChildContent/TestComponent.mappings.txt @@ -1,10 +1,15 @@ -Source Location: (34:0,34 [4] x:\dir\subdir\Test\TestComponent.cshtml) +Source Location: (26:0,26 [4] x:\dir\subdir\Test\TestComponent.cshtml) +|Item| +Generated Location: (900:23,0 [4] ) +|Item| + +Source Location: (34:0,34 [4] x:\dir\subdir\Test\TestComponent.cshtml) |"hi"| -Generated Location: (958:23,0 [4] ) +Generated Location: (1145:31,0 [4] ) |"hi"| Source Location: (51:1,8 [17] x:\dir\subdir\Test\TestComponent.cshtml) |context.ToLower()| -Generated Location: (1357:34,0 [17] ) +Generated Location: (1544:42,0 [17] ) |context.ToLower()| diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_GenericChildContent_TypeInference/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_GenericChildContent_TypeInference/TestComponent.codegen.cs index 9e9d5ed11a1..b938222292e 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_GenericChildContent_TypeInference/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_GenericChildContent_TypeInference/TestComponent.codegen.cs @@ -51,7 +51,15 @@ internal static class TypeInference public static void CreateMyComponent_0(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder, int seq, int __seq0, TItem __arg0, int __seq1, global::Microsoft.AspNetCore.Components.RenderFragment __arg1) { __builder.OpenComponent>(seq); - __builder.AddComponentParameter(__seq0, "Item", __arg0); + __builder.AddComponentParameter(__seq0, nameof(global::Test.MyComponent. +#nullable restore +#line (1,14)-(1,18) "x:\dir\subdir\Test\TestComponent.cshtml" +Item + +#line default +#line hidden +#nullable disable + ), __arg0); __builder.AddComponentParameter(__seq1, "ChildContent", __arg1); __builder.CloseComponent(); } diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_GenericChildContent_TypeInference/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_GenericChildContent_TypeInference/TestComponent.mappings.txt index bf341df779f..881611aa2de 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_GenericChildContent_TypeInference/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_GenericChildContent_TypeInference/TestComponent.mappings.txt @@ -8,3 +8,8 @@ Source Location: (38:1,8 [17] x:\dir\subdir\Test\TestComponent.cshtml) Generated Location: (1117:32,0 [17] ) |context.ToLower()| +Source Location: (13:0,13 [4] x:\dir\subdir\Test\TestComponent.cshtml) +|Item| +Generated Location: (1953:56,0 [4] ) +|Item| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_GenericWeaklyTypedAttribute/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_GenericWeaklyTypedAttribute/TestComponent.codegen.cs index 3eae0879229..7c3a6c16573 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_GenericWeaklyTypedAttribute/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_GenericWeaklyTypedAttribute/TestComponent.codegen.cs @@ -18,7 +18,15 @@ public partial class TestComponent : global::Microsoft.AspNetCore.Components.Com protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { __builder.OpenComponent>(0); - __builder.AddComponentParameter(1, "Item", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( + __builder.AddComponentParameter(1, nameof(global::Test.MyComponent. +#nullable restore +#line (1,27)-(1,31) "x:\dir\subdir\Test\TestComponent.cshtml" +Item + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( #nullable restore #line (1,35)-(1,39) "x:\dir\subdir\Test\TestComponent.cshtml" "hi" diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_GenericWeaklyTypedAttribute/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_GenericWeaklyTypedAttribute/TestComponent.mappings.txt index ce11d3f5205..e8534d7eeb9 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_GenericWeaklyTypedAttribute/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_GenericWeaklyTypedAttribute/TestComponent.mappings.txt @@ -1,10 +1,15 @@ -Source Location: (34:0,34 [4] x:\dir\subdir\Test\TestComponent.cshtml) +Source Location: (26:0,26 [4] x:\dir\subdir\Test\TestComponent.cshtml) +|Item| +Generated Location: (900:23,0 [4] ) +|Item| + +Source Location: (34:0,34 [4] x:\dir\subdir\Test\TestComponent.cshtml) |"hi"| -Generated Location: (958:23,0 [4] ) +Generated Location: (1145:31,0 [4] ) |"hi"| Source Location: (50:0,50 [2] x:\dir\subdir\Test\TestComponent.cshtml) |17| -Generated Location: (1171:32,0 [2] ) +Generated Location: (1358:40,0 [2] ) |17| diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_GenericWeaklyTypedAttribute_TypeInference/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_GenericWeaklyTypedAttribute_TypeInference/TestComponent.codegen.cs index c0880f326f0..a4fb9e5d0de 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_GenericWeaklyTypedAttribute_TypeInference/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_GenericWeaklyTypedAttribute_TypeInference/TestComponent.codegen.cs @@ -46,7 +46,15 @@ internal static class TypeInference public static void CreateMyComponent_0(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder, int seq, int __seq0, TItem __arg0, int __seq1, global::System.Object __arg1) { __builder.OpenComponent>(seq); - __builder.AddComponentParameter(__seq0, "Item", __arg0); + __builder.AddComponentParameter(__seq0, nameof(global::Test.MyComponent. +#nullable restore +#line (1,14)-(1,18) "x:\dir\subdir\Test\TestComponent.cshtml" +Item + +#line default +#line hidden +#nullable disable + ), __arg0); __builder.AddComponentParameter(__seq1, "Other", __arg1); __builder.CloseComponent(); } diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_GenericWeaklyTypedAttribute_TypeInference/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_GenericWeaklyTypedAttribute_TypeInference/TestComponent.mappings.txt index 47ba381a658..83a7707fa63 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_GenericWeaklyTypedAttribute_TypeInference/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_GenericWeaklyTypedAttribute_TypeInference/TestComponent.mappings.txt @@ -8,3 +8,8 @@ Source Location: (37:0,37 [2] x:\dir\subdir\Test\TestComponent.cshtml) Generated Location: (994:30,0 [2] ) |17| +Source Location: (13:0,13 [4] x:\dir\subdir\Test\TestComponent.cshtml) +|Item| +Generated Location: (1696:51,0 [4] ) +|Item| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_Generic_TypeInference/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_Generic_TypeInference/TestComponent.codegen.cs index 36a64699051..7eb36f2acfe 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_Generic_TypeInference/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_Generic_TypeInference/TestComponent.codegen.cs @@ -38,7 +38,15 @@ internal static class TypeInference public static void CreateMyComponent_0(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder, int seq, int __seq0, TItem __arg0) { __builder.OpenComponent>(seq); - __builder.AddComponentParameter(__seq0, "Item", __arg0); + __builder.AddComponentParameter(__seq0, nameof(global::Test.MyComponent. +#nullable restore +#line (1,14)-(1,18) "x:\dir\subdir\Test\TestComponent.cshtml" +Item + +#line default +#line hidden +#nullable disable + ), __arg0); __builder.CloseComponent(); } } diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_Generic_TypeInference/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_Generic_TypeInference/TestComponent.mappings.txt index 25bd609d281..c79b887e47f 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_Generic_TypeInference/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_Generic_TypeInference/TestComponent.mappings.txt @@ -3,3 +3,8 @@ Generated Location: (837:22,0 [4] ) |"hi"| +Source Location: (13:0,13 [4] x:\dir\subdir\Test\TestComponent.cshtml) +|Item| +Generated Location: (1499:43,0 [4] ) +|Item| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_Generic_TypeInference_Multiple/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_Generic_TypeInference_Multiple/TestComponent.codegen.cs index a58d0421b11..e7d214c1e89 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_Generic_TypeInference_Multiple/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_Generic_TypeInference_Multiple/TestComponent.codegen.cs @@ -58,19 +58,43 @@ internal static class TypeInference public static void CreateMyComponent_0(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder, int seq, int __seq0, TItem __arg0) { __builder.OpenComponent>(seq); - __builder.AddComponentParameter(__seq0, "Item", __arg0); + __builder.AddComponentParameter(__seq0, nameof(global::Test.MyComponent. +#nullable restore +#line (1,14)-(1,18) "x:\dir\subdir\Test\TestComponent.cshtml" +Item + +#line default +#line hidden +#nullable disable + ), __arg0); __builder.CloseComponent(); } public static void CreateMyComponent_1(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder, int seq, int __seq0, TItem __arg0) { __builder.OpenComponent>(seq); - __builder.AddComponentParameter(__seq0, "Item", __arg0); + __builder.AddComponentParameter(__seq0, nameof(global::Test.MyComponent. +#nullable restore +#line (2,14)-(2,18) "x:\dir\subdir\Test\TestComponent.cshtml" +Item + +#line default +#line hidden +#nullable disable + ), __arg0); __builder.CloseComponent(); } public static void CreateMyComponent_2(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder, int seq, int __seq0, TItem __arg0) { __builder.OpenComponent>(seq); - __builder.AddComponentParameter(__seq0, "Item", __arg0); + __builder.AddComponentParameter(__seq0, nameof(global::Test.MyComponent. +#nullable restore +#line (3,14)-(3,18) "x:\dir\subdir\Test\TestComponent.cshtml" +Item + +#line default +#line hidden +#nullable disable + ), __arg0); __builder.CloseComponent(); } } diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_Generic_TypeInference_Multiple/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_Generic_TypeInference_Multiple/TestComponent.mappings.txt index 12156559b25..ab7009a89c0 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_Generic_TypeInference_Multiple/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_Generic_TypeInference_Multiple/TestComponent.mappings.txt @@ -13,3 +13,18 @@ Source Location: (93:2,21 [6] x:\dir\subdir\Test\TestComponent.cshtml) Generated Location: (1461:42,0 [6] ) |"bye!"| +Source Location: (13:0,13 [4] x:\dir\subdir\Test\TestComponent.cshtml) +|Item| +Generated Location: (2125:63,0 [4] ) +|Item| + +Source Location: (44:1,13 [4] x:\dir\subdir\Test\TestComponent.cshtml) +|Item| +Generated Location: (2673:77,0 [4] ) +|Item| + +Source Location: (85:2,13 [4] x:\dir\subdir\Test\TestComponent.cshtml) +|Item| +Generated Location: (3221:91,0 [4] ) +|Item| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_MultipleGenerics/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_MultipleGenerics/TestComponent.codegen.cs index ea70ef46139..f8e66110117 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_MultipleGenerics/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_MultipleGenerics/TestComponent.codegen.cs @@ -18,7 +18,15 @@ public partial class TestComponent : global::Microsoft.AspNetCore.Components.Com protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { __builder.OpenComponent>(0); - __builder.AddComponentParameter(1, "Item", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( + __builder.AddComponentParameter(1, nameof(global::Test.MyComponent. +#nullable restore +#line (1,39)-(1,43) "x:\dir\subdir\Test\TestComponent.cshtml" +Item + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( #nullable restore #line (1,47)-(1,51) "x:\dir\subdir\Test\TestComponent.cshtml" "hi" diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_MultipleGenerics/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_MultipleGenerics/TestComponent.mappings.txt index 02b113386fc..f85807c89f1 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_MultipleGenerics/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_MultipleGenerics/TestComponent.mappings.txt @@ -1,15 +1,20 @@ -Source Location: (46:0,46 [4] x:\dir\subdir\Test\TestComponent.cshtml) +Source Location: (38:0,38 [4] x:\dir\subdir\Test\TestComponent.cshtml) +|Item| +Generated Location: (910:23,0 [4] ) +|Item| + +Source Location: (46:0,46 [4] x:\dir\subdir\Test\TestComponent.cshtml) |"hi"| -Generated Location: (963:23,0 [4] ) +Generated Location: (1155:31,0 [4] ) |"hi"| Source Location: (77:1,22 [17] x:\dir\subdir\Test\TestComponent.cshtml) |context.ToLower()| -Generated Location: (1363:34,0 [17] ) +Generated Location: (1555:42,0 [17] ) |context.ToLower()| Source Location: (158:3,3 [29] x:\dir\subdir\Test\TestComponent.cshtml) |System.Math.Max(0, item.Item)| -Generated Location: (1838:47,0 [29] ) +Generated Location: (2030:55,0 [29] ) |System.Math.Max(0, item.Item)| diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_MultipleGenerics_TypeInference/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_MultipleGenerics_TypeInference/TestComponent.codegen.cs index b275f839bda..60906343a16 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_MultipleGenerics_TypeInference/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_MultipleGenerics_TypeInference/TestComponent.codegen.cs @@ -71,8 +71,24 @@ internal static class TypeInference public static void CreateMyComponent_0(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder, int seq, int __seq0, TItem1 __arg0, int __seq1, global::System.Collections.Generic.List __arg1, int __seq2, global::Microsoft.AspNetCore.Components.RenderFragment __arg2, int __seq3, global::Microsoft.AspNetCore.Components.RenderFragment.Context> __arg3) { __builder.OpenComponent>(seq); - __builder.AddComponentParameter(__seq0, "Item", __arg0); - __builder.AddComponentParameter(__seq1, "Items", __arg1); + __builder.AddComponentParameter(__seq0, nameof(global::Test.MyComponent. +#nullable restore +#line (1,14)-(1,18) "x:\dir\subdir\Test\TestComponent.cshtml" +Item + +#line default +#line hidden +#nullable disable + ), __arg0); + __builder.AddComponentParameter(__seq1, nameof(global::Test.MyComponent. +#nullable restore +#line (1,29)-(1,34) "x:\dir\subdir\Test\TestComponent.cshtml" +Items + +#line default +#line hidden +#nullable disable + ), __arg1); __builder.AddComponentParameter(__seq2, "ChildContent", __arg2); __builder.AddComponentParameter(__seq3, "AnotherChildContent", __arg3); __builder.CloseComponent(); diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_MultipleGenerics_TypeInference/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_MultipleGenerics_TypeInference/TestComponent.mappings.txt index 5a4685ea6b4..82707caaec6 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_MultipleGenerics_TypeInference/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_MultipleGenerics_TypeInference/TestComponent.mappings.txt @@ -18,3 +18,13 @@ Source Location: (159:3,3 [29] x:\dir\subdir\Test\TestComponent.cshtml) Generated Location: (1605:52,0 [29] ) |System.Math.Max(0, item.Item)| +Source Location: (13:0,13 [4] x:\dir\subdir\Test\TestComponent.cshtml) +|Item| +Generated Location: (2689:76,0 [4] ) +|Item| + +Source Location: (28:0,28 [5] x:\dir\subdir\Test\TestComponent.cshtml) +|Items| +Generated Location: (2946:85,0 [5] ) +|Items| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_NonGenericParameterizedChildContent_TypeInference/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_NonGenericParameterizedChildContent_TypeInference/TestComponent.codegen.cs index b000c57255f..7efea756386 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_NonGenericParameterizedChildContent_TypeInference/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_NonGenericParameterizedChildContent_TypeInference/TestComponent.codegen.cs @@ -60,7 +60,15 @@ internal static class TypeInference public static void CreateMyComponent_0(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder, int seq, int __seq0, TItem __arg0, int __seq1, global::Microsoft.AspNetCore.Components.RenderFragment __arg1, int __seq2, global::Microsoft.AspNetCore.Components.RenderFragment __arg2) { __builder.OpenComponent>(seq); - __builder.AddComponentParameter(__seq0, "Item", __arg0); + __builder.AddComponentParameter(__seq0, nameof(global::Test.MyComponent. +#nullable restore +#line (1,14)-(1,18) "x:\dir\subdir\Test\TestComponent.cshtml" +Item + +#line default +#line hidden +#nullable disable + ), __arg0); __builder.AddComponentParameter(__seq1, "GenericFragment", __arg1); __builder.AddComponentParameter(__seq2, "IntFragment", __arg2); __builder.CloseComponent(); diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_NonGenericParameterizedChildContent_TypeInference/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_NonGenericParameterizedChildContent_TypeInference/TestComponent.mappings.txt index 36999c446cc..8587da6c2be 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_NonGenericParameterizedChildContent_TypeInference/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_NonGenericParameterizedChildContent_TypeInference/TestComponent.mappings.txt @@ -13,3 +13,8 @@ Source Location: (103:2,16 [7] x:\dir\subdir\Test\TestComponent.cshtml) Generated Location: (1345:42,0 [7] ) |context| +Source Location: (13:0,13 [4] x:\dir\subdir\Test\TestComponent.cshtml) +|Item| +Generated Location: (2224:65,0 [4] ) +|Item| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_WithChildContent/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_WithChildContent/TestComponent.codegen.cs index cb7efdd6c8a..262644b2a87 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_WithChildContent/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_WithChildContent/TestComponent.codegen.cs @@ -18,7 +18,15 @@ public partial class TestComponent : global::Microsoft.AspNetCore.Components.Com protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { __builder.OpenComponent(0); - __builder.AddComponentParameter(1, "MyAttr", "abc"); + __builder.AddComponentParameter(1, nameof(global::Test.MyComponent. +#nullable restore +#line (1,14)-(1,20) "x:\dir\subdir\Test\TestComponent.cshtml" +MyAttr + +#line default +#line hidden +#nullable disable + ), "abc"); __builder.AddAttribute(2, "ChildContent", (global::Microsoft.AspNetCore.Components.RenderFragment)((__builder2) => { __builder2.AddContent(3, "Some text"); __builder2.AddMarkupContent(4, "Nested text"); diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_WithChildContent/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_WithChildContent/TestComponent.mappings.txt new file mode 100644 index 00000000000..921c305e44c --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_WithChildContent/TestComponent.mappings.txt @@ -0,0 +1,5 @@ +Source Location: (13:0,13 [6] x:\dir\subdir\Test\TestComponent.cshtml) +|MyAttr| +Generated Location: (884:23,0 [6] ) +|MyAttr| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_WithExplicitEventHandler/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_WithExplicitEventHandler/TestComponent.codegen.cs index 79b5615477c..7d5ef13cd70 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_WithExplicitEventHandler/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_WithExplicitEventHandler/TestComponent.codegen.cs @@ -18,7 +18,15 @@ public partial class TestComponent : global::Microsoft.AspNetCore.Components.Com protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { __builder.OpenComponent(0); - __builder.AddComponentParameter(1, "OnClick", (global::System.Action)( + __builder.AddComponentParameter(1, nameof(global::Test.MyComponent. +#nullable restore +#line (1,14)-(1,21) "x:\dir\subdir\Test\TestComponent.cshtml" +OnClick + +#line default +#line hidden +#nullable disable + ), (global::System.Action)( #nullable restore #line (1,24)-(1,33) "x:\dir\subdir\Test\TestComponent.cshtml" Increment diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_WithExplicitEventHandler/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_WithExplicitEventHandler/TestComponent.mappings.txt index 4dab1994178..0cf47482c50 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_WithExplicitEventHandler/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_WithExplicitEventHandler/TestComponent.mappings.txt @@ -1,6 +1,11 @@ -Source Location: (23:0,23 [9] x:\dir\subdir\Test\TestComponent.cshtml) +Source Location: (13:0,13 [7] x:\dir\subdir\Test\TestComponent.cshtml) +|OnClick| +Generated Location: (884:23,0 [7] ) +|OnClick| + +Source Location: (23:0,23 [9] x:\dir\subdir\Test\TestComponent.cshtml) |Increment| -Generated Location: (905:23,0 [9] ) +Generated Location: (1084:31,0 [9] ) |Increment| Source Location: (46:2,7 [98] x:\dir\subdir\Test\TestComponent.cshtml) @@ -10,7 +15,7 @@ Source Location: (46:2,7 [98] x:\dir\subdir\Test\TestComponent.cshtml) counter++; } | -Generated Location: (1153:34,0 [98] ) +Generated Location: (1332:42,0 [98] ) | private int counter; private void Increment(EventArgs e) { diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_WithExplicitStringParameter/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_WithExplicitStringParameter/TestComponent.codegen.cs index 4db66734aba..b5b931e20fe 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_WithExplicitStringParameter/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_WithExplicitStringParameter/TestComponent.codegen.cs @@ -18,7 +18,15 @@ public partial class TestComponent : global::Microsoft.AspNetCore.Components.Com protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { __builder.OpenComponent(0); - __builder.AddComponentParameter(1, "StringProperty", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( + __builder.AddComponentParameter(1, nameof(global::Test.MyComponent. +#nullable restore +#line (1,14)-(1,28) "x:\dir\subdir\Test\TestComponent.cshtml" +StringProperty + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( #nullable restore #line (1,32)-(1,45) "x:\dir\subdir\Test\TestComponent.cshtml" 42.ToString() diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_WithExplicitStringParameter/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_WithExplicitStringParameter/TestComponent.mappings.txt index 71e59e73b2c..e9caeb22f6a 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_WithExplicitStringParameter/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_WithExplicitStringParameter/TestComponent.mappings.txt @@ -1,5 +1,10 @@ -Source Location: (31:0,31 [13] x:\dir\subdir\Test\TestComponent.cshtml) +Source Location: (13:0,13 [14] x:\dir\subdir\Test\TestComponent.cshtml) +|StringProperty| +Generated Location: (884:23,0 [14] ) +|StringProperty| + +Source Location: (31:0,31 [13] x:\dir\subdir\Test\TestComponent.cshtml) |42.ToString()| -Generated Location: (975:23,0 [13] ) +Generated Location: (1154:31,0 [13] ) |42.ToString()| diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_WithGenericChildContent/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_WithGenericChildContent/TestComponent.codegen.cs index 9ffd0c64832..e5f348b8403 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_WithGenericChildContent/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_WithGenericChildContent/TestComponent.codegen.cs @@ -18,7 +18,15 @@ public partial class TestComponent : global::Microsoft.AspNetCore.Components.Com protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { __builder.OpenComponent(0); - __builder.AddComponentParameter(1, "MyAttr", "abc"); + __builder.AddComponentParameter(1, nameof(global::Test.MyComponent. +#nullable restore +#line (1,14)-(1,20) "x:\dir\subdir\Test\TestComponent.cshtml" +MyAttr + +#line default +#line hidden +#nullable disable + ), "abc"); __builder.AddAttribute(2, "ChildContent", (global::Microsoft.AspNetCore.Components.RenderFragment)((context) => (__builder2) => { __builder2.AddContent(3, "Some text"); __builder2.OpenElement(4, "some-child"); diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_WithGenericChildContent/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_WithGenericChildContent/TestComponent.mappings.txt index c898b27063c..50912aabae5 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_WithGenericChildContent/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_WithGenericChildContent/TestComponent.mappings.txt @@ -1,5 +1,10 @@ -Source Location: (54:0,54 [26] x:\dir\subdir\Test\TestComponent.cshtml) +Source Location: (13:0,13 [6] x:\dir\subdir\Test\TestComponent.cshtml) +|MyAttr| +Generated Location: (884:23,0 [6] ) +|MyAttr| + +Source Location: (54:0,54 [26] x:\dir\subdir\Test\TestComponent.cshtml) |context.ToLowerInvariant()| -Generated Location: (1239:28,0 [26] ) +Generated Location: (1418:36,0 [26] ) |context.ToLowerInvariant()| diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_WithGenericChildContent_SetsParameterName/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_WithGenericChildContent_SetsParameterName/TestComponent.codegen.cs index 87df61c2717..44ea67ef970 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_WithGenericChildContent_SetsParameterName/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_WithGenericChildContent_SetsParameterName/TestComponent.codegen.cs @@ -18,7 +18,15 @@ public partial class TestComponent : global::Microsoft.AspNetCore.Components.Com protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { __builder.OpenComponent(0); - __builder.AddComponentParameter(1, "MyAttr", "abc"); + __builder.AddComponentParameter(1, nameof(global::Test.MyComponent. +#nullable restore +#line (1,14)-(1,20) "x:\dir\subdir\Test\TestComponent.cshtml" +MyAttr + +#line default +#line hidden +#nullable disable + ), "abc"); __builder.AddAttribute(2, "ChildContent", (global::Microsoft.AspNetCore.Components.RenderFragment)((item) => (__builder2) => { __builder2.AddMarkupContent(3, "\r\n Some text"); __builder2.OpenElement(4, "some-child"); diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_WithGenericChildContent_SetsParameterName/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_WithGenericChildContent_SetsParameterName/TestComponent.mappings.txt index e5a223b87df..776d0225c13 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_WithGenericChildContent_SetsParameterName/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_WithGenericChildContent_SetsParameterName/TestComponent.mappings.txt @@ -1,5 +1,10 @@ -Source Location: (93:2,32 [23] x:\dir\subdir\Test\TestComponent.cshtml) +Source Location: (13:0,13 [6] x:\dir\subdir\Test\TestComponent.cshtml) +|MyAttr| +Generated Location: (884:23,0 [6] ) +|MyAttr| + +Source Location: (93:2,32 [23] x:\dir\subdir\Test\TestComponent.cshtml) |item.ToLowerInvariant()| -Generated Location: (1250:28,0 [23] ) +Generated Location: (1429:36,0 [23] ) |item.ToLowerInvariant()| diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_WithGenericChildContent_SetsParameterNameOnComponent/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_WithGenericChildContent_SetsParameterNameOnComponent/TestComponent.codegen.cs index 87df61c2717..44ea67ef970 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_WithGenericChildContent_SetsParameterNameOnComponent/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_WithGenericChildContent_SetsParameterNameOnComponent/TestComponent.codegen.cs @@ -18,7 +18,15 @@ public partial class TestComponent : global::Microsoft.AspNetCore.Components.Com protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { __builder.OpenComponent(0); - __builder.AddComponentParameter(1, "MyAttr", "abc"); + __builder.AddComponentParameter(1, nameof(global::Test.MyComponent. +#nullable restore +#line (1,14)-(1,20) "x:\dir\subdir\Test\TestComponent.cshtml" +MyAttr + +#line default +#line hidden +#nullable disable + ), "abc"); __builder.AddAttribute(2, "ChildContent", (global::Microsoft.AspNetCore.Components.RenderFragment)((item) => (__builder2) => { __builder2.AddMarkupContent(3, "\r\n Some text"); __builder2.OpenElement(4, "some-child"); diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_WithGenericChildContent_SetsParameterNameOnComponent/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_WithGenericChildContent_SetsParameterNameOnComponent/TestComponent.mappings.txt index e5a223b87df..776d0225c13 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_WithGenericChildContent_SetsParameterNameOnComponent/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_WithGenericChildContent_SetsParameterNameOnComponent/TestComponent.mappings.txt @@ -1,5 +1,10 @@ -Source Location: (93:2,32 [23] x:\dir\subdir\Test\TestComponent.cshtml) +Source Location: (13:0,13 [6] x:\dir\subdir\Test\TestComponent.cshtml) +|MyAttr| +Generated Location: (884:23,0 [6] ) +|MyAttr| + +Source Location: (93:2,32 [23] x:\dir\subdir\Test\TestComponent.cshtml) |item.ToLowerInvariant()| -Generated Location: (1250:28,0 [23] ) +Generated Location: (1429:36,0 [23] ) |item.ToLowerInvariant()| diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_WithLambdaEventHandler/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_WithLambdaEventHandler/TestComponent.codegen.cs index bb0620fe558..4877f647ddb 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_WithLambdaEventHandler/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_WithLambdaEventHandler/TestComponent.codegen.cs @@ -18,7 +18,15 @@ public partial class TestComponent : global::Microsoft.AspNetCore.Components.Com protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { __builder.OpenComponent(0); - __builder.AddComponentParameter(1, "OnClick", (global::System.Action)( + __builder.AddComponentParameter(1, nameof(global::Test.MyComponent. +#nullable restore +#line (1,14)-(1,21) "x:\dir\subdir\Test\TestComponent.cshtml" +OnClick + +#line default +#line hidden +#nullable disable + ), (global::System.Action)( #nullable restore #line (1,25)-(1,46) "x:\dir\subdir\Test\TestComponent.cshtml" e => { Increment(); } diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_WithLambdaEventHandler/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_WithLambdaEventHandler/TestComponent.mappings.txt index 3d0b6496a5c..e26ef4a8636 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_WithLambdaEventHandler/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_WithLambdaEventHandler/TestComponent.mappings.txt @@ -1,6 +1,11 @@ -Source Location: (24:0,24 [21] x:\dir\subdir\Test\TestComponent.cshtml) +Source Location: (13:0,13 [7] x:\dir\subdir\Test\TestComponent.cshtml) +|OnClick| +Generated Location: (884:23,0 [7] ) +|OnClick| + +Source Location: (24:0,24 [21] x:\dir\subdir\Test\TestComponent.cshtml) |e => { Increment(); }| -Generated Location: (905:23,0 [21] ) +Generated Location: (1084:31,0 [21] ) |e => { Increment(); }| Source Location: (60:2,7 [87] x:\dir\subdir\Test\TestComponent.cshtml) @@ -10,7 +15,7 @@ Source Location: (60:2,7 [87] x:\dir\subdir\Test\TestComponent.cshtml) counter++; } | -Generated Location: (1165:34,0 [87] ) +Generated Location: (1344:42,0 [87] ) | private int counter; private void Increment() { diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_WithParameters/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_WithParameters/TestComponent.codegen.cs index 91826a5afa5..b8a7004c525 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_WithParameters/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_WithParameters/TestComponent.codegen.cs @@ -18,7 +18,15 @@ public partial class TestComponent : global::Microsoft.AspNetCore.Components.Com protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { __builder.OpenComponent(0); - __builder.AddComponentParameter(1, "IntProperty", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( + __builder.AddComponentParameter(1, nameof(global::Test.MyComponent. +#nullable restore +#line (2,5)-(2,16) "x:\dir\subdir\Test\TestComponent.cshtml" +IntProperty + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( #nullable restore #line (2,18)-(2,21) "x:\dir\subdir\Test\TestComponent.cshtml" 123 @@ -27,7 +35,15 @@ protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components. #line hidden #nullable disable )); - __builder.AddComponentParameter(2, "BoolProperty", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( + __builder.AddComponentParameter(2, nameof(global::Test.MyComponent. +#nullable restore +#line (3,5)-(3,17) "x:\dir\subdir\Test\TestComponent.cshtml" +BoolProperty + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( #nullable restore #line (3,19)-(3,23) "x:\dir\subdir\Test\TestComponent.cshtml" true @@ -36,8 +52,24 @@ protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components. #line hidden #nullable disable )); - __builder.AddComponentParameter(3, "StringProperty", "My string"); - __builder.AddComponentParameter(4, "ObjectProperty", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( + __builder.AddComponentParameter(3, nameof(global::Test.MyComponent. +#nullable restore +#line (4,5)-(4,19) "x:\dir\subdir\Test\TestComponent.cshtml" +StringProperty + +#line default +#line hidden +#nullable disable + ), "My string"); + __builder.AddComponentParameter(4, nameof(global::Test.MyComponent. +#nullable restore +#line (5,5)-(5,19) "x:\dir\subdir\Test\TestComponent.cshtml" +ObjectProperty + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( #nullable restore #line (5,21)-(5,35) "x:\dir\subdir\Test\TestComponent.cshtml" new SomeType() diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_WithParameters/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_WithParameters/TestComponent.mappings.txt index 86f0cefdfdb..10e3337479b 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_WithParameters/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_WithParameters/TestComponent.mappings.txt @@ -1,15 +1,35 @@ -Source Location: (31:1,17 [3] x:\dir\subdir\Test\TestComponent.cshtml) +Source Location: (18:1,4 [11] x:\dir\subdir\Test\TestComponent.cshtml) +|IntProperty| +Generated Location: (883:23,0 [11] ) +|IntProperty| + +Source Location: (31:1,17 [3] x:\dir\subdir\Test\TestComponent.cshtml) |123| -Generated Location: (971:23,0 [3] ) +Generated Location: (1149:31,0 [3] ) |123| +Source Location: (41:2,4 [12] x:\dir\subdir\Test\TestComponent.cshtml) +|BoolProperty| +Generated Location: (1383:40,0 [12] ) +|BoolProperty| + Source Location: (55:2,18 [4] x:\dir\subdir\Test\TestComponent.cshtml) |true| -Generated Location: (1296:32,0 [4] ) +Generated Location: (1652:48,0 [4] ) |true| +Source Location: (66:3,4 [14] x:\dir\subdir\Test\TestComponent.cshtml) +|StringProperty| +Generated Location: (1887:57,0 [14] ) +|StringProperty| + +Source Location: (98:4,4 [14] x:\dir\subdir\Test\TestComponent.cshtml) +|ObjectProperty| +Generated Location: (2145:66,0 [14] ) +|ObjectProperty| + Source Location: (114:4,20 [14] x:\dir\subdir\Test\TestComponent.cshtml) |new SomeType()| -Generated Location: (1703:42,0 [14] ) +Generated Location: (2415:74,0 [14] ) |new SomeType()| diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentParameter_TypeMismatch_ReportsDiagnostic/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentParameter_TypeMismatch_ReportsDiagnostic/TestComponent.codegen.cs index e3b7da235d0..8cce71c01f8 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentParameter_TypeMismatch_ReportsDiagnostic/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentParameter_TypeMismatch_ReportsDiagnostic/TestComponent.codegen.cs @@ -18,7 +18,15 @@ public partial class TestComponent : global::Microsoft.AspNetCore.Components.Com protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { __builder.OpenComponent(0); - __builder.AddComponentParameter(1, "Coolness", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( + __builder.AddComponentParameter(1, nameof(global::Test.CoolnessMeter. +#nullable restore +#line (1,16)-(1,24) "x:\dir\subdir\Test\TestComponent.cshtml" +Coolness + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( #nullable restore #line (1,28)-(1,39) "x:\dir\subdir\Test\TestComponent.cshtml" "very-cool" diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentParameter_TypeMismatch_ReportsDiagnostic/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentParameter_TypeMismatch_ReportsDiagnostic/TestComponent.mappings.txt index 0dd34ab1529..f1a67c9fd9f 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentParameter_TypeMismatch_ReportsDiagnostic/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentParameter_TypeMismatch_ReportsDiagnostic/TestComponent.mappings.txt @@ -1,5 +1,10 @@ -Source Location: (27:0,27 [11] x:\dir\subdir\Test\TestComponent.cshtml) +Source Location: (15:0,15 [8] x:\dir\subdir\Test\TestComponent.cshtml) +|Coolness| +Generated Location: (888:23,0 [8] ) +|Coolness| + +Source Location: (27:0,27 [11] x:\dir\subdir\Test\TestComponent.cshtml) |"very-cool"| -Generated Location: (970:23,0 [11] ) +Generated Location: (1151:31,0 [11] ) |"very-cool"| diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithBooleanParameter/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithBooleanParameter/TestComponent.codegen.cs index ffcca2bac3e..f64a2c2f8d0 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithBooleanParameter/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithBooleanParameter/TestComponent.codegen.cs @@ -30,7 +30,15 @@ protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components. __builder.CloseElement(); __builder.AddMarkupContent(2, "\r\n\r\n"); __builder.OpenComponent(3); - __builder.AddComponentParameter(4, "TestBool", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( + __builder.AddComponentParameter(4, nameof(global::Test.TestComponent. +#nullable restore +#line (3,16)-(3,24) "x:\dir\subdir\Test\TestComponent.cshtml" +TestBool + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( #nullable restore #line (3,26)-(3,30) "x:\dir\subdir\Test\TestComponent.cshtml" true diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithBooleanParameter/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithBooleanParameter/TestComponent.mappings.txt index 19bd857a72a..a9e29cbd6f0 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithBooleanParameter/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithBooleanParameter/TestComponent.mappings.txt @@ -3,9 +3,14 @@ Generated Location: (823:23,0 [8] ) |TestBool| +Source Location: (45:2,15 [8] x:\dir\subdir\Test\TestComponent.cshtml) +|TestBool| +Generated Location: (1228:35,0 [8] ) +|TestBool| + Source Location: (55:2,25 [4] x:\dir\subdir\Test\TestComponent.cshtml) |true| -Generated Location: (1312:35,0 [4] ) +Generated Location: (1493:43,0 [4] ) |true| Source Location: (74:4,7 [59] x:\dir\subdir\Test\TestComponent.cshtml) @@ -13,7 +18,7 @@ Source Location: (74:4,7 [59] x:\dir\subdir\Test\TestComponent.cshtml) [Parameter] public bool TestBool { get; set; } | -Generated Location: (1555:46,0 [59] ) +Generated Location: (1736:54,0 [59] ) | [Parameter] public bool TestBool { get; set; } diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithBooleanParameter_Minimized/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithBooleanParameter_Minimized/TestComponent.codegen.cs index 5a49d3e15d3..c48f84d5096 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithBooleanParameter_Minimized/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithBooleanParameter_Minimized/TestComponent.codegen.cs @@ -30,7 +30,15 @@ protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components. __builder.CloseElement(); __builder.AddMarkupContent(2, "\r\n\r\n"); __builder.OpenComponent(3); - __builder.AddComponentParameter(4, "TestBool", true); + __builder.AddComponentParameter(4, nameof(global::Test.TestComponent. +#nullable restore +#line (3,16)-(3,24) "x:\dir\subdir\Test\TestComponent.cshtml" +TestBool + +#line default +#line hidden +#nullable disable + ), true); __builder.CloseComponent(); } #pragma warning restore 1998 diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithBooleanParameter_Minimized/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithBooleanParameter_Minimized/TestComponent.mappings.txt index 8dd9201f08f..4e1e09c84e5 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithBooleanParameter_Minimized/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithBooleanParameter_Minimized/TestComponent.mappings.txt @@ -3,12 +3,17 @@ Generated Location: (823:23,0 [8] ) |TestBool| +Source Location: (45:2,15 [8] x:\dir\subdir\Test\TestComponent.cshtml) +|TestBool| +Generated Location: (1228:35,0 [8] ) +|TestBool| + Source Location: (67:4,7 [59] x:\dir\subdir\Test\TestComponent.cshtml) | [Parameter] public bool TestBool { get; set; } | -Generated Location: (1300:38,0 [59] ) +Generated Location: (1481:46,0 [59] ) | [Parameter] public bool TestBool { get; set; } diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithConstrainedTypeParameters/UseTestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithConstrainedTypeParameters/UseTestComponent.codegen.cs index 19ffd526e4c..5c20d7e723c 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithConstrainedTypeParameters/UseTestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithConstrainedTypeParameters/UseTestComponent.codegen.cs @@ -88,9 +88,33 @@ public static void CreateTestComponent_0(global::Microso where TItem3 : global::Image, new() { __builder.OpenComponent>(seq); - __builder.AddComponentParameter(__seq0, "Item1", __arg0); - __builder.AddComponentParameter(__seq1, "Items2", __arg1); - __builder.AddComponentParameter(__seq2, "Item3", __arg2); + __builder.AddComponentParameter(__seq0, nameof(global::Test.TestComponent. +#nullable restore +#line (2,16)-(2,21) "x:\dir\subdir\Test\UseTestComponent.cshtml" +Item1 + +#line default +#line hidden +#nullable disable + ), __arg0); + __builder.AddComponentParameter(__seq1, nameof(global::Test.TestComponent. +#nullable restore +#line (2,29)-(2,35) "x:\dir\subdir\Test\UseTestComponent.cshtml" +Items2 + +#line default +#line hidden +#nullable disable + ), __arg1); + __builder.AddComponentParameter(__seq2, nameof(global::Test.TestComponent. +#nullable restore +#line (2,43)-(2,48) "x:\dir\subdir\Test\UseTestComponent.cshtml" +Item3 + +#line default +#line hidden +#nullable disable + ), __arg2); __builder.AddComponentParameter(__seq3, "ChildContent", __arg3); __builder.CloseComponent(); } diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithConstrainedTypeParameters/UseTestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithConstrainedTypeParameters/UseTestComponent.mappings.txt index 27b6dad9f01..9c6d72447c4 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithConstrainedTypeParameters/UseTestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithConstrainedTypeParameters/UseTestComponent.mappings.txt @@ -40,3 +40,18 @@ Generated Location: (1854:67,0 [268] ) List items = new List() { tag1, tag2 }; | +Source Location: (28:1,15 [5] x:\dir\subdir\Test\UseTestComponent.cshtml) +|Item1| +Generated Location: (3089:93,0 [5] ) +|Item1| + +Source Location: (41:1,28 [6] x:\dir\subdir\Test\UseTestComponent.cshtml) +|Items2| +Generated Location: (3360:102,0 [6] ) +|Items2| + +Source Location: (55:1,42 [5] x:\dir\subdir\Test\UseTestComponent.cshtml) +|Item3| +Generated Location: (3632:111,0 [5] ) +|Item3| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithConstrainedTypeParameters_WithSemicolon/UseTestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithConstrainedTypeParameters_WithSemicolon/UseTestComponent.codegen.cs index 19ffd526e4c..5c20d7e723c 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithConstrainedTypeParameters_WithSemicolon/UseTestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithConstrainedTypeParameters_WithSemicolon/UseTestComponent.codegen.cs @@ -88,9 +88,33 @@ public static void CreateTestComponent_0(global::Microso where TItem3 : global::Image, new() { __builder.OpenComponent>(seq); - __builder.AddComponentParameter(__seq0, "Item1", __arg0); - __builder.AddComponentParameter(__seq1, "Items2", __arg1); - __builder.AddComponentParameter(__seq2, "Item3", __arg2); + __builder.AddComponentParameter(__seq0, nameof(global::Test.TestComponent. +#nullable restore +#line (2,16)-(2,21) "x:\dir\subdir\Test\UseTestComponent.cshtml" +Item1 + +#line default +#line hidden +#nullable disable + ), __arg0); + __builder.AddComponentParameter(__seq1, nameof(global::Test.TestComponent. +#nullable restore +#line (2,29)-(2,35) "x:\dir\subdir\Test\UseTestComponent.cshtml" +Items2 + +#line default +#line hidden +#nullable disable + ), __arg1); + __builder.AddComponentParameter(__seq2, nameof(global::Test.TestComponent. +#nullable restore +#line (2,43)-(2,48) "x:\dir\subdir\Test\UseTestComponent.cshtml" +Item3 + +#line default +#line hidden +#nullable disable + ), __arg2); __builder.AddComponentParameter(__seq3, "ChildContent", __arg3); __builder.CloseComponent(); } diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithConstrainedTypeParameters_WithSemicolon/UseTestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithConstrainedTypeParameters_WithSemicolon/UseTestComponent.mappings.txt index 27b6dad9f01..9c6d72447c4 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithConstrainedTypeParameters_WithSemicolon/UseTestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithConstrainedTypeParameters_WithSemicolon/UseTestComponent.mappings.txt @@ -40,3 +40,18 @@ Generated Location: (1854:67,0 [268] ) List items = new List() { tag1, tag2 }; | +Source Location: (28:1,15 [5] x:\dir\subdir\Test\UseTestComponent.cshtml) +|Item1| +Generated Location: (3089:93,0 [5] ) +|Item1| + +Source Location: (41:1,28 [6] x:\dir\subdir\Test\UseTestComponent.cshtml) +|Items2| +Generated Location: (3360:102,0 [6] ) +|Items2| + +Source Location: (55:1,42 [5] x:\dir\subdir\Test\UseTestComponent.cshtml) +|Item3| +Generated Location: (3632:111,0 [5] ) +|Item3| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithDecimalParameter/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithDecimalParameter/TestComponent.codegen.cs index e5ff4d25f54..17f66469a61 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithDecimalParameter/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithDecimalParameter/TestComponent.codegen.cs @@ -30,7 +30,15 @@ protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components. __builder.CloseElement(); __builder.AddMarkupContent(2, "\r\n\r\n"); __builder.OpenComponent(3); - __builder.AddComponentParameter(4, "TestDecimal", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( + __builder.AddComponentParameter(4, nameof(global::Test.TestComponent. +#nullable restore +#line (3,16)-(3,27) "x:\dir\subdir\Test\TestComponent.cshtml" +TestDecimal + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( #nullable restore #line (3,29)-(3,30) "x:\dir\subdir\Test\TestComponent.cshtml" 4 diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithDecimalParameter/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithDecimalParameter/TestComponent.mappings.txt index 07559739956..3d7e1dab6e7 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithDecimalParameter/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithDecimalParameter/TestComponent.mappings.txt @@ -3,9 +3,14 @@ Generated Location: (823:23,0 [11] ) |TestDecimal| +Source Location: (48:2,15 [11] x:\dir\subdir\Test\TestComponent.cshtml) +|TestDecimal| +Generated Location: (1231:35,0 [11] ) +|TestDecimal| + Source Location: (61:2,28 [1] x:\dir\subdir\Test\TestComponent.cshtml) |4| -Generated Location: (1318:35,0 [1] ) +Generated Location: (1499:43,0 [1] ) |4| Source Location: (77:4,7 [65] x:\dir\subdir\Test\TestComponent.cshtml) @@ -13,7 +18,7 @@ Source Location: (77:4,7 [65] x:\dir\subdir\Test\TestComponent.cshtml) [Parameter] public decimal TestDecimal { get; set; } | -Generated Location: (1558:46,0 [65] ) +Generated Location: (1739:54,0 [65] ) | [Parameter] public decimal TestDecimal { get; set; } diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithDynamicParameter/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithDynamicParameter/TestComponent.codegen.cs index f6d0e155b5a..b6410d8111c 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithDynamicParameter/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithDynamicParameter/TestComponent.codegen.cs @@ -30,7 +30,15 @@ protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components. __builder.CloseElement(); __builder.AddMarkupContent(2, "\r\n\r\n"); __builder.OpenComponent(3); - __builder.AddComponentParameter(4, "TestDynamic", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( + __builder.AddComponentParameter(4, nameof(global::Test.TestComponent. +#nullable restore +#line (3,16)-(3,27) "x:\dir\subdir\Test\TestComponent.cshtml" +TestDynamic + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( #nullable restore #line (3,29)-(3,30) "x:\dir\subdir\Test\TestComponent.cshtml" 4 diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithDynamicParameter/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithDynamicParameter/TestComponent.mappings.txt index 733795318e1..0904e8376a3 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithDynamicParameter/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithDynamicParameter/TestComponent.mappings.txt @@ -3,9 +3,14 @@ Generated Location: (823:23,0 [11] ) |TestDynamic| +Source Location: (48:2,15 [11] x:\dir\subdir\Test\TestComponent.cshtml) +|TestDynamic| +Generated Location: (1231:35,0 [11] ) +|TestDynamic| + Source Location: (61:2,28 [1] x:\dir\subdir\Test\TestComponent.cshtml) |4| -Generated Location: (1303:35,0 [1] ) +Generated Location: (1484:43,0 [1] ) |4| Source Location: (77:4,7 [65] x:\dir\subdir\Test\TestComponent.cshtml) @@ -13,7 +18,7 @@ Source Location: (77:4,7 [65] x:\dir\subdir\Test\TestComponent.cshtml) [Parameter] public dynamic TestDynamic { get; set; } | -Generated Location: (1543:46,0 [65] ) +Generated Location: (1724:54,0 [65] ) | [Parameter] public dynamic TestDynamic { get; set; } diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithTupleParameter/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithTupleParameter/TestComponent.codegen.cs index 5a469ce8c08..49c1f8db49d 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithTupleParameter/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithTupleParameter/TestComponent.codegen.cs @@ -18,7 +18,15 @@ public partial class TestComponent : global::Microsoft.AspNetCore.Components.Com protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { __builder.OpenComponent(0); - __builder.AddComponentParameter(1, "Gutter", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck<(System.Int32 Horizontal, System.Int32 Vertical)>( + __builder.AddComponentParameter(1, nameof(global::Test.TestComponent. +#nullable restore +#line (5,16)-(5,22) "x:\dir\subdir\Test\TestComponent.cshtml" +Gutter + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck<(System.Int32 Horizontal, System.Int32 Vertical)>( #nullable restore #line (5,24)-(5,32) "x:\dir\subdir\Test\TestComponent.cshtml" (32, 16) diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithTupleParameter/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithTupleParameter/TestComponent.mappings.txt index c54a7779c8e..b75023acb7c 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithTupleParameter/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithTupleParameter/TestComponent.mappings.txt @@ -1,13 +1,18 @@ -Source Location: (113:4,23 [8] x:\dir\subdir\Test\TestComponent.cshtml) +Source Location: (105:4,15 [6] x:\dir\subdir\Test\TestComponent.cshtml) +|Gutter| +Generated Location: (888:23,0 [6] ) +|Gutter| + +Source Location: (113:4,23 [8] x:\dir\subdir\Test\TestComponent.cshtml) |(32, 16)| -Generated Location: (996:23,0 [8] ) +Generated Location: (1177:31,0 [8] ) |(32, 16)| Source Location: (7:0,7 [78] x:\dir\subdir\Test\TestComponent.cshtml) | [Parameter] public (int Horizontal, int Vertical) Gutter { get; set; } | -Generated Location: (1243:34,0 [78] ) +Generated Location: (1424:42,0 [78] ) | [Parameter] public (int Horizontal, int Vertical) Gutter { get; set; } | diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithTypeParameterArray/UseTestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithTypeParameterArray/UseTestComponent.codegen.cs index f1de06c4d31..0b85907d5e4 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithTypeParameterArray/UseTestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithTypeParameterArray/UseTestComponent.codegen.cs @@ -85,9 +85,33 @@ internal static class TypeInference public static void CreateTestComponent_0(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder, int seq, int __seq0, TItem[] __arg0, int __seq1, global::System.Collections.Generic.List __arg1, int __seq2, global::System.Func __arg2, int __seq3, global::Microsoft.AspNetCore.Components.RenderFragment __arg3) { __builder.OpenComponent>(seq); - __builder.AddComponentParameter(__seq0, "Items1", __arg0); - __builder.AddComponentParameter(__seq1, "Items2", __arg1); - __builder.AddComponentParameter(__seq2, "Items3", __arg2); + __builder.AddComponentParameter(__seq0, nameof(global::Test.TestComponent. +#nullable restore +#line (2,16)-(2,22) "x:\dir\subdir\Test\UseTestComponent.cshtml" +Items1 + +#line default +#line hidden +#nullable disable + ), __arg0); + __builder.AddComponentParameter(__seq1, nameof(global::Test.TestComponent. +#nullable restore +#line (2,30)-(2,36) "x:\dir\subdir\Test\UseTestComponent.cshtml" +Items2 + +#line default +#line hidden +#nullable disable + ), __arg1); + __builder.AddComponentParameter(__seq2, nameof(global::Test.TestComponent. +#nullable restore +#line (2,44)-(2,50) "x:\dir\subdir\Test\UseTestComponent.cshtml" +Items3 + +#line default +#line hidden +#nullable disable + ), __arg2); __builder.AddComponentParameter(__seq3, "ChildContent", __arg3); __builder.CloseComponent(); } diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithTypeParameterArray/UseTestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithTypeParameterArray/UseTestComponent.mappings.txt index dc61c3839b3..f2558e314bd 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithTypeParameterArray/UseTestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithTypeParameterArray/UseTestComponent.mappings.txt @@ -40,3 +40,18 @@ Generated Location: (1872:67,0 [208] ) Tag[] items3() => new [] { tag }; | +Source Location: (28:1,15 [6] x:\dir\subdir\Test\UseTestComponent.cshtml) +|Items1| +Generated Location: (2889:90,0 [6] ) +|Items1| + +Source Location: (42:1,29 [6] x:\dir\subdir\Test\UseTestComponent.cshtml) +|Items2| +Generated Location: (3144:99,0 [6] ) +|Items2| + +Source Location: (56:1,43 [6] x:\dir\subdir\Test\UseTestComponent.cshtml) +|Items3| +Generated Location: (3399:108,0 [6] ) +|Items3| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithTypeParameterValueTuple/UseTestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithTypeParameterValueTuple/UseTestComponent.codegen.cs index f7ac013ac86..3e310282284 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithTypeParameterValueTuple/UseTestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithTypeParameterValueTuple/UseTestComponent.codegen.cs @@ -76,8 +76,24 @@ internal static class TypeInference public static void CreateTestComponent_0(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder, int seq, int __seq0, (TItem1, TItem2) __arg0, int __seq1, global::System.Collections.Generic.List<(TItem1, TItem2)> __arg1, int __seq2, global::Microsoft.AspNetCore.Components.RenderFragment<(TItem1, TItem2)> __arg2) { __builder.OpenComponent>(seq); - __builder.AddComponentParameter(__seq0, "Item1", __arg0); - __builder.AddComponentParameter(__seq1, "Items2", __arg1); + __builder.AddComponentParameter(__seq0, nameof(global::Test.TestComponent. +#nullable restore +#line (2,16)-(2,21) "x:\dir\subdir\Test\UseTestComponent.cshtml" +Item1 + +#line default +#line hidden +#nullable disable + ), __arg0); + __builder.AddComponentParameter(__seq1, nameof(global::Test.TestComponent. +#nullable restore +#line (2,28)-(2,34) "x:\dir\subdir\Test\UseTestComponent.cshtml" +Items2 + +#line default +#line hidden +#nullable disable + ), __arg1); __builder.AddComponentParameter(__seq2, "ChildContent", __arg2); __builder.CloseComponent(); } diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithTypeParameterValueTuple/UseTestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithTypeParameterValueTuple/UseTestComponent.mappings.txt index 131c7372ac2..7d3da0247d0 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithTypeParameterValueTuple/UseTestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithTypeParameterValueTuple/UseTestComponent.mappings.txt @@ -33,3 +33,13 @@ Generated Location: (1694:59,0 [176] ) List<(string, int)> items2 = new List<(string, int)>() { item2 }; | +Source Location: (28:1,15 [5] x:\dir\subdir\Test\UseTestComponent.cshtml) +|Item1| +Generated Location: (2684:81,0 [5] ) +|Item1| + +Source Location: (40:1,27 [6] x:\dir\subdir\Test\UseTestComponent.cshtml) +|Items2| +Generated Location: (2947:90,0 [6] ) +|Items2| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithTypeParameterValueTupleGloballyQualifiedTypes/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithTypeParameterValueTupleGloballyQualifiedTypes/TestComponent.codegen.cs index 7ebe9645b42..6853da41fae 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithTypeParameterValueTupleGloballyQualifiedTypes/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithTypeParameterValueTupleGloballyQualifiedTypes/TestComponent.codegen.cs @@ -86,7 +86,15 @@ internal static class TypeInference public static void CreateTestComponent_0(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder, int seq, int __seq0, TParam __arg0, int __seq1, global::Microsoft.AspNetCore.Components.RenderFragment<(global::N.MyClass I1, global::N.MyStruct I2, TParam P)> __arg1) { __builder.OpenComponent>(seq); - __builder.AddComponentParameter(__seq0, "InferParam", __arg0); + __builder.AddComponentParameter(__seq0, nameof(global::Test.TestComponent. +#nullable restore +#line (12,16)-(12,26) "x:\dir\subdir\Test\TestComponent.cshtml" +InferParam + +#line default +#line hidden +#nullable disable + ), __arg0); __builder.AddComponentParameter(__seq1, "Template", __arg1); __builder.CloseComponent(); } diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithTypeParameterValueTupleGloballyQualifiedTypes/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithTypeParameterValueTupleGloballyQualifiedTypes/TestComponent.mappings.txt index 33894a6a12b..d5f139dc12e 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithTypeParameterValueTupleGloballyQualifiedTypes/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithTypeParameterValueTupleGloballyQualifiedTypes/TestComponent.mappings.txt @@ -42,3 +42,8 @@ Generated Location: (1850:67,0 [169] ) public RenderFragment<(MyClass I1, MyStruct I2, TParam P)> Template { get; set; } | +Source Location: (227:11,15 [10] x:\dir\subdir\Test\TestComponent.cshtml) +|InferParam| +Generated Location: (2756:91,0 [10] ) +|InferParam| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithTypeParameterValueTuple_ExplicitGenericArguments/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithTypeParameterValueTuple_ExplicitGenericArguments/TestComponent.codegen.cs index 843373d9f54..e78e9fe66a5 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithTypeParameterValueTuple_ExplicitGenericArguments/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithTypeParameterValueTuple_ExplicitGenericArguments/TestComponent.codegen.cs @@ -48,7 +48,15 @@ public partial class TestComponent< protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { __builder.OpenComponent>(0); - __builder.AddComponentParameter(1, "Data", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck>( + __builder.AddComponentParameter(1, nameof(global::Test.TestComponent. +#nullable restore +#line (4,16)-(4,20) "x:\dir\subdir\Test\TestComponent.cshtml" +Data + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck>( #nullable restore #line (4,22)-(4,26) "x:\dir\subdir\Test\TestComponent.cshtml" null diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithTypeParameterValueTuple_ExplicitGenericArguments/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithTypeParameterValueTuple_ExplicitGenericArguments/TestComponent.mappings.txt index 1123cc735ce..e5acaedd34f 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithTypeParameterValueTuple_ExplicitGenericArguments/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ComponentWithTypeParameterValueTuple_ExplicitGenericArguments/TestComponent.mappings.txt @@ -18,9 +18,14 @@ Source Location: (61:1,18 [21] x:\dir\subdir\Test\TestComponent.cshtml) Generated Location: (981:39,0 [21] ) |where TValue : struct| +Source Location: (101:3,15 [4] x:\dir\subdir\Test\TestComponent.cshtml) +|Data| +Generated Location: (1531:53,0 [4] ) +|Data| + Source Location: (107:3,21 [4] x:\dir\subdir\Test\TestComponent.cshtml) |null| -Generated Location: (1643:53,0 [4] ) +Generated Location: (1842:61,0 [4] ) |null| Source Location: (161:5,7 [87] x:\dir\subdir\Test\TestComponent.cshtml) @@ -28,7 +33,7 @@ Source Location: (161:5,7 [87] x:\dir\subdir\Test\TestComponent.cshtml) [Parameter] public List<(TDomain Domain, TValue Value)> Data { get; set; } | -Generated Location: (1886:64,0 [87] ) +Generated Location: (2085:72,0 [87] ) | [Parameter] public List<(TDomain Domain, TValue Value)> Data { get; set; } diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_ComplexContentInAttribute/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_ComplexContentInAttribute/TestComponent.codegen.cs index 0d65291766a..18bba287c83 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_ComplexContentInAttribute/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_ComplexContentInAttribute/TestComponent.codegen.cs @@ -18,7 +18,15 @@ public partial class TestComponent : global::Microsoft.AspNetCore.Components.Com protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { __builder.OpenComponent(0); - __builder.AddComponentParameter(1, "StringProperty", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( + __builder.AddComponentParameter(1, nameof(global::Test.MyComponent. +#nullable restore +#line (1,14)-(1,28) "x:\dir\subdir\Test\TestComponent.cshtml" +StringProperty + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( #nullable restore #line (1,31)-(1,37) "x:\dir\subdir\Test\TestComponent.cshtml" MyEnum diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_ComplexContentInAttribute/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_ComplexContentInAttribute/TestComponent.mappings.txt index 2e94408dff4..511a568cbcc 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_ComplexContentInAttribute/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_ComplexContentInAttribute/TestComponent.mappings.txt @@ -1,6 +1,11 @@ -Source Location: (30:0,30 [6] x:\dir\subdir\Test\TestComponent.cshtml) +Source Location: (13:0,13 [14] x:\dir\subdir\Test\TestComponent.cshtml) +|StringProperty| +Generated Location: (884:23,0 [14] ) +|StringProperty| + +Source Location: (30:0,30 [6] x:\dir\subdir\Test\TestComponent.cshtml) |MyEnum| -Generated Location: (975:23,0 [6] ) +Generated Location: (1154:31,0 [6] ) |MyEnum| Source Location: (52:2,7 [67] x:\dir\subdir\Test\TestComponent.cshtml) @@ -11,7 +16,7 @@ Source Location: (52:2,7 [67] x:\dir\subdir\Test\TestComponent.cshtml) Two } | -Generated Location: (1220:34,0 [67] ) +Generated Location: (1399:42,0 [67] ) | public enum MyEnum { diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_ComplexContentInAttribute_02/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_ComplexContentInAttribute_02/TestComponent.codegen.cs index 0d65291766a..18bba287c83 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_ComplexContentInAttribute_02/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_ComplexContentInAttribute_02/TestComponent.codegen.cs @@ -18,7 +18,15 @@ public partial class TestComponent : global::Microsoft.AspNetCore.Components.Com protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { __builder.OpenComponent(0); - __builder.AddComponentParameter(1, "StringProperty", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( + __builder.AddComponentParameter(1, nameof(global::Test.MyComponent. +#nullable restore +#line (1,14)-(1,28) "x:\dir\subdir\Test\TestComponent.cshtml" +StringProperty + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( #nullable restore #line (1,31)-(1,37) "x:\dir\subdir\Test\TestComponent.cshtml" MyEnum diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_ComplexContentInAttribute_02/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_ComplexContentInAttribute_02/TestComponent.mappings.txt index 2e94408dff4..511a568cbcc 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_ComplexContentInAttribute_02/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_ComplexContentInAttribute_02/TestComponent.mappings.txt @@ -1,6 +1,11 @@ -Source Location: (30:0,30 [6] x:\dir\subdir\Test\TestComponent.cshtml) +Source Location: (13:0,13 [14] x:\dir\subdir\Test\TestComponent.cshtml) +|StringProperty| +Generated Location: (884:23,0 [14] ) +|StringProperty| + +Source Location: (30:0,30 [6] x:\dir\subdir\Test\TestComponent.cshtml) |MyEnum| -Generated Location: (975:23,0 [6] ) +Generated Location: (1154:31,0 [6] ) |MyEnum| Source Location: (52:2,7 [67] x:\dir\subdir\Test\TestComponent.cshtml) @@ -11,7 +16,7 @@ Source Location: (52:2,7 [67] x:\dir\subdir\Test\TestComponent.cshtml) Two } | -Generated Location: (1220:34,0 [67] ) +Generated Location: (1399:42,0 [67] ) | public enum MyEnum { diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_ComplexContentInAttribute_03/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_ComplexContentInAttribute_03/TestComponent.codegen.cs index 88bdd4314f5..cf9517c771a 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_ComplexContentInAttribute_03/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_ComplexContentInAttribute_03/TestComponent.codegen.cs @@ -18,7 +18,15 @@ public partial class TestComponent : global::Microsoft.AspNetCore.Components.Com protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { __builder.OpenComponent(0); - __builder.AddComponentParameter(1, "StringProperty", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( + __builder.AddComponentParameter(1, nameof(global::Test.MyComponent. +#nullable restore +#line (1,14)-(1,28) "x:\dir\subdir\Test\TestComponent.cshtml" +StringProperty + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( #nullable restore #line (1,31)-(1,32) "x:\dir\subdir\Test\TestComponent.cshtml" x diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_ComplexContentInAttribute_03/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_ComplexContentInAttribute_03/TestComponent.mappings.txt index 4d50c2d2481..df7687f3876 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_ComplexContentInAttribute_03/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_ComplexContentInAttribute_03/TestComponent.mappings.txt @@ -1,18 +1,23 @@ -Source Location: (30:0,30 [1] x:\dir\subdir\Test\TestComponent.cshtml) +Source Location: (13:0,13 [14] x:\dir\subdir\Test\TestComponent.cshtml) +|StringProperty| +Generated Location: (884:23,0 [14] ) +|StringProperty| + +Source Location: (30:0,30 [1] x:\dir\subdir\Test\TestComponent.cshtml) |x| -Generated Location: (975:23,0 [1] ) +Generated Location: (1154:31,0 [1] ) |x| Source Location: (39:0,39 [8] x:\dir\subdir\Test\TestComponent.cshtml) |"string"| -Generated Location: (1110:30,0 [8] ) +Generated Location: (1289:38,0 [8] ) |"string"| Source Location: (63:2,7 [18] x:\dir\subdir\Test\TestComponent.cshtml) | int x = 1; | -Generated Location: (1357:41,0 [18] ) +Generated Location: (1536:49,0 [18] ) | int x = 1; | diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_MatchingIsCaseSensitive/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_MatchingIsCaseSensitive/TestComponent.codegen.cs index 0d546faa7ec..5a0c90c147e 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_MatchingIsCaseSensitive/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_MatchingIsCaseSensitive/TestComponent.codegen.cs @@ -22,7 +22,15 @@ protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components. __builder.AddMarkupContent(1, "\r\n\r\n"); __builder.OpenComponent(2); __builder.AddComponentParameter(3, "intproperty", "1"); - __builder.AddComponentParameter(4, "BoolProperty", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( + __builder.AddComponentParameter(4, nameof(global::Test.MyComponent. +#nullable restore +#line (3,30)-(3,42) "x:\dir\subdir\Test\TestComponent.cshtml" +BoolProperty + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( #nullable restore #line (3,44)-(3,48) "x:\dir\subdir\Test\TestComponent.cshtml" true diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_MatchingIsCaseSensitive/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_MatchingIsCaseSensitive/TestComponent.mappings.txt index b6df31a8b9b..1ea450a69b9 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_MatchingIsCaseSensitive/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_MatchingIsCaseSensitive/TestComponent.mappings.txt @@ -1,5 +1,10 @@ -Source Location: (77:2,43 [4] x:\dir\subdir\Test\TestComponent.cshtml) +Source Location: (63:2,29 [12] x:\dir\subdir\Test\TestComponent.cshtml) +|BoolProperty| +Generated Location: (1144:27,0 [12] ) +|BoolProperty| + +Source Location: (77:2,43 [4] x:\dir\subdir\Test\TestComponent.cshtml) |true| -Generated Location: (1234:27,0 [4] ) +Generated Location: (1413:35,0 [4] ) |true| diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_MultipleComponentsDifferByCase/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_MultipleComponentsDifferByCase/TestComponent.codegen.cs index 0027d248057..10559c674e3 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_MultipleComponentsDifferByCase/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_MultipleComponentsDifferByCase/TestComponent.codegen.cs @@ -18,7 +18,15 @@ public partial class TestComponent : global::Microsoft.AspNetCore.Components.Com protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { __builder.OpenComponent(0); - __builder.AddComponentParameter(1, "IntProperty", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( + __builder.AddComponentParameter(1, nameof(global::Test.MyComponent. +#nullable restore +#line (1,14)-(1,25) "x:\dir\subdir\Test\TestComponent.cshtml" +IntProperty + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( #nullable restore #line (1,27)-(1,28) "x:\dir\subdir\Test\TestComponent.cshtml" 1 @@ -30,7 +38,15 @@ protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components. __builder.CloseComponent(); __builder.AddMarkupContent(2, "\r\n"); __builder.OpenComponent(3); - __builder.AddComponentParameter(4, "IntProperty", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( + __builder.AddComponentParameter(4, nameof(global::Test.Mycomponent. +#nullable restore +#line (2,14)-(2,25) "x:\dir\subdir\Test\TestComponent.cshtml" +IntProperty + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( #nullable restore #line (2,27)-(2,28) "x:\dir\subdir\Test\TestComponent.cshtml" 2 diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_MultipleComponentsDifferByCase/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_MultipleComponentsDifferByCase/TestComponent.mappings.txt index 524166114d3..7a1049b1e95 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_MultipleComponentsDifferByCase/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_MultipleComponentsDifferByCase/TestComponent.mappings.txt @@ -1,10 +1,20 @@ -Source Location: (26:0,26 [1] x:\dir\subdir\Test\TestComponent.cshtml) +Source Location: (13:0,13 [11] x:\dir\subdir\Test\TestComponent.cshtml) +|IntProperty| +Generated Location: (884:23,0 [11] ) +|IntProperty| + +Source Location: (26:0,26 [1] x:\dir\subdir\Test\TestComponent.cshtml) |1| -Generated Location: (971:23,0 [1] ) +Generated Location: (1150:31,0 [1] ) |1| +Source Location: (46:1,13 [11] x:\dir\subdir\Test\TestComponent.cshtml) +|IntProperty| +Generated Location: (1543:43,0 [11] ) +|IntProperty| + Source Location: (59:1,26 [1] x:\dir\subdir\Test\TestComponent.cshtml) |2| -Generated Location: (1451:35,0 [1] ) +Generated Location: (1809:51,0 [1] ) |2| diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithEditorRequiredParameter_ValueSpecified/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithEditorRequiredParameter_ValueSpecified/TestComponent.codegen.cs index d86e160bc19..e7117047bc7 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithEditorRequiredParameter_ValueSpecified/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithEditorRequiredParameter_ValueSpecified/TestComponent.codegen.cs @@ -18,7 +18,15 @@ public partial class TestComponent : global::Microsoft.AspNetCore.Components.Com protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { __builder.OpenComponent(0); - __builder.AddComponentParameter(1, "Property1", "Some Value"); + __builder.AddComponentParameter(1, nameof(global::Test.ComponentWithEditorRequiredParameters. +#nullable restore +#line (1,40)-(1,49) "x:\dir\subdir\Test\TestComponent.cshtml" +Property1 + +#line default +#line hidden +#nullable disable + ), "Some Value"); __builder.CloseComponent(); } #pragma warning restore 1998 diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithEditorRequiredParameter_ValueSpecified/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithEditorRequiredParameter_ValueSpecified/TestComponent.mappings.txt new file mode 100644 index 00000000000..15fec8d0b07 --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithEditorRequiredParameter_ValueSpecified/TestComponent.mappings.txt @@ -0,0 +1,5 @@ +Source Location: (39:0,39 [9] x:\dir\subdir\Test\TestComponent.cshtml) +|Property1| +Generated Location: (936:23,0 [9] ) +|Property1| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithEditorRequiredParameter_ValueSpecifiedUsingBind/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithEditorRequiredParameter_ValueSpecifiedUsingBind/TestComponent.codegen.cs index b407e9afff8..38362aa9632 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithEditorRequiredParameter_ValueSpecifiedUsingBind/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithEditorRequiredParameter_ValueSpecifiedUsingBind/TestComponent.codegen.cs @@ -18,7 +18,15 @@ public partial class TestComponent : global::Microsoft.AspNetCore.Components.Com protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { __builder.OpenComponent(0); - __builder.AddComponentParameter(1, "Property1", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( + __builder.AddComponentParameter(1, nameof(global::Test.ComponentWithEditorRequiredParameters. +#nullable restore +#line (1,46)-(1,55) "x:\dir\subdir\Test\TestComponent.cshtml" +Property1 + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( #nullable restore #line (1,57)-(1,64) "x:\dir\subdir\Test\TestComponent.cshtml" myField diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithEditorRequiredParameter_ValueSpecifiedUsingBind/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithEditorRequiredParameter_ValueSpecifiedUsingBind/TestComponent.mappings.txt index 4a073d20f8e..e51e016bdd3 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithEditorRequiredParameter_ValueSpecifiedUsingBind/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithEditorRequiredParameter_ValueSpecifiedUsingBind/TestComponent.mappings.txt @@ -1,13 +1,18 @@ -Source Location: (56:0,56 [7] x:\dir\subdir\Test\TestComponent.cshtml) +Source Location: (45:0,45 [9] x:\dir\subdir\Test\TestComponent.cshtml) +|Property1| +Generated Location: (936:23,0 [9] ) +|Property1| + +Source Location: (56:0,56 [7] x:\dir\subdir\Test\TestComponent.cshtml) |myField| -Generated Location: (996:23,0 [7] ) +Generated Location: (1201:31,0 [7] ) |myField| Source Location: (78:2,7 [46] x:\dir\subdir\Test\TestComponent.cshtml) | private string myField = "Some Value"; | -Generated Location: (1457:35,0 [46] ) +Generated Location: (1662:43,0 [46] ) | private string myField = "Some Value"; | diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithEscapedParameterName/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithEscapedParameterName/TestComponent.codegen.cs index 2bf8e4183d3..f52672116a7 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithEscapedParameterName/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithEscapedParameterName/TestComponent.codegen.cs @@ -18,7 +18,15 @@ public partial class TestComponent : global::Microsoft.AspNetCore.Components.Com protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { __builder.OpenComponent(0); - __builder.AddComponentParameter(1, "class", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( + __builder.AddComponentParameter(1, nameof(global::Test.MyComponent. +#nullable restore +#line (1,14)-(1,19) 1 "x:\dir\subdir\Test\TestComponent.cshtml" +@class + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( #nullable restore #line (1,21)-(1,22) "x:\dir\subdir\Test\TestComponent.cshtml" 1 @@ -27,7 +35,15 @@ protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components. #line hidden #nullable disable )); - __builder.AddComponentParameter(2, "Prop2", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( + __builder.AddComponentParameter(2, nameof(global::Test.MyComponent. +#nullable restore +#line (1,24)-(1,29) "x:\dir\subdir\Test\TestComponent.cshtml" +Prop2 + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( #nullable restore #line (1,31)-(1,32) "x:\dir\subdir\Test\TestComponent.cshtml" 2 diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithEscapedParameterName/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithEscapedParameterName/TestComponent.mappings.txt index b0bc091e3b9..dce07277ced 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithEscapedParameterName/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithEscapedParameterName/TestComponent.mappings.txt @@ -1,10 +1,20 @@ -Source Location: (20:0,20 [1] x:\dir\subdir\Test\TestComponent.cshtml) +Source Location: (13:0,13 [5] x:\dir\subdir\Test\TestComponent.cshtml) +|class| +Generated Location: (887:23,1 [5] ) +|class| + +Source Location: (20:0,20 [1] x:\dir\subdir\Test\TestComponent.cshtml) |1| -Generated Location: (965:23,0 [1] ) +Generated Location: (1147:31,0 [1] ) |1| +Source Location: (23:0,23 [5] x:\dir\subdir\Test\TestComponent.cshtml) +|Prop2| +Generated Location: (1380:40,0 [5] ) +|Prop2| + Source Location: (30:0,30 [1] x:\dir\subdir\Test\TestComponent.cshtml) |2| -Generated Location: (1279:32,0 [1] ) +Generated Location: (1640:48,0 [1] ) |2| diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithInitOnlyParameter/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithInitOnlyParameter/TestComponent.codegen.cs index 092c2bb3c39..034146680a6 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithInitOnlyParameter/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithInitOnlyParameter/TestComponent.codegen.cs @@ -18,7 +18,15 @@ public partial class TestComponent : global::Microsoft.AspNetCore.Components.Com protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { __builder.OpenComponent(0); - __builder.AddComponentParameter(1, "Prop", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( + __builder.AddComponentParameter(1, nameof(global::Test.MyComponent. +#nullable restore +#line (1,14)-(1,18) "x:\dir\subdir\Test\TestComponent.cshtml" +Prop + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( #nullable restore #line (1,20)-(1,21) "x:\dir\subdir\Test\TestComponent.cshtml" 1 diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithInitOnlyParameter/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithInitOnlyParameter/TestComponent.mappings.txt index a3f7acf4b58..3dd1f28e91a 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithInitOnlyParameter/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithInitOnlyParameter/TestComponent.mappings.txt @@ -1,5 +1,10 @@ -Source Location: (19:0,19 [1] x:\dir\subdir\Test\TestComponent.cshtml) +Source Location: (13:0,13 [4] x:\dir\subdir\Test\TestComponent.cshtml) +|Prop| +Generated Location: (884:23,0 [4] ) +|Prop| + +Source Location: (19:0,19 [1] x:\dir\subdir\Test\TestComponent.cshtml) |1| -Generated Location: (964:23,0 [1] ) +Generated Location: (1143:31,0 [1] ) |1| diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithNamespaceDirective/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithNamespaceDirective/TestComponent.codegen.cs index 81194f44988..87d6f3e0ef5 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithNamespaceDirective/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithNamespaceDirective/TestComponent.codegen.cs @@ -31,11 +31,27 @@ public partial class TestComponent : global::Microsoft.AspNetCore.Components.Com protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { __builder.OpenComponent(0); - __builder.AddComponentParameter(1, "Header", "head"); + __builder.AddComponentParameter(1, nameof(global::Test.HeaderComponent. +#nullable restore +#line (4,18)-(4,24) "x:\dir\subdir\Test\TestComponent.cshtml" +Header + +#line default +#line hidden +#nullable disable + ), "head"); __builder.CloseComponent(); __builder.AddMarkupContent(2, "\r\n"); __builder.OpenComponent(3); - __builder.AddComponentParameter(4, "Footer", "feet"); + __builder.AddComponentParameter(4, nameof(global::AnotherTest.FooterComponent. +#nullable restore +#line (6,18)-(6,24) "x:\dir\subdir\Test\TestComponent.cshtml" +Footer + +#line default +#line hidden +#nullable disable + ), "feet"); __builder.CloseComponent(); } #pragma warning restore 1998 diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithNamespaceDirective/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithNamespaceDirective/TestComponent.mappings.txt index f4c4836b1bd..5b73f7ee9a2 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithNamespaceDirective/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithNamespaceDirective/TestComponent.mappings.txt @@ -10,3 +10,13 @@ Generated Location: (512:19,0 [12] ) |using Test | +Source Location: (56:3,17 [6] x:\dir\subdir\Test\TestComponent.cshtml) +|Header| +Generated Location: (1145:36,0 [6] ) +|Header| + +Source Location: (109:5,17 [6] x:\dir\subdir\Test\TestComponent.cshtml) +|Footer| +Generated Location: (1573:48,0 [6] ) +|Footer| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithNullableActionParameter/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithNullableActionParameter/TestComponent.codegen.cs index a7ec272cf88..acadee39e3c 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithNullableActionParameter/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithNullableActionParameter/TestComponent.codegen.cs @@ -18,7 +18,15 @@ public partial class TestComponent : global::Microsoft.AspNetCore.Components.Com protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { __builder.OpenComponent(0); - __builder.AddComponentParameter(1, "NullableAction", (global::System.Action)( + __builder.AddComponentParameter(1, nameof(global::Test.ComponentWithNullableAction. +#nullable restore +#line (1,30)-(1,44) "x:\dir\subdir\Test\TestComponent.cshtml" +NullableAction + +#line default +#line hidden +#nullable disable + ), (global::System.Action)( #nullable restore #line (1,47)-(1,61) "x:\dir\subdir\Test\TestComponent.cshtml" NullableAction diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithNullableActionParameter/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithNullableActionParameter/TestComponent.mappings.txt index 5c491dac743..a09bb965918 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithNullableActionParameter/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithNullableActionParameter/TestComponent.mappings.txt @@ -1,6 +1,11 @@ -Source Location: (46:0,46 [14] x:\dir\subdir\Test\TestComponent.cshtml) +Source Location: (29:0,29 [14] x:\dir\subdir\Test\TestComponent.cshtml) |NullableAction| -Generated Location: (910:23,0 [14] ) +Generated Location: (916:23,0 [14] ) +|NullableAction| + +Source Location: (46:0,46 [14] x:\dir\subdir\Test\TestComponent.cshtml) +|NullableAction| +Generated Location: (1105:31,0 [14] ) |NullableAction| Source Location: (73:1,7 [61] x:\dir\subdir\Test\TestComponent.cshtml) @@ -8,7 +13,7 @@ Source Location: (73:1,7 [61] x:\dir\subdir\Test\TestComponent.cshtml) [Parameter] public Action NullableAction { get; set; } | -Generated Location: (1163:34,0 [61] ) +Generated Location: (1358:42,0 [61] ) | [Parameter] public Action NullableAction { get; set; } diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithNullableRenderFragmentParameter/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithNullableRenderFragmentParameter/TestComponent.codegen.cs index 809c2fb6519..4d44d3a52e2 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithNullableRenderFragmentParameter/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithNullableRenderFragmentParameter/TestComponent.codegen.cs @@ -18,7 +18,15 @@ public partial class TestComponent : global::Microsoft.AspNetCore.Components.Com protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { __builder.OpenComponent(0); - __builder.AddComponentParameter(1, "Header", (global::Microsoft.AspNetCore.Components.RenderFragment)( + __builder.AddComponentParameter(1, nameof(global::Test.ComponentWithNullableRenderFragment. +#nullable restore +#line (1,38)-(1,44) "x:\dir\subdir\Test\TestComponent.cshtml" +Header + +#line default +#line hidden +#nullable disable + ), (global::Microsoft.AspNetCore.Components.RenderFragment)( #nullable restore #line (1,47)-(1,53) "x:\dir\subdir\Test\TestComponent.cshtml" Header diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithNullableRenderFragmentParameter/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithNullableRenderFragmentParameter/TestComponent.mappings.txt index a14d4e3dc47..3063c1dff0d 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithNullableRenderFragmentParameter/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithNullableRenderFragmentParameter/TestComponent.mappings.txt @@ -1,13 +1,18 @@ -Source Location: (46:0,46 [6] x:\dir\subdir\Test\TestComponent.cshtml) +Source Location: (37:0,37 [6] x:\dir\subdir\Test\TestComponent.cshtml) |Header| -Generated Location: (943:23,0 [6] ) +Generated Location: (932:23,0 [6] ) +|Header| + +Source Location: (46:0,46 [6] x:\dir\subdir\Test\TestComponent.cshtml) +|Header| +Generated Location: (1146:31,0 [6] ) |Header| Source Location: (65:1,7 [59] x:\dir\subdir\Test\TestComponent.cshtml) | [Parameter] public RenderFragment Header { get; set; } | -Generated Location: (1188:34,0 [59] ) +Generated Location: (1391:42,0 [59] ) | [Parameter] public RenderFragment Header { get; set; } | diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithRef_Nullable_Generic/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithRef_Nullable_Generic/TestComponent.codegen.cs index 60884826c82..62f0b3a0062 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithRef_Nullable_Generic/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithRef_Nullable_Generic/TestComponent.codegen.cs @@ -58,7 +58,15 @@ internal static class TypeInference public static void CreateMyComponent_0(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder, int seq, int __seq0, T __arg0, int __seq1, global::System.Action> __arg1) { __builder.OpenComponent>(seq); - __builder.AddComponentParameter(__seq0, "MyParameter", __arg0); + __builder.AddComponentParameter(__seq0, nameof(global::Test.MyComponent. +#nullable restore +#line (1,33)-(1,44) "x:\dir\subdir\Test\TestComponent.cshtml" +MyParameter + +#line default +#line hidden +#nullable disable + ), __arg0); __builder.AddComponentReferenceCapture(__seq1, (__value) => { __arg1((global::Test.MyComponent)__value); }); __builder.CloseComponent(); } diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithRef_Nullable_Generic/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithRef_Nullable_Generic/TestComponent.mappings.txt index 2f653779880..b9847f8c6aa 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithRef_Nullable_Generic/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithRef_Nullable_Generic/TestComponent.mappings.txt @@ -19,3 +19,8 @@ Generated Location: (1257:42,0 [114] ) public void Use() { System.GC.KeepAlive(myComponent); } | +Source Location: (32:0,32 [11] x:\dir\subdir\Test\TestComponent.cshtml) +|MyParameter| +Generated Location: (2019:63,0 [11] ) +|MyParameter| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithSplat_GenericTypeInference/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithSplat_GenericTypeInference/TestComponent.codegen.cs index 7ba15dd92be..58561d050be 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithSplat_GenericTypeInference/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithSplat_GenericTypeInference/TestComponent.codegen.cs @@ -55,7 +55,15 @@ internal static class TypeInference public static void CreateMyComponent_0(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder, int seq, int __seq0, T __arg0, int __seq1, global::System.Collections.Generic.IEnumerable> __arg1) { __builder.OpenComponent>(seq); - __builder.AddComponentParameter(__seq0, "Value", __arg0); + __builder.AddComponentParameter(__seq0, nameof(global::Test.MyComponent. +#nullable restore +#line (1,14)-(1,19) "x:\dir\subdir\Test\TestComponent.cshtml" +Value + +#line default +#line hidden +#nullable disable + ), __arg0); __builder.AddMultipleAttributes(__seq1, __arg1); __builder.CloseComponent(); } diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithSplat_GenericTypeInference/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithSplat_GenericTypeInference/TestComponent.mappings.txt index 8b2efbb9312..3bd696a8af1 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithSplat_GenericTypeInference/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithSplat_GenericTypeInference/TestComponent.mappings.txt @@ -17,3 +17,8 @@ Generated Location: (1203:40,0 [93] ) private Dictionary someAttributes = new Dictionary(); | +Source Location: (13:0,13 [5] x:\dir\subdir\Test\TestComponent.cshtml) +|Value| +Generated Location: (2005:60,0 [5] ) +|Value| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithWriteOnlyParameter/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithWriteOnlyParameter/TestComponent.codegen.cs index 092c2bb3c39..034146680a6 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithWriteOnlyParameter/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithWriteOnlyParameter/TestComponent.codegen.cs @@ -18,7 +18,15 @@ public partial class TestComponent : global::Microsoft.AspNetCore.Components.Com protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { __builder.OpenComponent(0); - __builder.AddComponentParameter(1, "Prop", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( + __builder.AddComponentParameter(1, nameof(global::Test.MyComponent. +#nullable restore +#line (1,14)-(1,18) "x:\dir\subdir\Test\TestComponent.cshtml" +Prop + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( #nullable restore #line (1,20)-(1,21) "x:\dir\subdir\Test\TestComponent.cshtml" 1 diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithWriteOnlyParameter/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithWriteOnlyParameter/TestComponent.mappings.txt index a3f7acf4b58..3dd1f28e91a 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithWriteOnlyParameter/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithWriteOnlyParameter/TestComponent.mappings.txt @@ -1,5 +1,10 @@ -Source Location: (19:0,19 [1] x:\dir\subdir\Test\TestComponent.cshtml) +Source Location: (13:0,13 [4] x:\dir\subdir\Test\TestComponent.cshtml) +|Prop| +Generated Location: (884:23,0 [4] ) +|Prop| + +Source Location: (19:0,19 [1] x:\dir\subdir\Test\TestComponent.cshtml) |1| -Generated Location: (964:23,0 [1] ) +Generated Location: (1143:31,0 [1] ) |1| diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/DuplicateComponentParameters_IsAnError/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/DuplicateComponentParameters_IsAnError/TestComponent.codegen.cs index 296e1590ebb..b3e3fafff38 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/DuplicateComponentParameters_IsAnError/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/DuplicateComponentParameters_IsAnError/TestComponent.codegen.cs @@ -18,7 +18,15 @@ public partial class TestComponent : global::Microsoft.AspNetCore.Components.Com protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { __builder.OpenComponent(0); - __builder.AddComponentParameter(1, "Message", "test"); + __builder.AddComponentParameter(1, nameof(global::Test.MyComponent. +#nullable restore +#line (1,14)-(1,21) "x:\dir\subdir\Test\TestComponent.cshtml" +Message + +#line default +#line hidden +#nullable disable + ), "test"); __builder.AddComponentParameter(2, "mESSAGE", "test"); __builder.CloseComponent(); } diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/DuplicateComponentParameters_IsAnError/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/DuplicateComponentParameters_IsAnError/TestComponent.mappings.txt new file mode 100644 index 00000000000..aee5de94f20 --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/DuplicateComponentParameters_IsAnError/TestComponent.mappings.txt @@ -0,0 +1,5 @@ +Source Location: (13:0,13 [7] x:\dir\subdir\Test\TestComponent.cshtml) +|Message| +Generated Location: (884:23,0 [7] ) +|Message| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/DuplicateComponentParameters_IsAnError_BindMessage/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/DuplicateComponentParameters_IsAnError_BindMessage/TestComponent.codegen.cs index 0dbc75254a8..912e12b4529 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/DuplicateComponentParameters_IsAnError_BindMessage/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/DuplicateComponentParameters_IsAnError_BindMessage/TestComponent.codegen.cs @@ -18,7 +18,15 @@ public partial class TestComponent : global::Microsoft.AspNetCore.Components.Com protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { __builder.OpenComponent(0); - __builder.AddComponentParameter(1, "Message", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( + __builder.AddComponentParameter(1, nameof(global::Test.MyComponent. +#nullable restore +#line (1,14)-(1,21) "x:\dir\subdir\Test\TestComponent.cshtml" +Message + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( #nullable restore #line (1,24)-(1,31) "x:\dir\subdir\Test\TestComponent.cshtml" message @@ -27,7 +35,15 @@ protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components. #line hidden #nullable disable )); - __builder.AddComponentParameter(2, "Message", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( + __builder.AddComponentParameter(2, nameof(global::Test.MyComponent. +#nullable restore +#line (1,39)-(1,46) "x:\dir\subdir\Test\TestComponent.cshtml" +Message + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( #nullable restore #line (1,49)-(1,56) "x:\dir\subdir\Test\TestComponent.cshtml" message @@ -36,8 +52,8 @@ protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components. #line hidden #nullable disable )); - __builder.AddComponentParameter(3, "MessageChanged", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck>(global::Microsoft.AspNetCore.Components.EventCallback.Factory.Create(this, global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.CreateInferredEventCallback(this, __value => message = __value, message)))); - __builder.AddComponentParameter(4, "MessageExpression", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck>>(() => message)); + __builder.AddComponentParameter(3, nameof(global::Test.MyComponent.MessageChanged), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck>(global::Microsoft.AspNetCore.Components.EventCallback.Factory.Create(this, global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.CreateInferredEventCallback(this, __value => message = __value, message)))); + __builder.AddComponentParameter(4, nameof(global::Test.MyComponent.MessageExpression), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck>>(() => message)); __builder.CloseComponent(); } #pragma warning restore 1998 diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/DuplicateComponentParameters_IsAnError_BindMessage/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/DuplicateComponentParameters_IsAnError_BindMessage/TestComponent.mappings.txt index 1bb00d156f7..0b6febc8b85 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/DuplicateComponentParameters_IsAnError_BindMessage/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/DuplicateComponentParameters_IsAnError_BindMessage/TestComponent.mappings.txt @@ -1,18 +1,28 @@ -Source Location: (23:0,23 [7] x:\dir\subdir\Test\TestComponent.cshtml) +Source Location: (13:0,13 [7] x:\dir\subdir\Test\TestComponent.cshtml) +|Message| +Generated Location: (884:23,0 [7] ) +|Message| + +Source Location: (23:0,23 [7] x:\dir\subdir\Test\TestComponent.cshtml) |message| -Generated Location: (968:23,0 [7] ) +Generated Location: (1147:31,0 [7] ) |message| +Source Location: (38:0,38 [7] x:\dir\subdir\Test\TestComponent.cshtml) +|Message| +Generated Location: (1386:40,0 [7] ) +|Message| + Source Location: (48:0,48 [7] x:\dir\subdir\Test\TestComponent.cshtml) |message| -Generated Location: (1291:32,0 [7] ) +Generated Location: (1649:48,0 [7] ) |message| Source Location: (73:1,12 [30] x:\dir\subdir\Test\TestComponent.cshtml) | string message = "hi"; | -Generated Location: (2253:45,0 [30] ) +Generated Location: (2673:61,0 [30] ) | string message = "hi"; | diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/DuplicateComponentParameters_IsAnError_BindMessageChanged/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/DuplicateComponentParameters_IsAnError_BindMessageChanged/TestComponent.codegen.cs index eea0d501b78..66d476bcf1b 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/DuplicateComponentParameters_IsAnError_BindMessageChanged/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/DuplicateComponentParameters_IsAnError_BindMessageChanged/TestComponent.codegen.cs @@ -18,7 +18,15 @@ public partial class TestComponent : global::Microsoft.AspNetCore.Components.Com protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { __builder.OpenComponent(0); - __builder.AddComponentParameter(1, "MessageChanged", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck>(global::Microsoft.AspNetCore.Components.EventCallback.Factory.Create(this, + __builder.AddComponentParameter(1, nameof(global::Test.MyComponent. +#nullable restore +#line (1,14)-(1,28) "x:\dir\subdir\Test\TestComponent.cshtml" +MessageChanged + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck>(global::Microsoft.AspNetCore.Components.EventCallback.Factory.Create(this, #nullable restore #line (1,32)-(1,41) "x:\dir\subdir\Test\TestComponent.cshtml" (s) => {} @@ -27,7 +35,15 @@ protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components. #line hidden #nullable disable ))); - __builder.AddComponentParameter(2, "Message", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( + __builder.AddComponentParameter(2, nameof(global::Test.MyComponent. +#nullable restore +#line (1,50)-(1,57) "x:\dir\subdir\Test\TestComponent.cshtml" +Message + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( #nullable restore #line (1,60)-(1,67) "x:\dir\subdir\Test\TestComponent.cshtml" message @@ -36,8 +52,8 @@ protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components. #line hidden #nullable disable )); - __builder.AddComponentParameter(3, "MessageChanged", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck>(global::Microsoft.AspNetCore.Components.EventCallback.Factory.Create(this, global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.CreateInferredEventCallback(this, __value => message = __value, message)))); - __builder.AddComponentParameter(4, "MessageExpression", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck>>(() => message)); + __builder.AddComponentParameter(3, nameof(global::Test.MyComponent.MessageChanged), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck>(global::Microsoft.AspNetCore.Components.EventCallback.Factory.Create(this, global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.CreateInferredEventCallback(this, __value => message = __value, message)))); + __builder.AddComponentParameter(4, nameof(global::Test.MyComponent.MessageExpression), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck>>(() => message)); __builder.CloseComponent(); } #pragma warning restore 1998 diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/DuplicateComponentParameters_IsAnError_BindMessageChanged/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/DuplicateComponentParameters_IsAnError_BindMessageChanged/TestComponent.mappings.txt index 5d2bb1c9f50..924aed3be4a 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/DuplicateComponentParameters_IsAnError_BindMessageChanged/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/DuplicateComponentParameters_IsAnError_BindMessageChanged/TestComponent.mappings.txt @@ -1,18 +1,28 @@ -Source Location: (31:0,31 [9] x:\dir\subdir\Test\TestComponent.cshtml) +Source Location: (13:0,13 [14] x:\dir\subdir\Test\TestComponent.cshtml) +|MessageChanged| +Generated Location: (884:23,0 [14] ) +|MessageChanged| + +Source Location: (31:0,31 [9] x:\dir\subdir\Test\TestComponent.cshtml) |(s) => {}| -Generated Location: (1128:23,0 [9] ) +Generated Location: (1307:31,0 [9] ) |(s) => {}| +Source Location: (49:0,49 [7] x:\dir\subdir\Test\TestComponent.cshtml) +|Message| +Generated Location: (1549:40,0 [7] ) +|Message| + Source Location: (59:0,59 [7] x:\dir\subdir\Test\TestComponent.cshtml) |message| -Generated Location: (1454:32,0 [7] ) +Generated Location: (1812:48,0 [7] ) |message| Source Location: (84:1,12 [30] x:\dir\subdir\Test\TestComponent.cshtml) | string message = "hi"; | -Generated Location: (2416:45,0 [30] ) +Generated Location: (2836:61,0 [30] ) | string message = "hi"; | diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/DuplicateComponentParameters_IsAnError_BindMessageExpression/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/DuplicateComponentParameters_IsAnError_BindMessageExpression/TestComponent.codegen.cs index 59e61045e03..2e4a9d50315 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/DuplicateComponentParameters_IsAnError_BindMessageExpression/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/DuplicateComponentParameters_IsAnError_BindMessageExpression/TestComponent.codegen.cs @@ -18,7 +18,15 @@ public partial class TestComponent : global::Microsoft.AspNetCore.Components.Com protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { __builder.OpenComponent(0); - __builder.AddComponentParameter(1, "MessageExpression", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck>>( + __builder.AddComponentParameter(1, nameof(global::Test.MyComponent. +#nullable restore +#line (1,39)-(1,56) "x:\dir\subdir\Test\TestComponent.cshtml" +MessageExpression + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck>>( #nullable restore #line (1,60)-(1,69) "x:\dir\subdir\Test\TestComponent.cshtml" (s) => {} @@ -27,7 +35,15 @@ protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components. #line hidden #nullable disable )); - __builder.AddComponentParameter(2, "Message", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( + __builder.AddComponentParameter(2, nameof(global::Test.MyComponent. +#nullable restore +#line (1,20)-(1,27) "x:\dir\subdir\Test\TestComponent.cshtml" +Message + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( #nullable restore #line (1,30)-(1,37) "x:\dir\subdir\Test\TestComponent.cshtml" message @@ -36,8 +52,8 @@ protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components. #line hidden #nullable disable )); - __builder.AddComponentParameter(3, "MessageChanged", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck>(global::Microsoft.AspNetCore.Components.EventCallback.Factory.Create(this, global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.CreateInferredEventCallback(this, __value => message = __value, message)))); - __builder.AddComponentParameter(4, "MessageExpression", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck>>(() => message)); + __builder.AddComponentParameter(3, nameof(global::Test.MyComponent.MessageChanged), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck>(global::Microsoft.AspNetCore.Components.EventCallback.Factory.Create(this, global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.CreateInferredEventCallback(this, __value => message = __value, message)))); + __builder.AddComponentParameter(4, nameof(global::Test.MyComponent.MessageExpression), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck>>(() => message)); __builder.CloseComponent(); } #pragma warning restore 1998 diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/DuplicateComponentParameters_IsAnError_BindMessageExpression/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/DuplicateComponentParameters_IsAnError_BindMessageExpression/TestComponent.mappings.txt index 60f0b727c59..16fac7b9e88 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/DuplicateComponentParameters_IsAnError_BindMessageExpression/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/DuplicateComponentParameters_IsAnError_BindMessageExpression/TestComponent.mappings.txt @@ -1,18 +1,28 @@ -Source Location: (59:0,59 [9] x:\dir\subdir\Test\TestComponent.cshtml) +Source Location: (38:0,38 [17] x:\dir\subdir\Test\TestComponent.cshtml) +|MessageExpression| +Generated Location: (884:23,0 [17] ) +|MessageExpression| + +Source Location: (59:0,59 [9] x:\dir\subdir\Test\TestComponent.cshtml) |(s) => {}| -Generated Location: (1029:23,0 [9] ) +Generated Location: (1208:31,0 [9] ) |(s) => {}| +Source Location: (19:0,19 [7] x:\dir\subdir\Test\TestComponent.cshtml) +|Message| +Generated Location: (1449:40,0 [7] ) +|Message| + Source Location: (29:0,29 [7] x:\dir\subdir\Test\TestComponent.cshtml) |message| -Generated Location: (1354:32,0 [7] ) +Generated Location: (1712:48,0 [7] ) |message| Source Location: (87:1,12 [30] x:\dir\subdir\Test\TestComponent.cshtml) | string message = "hi"; | -Generated Location: (2316:45,0 [30] ) +Generated Location: (2736:61,0 [30] ) | string message = "hi"; | diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/DuplicateComponentParameters_IsAnError_Multiple/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/DuplicateComponentParameters_IsAnError_Multiple/TestComponent.codegen.cs index 9cc35a65267..34d87a31a3a 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/DuplicateComponentParameters_IsAnError_Multiple/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/DuplicateComponentParameters_IsAnError_Multiple/TestComponent.codegen.cs @@ -18,7 +18,15 @@ public partial class TestComponent : global::Microsoft.AspNetCore.Components.Com protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { __builder.OpenComponent(0); - __builder.AddComponentParameter(1, "Message", "test"); + __builder.AddComponentParameter(1, nameof(global::Test.MyComponent. +#nullable restore +#line (1,14)-(1,21) "x:\dir\subdir\Test\TestComponent.cshtml" +Message + +#line default +#line hidden +#nullable disable + ), "test"); __builder.AddComponentParameter(2, "mESSAGE", "test"); __builder.AddComponentParameter(3, "Message", "anotherone"); __builder.CloseComponent(); diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/DuplicateComponentParameters_IsAnError_Multiple/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/DuplicateComponentParameters_IsAnError_Multiple/TestComponent.mappings.txt new file mode 100644 index 00000000000..aee5de94f20 --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/DuplicateComponentParameters_IsAnError_Multiple/TestComponent.mappings.txt @@ -0,0 +1,5 @@ +Source Location: (13:0,13 [7] x:\dir\subdir\Test\TestComponent.cshtml) +|Message| +Generated Location: (884:23,0 [7] ) +|Message| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallbackOfT_Array/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallbackOfT_Array/TestComponent.codegen.cs index 28b8717174e..dbc6965ff06 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallbackOfT_Array/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallbackOfT_Array/TestComponent.codegen.cs @@ -47,9 +47,17 @@ internal static class TypeInference public static void CreateMyComponent_0(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder, int seq, int __seq0, TItem[] __arg0, int __seq1, global::Microsoft.AspNetCore.Components.EventCallback __arg1, int __seq2, global::System.Linq.Expressions.Expression> __arg2) { __builder.OpenComponent>(seq); - __builder.AddComponentParameter(__seq0, "Value", __arg0); - __builder.AddComponentParameter(__seq1, "ValueChanged", __arg1); - __builder.AddComponentParameter(__seq2, "ValueExpression", __arg2); + __builder.AddComponentParameter(__seq0, nameof(global::Test.MyComponent. +#nullable restore +#line (1,20)-(1,25) "x:\dir\subdir\Test\TestComponent.cshtml" +Value + +#line default +#line hidden +#nullable disable + ), __arg0); + __builder.AddComponentParameter(__seq1, nameof(global::Test.MyComponent.ValueChanged), __arg1); + __builder.AddComponentParameter(__seq2, nameof(global::Test.MyComponent.ValueExpression), __arg2); __builder.CloseComponent(); } } diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallbackOfT_Array/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallbackOfT_Array/TestComponent.mappings.txt index 10f72b8e39d..f85ca7aa75c 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallbackOfT_Array/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallbackOfT_Array/TestComponent.mappings.txt @@ -12,3 +12,8 @@ Generated Location: (1288:32,0 [64] ) string[] Selected { get; set; } = Array.Empty(); | +Source Location: (19:0,19 [5] x:\dir\subdir\Test\TestComponent.cshtml) +|Value| +Generated Location: (2123:52,0 [5] ) +|Value| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallbackOfT_GenericComponent_ExplicitType/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallbackOfT_GenericComponent_ExplicitType/TestComponent.codegen.cs index 9f5fad4582d..fed9b340433 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallbackOfT_GenericComponent_ExplicitType/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallbackOfT_GenericComponent_ExplicitType/TestComponent.codegen.cs @@ -18,7 +18,15 @@ public partial class TestComponent : global::Microsoft.AspNetCore.Components.Com protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { __builder.OpenComponent>(0); - __builder.AddComponentParameter(1, "OnClick", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck>(global::Microsoft.AspNetCore.Components.EventCallback.Factory.Create(this, + __builder.AddComponentParameter(1, nameof(global::Test.MyComponent. +#nullable restore +#line (1,25)-(1,32) "x:\dir\subdir\Test\TestComponent.cshtml" +OnClick + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck>(global::Microsoft.AspNetCore.Components.EventCallback.Factory.Create(this, #nullable restore #line (1,36)-(1,61) "x:\dir\subdir\Test\TestComponent.cshtml" (MyType arg) => counter++ diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallbackOfT_GenericComponent_ExplicitType/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallbackOfT_GenericComponent_ExplicitType/TestComponent.mappings.txt index 1ce30123c95..3f41808fbf2 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallbackOfT_GenericComponent_ExplicitType/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallbackOfT_GenericComponent_ExplicitType/TestComponent.mappings.txt @@ -1,13 +1,18 @@ -Source Location: (35:0,35 [25] x:\dir\subdir\Test\TestComponent.cshtml) +Source Location: (24:0,24 [7] x:\dir\subdir\Test\TestComponent.cshtml) +|OnClick| +Generated Location: (900:23,0 [7] ) +|OnClick| + +Source Location: (35:0,35 [25] x:\dir\subdir\Test\TestComponent.cshtml) |(MyType arg) => counter++| -Generated Location: (1099:23,0 [25] ) +Generated Location: (1286:31,0 [25] ) |(MyType arg) => counter++| Source Location: (75:2,7 [28] x:\dir\subdir\Test\TestComponent.cshtml) | private int counter; | -Generated Location: (1364:34,0 [28] ) +Generated Location: (1551:42,0 [28] ) | private int counter; | diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallbackOfT_GenericComponent_ExplicitType_MethodGroup/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallbackOfT_GenericComponent_ExplicitType_MethodGroup/TestComponent.codegen.cs index 0f07ceb6453..c4b7b0b3391 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallbackOfT_GenericComponent_ExplicitType_MethodGroup/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallbackOfT_GenericComponent_ExplicitType_MethodGroup/TestComponent.codegen.cs @@ -18,7 +18,15 @@ public partial class TestComponent : global::Microsoft.AspNetCore.Components.Com protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { __builder.OpenComponent>(0); - __builder.AddComponentParameter(1, "OnClick", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck>(global::Microsoft.AspNetCore.Components.EventCallback.Factory.Create(this, + __builder.AddComponentParameter(1, nameof(global::Test.MyComponent. +#nullable restore +#line (1,25)-(1,32) "x:\dir\subdir\Test\TestComponent.cshtml" +OnClick + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck>(global::Microsoft.AspNetCore.Components.EventCallback.Factory.Create(this, #nullable restore #line (1,34)-(1,43) "x:\dir\subdir\Test\TestComponent.cshtml" Increment diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallbackOfT_GenericComponent_ExplicitType_MethodGroup/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallbackOfT_GenericComponent_ExplicitType_MethodGroup/TestComponent.mappings.txt index 9cb861410fa..283074b54d3 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallbackOfT_GenericComponent_ExplicitType_MethodGroup/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallbackOfT_GenericComponent_ExplicitType_MethodGroup/TestComponent.mappings.txt @@ -1,6 +1,11 @@ -Source Location: (33:0,33 [9] x:\dir\subdir\Test\TestComponent.cshtml) +Source Location: (24:0,24 [7] x:\dir\subdir\Test\TestComponent.cshtml) +|OnClick| +Generated Location: (900:23,0 [7] ) +|OnClick| + +Source Location: (33:0,33 [9] x:\dir\subdir\Test\TestComponent.cshtml) |Increment| -Generated Location: (1099:23,0 [9] ) +Generated Location: (1286:31,0 [9] ) |Increment| Source Location: (56:2,7 [84] x:\dir\subdir\Test\TestComponent.cshtml) @@ -9,7 +14,7 @@ Source Location: (56:2,7 [84] x:\dir\subdir\Test\TestComponent.cshtml) public void Increment(MyType type) => counter++; | -Generated Location: (1348:34,0 [84] ) +Generated Location: (1535:42,0 [84] ) | private int counter; diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallbackOfT_GenericComponent_MissingTypeParameterBinding_01/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallbackOfT_GenericComponent_MissingTypeParameterBinding_01/TestComponent.codegen.cs index 79a79420fc0..9d12bd96b29 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallbackOfT_GenericComponent_MissingTypeParameterBinding_01/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallbackOfT_GenericComponent_MissingTypeParameterBinding_01/TestComponent.codegen.cs @@ -38,7 +38,15 @@ internal static class TypeInference public static void CreateMyComponent_0(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder, int seq, int __seq0, global::Microsoft.AspNetCore.Components.EventCallback __arg0) { __builder.OpenComponent>(seq); - __builder.AddComponentParameter(__seq0, "OnClick", __arg0); + __builder.AddComponentParameter(__seq0, nameof(global::Test.MyComponent. +#nullable restore +#line (1,14)-(1,21) "x:\dir\subdir\Test\TestComponent.cshtml" +OnClick + +#line default +#line hidden +#nullable disable + ), __arg0); __builder.CloseComponent(); } } diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallbackOfT_GenericComponent_MissingTypeParameterBinding_01/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallbackOfT_GenericComponent_MissingTypeParameterBinding_01/TestComponent.mappings.txt index 7e5e43de5a9..13f3621b2ea 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallbackOfT_GenericComponent_MissingTypeParameterBinding_01/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallbackOfT_GenericComponent_MissingTypeParameterBinding_01/TestComponent.mappings.txt @@ -7,3 +7,8 @@ Generated Location: (783:23,0 [28] ) private int counter; | +Source Location: (13:0,13 [7] x:\dir\subdir\Test\TestComponent.cshtml) +|OnClick| +Generated Location: (1477:43,0 [7] ) +|OnClick| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallback_CanPassEventCallbackOfT_Explicitly/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallback_CanPassEventCallbackOfT_Explicitly/TestComponent.codegen.cs index ffc40b8260e..63b42197108 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallback_CanPassEventCallbackOfT_Explicitly/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallback_CanPassEventCallbackOfT_Explicitly/TestComponent.codegen.cs @@ -24,7 +24,15 @@ public partial class TestComponent : global::Microsoft.AspNetCore.Components.Com protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { __builder.OpenComponent(0); - __builder.AddComponentParameter(1, "OnClick", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck>(global::Microsoft.AspNetCore.Components.EventCallback.Factory.Create(this, + __builder.AddComponentParameter(1, nameof(global::Test.MyComponent. +#nullable restore +#line (2,14)-(2,21) "x:\dir\subdir\Test\TestComponent.cshtml" +OnClick + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck>(global::Microsoft.AspNetCore.Components.EventCallback.Factory.Create(this, #nullable restore #line (2,25)-(2,86) "x:\dir\subdir\Test\TestComponent.cshtml" EventCallback.Factory.Create(this, Increment) diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallback_CanPassEventCallbackOfT_Explicitly/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallback_CanPassEventCallbackOfT_Explicitly/TestComponent.mappings.txt index e86721f9787..3efdbb64800 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallback_CanPassEventCallbackOfT_Explicitly/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallback_CanPassEventCallbackOfT_Explicitly/TestComponent.mappings.txt @@ -5,9 +5,14 @@ Generated Location: (371:12,0 [43] ) |using Microsoft.AspNetCore.Components.Web | +Source Location: (57:1,13 [7] x:\dir\subdir\Test\TestComponent.cshtml) +|OnClick| +Generated Location: (1027:29,0 [7] ) +|OnClick| + Source Location: (68:1,24 [61] x:\dir\subdir\Test\TestComponent.cshtml) |EventCallback.Factory.Create(this, Increment)| -Generated Location: (1338:29,0 [61] ) +Generated Location: (1517:37,0 [61] ) |EventCallback.Factory.Create(this, Increment)| Source Location: (144:3,7 [87] x:\dir\subdir\Test\TestComponent.cshtml) @@ -17,7 +22,7 @@ Source Location: (144:3,7 [87] x:\dir\subdir\Test\TestComponent.cshtml) counter++; } | -Generated Location: (1639:40,0 [87] ) +Generated Location: (1818:48,0 [87] ) | private int counter; private void Increment() { diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallback_CanPassEventCallbackOfT_Implicitly_Action/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallback_CanPassEventCallbackOfT_Implicitly_Action/TestComponent.codegen.cs index 2dfcdae4a45..0dac935c525 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallback_CanPassEventCallbackOfT_Implicitly_Action/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallback_CanPassEventCallbackOfT_Implicitly_Action/TestComponent.codegen.cs @@ -18,7 +18,15 @@ public partial class TestComponent : global::Microsoft.AspNetCore.Components.Com protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { __builder.OpenComponent(0); - __builder.AddComponentParameter(1, "OnClick", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck>(global::Microsoft.AspNetCore.Components.EventCallback.Factory.Create(this, + __builder.AddComponentParameter(1, nameof(global::Test.MyComponent. +#nullable restore +#line (1,14)-(1,21) "x:\dir\subdir\Test\TestComponent.cshtml" +OnClick + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck>(global::Microsoft.AspNetCore.Components.EventCallback.Factory.Create(this, #nullable restore #line (1,24)-(1,33) "x:\dir\subdir\Test\TestComponent.cshtml" Increment diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallback_CanPassEventCallbackOfT_Implicitly_Action/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallback_CanPassEventCallbackOfT_Implicitly_Action/TestComponent.mappings.txt index 64b18c5262f..9bfc98acdcf 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallback_CanPassEventCallbackOfT_Implicitly_Action/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallback_CanPassEventCallbackOfT_Implicitly_Action/TestComponent.mappings.txt @@ -1,6 +1,11 @@ -Source Location: (23:0,23 [9] x:\dir\subdir\Test\TestComponent.cshtml) +Source Location: (13:0,13 [7] x:\dir\subdir\Test\TestComponent.cshtml) +|OnClick| +Generated Location: (884:23,0 [7] ) +|OnClick| + +Source Location: (23:0,23 [9] x:\dir\subdir\Test\TestComponent.cshtml) |Increment| -Generated Location: (1195:23,0 [9] ) +Generated Location: (1374:31,0 [9] ) |Increment| Source Location: (46:2,7 [87] x:\dir\subdir\Test\TestComponent.cshtml) @@ -10,7 +15,7 @@ Source Location: (46:2,7 [87] x:\dir\subdir\Test\TestComponent.cshtml) counter++; } | -Generated Location: (1444:34,0 [87] ) +Generated Location: (1623:42,0 [87] ) | private int counter; private void Increment() { diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallback_CanPassEventCallbackOfT_Implicitly_ActionOfT/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallback_CanPassEventCallbackOfT_Implicitly_ActionOfT/TestComponent.codegen.cs index bb28619aca9..f50965277d2 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallback_CanPassEventCallbackOfT_Implicitly_ActionOfT/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallback_CanPassEventCallbackOfT_Implicitly_ActionOfT/TestComponent.codegen.cs @@ -24,7 +24,15 @@ public partial class TestComponent : global::Microsoft.AspNetCore.Components.Com protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { __builder.OpenComponent(0); - __builder.AddComponentParameter(1, "OnClick", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck>(global::Microsoft.AspNetCore.Components.EventCallback.Factory.Create(this, + __builder.AddComponentParameter(1, nameof(global::Test.MyComponent. +#nullable restore +#line (2,14)-(2,21) "x:\dir\subdir\Test\TestComponent.cshtml" +OnClick + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck>(global::Microsoft.AspNetCore.Components.EventCallback.Factory.Create(this, #nullable restore #line (2,24)-(2,33) "x:\dir\subdir\Test\TestComponent.cshtml" Increment diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallback_CanPassEventCallbackOfT_Implicitly_ActionOfT/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallback_CanPassEventCallbackOfT_Implicitly_ActionOfT/TestComponent.mappings.txt index edfa77707e0..991030dc414 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallback_CanPassEventCallbackOfT_Implicitly_ActionOfT/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallback_CanPassEventCallbackOfT_Implicitly_ActionOfT/TestComponent.mappings.txt @@ -5,9 +5,14 @@ Generated Location: (371:12,0 [43] ) |using Microsoft.AspNetCore.Components.Web | +Source Location: (57:1,13 [7] x:\dir\subdir\Test\TestComponent.cshtml) +|OnClick| +Generated Location: (1027:29,0 [7] ) +|OnClick| + Source Location: (67:1,23 [9] x:\dir\subdir\Test\TestComponent.cshtml) |Increment| -Generated Location: (1338:29,0 [9] ) +Generated Location: (1517:37,0 [9] ) |Increment| Source Location: (90:3,7 [103] x:\dir\subdir\Test\TestComponent.cshtml) @@ -17,7 +22,7 @@ Source Location: (90:3,7 [103] x:\dir\subdir\Test\TestComponent.cshtml) counter++; } | -Generated Location: (1587:40,0 [103] ) +Generated Location: (1766:48,0 [103] ) | private int counter; private void Increment(MouseEventArgs e) { diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallback_CanPassEventCallbackOfT_Implicitly_FuncOfTTask/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallback_CanPassEventCallbackOfT_Implicitly_FuncOfTTask/TestComponent.codegen.cs index 878f3333eab..9c57a1e5ad0 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallback_CanPassEventCallbackOfT_Implicitly_FuncOfTTask/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallback_CanPassEventCallbackOfT_Implicitly_FuncOfTTask/TestComponent.codegen.cs @@ -24,7 +24,15 @@ public partial class TestComponent : global::Microsoft.AspNetCore.Components.Com protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { __builder.OpenComponent(0); - __builder.AddComponentParameter(1, "OnClick", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck>(global::Microsoft.AspNetCore.Components.EventCallback.Factory.Create(this, + __builder.AddComponentParameter(1, nameof(global::Test.MyComponent. +#nullable restore +#line (2,14)-(2,21) "x:\dir\subdir\Test\TestComponent.cshtml" +OnClick + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck>(global::Microsoft.AspNetCore.Components.EventCallback.Factory.Create(this, #nullable restore #line (2,24)-(2,33) "x:\dir\subdir\Test\TestComponent.cshtml" Increment diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallback_CanPassEventCallbackOfT_Implicitly_FuncOfTTask/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallback_CanPassEventCallbackOfT_Implicitly_FuncOfTTask/TestComponent.mappings.txt index 3fbd03073eb..62195499f65 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallback_CanPassEventCallbackOfT_Implicitly_FuncOfTTask/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallback_CanPassEventCallbackOfT_Implicitly_FuncOfTTask/TestComponent.mappings.txt @@ -5,9 +5,14 @@ Generated Location: (371:12,0 [43] ) |using Microsoft.AspNetCore.Components.Web | +Source Location: (57:1,13 [7] x:\dir\subdir\Test\TestComponent.cshtml) +|OnClick| +Generated Location: (1027:29,0 [7] ) +|OnClick| + Source Location: (67:1,23 [9] x:\dir\subdir\Test\TestComponent.cshtml) |Increment| -Generated Location: (1338:29,0 [9] ) +Generated Location: (1517:37,0 [9] ) |Increment| Source Location: (90:3,7 [139] x:\dir\subdir\Test\TestComponent.cshtml) @@ -18,7 +23,7 @@ Source Location: (90:3,7 [139] x:\dir\subdir\Test\TestComponent.cshtml) return Task.CompletedTask; } | -Generated Location: (1588:40,0 [139] ) +Generated Location: (1767:48,0 [139] ) | private int counter; private Task Increment(MouseEventArgs e) { diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallback_CanPassEventCallbackOfT_Implicitly_FuncOfTask/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallback_CanPassEventCallbackOfT_Implicitly_FuncOfTask/TestComponent.codegen.cs index 8e806e0e6bd..4ee4be91234 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallback_CanPassEventCallbackOfT_Implicitly_FuncOfTask/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallback_CanPassEventCallbackOfT_Implicitly_FuncOfTask/TestComponent.codegen.cs @@ -18,7 +18,15 @@ public partial class TestComponent : global::Microsoft.AspNetCore.Components.Com protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { __builder.OpenComponent(0); - __builder.AddComponentParameter(1, "OnClick", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck>(global::Microsoft.AspNetCore.Components.EventCallback.Factory.Create(this, + __builder.AddComponentParameter(1, nameof(global::Test.MyComponent. +#nullable restore +#line (1,14)-(1,21) "x:\dir\subdir\Test\TestComponent.cshtml" +OnClick + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck>(global::Microsoft.AspNetCore.Components.EventCallback.Factory.Create(this, #nullable restore #line (1,24)-(1,33) "x:\dir\subdir\Test\TestComponent.cshtml" Increment diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallback_CanPassEventCallbackOfT_Implicitly_FuncOfTask/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallback_CanPassEventCallbackOfT_Implicitly_FuncOfTask/TestComponent.mappings.txt index 487d3793671..7108b3258d7 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallback_CanPassEventCallbackOfT_Implicitly_FuncOfTask/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallback_CanPassEventCallbackOfT_Implicitly_FuncOfTask/TestComponent.mappings.txt @@ -1,6 +1,11 @@ -Source Location: (23:0,23 [9] x:\dir\subdir\Test\TestComponent.cshtml) +Source Location: (13:0,13 [7] x:\dir\subdir\Test\TestComponent.cshtml) +|OnClick| +Generated Location: (884:23,0 [7] ) +|OnClick| + +Source Location: (23:0,23 [9] x:\dir\subdir\Test\TestComponent.cshtml) |Increment| -Generated Location: (1195:23,0 [9] ) +Generated Location: (1374:31,0 [9] ) |Increment| Source Location: (46:2,7 [123] x:\dir\subdir\Test\TestComponent.cshtml) @@ -11,7 +16,7 @@ Source Location: (46:2,7 [123] x:\dir\subdir\Test\TestComponent.cshtml) return Task.CompletedTask; } | -Generated Location: (1444:34,0 [123] ) +Generated Location: (1623:42,0 [123] ) | private int counter; private Task Increment() { diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallback_CanPassEventCallbackOfT_Implicitly_TypeMismatch/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallback_CanPassEventCallbackOfT_Implicitly_TypeMismatch/TestComponent.codegen.cs index cd245731b81..1415523be11 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallback_CanPassEventCallbackOfT_Implicitly_TypeMismatch/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallback_CanPassEventCallbackOfT_Implicitly_TypeMismatch/TestComponent.codegen.cs @@ -24,7 +24,15 @@ public partial class TestComponent : global::Microsoft.AspNetCore.Components.Com protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { __builder.OpenComponent(0); - __builder.AddComponentParameter(1, "OnClick", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck>(global::Microsoft.AspNetCore.Components.EventCallback.Factory.Create(this, + __builder.AddComponentParameter(1, nameof(global::Test.MyComponent. +#nullable restore +#line (2,14)-(2,21) "x:\dir\subdir\Test\TestComponent.cshtml" +OnClick + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck>(global::Microsoft.AspNetCore.Components.EventCallback.Factory.Create(this, #nullable restore #line (2,24)-(2,33) "x:\dir\subdir\Test\TestComponent.cshtml" Increment diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallback_CanPassEventCallbackOfT_Implicitly_TypeMismatch/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallback_CanPassEventCallbackOfT_Implicitly_TypeMismatch/TestComponent.mappings.txt index 53219d22308..c7d14769ef2 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallback_CanPassEventCallbackOfT_Implicitly_TypeMismatch/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallback_CanPassEventCallbackOfT_Implicitly_TypeMismatch/TestComponent.mappings.txt @@ -5,9 +5,14 @@ Generated Location: (371:12,0 [43] ) |using Microsoft.AspNetCore.Components.Web | +Source Location: (57:1,13 [7] x:\dir\subdir\Test\TestComponent.cshtml) +|OnClick| +Generated Location: (1027:29,0 [7] ) +|OnClick| + Source Location: (67:1,23 [9] x:\dir\subdir\Test\TestComponent.cshtml) |Increment| -Generated Location: (1338:29,0 [9] ) +Generated Location: (1517:37,0 [9] ) |Increment| Source Location: (90:3,7 [104] x:\dir\subdir\Test\TestComponent.cshtml) @@ -17,7 +22,7 @@ Source Location: (90:3,7 [104] x:\dir\subdir\Test\TestComponent.cshtml) counter++; } | -Generated Location: (1587:40,0 [104] ) +Generated Location: (1766:48,0 [104] ) | private int counter; private void Increment(ChangeEventArgs e) { diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallback_CanPassEventCallback_Explicitly/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallback_CanPassEventCallback_Explicitly/TestComponent.codegen.cs index 5baa666da41..febdfe3ea1b 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallback_CanPassEventCallback_Explicitly/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallback_CanPassEventCallback_Explicitly/TestComponent.codegen.cs @@ -18,7 +18,15 @@ public partial class TestComponent : global::Microsoft.AspNetCore.Components.Com protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { __builder.OpenComponent(0); - __builder.AddComponentParameter(1, "OnClick", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck(global::Microsoft.AspNetCore.Components.EventCallback.Factory.Create(this, + __builder.AddComponentParameter(1, nameof(global::Test.MyComponent. +#nullable restore +#line (1,14)-(1,21) "x:\dir\subdir\Test\TestComponent.cshtml" +OnClick + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck(global::Microsoft.AspNetCore.Components.EventCallback.Factory.Create(this, #nullable restore #line (1,25)-(1,70) "x:\dir\subdir\Test\TestComponent.cshtml" EventCallback.Factory.Create(this, Increment) diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallback_CanPassEventCallback_Explicitly/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallback_CanPassEventCallback_Explicitly/TestComponent.mappings.txt index 06b74d46b7f..cafda797e6a 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallback_CanPassEventCallback_Explicitly/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallback_CanPassEventCallback_Explicitly/TestComponent.mappings.txt @@ -1,6 +1,11 @@ -Source Location: (24:0,24 [45] x:\dir\subdir\Test\TestComponent.cshtml) +Source Location: (13:0,13 [7] x:\dir\subdir\Test\TestComponent.cshtml) +|OnClick| +Generated Location: (884:23,0 [7] ) +|OnClick| + +Source Location: (24:0,24 [45] x:\dir\subdir\Test\TestComponent.cshtml) |EventCallback.Factory.Create(this, Increment)| -Generated Location: (1075:23,0 [45] ) +Generated Location: (1254:31,0 [45] ) |EventCallback.Factory.Create(this, Increment)| Source Location: (84:2,7 [87] x:\dir\subdir\Test\TestComponent.cshtml) @@ -10,7 +15,7 @@ Source Location: (84:2,7 [87] x:\dir\subdir\Test\TestComponent.cshtml) counter++; } | -Generated Location: (1360:34,0 [87] ) +Generated Location: (1539:42,0 [87] ) | private int counter; private void Increment() { diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallback_CanPassEventCallback_Implicitly_Action/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallback_CanPassEventCallback_Implicitly_Action/TestComponent.codegen.cs index 22a940688d2..42ecee966bc 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallback_CanPassEventCallback_Implicitly_Action/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallback_CanPassEventCallback_Implicitly_Action/TestComponent.codegen.cs @@ -18,7 +18,15 @@ public partial class TestComponent : global::Microsoft.AspNetCore.Components.Com protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { __builder.OpenComponent(0); - __builder.AddComponentParameter(1, "OnClick", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck(global::Microsoft.AspNetCore.Components.EventCallback.Factory.Create(this, + __builder.AddComponentParameter(1, nameof(global::Test.MyComponent. +#nullable restore +#line (1,14)-(1,21) "x:\dir\subdir\Test\TestComponent.cshtml" +OnClick + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck(global::Microsoft.AspNetCore.Components.EventCallback.Factory.Create(this, #nullable restore #line (1,24)-(1,33) "x:\dir\subdir\Test\TestComponent.cshtml" Increment diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallback_CanPassEventCallback_Implicitly_Action/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallback_CanPassEventCallback_Implicitly_Action/TestComponent.mappings.txt index c12085ecae9..4d3475d6d60 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallback_CanPassEventCallback_Implicitly_Action/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallback_CanPassEventCallback_Implicitly_Action/TestComponent.mappings.txt @@ -1,6 +1,11 @@ -Source Location: (23:0,23 [9] x:\dir\subdir\Test\TestComponent.cshtml) +Source Location: (13:0,13 [7] x:\dir\subdir\Test\TestComponent.cshtml) +|OnClick| +Generated Location: (884:23,0 [7] ) +|OnClick| + +Source Location: (23:0,23 [9] x:\dir\subdir\Test\TestComponent.cshtml) |Increment| -Generated Location: (1075:23,0 [9] ) +Generated Location: (1254:31,0 [9] ) |Increment| Source Location: (46:2,7 [87] x:\dir\subdir\Test\TestComponent.cshtml) @@ -10,7 +15,7 @@ Source Location: (46:2,7 [87] x:\dir\subdir\Test\TestComponent.cshtml) counter++; } | -Generated Location: (1324:34,0 [87] ) +Generated Location: (1503:42,0 [87] ) | private int counter; private void Increment() { diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallback_CanPassEventCallback_Implicitly_ActionOfObject/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallback_CanPassEventCallback_Implicitly_ActionOfObject/TestComponent.codegen.cs index a7e57a9226c..7fe6c481a4e 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallback_CanPassEventCallback_Implicitly_ActionOfObject/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallback_CanPassEventCallback_Implicitly_ActionOfObject/TestComponent.codegen.cs @@ -18,7 +18,15 @@ public partial class TestComponent : global::Microsoft.AspNetCore.Components.Com protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { __builder.OpenComponent(0); - __builder.AddComponentParameter(1, "OnClick", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck(global::Microsoft.AspNetCore.Components.EventCallback.Factory.Create(this, + __builder.AddComponentParameter(1, nameof(global::Test.MyComponent. +#nullable restore +#line (1,14)-(1,21) "x:\dir\subdir\Test\TestComponent.cshtml" +OnClick + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck(global::Microsoft.AspNetCore.Components.EventCallback.Factory.Create(this, #nullable restore #line (1,24)-(1,33) "x:\dir\subdir\Test\TestComponent.cshtml" Increment diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallback_CanPassEventCallback_Implicitly_ActionOfObject/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallback_CanPassEventCallback_Implicitly_ActionOfObject/TestComponent.mappings.txt index c467c5725a5..f9a8b09c611 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallback_CanPassEventCallback_Implicitly_ActionOfObject/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallback_CanPassEventCallback_Implicitly_ActionOfObject/TestComponent.mappings.txt @@ -1,6 +1,11 @@ -Source Location: (23:0,23 [9] x:\dir\subdir\Test\TestComponent.cshtml) +Source Location: (13:0,13 [7] x:\dir\subdir\Test\TestComponent.cshtml) +|OnClick| +Generated Location: (884:23,0 [7] ) +|OnClick| + +Source Location: (23:0,23 [9] x:\dir\subdir\Test\TestComponent.cshtml) |Increment| -Generated Location: (1075:23,0 [9] ) +Generated Location: (1254:31,0 [9] ) |Increment| Source Location: (46:2,7 [95] x:\dir\subdir\Test\TestComponent.cshtml) @@ -10,7 +15,7 @@ Source Location: (46:2,7 [95] x:\dir\subdir\Test\TestComponent.cshtml) counter++; } | -Generated Location: (1324:34,0 [95] ) +Generated Location: (1503:42,0 [95] ) | private int counter; private void Increment(object e) { diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallback_CanPassEventCallback_Implicitly_FuncOfTask/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallback_CanPassEventCallback_Implicitly_FuncOfTask/TestComponent.codegen.cs index 69f05b6c5c8..c5318e1ac23 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallback_CanPassEventCallback_Implicitly_FuncOfTask/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallback_CanPassEventCallback_Implicitly_FuncOfTask/TestComponent.codegen.cs @@ -18,7 +18,15 @@ public partial class TestComponent : global::Microsoft.AspNetCore.Components.Com protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { __builder.OpenComponent(0); - __builder.AddComponentParameter(1, "OnClick", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck(global::Microsoft.AspNetCore.Components.EventCallback.Factory.Create(this, + __builder.AddComponentParameter(1, nameof(global::Test.MyComponent. +#nullable restore +#line (1,14)-(1,21) "x:\dir\subdir\Test\TestComponent.cshtml" +OnClick + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck(global::Microsoft.AspNetCore.Components.EventCallback.Factory.Create(this, #nullable restore #line (1,24)-(1,33) "x:\dir\subdir\Test\TestComponent.cshtml" Increment diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallback_CanPassEventCallback_Implicitly_FuncOfTask/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallback_CanPassEventCallback_Implicitly_FuncOfTask/TestComponent.mappings.txt index d97669881d8..9a1fbff6cf0 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallback_CanPassEventCallback_Implicitly_FuncOfTask/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallback_CanPassEventCallback_Implicitly_FuncOfTask/TestComponent.mappings.txt @@ -1,6 +1,11 @@ -Source Location: (23:0,23 [9] x:\dir\subdir\Test\TestComponent.cshtml) +Source Location: (13:0,13 [7] x:\dir\subdir\Test\TestComponent.cshtml) +|OnClick| +Generated Location: (884:23,0 [7] ) +|OnClick| + +Source Location: (23:0,23 [9] x:\dir\subdir\Test\TestComponent.cshtml) |Increment| -Generated Location: (1075:23,0 [9] ) +Generated Location: (1254:31,0 [9] ) |Increment| Source Location: (46:2,7 [123] x:\dir\subdir\Test\TestComponent.cshtml) @@ -11,7 +16,7 @@ Source Location: (46:2,7 [123] x:\dir\subdir\Test\TestComponent.cshtml) return Task.CompletedTask; } | -Generated Location: (1324:34,0 [123] ) +Generated Location: (1503:42,0 [123] ) | private int counter; private Task Increment() { diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallback_CanPassEventCallback_Implicitly_FuncOfobjectTask/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallback_CanPassEventCallback_Implicitly_FuncOfobjectTask/TestComponent.codegen.cs index 2c204c4e613..eff63cf8b8b 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallback_CanPassEventCallback_Implicitly_FuncOfobjectTask/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallback_CanPassEventCallback_Implicitly_FuncOfobjectTask/TestComponent.codegen.cs @@ -18,7 +18,15 @@ public partial class TestComponent : global::Microsoft.AspNetCore.Components.Com protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { __builder.OpenComponent(0); - __builder.AddComponentParameter(1, "OnClick", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck(global::Microsoft.AspNetCore.Components.EventCallback.Factory.Create(this, + __builder.AddComponentParameter(1, nameof(global::Test.MyComponent. +#nullable restore +#line (1,14)-(1,21) "x:\dir\subdir\Test\TestComponent.cshtml" +OnClick + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck(global::Microsoft.AspNetCore.Components.EventCallback.Factory.Create(this, #nullable restore #line (1,24)-(1,33) "x:\dir\subdir\Test\TestComponent.cshtml" Increment diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallback_CanPassEventCallback_Implicitly_FuncOfobjectTask/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallback_CanPassEventCallback_Implicitly_FuncOfobjectTask/TestComponent.mappings.txt index 3b9f4df6a8a..81c6fcdabc9 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallback_CanPassEventCallback_Implicitly_FuncOfobjectTask/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/EventCallback_CanPassEventCallback_Implicitly_FuncOfobjectTask/TestComponent.mappings.txt @@ -1,6 +1,11 @@ -Source Location: (23:0,23 [9] x:\dir\subdir\Test\TestComponent.cshtml) +Source Location: (13:0,13 [7] x:\dir\subdir\Test\TestComponent.cshtml) +|OnClick| +Generated Location: (884:23,0 [7] ) +|OnClick| + +Source Location: (23:0,23 [9] x:\dir\subdir\Test\TestComponent.cshtml) |Increment| -Generated Location: (1075:23,0 [9] ) +Generated Location: (1254:31,0 [9] ) |Increment| Source Location: (46:2,7 [131] x:\dir\subdir\Test\TestComponent.cshtml) @@ -11,7 +16,7 @@ Source Location: (46:2,7 [131] x:\dir\subdir\Test\TestComponent.cshtml) return Task.CompletedTask; } | -Generated Location: (1324:34,0 [131] ) +Generated Location: (1503:42,0 [131] ) | private int counter; private Task Increment(object e) { diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/FormName_Component_Generic/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/FormName_Component_Generic/TestComponent.codegen.cs index a266c72542e..f5de853a13c 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/FormName_Component_Generic/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/FormName_Component_Generic/TestComponent.codegen.cs @@ -98,7 +98,15 @@ public static void CreateTestComponent_0(global::Microsoft.AspNetCore.Compone __builder.AddComponentParameter(__seq0, "method", __arg0); __builder.AddComponentParameter(__seq1, "onsubmit", __arg1); __builder.AddComponentParameter(__seq2, "@formname", __arg2); - __builder.AddComponentParameter(__seq3, "Parameter", __arg3); + __builder.AddComponentParameter(__seq3, nameof(global::Test.TestComponent. +#nullable restore +#line (3,83)-(3,92) "x:\dir\subdir\Test\TestComponent.cshtml" +Parameter + +#line default +#line hidden +#nullable disable + ), __arg3); __builder.CloseComponent(); } public static void CreateTestComponent_1(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder, int seq, int __seq0, global::System.Object __arg0, int __seq1, global::System.Object __arg1, int __seq2, global::System.Object __arg2, int __seq3, T __arg3) @@ -107,7 +115,15 @@ public static void CreateTestComponent_1(global::Microsoft.AspNetCore.Compone __builder.AddComponentParameter(__seq0, "method", __arg0); __builder.AddComponentParameter(__seq1, "onsubmit", __arg1); __builder.AddComponentParameter(__seq2, "@formname", __arg2); - __builder.AddComponentParameter(__seq3, "Parameter", __arg3); + __builder.AddComponentParameter(__seq3, nameof(global::Test.TestComponent. +#nullable restore +#line (4,88)-(4,97) "x:\dir\subdir\Test\TestComponent.cshtml" +Parameter + +#line default +#line hidden +#nullable disable + ), __arg3); __builder.CloseComponent(); } } diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/FormName_Component_Generic/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/FormName_Component_Generic/TestComponent.mappings.txt index eb129a14b93..5497447eab9 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/FormName_Component_Generic/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/FormName_Component_Generic/TestComponent.mappings.txt @@ -44,3 +44,13 @@ Generated Location: (2379:80,0 [52] ) [Parameter] public T Parameter { get; set; } | +Source Location: (140:2,82 [9] x:\dir\subdir\Test\TestComponent.cshtml) +|Parameter| +Generated Location: (3349:103,0 [9] ) +|Parameter| + +Source Location: (245:3,87 [9] x:\dir\subdir\Test\TestComponent.cshtml) +|Parameter| +Generated Location: (4227:120,0 [9] ) +|Parameter| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/FormName_Component_Generic_RazorLangVersion7/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/FormName_Component_Generic_RazorLangVersion7/TestComponent.codegen.cs index 58450b3eddc..09fba466270 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/FormName_Component_Generic_RazorLangVersion7/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/FormName_Component_Generic_RazorLangVersion7/TestComponent.codegen.cs @@ -98,7 +98,15 @@ public static void CreateTestComponent_0(global::Microsoft.AspNetCore.Compone __builder.AddAttribute(__seq0, "method", (object)__arg0); __builder.AddAttribute(__seq1, "onsubmit", (object)__arg1); __builder.AddAttribute(__seq2, "@formname", (object)__arg2); - __builder.AddAttribute(__seq3, "Parameter", (object)__arg3); + __builder.AddAttribute(__seq3, nameof(global::Test.TestComponent. +#nullable restore +#line (3,83)-(3,92) "x:\dir\subdir\Test\TestComponent.cshtml" +Parameter + +#line default +#line hidden +#nullable disable + ), (object)__arg3); __builder.CloseComponent(); } public static void CreateTestComponent_1(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder, int seq, int __seq0, global::System.Object __arg0, int __seq1, global::System.Object __arg1, int __seq2, global::System.Object __arg2, int __seq3, T __arg3) @@ -107,7 +115,15 @@ public static void CreateTestComponent_1(global::Microsoft.AspNetCore.Compone __builder.AddAttribute(__seq0, "method", (object)__arg0); __builder.AddAttribute(__seq1, "onsubmit", (object)__arg1); __builder.AddAttribute(__seq2, "@formname", (object)__arg2); - __builder.AddAttribute(__seq3, "Parameter", (object)__arg3); + __builder.AddAttribute(__seq3, nameof(global::Test.TestComponent. +#nullable restore +#line (4,88)-(4,97) "x:\dir\subdir\Test\TestComponent.cshtml" +Parameter + +#line default +#line hidden +#nullable disable + ), (object)__arg3); __builder.CloseComponent(); } } diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/FormName_Component_Generic_RazorLangVersion7/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/FormName_Component_Generic_RazorLangVersion7/TestComponent.mappings.txt index eb129a14b93..86d9ee1083d 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/FormName_Component_Generic_RazorLangVersion7/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/FormName_Component_Generic_RazorLangVersion7/TestComponent.mappings.txt @@ -44,3 +44,13 @@ Generated Location: (2379:80,0 [52] ) [Parameter] public T Parameter { get; set; } | +Source Location: (140:2,82 [9] x:\dir\subdir\Test\TestComponent.cshtml) +|Parameter| +Generated Location: (3337:103,0 [9] ) +|Parameter| + +Source Location: (245:3,87 [9] x:\dir\subdir\Test\TestComponent.cshtml) +|Parameter| +Generated Location: (4211:120,0 [9] ) +|Parameter| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericBindToGenericComponent_ExplicitType_WithGetSet_Action/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericBindToGenericComponent_ExplicitType_WithGetSet_Action/TestComponent.codegen.cs index e58501bbf93..fc83dac0e5a 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericBindToGenericComponent_ExplicitType_WithGetSet_Action/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericBindToGenericComponent_ExplicitType_WithGetSet_Action/TestComponent.codegen.cs @@ -26,7 +26,15 @@ public partial class TestComponent< protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { __builder.OpenComponent>(0); - __builder.AddComponentParameter(1, "Value", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( + __builder.AddComponentParameter(1, nameof(global::Test.MyComponent. +#nullable restore +#line (2,36)-(2,41) "x:\dir\subdir\Test\TestComponent.cshtml" +Value + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( #nullable restore #line (2,47)-(2,58) "x:\dir\subdir\Test\TestComponent.cshtml" ParentValue @@ -35,7 +43,7 @@ protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components. #line hidden #nullable disable )); - __builder.AddComponentParameter(2, "ValueChanged", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck>(global::Microsoft.AspNetCore.Components.EventCallback.Factory.Create(this, global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.CreateInferredEventCallback(this, + __builder.AddComponentParameter(2, nameof(global::Test.MyComponent.ValueChanged), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck>(global::Microsoft.AspNetCore.Components.EventCallback.Factory.Create(this, global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.CreateInferredEventCallback(this, #nullable restore #line (2,77)-(2,88) "x:\dir\subdir\Test\TestComponent.cshtml" UpdateValue diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericBindToGenericComponent_ExplicitType_WithGetSet_Action/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericBindToGenericComponent_ExplicitType_WithGetSet_Action/TestComponent.mappings.txt index ad1862e26bc..e871ed53501 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericBindToGenericComponent_ExplicitType_WithGetSet_Action/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericBindToGenericComponent_ExplicitType_WithGetSet_Action/TestComponent.mappings.txt @@ -3,14 +3,19 @@ Generated Location: (474:16,0 [6] ) |TParam| +Source Location: (54:1,35 [5] x:\dir\subdir\Test\TestComponent.cshtml) +|Value| +Generated Location: (1048:31,0 [5] ) +|Value| + Source Location: (65:1,46 [11] x:\dir\subdir\Test\TestComponent.cshtml) |ParentValue| -Generated Location: (1107:31,0 [11] ) +Generated Location: (1294:39,0 [11] ) |ParentValue| Source Location: (95:1,76 [11] x:\dir\subdir\Test\TestComponent.cshtml) |UpdateValue| -Generated Location: (1668:40,0 [11] ) +Generated Location: (1894:48,0 [11] ) |UpdateValue| Source Location: (119:2,7 [128] x:\dir\subdir\Test\TestComponent.cshtml) @@ -19,7 +24,7 @@ Source Location: (119:2,7 [128] x:\dir\subdir\Test\TestComponent.cshtml) public void UpdateValue(TParam value) { ParentValue = value; } | -Generated Location: (1933:51,0 [128] ) +Generated Location: (2159:59,0 [128] ) | public TParam ParentValue { get; set; } = default; diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericBindToGenericComponent_ExplicitType_WithGetSet_EventCallback/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericBindToGenericComponent_ExplicitType_WithGetSet_EventCallback/TestComponent.codegen.cs index de8fd2e413d..d80a96ccd8f 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericBindToGenericComponent_ExplicitType_WithGetSet_EventCallback/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericBindToGenericComponent_ExplicitType_WithGetSet_EventCallback/TestComponent.codegen.cs @@ -26,7 +26,15 @@ public partial class TestComponent< protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { __builder.OpenComponent>(0); - __builder.AddComponentParameter(1, "Value", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( + __builder.AddComponentParameter(1, nameof(global::Test.MyComponent. +#nullable restore +#line (2,36)-(2,41) "x:\dir\subdir\Test\TestComponent.cshtml" +Value + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( #nullable restore #line (2,47)-(2,58) "x:\dir\subdir\Test\TestComponent.cshtml" ParentValue @@ -35,7 +43,7 @@ protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components. #line hidden #nullable disable )); - __builder.AddComponentParameter(2, "ValueChanged", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck>(global::Microsoft.AspNetCore.Components.EventCallback.Factory.Create(this, global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.CreateInferredEventCallback(this, + __builder.AddComponentParameter(2, nameof(global::Test.MyComponent.ValueChanged), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck>(global::Microsoft.AspNetCore.Components.EventCallback.Factory.Create(this, global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.CreateInferredEventCallback(this, #nullable restore #line (2,77)-(2,88) "x:\dir\subdir\Test\TestComponent.cshtml" UpdateValue diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericBindToGenericComponent_ExplicitType_WithGetSet_EventCallback/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericBindToGenericComponent_ExplicitType_WithGetSet_EventCallback/TestComponent.mappings.txt index c56d0553bfc..c05929e78f1 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericBindToGenericComponent_ExplicitType_WithGetSet_EventCallback/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericBindToGenericComponent_ExplicitType_WithGetSet_EventCallback/TestComponent.mappings.txt @@ -3,14 +3,19 @@ Generated Location: (474:16,0 [6] ) |TParam| +Source Location: (54:1,35 [5] x:\dir\subdir\Test\TestComponent.cshtml) +|Value| +Generated Location: (1048:31,0 [5] ) +|Value| + Source Location: (65:1,46 [11] x:\dir\subdir\Test\TestComponent.cshtml) |ParentValue| -Generated Location: (1107:31,0 [11] ) +Generated Location: (1294:39,0 [11] ) |ParentValue| Source Location: (95:1,76 [11] x:\dir\subdir\Test\TestComponent.cshtml) |UpdateValue| -Generated Location: (1668:40,0 [11] ) +Generated Location: (1894:48,0 [11] ) |UpdateValue| Source Location: (119:2,7 [118] x:\dir\subdir\Test\TestComponent.cshtml) @@ -18,7 +23,7 @@ Source Location: (119:2,7 [118] x:\dir\subdir\Test\TestComponent.cshtml) public TParam ParentValue { get; set; } = default; public EventCallback UpdateValue { get; set; } | -Generated Location: (1933:51,0 [118] ) +Generated Location: (2159:59,0 [118] ) | public TParam ParentValue { get; set; } = default; public EventCallback UpdateValue { get; set; } diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericBindToGenericComponent_ExplicitType_WithGetSet_Function/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericBindToGenericComponent_ExplicitType_WithGetSet_Function/TestComponent.codegen.cs index 03bec840a0d..912ae753437 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericBindToGenericComponent_ExplicitType_WithGetSet_Function/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericBindToGenericComponent_ExplicitType_WithGetSet_Function/TestComponent.codegen.cs @@ -26,7 +26,15 @@ public partial class TestComponent< protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { __builder.OpenComponent>(0); - __builder.AddComponentParameter(1, "Value", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( + __builder.AddComponentParameter(1, nameof(global::Test.MyComponent. +#nullable restore +#line (2,36)-(2,41) "x:\dir\subdir\Test\TestComponent.cshtml" +Value + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( #nullable restore #line (2,47)-(2,58) "x:\dir\subdir\Test\TestComponent.cshtml" ParentValue @@ -35,7 +43,7 @@ protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components. #line hidden #nullable disable )); - __builder.AddComponentParameter(2, "ValueChanged", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck>(global::Microsoft.AspNetCore.Components.EventCallback.Factory.Create(this, global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.CreateInferredEventCallback(this, + __builder.AddComponentParameter(2, nameof(global::Test.MyComponent.ValueChanged), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck>(global::Microsoft.AspNetCore.Components.EventCallback.Factory.Create(this, global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.CreateInferredEventCallback(this, #nullable restore #line (2,77)-(2,88) "x:\dir\subdir\Test\TestComponent.cshtml" UpdateValue diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericBindToGenericComponent_ExplicitType_WithGetSet_Function/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericBindToGenericComponent_ExplicitType_WithGetSet_Function/TestComponent.mappings.txt index 52bda8fdfcc..e2c545c5688 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericBindToGenericComponent_ExplicitType_WithGetSet_Function/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericBindToGenericComponent_ExplicitType_WithGetSet_Function/TestComponent.mappings.txt @@ -3,14 +3,19 @@ Generated Location: (474:16,0 [6] ) |TParam| +Source Location: (54:1,35 [5] x:\dir\subdir\Test\TestComponent.cshtml) +|Value| +Generated Location: (1048:31,0 [5] ) +|Value| + Source Location: (65:1,46 [11] x:\dir\subdir\Test\TestComponent.cshtml) |ParentValue| -Generated Location: (1107:31,0 [11] ) +Generated Location: (1294:39,0 [11] ) |ParentValue| Source Location: (95:1,76 [11] x:\dir\subdir\Test\TestComponent.cshtml) |UpdateValue| -Generated Location: (1668:40,0 [11] ) +Generated Location: (1894:48,0 [11] ) |UpdateValue| Source Location: (119:2,7 [155] x:\dir\subdir\Test\TestComponent.cshtml) @@ -19,7 +24,7 @@ Source Location: (119:2,7 [155] x:\dir\subdir\Test\TestComponent.cshtml) public Task UpdateValue(TParam value) { ParentValue = value; return Task.CompletedTask; } | -Generated Location: (1933:51,0 [155] ) +Generated Location: (2159:59,0 [155] ) | public TParam ParentValue { get; set; } = default; diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponentBindToGenericComponent_ExplicitType_WithAfter_Action/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponentBindToGenericComponent_ExplicitType_WithAfter_Action/TestComponent.codegen.cs index a624ee3be56..6835ab81603 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponentBindToGenericComponent_ExplicitType_WithAfter_Action/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponentBindToGenericComponent_ExplicitType_WithAfter_Action/TestComponent.codegen.cs @@ -26,7 +26,15 @@ public partial class TestComponent< protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { __builder.OpenComponent>(0); - __builder.AddComponentParameter(1, "Value", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( + __builder.AddComponentParameter(1, nameof(global::Test.MyComponent. +#nullable restore +#line (2,36)-(2,41) "x:\dir\subdir\Test\TestComponent.cshtml" +Value + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( #nullable restore #line (2,47)-(2,58) "x:\dir\subdir\Test\TestComponent.cshtml" ParentValue @@ -35,7 +43,7 @@ protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components. #line hidden #nullable disable )); - __builder.AddComponentParameter(2, "ValueChanged", (global::System.Action)( __value => { ParentValue = __value; global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.InvokeSynchronousDelegate( + __builder.AddComponentParameter(2, nameof(global::Test.MyComponent.ValueChanged), (global::System.Action)( __value => { ParentValue = __value; global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.InvokeSynchronousDelegate( #nullable restore #line (2,79)-(2,85) "x:\dir\subdir\Test\TestComponent.cshtml" Update diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponentBindToGenericComponent_ExplicitType_WithAfter_Action/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponentBindToGenericComponent_ExplicitType_WithAfter_Action/TestComponent.mappings.txt index 35f3774093b..3e969a7663c 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponentBindToGenericComponent_ExplicitType_WithAfter_Action/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponentBindToGenericComponent_ExplicitType_WithAfter_Action/TestComponent.mappings.txt @@ -3,14 +3,19 @@ Generated Location: (474:16,0 [6] ) |TParam| +Source Location: (54:1,35 [5] x:\dir\subdir\Test\TestComponent.cshtml) +|Value| +Generated Location: (1048:31,0 [5] ) +|Value| + Source Location: (65:1,46 [11] x:\dir\subdir\Test\TestComponent.cshtml) |ParentValue| -Generated Location: (1107:31,0 [11] ) +Generated Location: (1294:39,0 [11] ) |ParentValue| Source Location: (97:1,78 [6] x:\dir\subdir\Test\TestComponent.cshtml) |Update| -Generated Location: (1501:40,0 [6] ) +Generated Location: (1727:48,0 [6] ) |Update| Source Location: (116:2,7 [79] x:\dir\subdir\Test\TestComponent.cshtml) @@ -19,7 +24,7 @@ Source Location: (116:2,7 [79] x:\dir\subdir\Test\TestComponent.cshtml) public void Update() { } | -Generated Location: (1750:51,0 [79] ) +Generated Location: (1976:59,0 [79] ) | public TParam ParentValue { get; set; } diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponentBindToGenericComponent_InferredType_WithAfter_Action/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponentBindToGenericComponent_InferredType_WithAfter_Action/TestComponent.codegen.cs index 16f5be14c7f..91d7b1d6a9e 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponentBindToGenericComponent_InferredType_WithAfter_Action/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponentBindToGenericComponent_InferredType_WithAfter_Action/TestComponent.codegen.cs @@ -65,8 +65,16 @@ internal static class TypeInference public static void CreateMyComponent_0(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder, int seq, int __seq0, TValue __arg0, int __seq1, global::System.Action __arg1) { __builder.OpenComponent>(seq); - __builder.AddComponentParameter(__seq0, "Value", __arg0); - __builder.AddComponentParameter(__seq1, "ValueChanged", __arg1); + __builder.AddComponentParameter(__seq0, nameof(global::Test.MyComponent. +#nullable restore +#line (2,20)-(2,25) "x:\dir\subdir\Test\TestComponent.cshtml" +Value + +#line default +#line hidden +#nullable disable + ), __arg0); + __builder.AddComponentParameter(__seq1, nameof(global::Test.MyComponent.ValueChanged), __arg1); __builder.CloseComponent(); } } diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponentBindToGenericComponent_InferredType_WithAfter_Action/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponentBindToGenericComponent_InferredType_WithAfter_Action/TestComponent.mappings.txt index d1e7963e68b..4fbc1b895f8 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponentBindToGenericComponent_InferredType_WithAfter_Action/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponentBindToGenericComponent_InferredType_WithAfter_Action/TestComponent.mappings.txt @@ -26,3 +26,8 @@ Generated Location: (1491:48,0 [79] ) public void Update() { } | +Source Location: (38:1,19 [5] x:\dir\subdir\Test\TestComponent.cshtml) +|Value| +Generated Location: (2217:70,0 [5] ) +|Value| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponentBindToGenericComponent_InferredType_WithGetSet_Action/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponentBindToGenericComponent_InferredType_WithGetSet_Action/TestComponent.codegen.cs index d961ed95efe..85519c2896b 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponentBindToGenericComponent_InferredType_WithGetSet_Action/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponentBindToGenericComponent_InferredType_WithGetSet_Action/TestComponent.codegen.cs @@ -65,8 +65,16 @@ internal static class TypeInference public static void CreateMyComponent_0(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder, int seq, int __seq0, TValue __arg0, int __seq1, global::Microsoft.AspNetCore.Components.EventCallback __arg1) { __builder.OpenComponent>(seq); - __builder.AddComponentParameter(__seq0, "Value", __arg0); - __builder.AddComponentParameter(__seq1, "ValueChanged", __arg1); + __builder.AddComponentParameter(__seq0, nameof(global::Test.MyComponent. +#nullable restore +#line (2,20)-(2,25) "x:\dir\subdir\Test\TestComponent.cshtml" +Value + +#line default +#line hidden +#nullable disable + ), __arg0); + __builder.AddComponentParameter(__seq1, nameof(global::Test.MyComponent.ValueChanged), __arg1); __builder.CloseComponent(); } } diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponentBindToGenericComponent_InferredType_WithGetSet_Action/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponentBindToGenericComponent_InferredType_WithGetSet_Action/TestComponent.mappings.txt index 1a1cb5f9a97..6886fc84d8c 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponentBindToGenericComponent_InferredType_WithGetSet_Action/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponentBindToGenericComponent_InferredType_WithGetSet_Action/TestComponent.mappings.txt @@ -26,3 +26,8 @@ Generated Location: (1553:48,0 [128] ) public void UpdateValue(TParam value) { ParentValue = value; } | +Source Location: (38:1,19 [5] x:\dir\subdir\Test\TestComponent.cshtml) +|Value| +Generated Location: (2360:70,0 [5] ) +|Value| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponentBindToGenericComponent_InferredType_WithGetSet_EventCallback/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponentBindToGenericComponent_InferredType_WithGetSet_EventCallback/TestComponent.codegen.cs index 0f73dd02798..5d06df85eb8 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponentBindToGenericComponent_InferredType_WithGetSet_EventCallback/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponentBindToGenericComponent_InferredType_WithGetSet_EventCallback/TestComponent.codegen.cs @@ -64,8 +64,16 @@ internal static class TypeInference public static void CreateMyComponent_0(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder, int seq, int __seq0, TValue __arg0, int __seq1, global::Microsoft.AspNetCore.Components.EventCallback __arg1) { __builder.OpenComponent>(seq); - __builder.AddComponentParameter(__seq0, "Value", __arg0); - __builder.AddComponentParameter(__seq1, "ValueChanged", __arg1); + __builder.AddComponentParameter(__seq0, nameof(global::Test.MyComponent. +#nullable restore +#line (2,20)-(2,25) "x:\dir\subdir\Test\TestComponent.cshtml" +Value + +#line default +#line hidden +#nullable disable + ), __arg0); + __builder.AddComponentParameter(__seq1, nameof(global::Test.MyComponent.ValueChanged), __arg1); __builder.CloseComponent(); } } diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponentBindToGenericComponent_InferredType_WithGetSet_EventCallback/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponentBindToGenericComponent_InferredType_WithGetSet_EventCallback/TestComponent.mappings.txt index 1c62de8e2ec..d08c43f4646 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponentBindToGenericComponent_InferredType_WithGetSet_EventCallback/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponentBindToGenericComponent_InferredType_WithGetSet_EventCallback/TestComponent.mappings.txt @@ -24,3 +24,8 @@ Generated Location: (1553:48,0 [118] ) public EventCallback UpdateValue { get; set; } | +Source Location: (38:1,19 [5] x:\dir\subdir\Test\TestComponent.cshtml) +|Value| +Generated Location: (2350:69,0 [5] ) +|Value| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponentBindToGenericComponent_InferredType_WithGetSet_Function/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponentBindToGenericComponent_InferredType_WithGetSet_Function/TestComponent.codegen.cs index f741030d4a2..c8d9527c663 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponentBindToGenericComponent_InferredType_WithGetSet_Function/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponentBindToGenericComponent_InferredType_WithGetSet_Function/TestComponent.codegen.cs @@ -65,8 +65,16 @@ internal static class TypeInference public static void CreateMyComponent_0(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder, int seq, int __seq0, TValue __arg0, int __seq1, global::Microsoft.AspNetCore.Components.EventCallback __arg1) { __builder.OpenComponent>(seq); - __builder.AddComponentParameter(__seq0, "Value", __arg0); - __builder.AddComponentParameter(__seq1, "ValueChanged", __arg1); + __builder.AddComponentParameter(__seq0, nameof(global::Test.MyComponent. +#nullable restore +#line (2,20)-(2,25) "x:\dir\subdir\Test\TestComponent.cshtml" +Value + +#line default +#line hidden +#nullable disable + ), __arg0); + __builder.AddComponentParameter(__seq1, nameof(global::Test.MyComponent.ValueChanged), __arg1); __builder.CloseComponent(); } } diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponentBindToGenericComponent_InferredType_WithGetSet_Function/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponentBindToGenericComponent_InferredType_WithGetSet_Function/TestComponent.mappings.txt index b0a99b15f02..e0ca795cbd6 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponentBindToGenericComponent_InferredType_WithGetSet_Function/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponentBindToGenericComponent_InferredType_WithGetSet_Function/TestComponent.mappings.txt @@ -26,3 +26,8 @@ Generated Location: (1553:48,0 [155] ) public Task UpdateValue(TParam value) { ParentValue = value; return Task.CompletedTask; } | +Source Location: (38:1,19 [5] x:\dir\subdir\Test\TestComponent.cshtml) +|Value| +Generated Location: (2387:70,0 [5] ) +|Value| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_GenericEventCallbackWithGenericTypeParameter_NestedTypeExplicit/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_GenericEventCallbackWithGenericTypeParameter_NestedTypeExplicit/TestComponent.codegen.cs index a1bcf0160db..03218524b7c 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_GenericEventCallbackWithGenericTypeParameter_NestedTypeExplicit/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_GenericEventCallbackWithGenericTypeParameter_NestedTypeExplicit/TestComponent.codegen.cs @@ -32,7 +32,15 @@ public partial class TestComponent< protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { __builder.OpenComponent>(0); - __builder.AddComponentParameter(1, "MyEvent", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck>(global::Microsoft.AspNetCore.Components.EventCallback.Factory.Create(this, + __builder.AddComponentParameter(1, nameof(global::Test.MyComponent. +#nullable restore +#line (3,29)-(3,36) "x:\dir\subdir\Test\TestComponent.cshtml" +MyEvent + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck>(global::Microsoft.AspNetCore.Components.EventCallback.Factory.Create(this, #nullable restore #line (3,38)-(3,54) "x:\dir\subdir\Test\TestComponent.cshtml" (TChild x) => {} diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_GenericEventCallbackWithGenericTypeParameter_NestedTypeExplicit/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_GenericEventCallbackWithGenericTypeParameter_NestedTypeExplicit/TestComponent.mappings.txt index 89977e57a59..a286fd67250 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_GenericEventCallbackWithGenericTypeParameter_NestedTypeExplicit/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_GenericEventCallbackWithGenericTypeParameter_NestedTypeExplicit/TestComponent.mappings.txt @@ -10,8 +10,13 @@ Source Location: (11:0,11 [6] x:\dir\subdir\Test\TestComponent.cshtml) Generated Location: (586:22,0 [6] ) |TChild| +Source Location: (60:2,28 [7] x:\dir\subdir\Test\TestComponent.cshtml) +|MyEvent| +Generated Location: (1160:37,0 [7] ) +|MyEvent| + Source Location: (69:2,37 [16] x:\dir\subdir\Test\TestComponent.cshtml) |(TChild x) => {}| -Generated Location: (1359:37,0 [16] ) +Generated Location: (1546:45,0 [16] ) |(TChild x) => {}| diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_GenericEventCallbackWithGenericTypeParameter_NestedTypeInference/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_GenericEventCallbackWithGenericTypeParameter_NestedTypeInference/TestComponent.codegen.cs index 9e557fa03e8..c205d82ae7c 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_GenericEventCallbackWithGenericTypeParameter_NestedTypeInference/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_GenericEventCallbackWithGenericTypeParameter_NestedTypeInference/TestComponent.codegen.cs @@ -70,8 +70,24 @@ internal static class TypeInference public static void CreateMyComponent_0(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder, int seq, int __seq0, TItem __arg0, int __seq1, global::Microsoft.AspNetCore.Components.EventCallback __arg1) { __builder.OpenComponent>(seq); - __builder.AddComponentParameter(__seq0, "Item", __arg0); - __builder.AddComponentParameter(__seq1, "MyEvent", __arg1); + __builder.AddComponentParameter(__seq0, nameof(global::Test.MyComponent. +#nullable restore +#line (3,14)-(3,18) "x:\dir\subdir\Test\TestComponent.cshtml" +Item + +#line default +#line hidden +#nullable disable + ), __arg0); + __builder.AddComponentParameter(__seq1, nameof(global::Test.MyComponent. +#nullable restore +#line (3,31)-(3,38) "x:\dir\subdir\Test\TestComponent.cshtml" +MyEvent + +#line default +#line hidden +#nullable disable + ), __arg1); __builder.CloseComponent(); } } diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_GenericEventCallbackWithGenericTypeParameter_NestedTypeInference/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_GenericEventCallbackWithGenericTypeParameter_NestedTypeInference/TestComponent.mappings.txt index 907727abdac..a1f08fac985 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_GenericEventCallbackWithGenericTypeParameter_NestedTypeInference/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_GenericEventCallbackWithGenericTypeParameter_NestedTypeInference/TestComponent.mappings.txt @@ -31,3 +31,13 @@ Generated Location: (1544:54,0 [138] ) [Parameter] public EventCallback MyChildEvent { get; set; } | +Source Location: (45:2,13 [4] x:\dir\subdir\Test\TestComponent.cshtml) +|Item| +Generated Location: (2356:75,0 [4] ) +|Item| + +Source Location: (62:2,30 [7] x:\dir\subdir\Test\TestComponent.cshtml) +|MyEvent| +Generated Location: (2604:84,0 [7] ) +|MyEvent| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_GenericEventCallbackWithGenericTypeParameter_TypeInference/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_GenericEventCallbackWithGenericTypeParameter_TypeInference/TestComponent.codegen.cs index f91193f26ba..7ff8a891f84 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_GenericEventCallbackWithGenericTypeParameter_TypeInference/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_GenericEventCallbackWithGenericTypeParameter_TypeInference/TestComponent.codegen.cs @@ -52,8 +52,24 @@ internal static class TypeInference public static void CreateMyComponent_0(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder, int seq, int __seq0, TItem __arg0, int __seq1, global::Microsoft.AspNetCore.Components.EventCallback __arg1) { __builder.OpenComponent>(seq); - __builder.AddComponentParameter(__seq0, "Item", __arg0); - __builder.AddComponentParameter(__seq1, "MyEvent", __arg1); + __builder.AddComponentParameter(__seq0, nameof(global::Test.MyComponent. +#nullable restore +#line (2,14)-(2,18) "x:\dir\subdir\Test\TestComponent.cshtml" +Item + +#line default +#line hidden +#nullable disable + ), __arg0); + __builder.AddComponentParameter(__seq1, nameof(global::Test.MyComponent. +#nullable restore +#line (2,23)-(2,30) "x:\dir\subdir\Test\TestComponent.cshtml" +MyEvent + +#line default +#line hidden +#nullable disable + ), __arg1); __builder.CloseComponent(); } } diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_GenericEventCallbackWithGenericTypeParameter_TypeInference/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_GenericEventCallbackWithGenericTypeParameter_TypeInference/TestComponent.mappings.txt index 44717b0a389..3b1a27e4619 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_GenericEventCallbackWithGenericTypeParameter_TypeInference/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_GenericEventCallbackWithGenericTypeParameter_TypeInference/TestComponent.mappings.txt @@ -15,3 +15,13 @@ Source Location: (44:1,31 [13] x:\dir\subdir\Test\TestComponent.cshtml) Generated Location: (1178:36,0 [13] ) |(int x) => {}| +Source Location: (26:1,13 [4] x:\dir\subdir\Test\TestComponent.cshtml) +|Item| +Generated Location: (1931:57,0 [4] ) +|Item| + +Source Location: (35:1,22 [7] x:\dir\subdir\Test\TestComponent.cshtml) +|MyEvent| +Generated Location: (2179:66,0 [7] ) +|MyEvent| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_GenericEventCallbackWithNestedGenericTypeParameter_TypeInference/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_GenericEventCallbackWithNestedGenericTypeParameter_TypeInference/TestComponent.codegen.cs index cd68bd4f844..8884b3c8df2 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_GenericEventCallbackWithNestedGenericTypeParameter_TypeInference/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_GenericEventCallbackWithNestedGenericTypeParameter_TypeInference/TestComponent.codegen.cs @@ -57,8 +57,24 @@ internal static class TypeInference public static void CreateMyComponent_0(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder, int seq, int __seq0, TItem __arg0, int __seq1, global::Microsoft.AspNetCore.Components.EventCallback> __arg1) { __builder.OpenComponent>(seq); - __builder.AddComponentParameter(__seq0, "Item", __arg0); - __builder.AddComponentParameter(__seq1, "MyEvent", __arg1); + __builder.AddComponentParameter(__seq0, nameof(global::Test.MyComponent. +#nullable restore +#line (3,14)-(3,18) "x:\dir\subdir\Test\TestComponent.cshtml" +Item + +#line default +#line hidden +#nullable disable + ), __arg0); + __builder.AddComponentParameter(__seq1, nameof(global::Test.MyComponent. +#nullable restore +#line (3,23)-(3,30) "x:\dir\subdir\Test\TestComponent.cshtml" +MyEvent + +#line default +#line hidden +#nullable disable + ), __arg1); __builder.CloseComponent(); } } diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_GenericEventCallbackWithNestedGenericTypeParameter_TypeInference/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_GenericEventCallbackWithNestedGenericTypeParameter_TypeInference/TestComponent.mappings.txt index 54480971fbd..71a8ada88f0 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_GenericEventCallbackWithNestedGenericTypeParameter_TypeInference/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_GenericEventCallbackWithNestedGenericTypeParameter_TypeInference/TestComponent.mappings.txt @@ -22,3 +22,13 @@ Source Location: (79:2,31 [26] x:\dir\subdir\Test\TestComponent.cshtml) Generated Location: (1273:41,0 [26] ) |(IEnumerable x) => {}| +Source Location: (61:2,13 [4] x:\dir\subdir\Test\TestComponent.cshtml) +|Item| +Generated Location: (2087:62,0 [4] ) +|Item| + +Source Location: (70:2,22 [7] x:\dir\subdir\Test\TestComponent.cshtml) +|MyEvent| +Generated Location: (2335:71,0 [7] ) +|MyEvent| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_GenericEventCallback_TypeInference/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_GenericEventCallback_TypeInference/TestComponent.codegen.cs index 0d9d5d17fd4..10f4b66976e 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_GenericEventCallback_TypeInference/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_GenericEventCallback_TypeInference/TestComponent.codegen.cs @@ -52,8 +52,24 @@ internal static class TypeInference public static void CreateMyComponent_0(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder, int seq, int __seq0, TItem __arg0, int __seq1, global::Microsoft.AspNetCore.Components.EventCallback __arg1) { __builder.OpenComponent>(seq); - __builder.AddComponentParameter(__seq0, "Item", __arg0); - __builder.AddComponentParameter(__seq1, "MyEvent", __arg1); + __builder.AddComponentParameter(__seq0, nameof(global::Test.MyComponent. +#nullable restore +#line (2,14)-(2,18) "x:\dir\subdir\Test\TestComponent.cshtml" +Item + +#line default +#line hidden +#nullable disable + ), __arg0); + __builder.AddComponentParameter(__seq1, nameof(global::Test.MyComponent. +#nullable restore +#line (2,23)-(2,30) "x:\dir\subdir\Test\TestComponent.cshtml" +MyEvent + +#line default +#line hidden +#nullable disable + ), __arg1); __builder.CloseComponent(); } } diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_GenericEventCallback_TypeInference/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_GenericEventCallback_TypeInference/TestComponent.mappings.txt index e8192cc2125..fd318b297ef 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_GenericEventCallback_TypeInference/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_GenericEventCallback_TypeInference/TestComponent.mappings.txt @@ -15,3 +15,13 @@ Source Location: (44:1,31 [7] x:\dir\subdir\Test\TestComponent.cshtml) Generated Location: (1204:36,0 [7] ) |x => {}| +Source Location: (26:1,13 [4] x:\dir\subdir\Test\TestComponent.cshtml) +|Item| +Generated Location: (1970:57,0 [4] ) +|Item| + +Source Location: (35:1,22 [7] x:\dir\subdir\Test\TestComponent.cshtml) +|MyEvent| +Generated Location: (2218:66,0 [7] ) +|MyEvent| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_NestedGenericEventCallback_TypeInference/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_NestedGenericEventCallback_TypeInference/TestComponent.codegen.cs index f602b094a4a..4bfb77509b9 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_NestedGenericEventCallback_TypeInference/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_NestedGenericEventCallback_TypeInference/TestComponent.codegen.cs @@ -52,8 +52,24 @@ internal static class TypeInference public static void CreateMyComponent_0(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder, int seq, int __seq0, TItem __arg0, int __seq1, global::Microsoft.AspNetCore.Components.EventCallback>> __arg1) { __builder.OpenComponent>(seq); - __builder.AddComponentParameter(__seq0, "Item", __arg0); - __builder.AddComponentParameter(__seq1, "MyEvent", __arg1); + __builder.AddComponentParameter(__seq0, nameof(global::Test.MyComponent. +#nullable restore +#line (2,14)-(2,18) "x:\dir\subdir\Test\TestComponent.cshtml" +Item + +#line default +#line hidden +#nullable disable + ), __arg0); + __builder.AddComponentParameter(__seq1, nameof(global::Test.MyComponent. +#nullable restore +#line (2,23)-(2,30) "x:\dir\subdir\Test\TestComponent.cshtml" +MyEvent + +#line default +#line hidden +#nullable disable + ), __arg1); __builder.CloseComponent(); } } diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_NestedGenericEventCallback_TypeInference/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_NestedGenericEventCallback_TypeInference/TestComponent.mappings.txt index e983c33502f..26a914cccab 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_NestedGenericEventCallback_TypeInference/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_NestedGenericEventCallback_TypeInference/TestComponent.mappings.txt @@ -15,3 +15,13 @@ Source Location: (44:1,31 [7] x:\dir\subdir\Test\TestComponent.cshtml) Generated Location: (1293:36,0 [7] ) |x => {}| +Source Location: (26:1,13 [4] x:\dir\subdir\Test\TestComponent.cshtml) +|Item| +Generated Location: (2172:57,0 [4] ) +|Item| + +Source Location: (35:1,22 [7] x:\dir\subdir\Test\TestComponent.cshtml) +|MyEvent| +Generated Location: (2420:66,0 [7] ) +|MyEvent| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_NonGenericEventCallback_TypeInference/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_NonGenericEventCallback_TypeInference/TestComponent.codegen.cs index 2ae9e9ebcc0..9d0c8c4330a 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_NonGenericEventCallback_TypeInference/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_NonGenericEventCallback_TypeInference/TestComponent.codegen.cs @@ -52,8 +52,24 @@ internal static class TypeInference public static void CreateMyComponent_0(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder, int seq, int __seq0, TItem __arg0, int __seq1, global::Microsoft.AspNetCore.Components.EventCallback __arg1) { __builder.OpenComponent>(seq); - __builder.AddComponentParameter(__seq0, "Item", __arg0); - __builder.AddComponentParameter(__seq1, "MyEvent", __arg1); + __builder.AddComponentParameter(__seq0, nameof(global::Test.MyComponent. +#nullable restore +#line (2,14)-(2,18) "x:\dir\subdir\Test\TestComponent.cshtml" +Item + +#line default +#line hidden +#nullable disable + ), __arg0); + __builder.AddComponentParameter(__seq1, nameof(global::Test.MyComponent. +#nullable restore +#line (2,23)-(2,30) "x:\dir\subdir\Test\TestComponent.cshtml" +MyEvent + +#line default +#line hidden +#nullable disable + ), __arg1); __builder.CloseComponent(); } } diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_NonGenericEventCallback_TypeInference/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_NonGenericEventCallback_TypeInference/TestComponent.mappings.txt index 4c4268c0c3a..3f366b510a5 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_NonGenericEventCallback_TypeInference/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_NonGenericEventCallback_TypeInference/TestComponent.mappings.txt @@ -15,3 +15,13 @@ Source Location: (44:1,31 [7] x:\dir\subdir\Test\TestComponent.cshtml) Generated Location: (1178:36,0 [7] ) |x => {}| +Source Location: (26:1,13 [4] x:\dir\subdir\Test\TestComponent.cshtml) +|Item| +Generated Location: (1918:57,0 [4] ) +|Item| + +Source Location: (35:1,22 [7] x:\dir\subdir\Test\TestComponent.cshtml) +|MyEvent| +Generated Location: (2166:66,0 [7] ) +|MyEvent| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_NonGenericParameter_TypeInference/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_NonGenericParameter_TypeInference/TestComponent.codegen.cs index eef5971339c..cfb21834379 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_NonGenericParameter_TypeInference/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_NonGenericParameter_TypeInference/TestComponent.codegen.cs @@ -61,8 +61,24 @@ internal static class TypeInference public static void CreateMyComponent_0(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder, int seq, int __seq0, TItem __arg0, int __seq1, global::Test.Shared.MyClass __arg1) { __builder.OpenComponent>(seq); - __builder.AddComponentParameter(__seq0, "Item", __arg0); - __builder.AddComponentParameter(__seq1, "Foo", __arg1); + __builder.AddComponentParameter(__seq0, nameof(global::Test.MyComponent. +#nullable restore +#line (2,14)-(2,18) "x:\dir\subdir\Test\TestComponent.cshtml" +Item + +#line default +#line hidden +#nullable disable + ), __arg0); + __builder.AddComponentParameter(__seq1, nameof(global::Test.MyComponent. +#nullable restore +#line (2,23)-(2,26) "x:\dir\subdir\Test\TestComponent.cshtml" +Foo + +#line default +#line hidden +#nullable disable + ), __arg1); __builder.CloseComponent(); } } diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_NonGenericParameter_TypeInference/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_NonGenericParameter_TypeInference/TestComponent.mappings.txt index a3c48260224..198fb7aa76b 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_NonGenericParameter_TypeInference/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_NonGenericParameter_TypeInference/TestComponent.mappings.txt @@ -24,3 +24,13 @@ Generated Location: (1312:46,0 [38] ) MyClass Hello = new MyClass(); | +Source Location: (33:1,13 [4] x:\dir\subdir\Test\TestComponent.cshtml) +|Item| +Generated Location: (1991:66,0 [4] ) +|Item| + +Source Location: (42:1,22 [3] x:\dir\subdir\Test\TestComponent.cshtml) +|Foo| +Generated Location: (2239:75,0 [3] ) +|Foo| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_NonPrimitiveType/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_NonPrimitiveType/TestComponent.codegen.cs index 3282d295c64..735be01c55b 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_NonPrimitiveType/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_NonPrimitiveType/TestComponent.codegen.cs @@ -18,7 +18,15 @@ public partial class TestComponent : global::Microsoft.AspNetCore.Components.Com protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { __builder.OpenComponent>(0); - __builder.AddComponentParameter(1, "Item", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( + __builder.AddComponentParameter(1, nameof(global::Test.MyComponent. +#nullable restore +#line (1,33)-(1,37) "x:\dir\subdir\Test\TestComponent.cshtml" +Item + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( #nullable restore #line (1,39)-(1,55) "x:\dir\subdir\Test\TestComponent.cshtml" new CustomType() diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_NonPrimitiveType/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_NonPrimitiveType/TestComponent.mappings.txt index af87245247b..6025f203173 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_NonPrimitiveType/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_NonPrimitiveType/TestComponent.mappings.txt @@ -1,5 +1,10 @@ -Source Location: (38:0,38 [16] x:\dir\subdir\Test\TestComponent.cshtml) +Source Location: (32:0,32 [4] x:\dir\subdir\Test\TestComponent.cshtml) +|Item| +Generated Location: (908:23,0 [4] ) +|Item| + +Source Location: (38:0,38 [16] x:\dir\subdir\Test\TestComponent.cshtml) |new CustomType()| -Generated Location: (966:23,0 [16] ) +Generated Location: (1157:31,0 [16] ) |new CustomType()| diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_NonPrimitiveTypeRenderFragment/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_NonPrimitiveTypeRenderFragment/TestComponent.codegen.cs index 6d16823742c..013a9ea7c53 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_NonPrimitiveTypeRenderFragment/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_NonPrimitiveTypeRenderFragment/TestComponent.codegen.cs @@ -49,7 +49,15 @@ internal static class TypeInference public static void CreateMyComponent_0(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder, int seq, int __seq0, TItem __arg0, int __seq1, global::Microsoft.AspNetCore.Components.RenderFragment __arg1) { __builder.OpenComponent>(seq); - __builder.AddComponentParameter(__seq0, "Item", __arg0); + __builder.AddComponentParameter(__seq0, nameof(global::Test.MyComponent. +#nullable restore +#line (1,14)-(1,18) "x:\dir\subdir\Test\TestComponent.cshtml" +Item + +#line default +#line hidden +#nullable disable + ), __arg0); __builder.AddComponentParameter(__seq1, "ChildContent", __arg1); __builder.CloseComponent(); } diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_NonPrimitiveTypeRenderFragment/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_NonPrimitiveTypeRenderFragment/TestComponent.mappings.txt index a13b7c5e46d..eab6009cf14 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_NonPrimitiveTypeRenderFragment/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_NonPrimitiveTypeRenderFragment/TestComponent.mappings.txt @@ -8,3 +8,8 @@ Source Location: (38:0,38 [18] x:\dir\subdir\Test\TestComponent.cshtml) Generated Location: (1079:31,0 [18] ) |context.ToString()| +Source Location: (13:0,13 [4] x:\dir\subdir\Test\TestComponent.cshtml) +|Item| +Generated Location: (1890:54,0 [4] ) +|Item| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_TypeParameterOrdering/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_TypeParameterOrdering/TestComponent.codegen.cs index ded26fc1151..a6fdc26676f 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_TypeParameterOrdering/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_TypeParameterOrdering/TestComponent.codegen.cs @@ -18,7 +18,15 @@ public partial class TestComponent : global::Microsoft.AspNetCore.Components.Com protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { __builder.OpenComponent>(0); - __builder.AddComponentParameter(1, "Value", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( + __builder.AddComponentParameter(1, nameof(global::Test.MyComponent. +#nullable restore +#line (1,64)-(1,69) "x:\dir\subdir\Test\TestComponent.cshtml" +Value + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( #nullable restore #line (1,71)-(1,86) "x:\dir\subdir\Test\TestComponent.cshtml" _componentValue @@ -27,11 +35,19 @@ protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components. #line hidden #nullable disable )); - __builder.AddComponentParameter(2, "ValueChanged", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck>(global::Microsoft.AspNetCore.Components.EventCallback.Factory.Create(this, global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.CreateInferredEventCallback(this, __value => _componentValue = __value, _componentValue)))); + __builder.AddComponentParameter(2, nameof(global::Test.MyComponent.ValueChanged), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck>(global::Microsoft.AspNetCore.Components.EventCallback.Factory.Create(this, global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.CreateInferredEventCallback(this, __value => _componentValue = __value, _componentValue)))); __builder.CloseComponent(); __builder.AddMarkupContent(3, "\r\n"); __builder.OpenComponent>(4); - __builder.AddComponentParameter(5, "Value", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( + __builder.AddComponentParameter(5, nameof(global::Test.MyComponent. +#nullable restore +#line (2,64)-(2,69) "x:\dir\subdir\Test\TestComponent.cshtml" +Value + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( #nullable restore #line (2,71)-(2,86) "x:\dir\subdir\Test\TestComponent.cshtml" _componentValue @@ -40,7 +56,7 @@ protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components. #line hidden #nullable disable )); - __builder.AddComponentParameter(6, "ValueChanged", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck>(global::Microsoft.AspNetCore.Components.EventCallback.Factory.Create(this, global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.CreateInferredEventCallback(this, __value => _componentValue = __value, _componentValue)))); + __builder.AddComponentParameter(6, nameof(global::Test.MyComponent.ValueChanged), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck>(global::Microsoft.AspNetCore.Components.EventCallback.Factory.Create(this, global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.CreateInferredEventCallback(this, __value => _componentValue = __value, _componentValue)))); __builder.CloseComponent(); } #pragma warning restore 1998 diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_TypeParameterOrdering/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_TypeParameterOrdering/TestComponent.mappings.txt index bfb508c5ad9..16740d2ea60 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_TypeParameterOrdering/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_TypeParameterOrdering/TestComponent.mappings.txt @@ -1,18 +1,28 @@ -Source Location: (70:0,70 [15] x:\dir\subdir\Test\TestComponent.cshtml) +Source Location: (63:0,63 [5] x:\dir\subdir\Test\TestComponent.cshtml) +|Value| +Generated Location: (940:23,0 [5] ) +|Value| + +Source Location: (70:0,70 [15] x:\dir\subdir\Test\TestComponent.cshtml) |_componentValue| -Generated Location: (979:23,0 [15] ) +Generated Location: (1186:31,0 [15] ) |_componentValue| +Source Location: (154:1,63 [5] x:\dir\subdir\Test\TestComponent.cshtml) +|Value| +Generated Location: (2165:44,0 [5] ) +|Value| + Source Location: (161:1,70 [15] x:\dir\subdir\Test\TestComponent.cshtml) |_componentValue| -Generated Location: (1938:36,0 [15] ) +Generated Location: (2411:52,0 [15] ) |_componentValue| Source Location: (191:3,7 [46] x:\dir\subdir\Test\TestComponent.cshtml) | string _componentValue = string.Empty; | -Generated Location: (2649:48,0 [46] ) +Generated Location: (3181:64,0 [46] ) | string _componentValue = string.Empty; | diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_UnmanagedConstraint/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_UnmanagedConstraint/TestComponent.codegen.cs index 1b451938c07..679657cbbd5 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_UnmanagedConstraint/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_UnmanagedConstraint/TestComponent.codegen.cs @@ -45,7 +45,15 @@ public static void CreateMyComponent_0(global::Microsoft.AspNetCore.Component where T : unmanaged { __builder.OpenComponent>(seq); - __builder.AddComponentParameter(__seq0, "Parameter", __arg0); + __builder.AddComponentParameter(__seq0, nameof(global::Test.MyComponent. +#nullable restore +#line (2,14)-(2,23) "x:\dir\subdir\Test\TestComponent.cshtml" +Parameter + +#line default +#line hidden +#nullable disable + ), __arg0); __builder.CloseComponent(); } } diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_UnmanagedConstraint/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_UnmanagedConstraint/TestComponent.mappings.txt index c6880b2492c..59f05ea2ea0 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_UnmanagedConstraint/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_UnmanagedConstraint/TestComponent.mappings.txt @@ -10,3 +10,8 @@ Source Location: (37:1,24 [1] x:\dir\subdir\Test\TestComponent.cshtml) Generated Location: (949:28,0 [1] ) |1| +Source Location: (26:1,13 [9] x:\dir\subdir\Test\TestComponent.cshtml) +|Parameter| +Generated Location: (1625:50,0 [9] ) +|Parameter| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_WithComponentRef_CreatesDiagnostic/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_WithComponentRef_CreatesDiagnostic/TestComponent.codegen.cs index f6657c929c4..d5bb8fc90a0 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_WithComponentRef_CreatesDiagnostic/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_WithComponentRef_CreatesDiagnostic/TestComponent.codegen.cs @@ -18,7 +18,15 @@ public partial class TestComponent : global::Microsoft.AspNetCore.Components.Com protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { __builder.OpenComponent>(0); - __builder.AddComponentParameter(1, "Item", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( + __builder.AddComponentParameter(1, nameof(global::Test.MyComponent. +#nullable restore +#line (1,24)-(1,28) "x:\dir\subdir\Test\TestComponent.cshtml" +Item + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( #nullable restore #line (1,30)-(1,31) "x:\dir\subdir\Test\TestComponent.cshtml" 3 diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_WithComponentRef_CreatesDiagnostic/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_WithComponentRef_CreatesDiagnostic/TestComponent.mappings.txt index e8cb29e407b..10d1feee149 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_WithComponentRef_CreatesDiagnostic/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_WithComponentRef_CreatesDiagnostic/TestComponent.mappings.txt @@ -1,11 +1,16 @@ -Source Location: (29:0,29 [1] x:\dir\subdir\Test\TestComponent.cshtml) +Source Location: (23:0,23 [4] x:\dir\subdir\Test\TestComponent.cshtml) +|Item| +Generated Location: (894:23,0 [4] ) +|Item| + +Source Location: (29:0,29 [1] x:\dir\subdir\Test\TestComponent.cshtml) |3| -Generated Location: (952:23,0 [1] ) +Generated Location: (1136:31,0 [1] ) |3| Source Location: (38:0,38 [3] x:\dir\subdir\Test\TestComponent.cshtml) |_my| -Generated Location: (1174:32,0 [3] ) +Generated Location: (1358:40,0 [3] ) |_my| Source Location: (56:2,7 [90] x:\dir\subdir\Test\TestComponent.cshtml) @@ -13,7 +18,7 @@ Source Location: (56:2,7 [90] x:\dir\subdir\Test\TestComponent.cshtml) private MyComponent _my; public void Foo() { System.GC.KeepAlive(_my); } | -Generated Location: (1482:45,0 [90] ) +Generated Location: (1666:53,0 [90] ) | private MyComponent _my; public void Foo() { System.GC.KeepAlive(_my); } diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_WithComponentRef_TypeInference_CreatesDiagnostic/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_WithComponentRef_TypeInference_CreatesDiagnostic/TestComponent.codegen.cs index 5461870322b..2c8e92cfa22 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_WithComponentRef_TypeInference_CreatesDiagnostic/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_WithComponentRef_TypeInference_CreatesDiagnostic/TestComponent.codegen.cs @@ -58,7 +58,15 @@ internal static class TypeInference public static void CreateMyComponent_0(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder, int seq, int __seq0, TItem __arg0, int __seq1, global::System.Action> __arg1) { __builder.OpenComponent>(seq); - __builder.AddComponentParameter(__seq0, "Item", __arg0); + __builder.AddComponentParameter(__seq0, nameof(global::Test.MyComponent. +#nullable restore +#line (1,14)-(1,18) "x:\dir\subdir\Test\TestComponent.cshtml" +Item + +#line default +#line hidden +#nullable disable + ), __arg0); __builder.AddComponentReferenceCapture(__seq1, (__value) => { __arg1((global::Test.MyComponent)__value); }); __builder.CloseComponent(); } diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_WithComponentRef_TypeInference_CreatesDiagnostic/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_WithComponentRef_TypeInference_CreatesDiagnostic/TestComponent.mappings.txt index 7f2ff5ec0f8..2092c343fd4 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_WithComponentRef_TypeInference_CreatesDiagnostic/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_WithComponentRef_TypeInference_CreatesDiagnostic/TestComponent.mappings.txt @@ -19,3 +19,8 @@ Generated Location: (1249:42,0 [90] ) public void Foo() { System.GC.KeepAlive(_my); } | +Source Location: (13:0,13 [4] x:\dir\subdir\Test\TestComponent.cshtml) +|Item| +Generated Location: (2007:63,0 [4] ) +|Item| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_WithFullyQualifiedTagName/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_WithFullyQualifiedTagName/TestComponent.codegen.cs index 20ae0865efc..aedf5743f1e 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_WithFullyQualifiedTagName/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_WithFullyQualifiedTagName/TestComponent.codegen.cs @@ -51,7 +51,15 @@ internal static class TypeInference public static void CreateTest_MyComponent_0(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder, int seq, int __seq0, TItem __arg0, int __seq1, global::Microsoft.AspNetCore.Components.RenderFragment __arg1) { __builder.OpenComponent>(seq); - __builder.AddComponentParameter(__seq0, "Item", __arg0); + __builder.AddComponentParameter(__seq0, nameof(global::Test.MyComponent. +#nullable restore +#line (1,19)-(1,23) "x:\dir\subdir\Test\TestComponent.cshtml" +Item + +#line default +#line hidden +#nullable disable + ), __arg0); __builder.AddComponentParameter(__seq1, "ChildContent", __arg1); __builder.CloseComponent(); } diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_WithFullyQualifiedTagName/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_WithFullyQualifiedTagName/TestComponent.mappings.txt index a8b2ac62d1a..6af0f79e6e2 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_WithFullyQualifiedTagName/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_WithFullyQualifiedTagName/TestComponent.mappings.txt @@ -8,3 +8,8 @@ Source Location: (43:1,8 [17] x:\dir\subdir\Test\TestComponent.cshtml) Generated Location: (1122:32,0 [17] ) |context.ToLower()| +Source Location: (18:0,18 [4] x:\dir\subdir\Test\TestComponent.cshtml) +|Item| +Generated Location: (1963:56,0 [4] ) +|Item| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_WithKey/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_WithKey/TestComponent.codegen.cs index be7a6840a8e..96def464891 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_WithKey/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_WithKey/TestComponent.codegen.cs @@ -18,7 +18,15 @@ public partial class TestComponent : global::Microsoft.AspNetCore.Components.Com protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { __builder.OpenComponent>(0); - __builder.AddComponentParameter(1, "Item", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( + __builder.AddComponentParameter(1, nameof(global::Test.MyComponent. +#nullable restore +#line (1,24)-(1,28) "x:\dir\subdir\Test\TestComponent.cshtml" +Item + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( #nullable restore #line (1,30)-(1,31) "x:\dir\subdir\Test\TestComponent.cshtml" 3 diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_WithKey/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_WithKey/TestComponent.mappings.txt index 787b93986fb..f807211352c 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_WithKey/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_WithKey/TestComponent.mappings.txt @@ -1,18 +1,23 @@ -Source Location: (29:0,29 [1] x:\dir\subdir\Test\TestComponent.cshtml) +Source Location: (23:0,23 [4] x:\dir\subdir\Test\TestComponent.cshtml) +|Item| +Generated Location: (894:23,0 [4] ) +|Item| + +Source Location: (29:0,29 [1] x:\dir\subdir\Test\TestComponent.cshtml) |3| -Generated Location: (952:23,0 [1] ) +Generated Location: (1136:31,0 [1] ) |3| Source Location: (38:0,38 [8] x:\dir\subdir\Test\TestComponent.cshtml) |_someKey| -Generated Location: (1135:32,0 [8] ) +Generated Location: (1319:40,0 [8] ) |_someKey| Source Location: (61:2,7 [47] x:\dir\subdir\Test\TestComponent.cshtml) | private object _someKey = new object(); | -Generated Location: (1383:44,0 [47] ) +Generated Location: (1567:52,0 [47] ) | private object _someKey = new object(); | diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_WithKey_TypeInference/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_WithKey_TypeInference/TestComponent.codegen.cs index 98fd7b0e1fd..852ed3a9bcf 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_WithKey_TypeInference/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_WithKey_TypeInference/TestComponent.codegen.cs @@ -56,7 +56,15 @@ internal static class TypeInference public static void CreateMyComponent_0(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder, int seq, int __seq0, TItem __arg0, int __seq1, object __arg1) { __builder.OpenComponent>(seq); - __builder.AddComponentParameter(__seq0, "Item", __arg0); + __builder.AddComponentParameter(__seq0, nameof(global::Test.MyComponent. +#nullable restore +#line (1,14)-(1,18) "x:\dir\subdir\Test\TestComponent.cshtml" +Item + +#line default +#line hidden +#nullable disable + ), __arg0); __builder.SetKey(__arg1); __builder.CloseComponent(); } diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_WithKey_TypeInference/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_WithKey_TypeInference/TestComponent.mappings.txt index e0b38a29243..f5c85016a03 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_WithKey_TypeInference/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_WithKey_TypeInference/TestComponent.mappings.txt @@ -17,3 +17,8 @@ Generated Location: (1198:41,0 [47] ) private object _someKey = new object(); | +Source Location: (13:0,13 [4] x:\dir\subdir\Test\TestComponent.cshtml) +|Item| +Generated Location: (1865:61,0 [4] ) +|Item| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/NonGenericComponent_WithGenericEventHandler/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/NonGenericComponent_WithGenericEventHandler/TestComponent.codegen.cs index 4f4d49815b4..533b668a77c 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/NonGenericComponent_WithGenericEventHandler/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/NonGenericComponent_WithGenericEventHandler/TestComponent.codegen.cs @@ -18,7 +18,15 @@ public partial class TestComponent : global::Microsoft.AspNetCore.Components.Com protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { __builder.OpenComponent(0); - __builder.AddComponentParameter(1, "Item", "Hello"); + __builder.AddComponentParameter(1, nameof(global::Test.MyComponent. +#nullable restore +#line (1,14)-(1,18) "x:\dir\subdir\Test\TestComponent.cshtml" +Item + +#line default +#line hidden +#nullable disable + ), "Hello"); __builder.AddComponentParameter(2, "MyEvent", "MyEventHandler"); __builder.CloseComponent(); } diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/NonGenericComponent_WithGenericEventHandler/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/NonGenericComponent_WithGenericEventHandler/TestComponent.mappings.txt index 997a06852a1..a358475d932 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/NonGenericComponent_WithGenericEventHandler/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/NonGenericComponent_WithGenericEventHandler/TestComponent.mappings.txt @@ -1,8 +1,13 @@ -Source Location: (64:2,7 [39] x:\dir\subdir\Test\TestComponent.cshtml) +Source Location: (13:0,13 [4] x:\dir\subdir\Test\TestComponent.cshtml) +|Item| +Generated Location: (884:23,0 [4] ) +|Item| + +Source Location: (64:2,7 [39] x:\dir\subdir\Test\TestComponent.cshtml) | public void MyEventHandler() {} | -Generated Location: (1035:27,0 [39] ) +Generated Location: (1214:35,0 [39] ) | public void MyEventHandler() {} | diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/RazorTemplate_AsComponentParameter_MixedContent/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/RazorTemplate_AsComponentParameter_MixedContent/TestComponent.codegen.cs index 12b155f90c5..379a952c6bf 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/RazorTemplate_AsComponentParameter_MixedContent/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/RazorTemplate_AsComponentParameter_MixedContent/TestComponent.codegen.cs @@ -58,7 +58,15 @@ protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components. #nullable disable __builder.OpenComponent(5); - __builder.AddComponentParameter(6, "Template", (global::Microsoft.AspNetCore.Components.RenderFragment)( + __builder.AddComponentParameter(6, nameof(global::Test.MyComponent. +#nullable restore +#line (2,14)-(2,22) "x:\dir\subdir\Test\TestComponent.cshtml" +Template + +#line default +#line hidden +#nullable disable + ), (global::Microsoft.AspNetCore.Components.RenderFragment)( #nullable restore #line (2,25)-(2,33) "x:\dir\subdir\Test\TestComponent.cshtml" template diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/RazorTemplate_AsComponentParameter_MixedContent/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/RazorTemplate_AsComponentParameter_MixedContent/TestComponent.mappings.txt index 6b0b12624ab..90e2fb31129 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/RazorTemplate_AsComponentParameter_MixedContent/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/RazorTemplate_AsComponentParameter_MixedContent/TestComponent.mappings.txt @@ -18,8 +18,13 @@ Source Location: (107:0,107 [2] x:\dir\subdir\Test\TestComponent.cshtml) Generated Location: (1595:53,0 [2] ) |; | +Source Location: (125:1,13 [8] x:\dir\subdir\Test\TestComponent.cshtml) +|Template| +Generated Location: (1881:63,0 [8] ) +|Template| + Source Location: (136:1,24 [8] x:\dir\subdir\Test\TestComponent.cshtml) |template| -Generated Location: (1932:63,0 [8] ) +Generated Location: (2111:71,0 [8] ) |template| diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/RazorTemplate_ContainsComponent/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/RazorTemplate_ContainsComponent/TestComponent.codegen.cs index c1efebbcbff..9848d53dfa7 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/RazorTemplate_ContainsComponent/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/RazorTemplate_ContainsComponent/TestComponent.codegen.cs @@ -29,7 +29,15 @@ protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components. (__builder2) => { __builder2.OpenElement(0, "div"); __builder2.OpenComponent(1); - __builder2.AddComponentParameter(2, "Name", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( + __builder2.AddComponentParameter(2, nameof(global::Test.MyComponent. +#nullable restore +#line (2,63)-(2,67) "x:\dir\subdir\Test\TestComponent.cshtml" +Name + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( #nullable restore #line (2,70)-(2,81) "x:\dir\subdir\Test\TestComponent.cshtml" person.Name diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/RazorTemplate_ContainsComponent/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/RazorTemplate_ContainsComponent/TestComponent.mappings.txt index 7f40592ed3a..63a212472e1 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/RazorTemplate_ContainsComponent/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/RazorTemplate_ContainsComponent/TestComponent.mappings.txt @@ -5,15 +5,20 @@ Generated Location: (735:21,0 [45] ) | RenderFragment p = (person) => | +Source Location: (66:1,62 [4] x:\dir\subdir\Test\TestComponent.cshtml) +|Name| +Generated Location: (1156:34,0 [4] ) +|Name| + Source Location: (73:1,69 [11] x:\dir\subdir\Test\TestComponent.cshtml) |person.Name| -Generated Location: (1237:34,0 [11] ) +Generated Location: (1420:42,0 [11] ) |person.Name| Source Location: (93:1,89 [3] x:\dir\subdir\Test\TestComponent.cshtml) |; | -Generated Location: (1507:45,0 [3] ) +Generated Location: (1690:53,0 [3] ) |; | @@ -24,7 +29,7 @@ Source Location: (106:3,7 [76] x:\dir\subdir\Test\TestComponent.cshtml) public string Name { get; set; } } | -Generated Location: (1691:55,0 [76] ) +Generated Location: (1874:63,0 [76] ) | class Person { diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/RazorTemplate_FollowedByComponent/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/RazorTemplate_FollowedByComponent/TestComponent.codegen.cs index 2d5483ff6aa..ee3a7be5d2e 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/RazorTemplate_FollowedByComponent/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/RazorTemplate_FollowedByComponent/TestComponent.codegen.cs @@ -29,7 +29,15 @@ protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components. (__builder2) => { __builder2.OpenElement(0, "div"); __builder2.OpenComponent(1); - __builder2.AddComponentParameter(2, "Name", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( + __builder2.AddComponentParameter(2, nameof(global::Test.MyComponent. +#nullable restore +#line (2,63)-(2,67) "x:\dir\subdir\Test\TestComponent.cshtml" +Name + +#line default +#line hidden +#nullable disable + ), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( #nullable restore #line (2,70)-(2,81) "x:\dir\subdir\Test\TestComponent.cshtml" person.Name diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/RazorTemplate_FollowedByComponent/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/RazorTemplate_FollowedByComponent/TestComponent.mappings.txt index b797c9a1b4c..5885f598c7f 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/RazorTemplate_FollowedByComponent/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/RazorTemplate_FollowedByComponent/TestComponent.mappings.txt @@ -5,21 +5,26 @@ Generated Location: (735:21,0 [45] ) | RenderFragment p = (person) => | +Source Location: (66:1,62 [4] x:\dir\subdir\Test\TestComponent.cshtml) +|Name| +Generated Location: (1156:34,0 [4] ) +|Name| + Source Location: (73:1,69 [11] x:\dir\subdir\Test\TestComponent.cshtml) |person.Name| -Generated Location: (1237:34,0 [11] ) +Generated Location: (1420:42,0 [11] ) |person.Name| Source Location: (93:1,89 [3] x:\dir\subdir\Test\TestComponent.cshtml) |; | -Generated Location: (1507:45,0 [3] ) +Generated Location: (1690:53,0 [3] ) |; | Source Location: (116:4,2 [15] x:\dir\subdir\Test\TestComponent.cshtml) |"hello, world!"| -Generated Location: (1883:56,0 [15] ) +Generated Location: (2066:64,0 [15] ) |"hello, world!"| Source Location: (159:7,7 [76] x:\dir\subdir\Test\TestComponent.cshtml) @@ -29,7 +34,7 @@ Source Location: (159:7,7 [76] x:\dir\subdir\Test\TestComponent.cshtml) public string Name { get; set; } } | -Generated Location: (2173:69,0 [76] ) +Generated Location: (2356:77,0 [76] ) | class Person { diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/RazorTemplate_Generic_AsComponentParameter/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/RazorTemplate_Generic_AsComponentParameter/TestComponent.codegen.cs index 9c0087cc285..22754f76221 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/RazorTemplate_Generic_AsComponentParameter/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/RazorTemplate_Generic_AsComponentParameter/TestComponent.codegen.cs @@ -47,7 +47,15 @@ protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components. #nullable disable __builder.OpenComponent(2); - __builder.AddComponentParameter(3, "PersonTemplate", (global::Microsoft.AspNetCore.Components.RenderFragment)( + __builder.AddComponentParameter(3, nameof(global::Test.MyComponent. +#nullable restore +#line (2,14)-(2,28) "x:\dir\subdir\Test\TestComponent.cshtml" +PersonTemplate + +#line default +#line hidden +#nullable disable + ), (global::Microsoft.AspNetCore.Components.RenderFragment)( #nullable restore #line (2,31)-(2,39) "x:\dir\subdir\Test\TestComponent.cshtml" template diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/RazorTemplate_Generic_AsComponentParameter/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/RazorTemplate_Generic_AsComponentParameter/TestComponent.mappings.txt index 308b9dd4a1c..6c66253d0b8 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/RazorTemplate_Generic_AsComponentParameter/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/RazorTemplate_Generic_AsComponentParameter/TestComponent.mappings.txt @@ -13,8 +13,13 @@ Source Location: (73:0,73 [2] x:\dir\subdir\Test\TestComponent.cshtml) Generated Location: (1267:42,0 [2] ) |; | +Source Location: (91:1,13 [14] x:\dir\subdir\Test\TestComponent.cshtml) +|PersonTemplate| +Generated Location: (1553:52,0 [14] ) +|PersonTemplate| + Source Location: (108:1,30 [8] x:\dir\subdir\Test\TestComponent.cshtml) |template| -Generated Location: (1609:52,0 [8] ) +Generated Location: (1788:60,0 [8] ) |template| diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Regression_772/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Regression_772/TestComponent.codegen.cs index 4721359c268..1d8ac4b40fc 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Regression_772/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Regression_772/TestComponent.codegen.cs @@ -29,7 +29,15 @@ protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components. { __builder.AddMarkupContent(0, "

Hello, world!

\r\n\r\nWelcome to your new app.\r\n\r\n"); __builder.OpenComponent(1); - __builder.AddComponentParameter(2, "Title", "\r\n"); + __builder.AddComponentParameter(2, nameof(global::Test.SurveyPrompt. +#nullable restore +#line (7,15)-(7,20) "x:\dir\subdir\Test\TestComponent.cshtml" +Title + +#line default +#line hidden +#nullable disable + ), "\r\n"); __builder.CloseComponent(); } #pragma warning restore 1998 diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Regression_772/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Regression_772/TestComponent.mappings.txt index 8cb6ad5348e..62a314b52ff 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Regression_772/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Regression_772/TestComponent.mappings.txt @@ -3,3 +3,8 @@ Generated Location: (504:16,0 [3] ) |"/"| +Source Location: (81:6,14 [5] x:\dir\subdir\Test\TestComponent.cshtml) +|Title| +Generated Location: (1235:34,0 [5] ) +|Title| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Regression_773/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Regression_773/TestComponent.codegen.cs index 125649003d1..7ca461550e5 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Regression_773/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Regression_773/TestComponent.codegen.cs @@ -29,7 +29,15 @@ protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components. { __builder.AddMarkupContent(0, "

Hello, world!

\r\n\r\nWelcome to your new app.\r\n\r\n"); __builder.OpenComponent(1); - __builder.AddComponentParameter(2, "Title", "
Test!
"); + __builder.AddComponentParameter(2, nameof(global::Test.SurveyPrompt. +#nullable restore +#line (7,15)-(7,20) "x:\dir\subdir\Test\TestComponent.cshtml" +Title + +#line default +#line hidden +#nullable disable + ), "
Test!
"); __builder.CloseComponent(); } #pragma warning restore 1998 diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Regression_773/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Regression_773/TestComponent.mappings.txt index 8cb6ad5348e..62a314b52ff 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Regression_773/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Regression_773/TestComponent.mappings.txt @@ -3,3 +3,8 @@ Generated Location: (504:16,0 [3] ) |"/"| +Source Location: (81:6,14 [5] x:\dir\subdir\Test\TestComponent.cshtml) +|Title| +Generated Location: (1235:34,0 [5] ) +|Title| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/RenderMode_Attribute_With_Existing_Attributes/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/RenderMode_Attribute_With_Existing_Attributes/TestComponent.codegen.cs index 84033d2bc62..444c83c334e 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/RenderMode_Attribute_With_Existing_Attributes/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/RenderMode_Attribute_With_Existing_Attributes/TestComponent.codegen.cs @@ -18,7 +18,15 @@ public partial class TestComponent : global::Microsoft.AspNetCore.Components.Com protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) { __builder.OpenComponent(0); - __builder.AddComponentParameter(1, "P2", "abc"); + __builder.AddComponentParameter(1, nameof(global::Test.TestComponent. +#nullable restore +#line (1,16)-(1,18) "x:\dir\subdir\Test\TestComponent.cshtml" +P2 + +#line default +#line hidden +#nullable disable + ), "abc"); global::Microsoft.AspNetCore.Components.IComponentRenderMode __renderMode = #nullable restore #line (1,38)-(1,102) "x:\dir\subdir\Test\TestComponent.cshtml" @@ -29,7 +37,15 @@ protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components. #nullable disable ; - __builder.AddComponentParameter(2, "P1", "def"); + __builder.AddComponentParameter(2, nameof(global::Test.TestComponent. +#nullable restore +#line (1,104)-(1,106) "x:\dir\subdir\Test\TestComponent.cshtml" +P1 + +#line default +#line hidden +#nullable disable + ), "def"); __builder.AddComponentRenderMode(__renderMode); __builder.CloseComponent(); } diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/RenderMode_Attribute_With_Existing_Attributes/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/RenderMode_Attribute_With_Existing_Attributes/TestComponent.mappings.txt index 18a6d9f8239..d04dd17a216 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/RenderMode_Attribute_With_Existing_Attributes/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/RenderMode_Attribute_With_Existing_Attributes/TestComponent.mappings.txt @@ -1,15 +1,25 @@ -Source Location: (37:0,37 [64] x:\dir\subdir\Test\TestComponent.cshtml) +Source Location: (15:0,15 [2] x:\dir\subdir\Test\TestComponent.cshtml) +|P2| +Generated Location: (888:23,0 [2] ) +|P2| + +Source Location: (37:0,37 [64] x:\dir\subdir\Test\TestComponent.cshtml) |Microsoft.AspNetCore.Components.Web.RenderMode.InteractiveServer| -Generated Location: (958:24,0 [64] ) +Generated Location: (1139:32,0 [64] ) |Microsoft.AspNetCore.Components.Web.RenderMode.InteractiveServer| +Source Location: (103:0,103 [2] x:\dir\subdir\Test\TestComponent.cshtml) +|P1| +Generated Location: (1439:42,0 [2] ) +|P1| + Source Location: (126:3,1 [94] x:\dir\subdir\Test\TestComponent.cshtml) | [Parameter]public string P1 {get; set;} [Parameter]public string P2 {get; set;} | -Generated Location: (1384:38,0 [94] ) +Generated Location: (1748:54,0 [94] ) | [Parameter]public string P1 {get; set;} diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/RenderMode_With_TypeInference/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/RenderMode_With_TypeInference/TestComponent.codegen.cs index cc3511d6edb..058dc02da3e 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/RenderMode_With_TypeInference/TestComponent.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/RenderMode_With_TypeInference/TestComponent.codegen.cs @@ -72,7 +72,15 @@ public static void CreateTestComponent_0(global::Microsoft.AspNetCo where TRenderMode : global::Microsoft.AspNetCore.Components.IComponentRenderMode { __builder.OpenComponent>(seq); - __builder.AddComponentParameter(__seq1, "RenderModeParam", __arg1); + __builder.AddComponentParameter(__seq1, nameof(global::Test.TestComponent. +#nullable restore +#line (3,46)-(3,61) "x:\dir\subdir\Test\TestComponent.cshtml" +RenderModeParam + +#line default +#line hidden +#nullable disable + ), __arg1); __builder.AddComponentRenderMode(__arg0); __builder.CloseComponent(); } diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/RenderMode_With_TypeInference/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/RenderMode_With_TypeInference/TestComponent.mappings.txt index 67088916965..5a28ba16584 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/RenderMode_With_TypeInference/TestComponent.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/RenderMode_With_TypeInference/TestComponent.mappings.txt @@ -27,3 +27,8 @@ Generated Location: (1630:56,0 [67] ) [Parameter] public TRenderMode RenderModeParam { get; set;} | +Source Location: (144:2,45 [15] x:\dir\subdir\Test\TestComponent.cshtml) +|RenderModeParam| +Generated Location: (2487:77,0 [15] ) +|RenderModeParam| + diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/CSharp/ComponentTagHelperDescriptorProvider.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/CSharp/ComponentTagHelperDescriptorProvider.cs index 265aef0c788..26e350f2aea 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/CSharp/ComponentTagHelperDescriptorProvider.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/CSharp/ComponentTagHelperDescriptorProvider.cs @@ -178,7 +178,7 @@ private static TagHelperDescriptor CreateNameMatchingDescriptor( continue; } - CreateProperty(builder, property, kind); + CreateProperty(builder, type, property, kind); } if (builder.BoundAttributes.Any(static a => a.IsParameterizedChildContentProperty()) && @@ -195,13 +195,14 @@ private static TagHelperDescriptor CreateNameMatchingDescriptor( return builder.Build(); } - private static void CreateProperty(TagHelperDescriptorBuilder builder, IPropertySymbol property, PropertyKind kind) + private static void CreateProperty(TagHelperDescriptorBuilder builder, INamedTypeSymbol containingSymbol, IPropertySymbol property, PropertyKind kind) { builder.BindAttribute(pb => { using var metadata = new MetadataBuilder(); pb.Name = property.Name; + pb.ContainingType = containingSymbol.ToDisplayString(SymbolExtensions.FullNameTypeDisplayFormat); pb.TypeName = property.Type.ToDisplayString(SymbolExtensions.FullNameTypeDisplayFormat); pb.IsEditorRequired = property.GetAttributes().Any( static a => a.AttributeClass.HasFullName("Microsoft.AspNetCore.Components.EditorRequiredAttribute")); diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/BoundAttributeDescriptor.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/BoundAttributeDescriptor.cs index 8afc06db0f0..67c6356ac52 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/BoundAttributeDescriptor.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/BoundAttributeDescriptor.cs @@ -35,6 +35,7 @@ private enum BoundAttributeFlags public string Name { get; } public string TypeName { get; } public string DisplayName { get; } + public string? ContainingType { get; } public string? IndexerNamePrefix { get; } public string? IndexerTypeName { get; } @@ -62,6 +63,7 @@ internal BoundAttributeDescriptor( string? indexerTypeName, DocumentationObject documentationObject, string displayName, + string? containingType, bool caseSensitive, bool isEditorRequired, ImmutableArray parameters, @@ -76,6 +78,7 @@ internal BoundAttributeDescriptor( IndexerTypeName = indexerTypeName; _documentationObject = documentationObject; DisplayName = displayName; + ContainingType = containingType; Parameters = parameters.NullToEmpty(); Metadata = metadata ?? MetadataCollection.Empty; @@ -137,6 +140,7 @@ private protected override void BuildChecksum(in Checksum.Builder builder) builder.AppendData(IndexerNamePrefix); builder.AppendData(IndexerTypeName); builder.AppendData(DisplayName); + builder.AppendData(ContainingType); DocumentationObject.AppendToChecksum(in builder); diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/BoundAttributeDescriptorBuilder.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/BoundAttributeDescriptorBuilder.cs index 4ba97cc1182..77c347e9808 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/BoundAttributeDescriptorBuilder.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/BoundAttributeDescriptorBuilder.cs @@ -67,6 +67,8 @@ public string? Documentation public string? DisplayName { get; set; } + public string? ContainingType { get; set; } + public IDictionary Metadata => _metadata.MetadataDictionary; public void SetMetadata(MetadataCollection metadata) => _metadata.SetMetadataCollection(metadata); @@ -113,6 +115,7 @@ private protected override BoundAttributeDescriptor BuildCore(ImmutableArray + /// Writes an "@" character if the provided identifier needs escaping in c# + ///
+ public static CodeWriter WriteIdentifierEscapeIfNeeded(this CodeWriter writer, string identifier) + { + if (IdentifierRequiresEscaping(identifier)) + { + writer.Write("@"); + } + return writer; + } + + public static bool IdentifierRequiresEscaping(this string identifier) + { + return CodeAnalysis.CSharp.SyntaxFacts.GetKeywordKind(identifier) != CodeAnalysis.CSharp.SyntaxKind.None || + CodeAnalysis.CSharp.SyntaxFacts.GetContextualKeywordKind(identifier) != CodeAnalysis.CSharp.SyntaxKind.None; + } + public static CSharpCodeWritingScope BuildScope(this CodeWriter writer) { return new CSharpCodeWritingScope(writer); @@ -845,8 +863,10 @@ public LinePragmaWriter( if (!_context.Options.UseEnhancedLinePragma) { context.CodeWriter.WritePadding(0, span, context); + characterOffset = 0; } - context.AddSourceMappingFor(span); + + context.AddSourceMappingFor(span, characterOffset); } } diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/DefaultCodeRenderingContext.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/DefaultCodeRenderingContext.cs index 109ab30dd6f..0769b7045eb 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/DefaultCodeRenderingContext.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/DefaultCodeRenderingContext.cs @@ -117,7 +117,7 @@ public override void AddSourceMappingFor(IntermediateNode node) AddSourceMappingFor(node.Source.Value); } - public override void AddSourceMappingFor(SourceSpan source) + public override void AddSourceMappingFor(SourceSpan source, int offset = 0) { if (SourceDocument.FilePath != null && !string.Equals(SourceDocument.FilePath, source.FilePath, StringComparison.OrdinalIgnoreCase)) @@ -126,7 +126,9 @@ public override void AddSourceMappingFor(SourceSpan source) return; } - var generatedLocation = new SourceSpan(CodeWriter.Location, source.Length); + var currentLocation = CodeWriter.Location with { AbsoluteIndex = CodeWriter.Location.AbsoluteIndex + offset, CharacterIndex = CodeWriter.Location.CharacterIndex + offset }; + + var generatedLocation = new SourceSpan(currentLocation, source.Length); var sourceMapping = new SourceMapping(source, generatedLocation); SourceMappings.Add(sourceMapping); diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/Components/ComponentBindLoweringPass.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/Components/ComponentBindLoweringPass.cs index 4390751cc1d..5a13ea30750 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/Components/ComponentBindLoweringPass.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/Components/ComponentBindLoweringPass.cs @@ -537,6 +537,7 @@ private IntermediateNode[] RewriteUsage(IntermediateNode parent, BindEntry bindE ComponentAttributeIntermediateNode valueNode = node != null ? new ComponentAttributeIntermediateNode(node) : new ComponentAttributeIntermediateNode(getNode); valueNode.Annotations[ComponentMetadata.Common.OriginalAttributeName] = bindEntry.GetOriginalAttributeName(); + valueNode.Annotations[ComponentMetadata.Bind.PropertySpan] = bindEntry.GetOriginalPropertySpan(); valueNode.AttributeName = valueAttributeName; valueNode.BoundAttribute = valueAttribute; // Might be null if it doesn't match a component attribute valueNode.PropertyName = valuePropertyName; @@ -554,6 +555,8 @@ private IntermediateNode[] RewriteUsage(IntermediateNode parent, BindEntry bindE var changeNode = node != null ? new ComponentAttributeIntermediateNode(node) : new ComponentAttributeIntermediateNode(getNode); changeNode.Annotations[ComponentMetadata.Common.OriginalAttributeName] = bindEntry.GetOriginalAttributeName(); + changeNode.Annotations[ComponentMetadata.Bind.PropertySpan] = bindEntry.GetOriginalPropertySpan(); + changeNode.Annotations[ComponentMetadata.Bind.IsSynthesized] = bool.TrueString; changeNode.AttributeName = changeAttributeName; changeNode.BoundAttribute = changeAttribute; // Might be null if it doesn't match a component attribute changeNode.PropertyName = changeAttribute?.GetPropertyName(); @@ -575,6 +578,8 @@ private IntermediateNode[] RewriteUsage(IntermediateNode parent, BindEntry bindE { var expressionNode = node != null ? new ComponentAttributeIntermediateNode(node) : new ComponentAttributeIntermediateNode(getNode); expressionNode.Annotations[ComponentMetadata.Common.OriginalAttributeName] = bindEntry.GetOriginalAttributeName(); + expressionNode.Annotations[ComponentMetadata.Bind.PropertySpan] = bindEntry.GetOriginalPropertySpan(); + expressionNode.Annotations[ComponentMetadata.Bind.IsSynthesized] = bool.TrueString; expressionNode.AttributeName = expressionAttributeName; expressionNode.BoundAttribute = expressionAttribute; expressionNode.PropertyName = expressionAttribute.GetPropertyName(); @@ -613,6 +618,7 @@ private static void TryAddDesignTimePropertyAccessHelperNode(ImmutableArray BindNode?.TagHelper.GetChangeAttributeName() ?? BindGetNode?.TagHelper.GetChangeAttributeName(); public string GetEffectiveBindNodeExpressionAttributeName() => BindNode?.TagHelper.GetExpressionAttributeName() ?? BindGetNode?.TagHelper.GetExpressionAttributeName(); + + internal SourceSpan? GetOriginalPropertySpan() + { + var node = BindNode ?? (IntermediateNode)BindGetNode; + if (node?.Annotations[ComponentMetadata.Common.OriginalAttributeSpan] is SourceSpan attributeSourceSpan) + { + var offset = "bind-".Length; + return new SourceSpan(attributeSourceSpan.FilePath, + attributeSourceSpan.AbsoluteIndex + offset, + attributeSourceSpan.LineIndex, + attributeSourceSpan.CharacterIndex + offset, + attributeSourceSpan.Length - offset, + attributeSourceSpan.LineCount, + attributeSourceSpan.EndCharacterIndex); + } + return null; + } } } diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/Components/ComponentDesignTimeNodeWriter.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/Components/ComponentDesignTimeNodeWriter.cs index abe554af095..8702653d9ae 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/Components/ComponentDesignTimeNodeWriter.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/Components/ComponentDesignTimeNodeWriter.cs @@ -603,7 +603,7 @@ public override void WriteComponent(CodeRenderingContext context, ComponentInter public override void WriteComponentTypeInferenceMethod(CodeRenderingContext context, ComponentTypeInferenceMethodIntermediateNode node) { - base.WriteComponentTypeInferenceMethod(context, node, returnComponentType: true); + base.WriteComponentTypeInferenceMethod(context, node, returnComponentType: true, allowNameof: false); } private void WriteTypeInferenceMethodParameterInnards(CodeRenderingContext context, TypeInferenceMethodParameter parameter) @@ -746,12 +746,7 @@ private void WritePropertyAccess(CodeRenderingContext context, ComponentAttribut using (context.CodeWriter.BuildLinePragma(attributeSourceSpan, context)) { context.CodeWriter.WritePadding(0, attributeSourceSpan, context); - // Escape the property name in case it's a C# keyword - if (CSharpSyntaxFacts.GetKeywordKind(node.PropertyName) != CSharpSyntaxKind.None || - CSharpSyntaxFacts.GetContextualKeywordKind(node.PropertyName) != CSharpSyntaxKind.None) - { - context.CodeWriter.Write("@"); - } + context.CodeWriter.WriteIdentifierEscapeIfNeeded(node.PropertyName); context.AddSourceMappingFor(attributeSourceSpan); context.CodeWriter.WriteLine(node.PropertyName); } diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/Components/ComponentGenericTypePass.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/Components/ComponentGenericTypePass.cs index e389625bb7c..a1cf92a0186 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/Components/ComponentGenericTypePass.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/Components/ComponentGenericTypePass.cs @@ -341,6 +341,8 @@ private void RewriteTypeNames(TypeNameRewriter rewriter, ComponentIntermediateNo foreach (var attribute in node.Attributes) { + attribute.Annotations[ComponentMetadata.Component.ConcreteContainingType] = node.TypeName; + var globallyQualifiedTypeName = attribute.BoundAttribute?.GetGloballyQualifiedTypeName(); if (attribute.TypeName != null) diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/Components/ComponentMetadata.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/Components/ComponentMetadata.cs index 2572ce22258..3c2450c82a1 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/Components/ComponentMetadata.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/Components/ComponentMetadata.cs @@ -68,6 +68,24 @@ public static class Bind public const string IsInvariantCulture = "Components.Bind.IsInvariantCulture"; public const string Format = "Components.Bind.Format"; + + /// + /// Represents the sub-span of the bind node that actually represents the property + /// + /// + ///
+        /// @bind-Value:get=""
+        /// ^----------------^ Regular node span
+        ///       ^---^        Property span
+        /// 
+ ///
+ public const string PropertySpan = "Components.Bind.PropertySpan"; + + /// + /// Used to track if this node was synthesized by the compiler and + /// not explicitly written by a user. + /// + public const string IsSynthesized = "Components.Bind.IsSynthesized"; } public static class ChildContent @@ -126,6 +144,12 @@ public static class Component public const string FullyQualifiedNameMatch = "Components.FullyQualifiedNameMatch"; public const string InitOnlyProperty = "Components.InitOnlyProperty"; + + /// + /// When a generic component is re-written with its concrete implementation type + /// We use this metadata on its bound attributes to track the updated type. + /// + public const string ConcreteContainingType = "Components.ConcreteContainingType"; } public static class EventHandler diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/Components/ComponentNodeWriter.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/Components/ComponentNodeWriter.cs index be0b2db28cb..01fc235d3ed 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/Components/ComponentNodeWriter.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/Components/ComponentNodeWriter.cs @@ -62,12 +62,6 @@ public sealed override void WriteCSharpCodeAttributeValue(CodeRenderingContext c return; } - // Currently the same for design time and runtime - public override void WriteComponentTypeInferenceMethod(CodeRenderingContext context, ComponentTypeInferenceMethodIntermediateNode node) - { - WriteComponentTypeInferenceMethod(context, node, returnComponentType: false); - } - protected bool ShouldSuppressTypeInferenceCall(ComponentIntermediateNode node) { // When RZ10001 (type of component cannot be inferred) is reported, we want to suppress the equivalent CS0411 errors, @@ -75,7 +69,7 @@ protected bool ShouldSuppressTypeInferenceCall(ComponentIntermediateNode node) return node.Diagnostics.Any(d => d.Id == ComponentDiagnosticFactory.GenericComponentTypeInferenceUnderspecified.Id); } - protected void WriteComponentTypeInferenceMethod(CodeRenderingContext context, ComponentTypeInferenceMethodIntermediateNode node, bool returnComponentType) + protected void WriteComponentTypeInferenceMethod(CodeRenderingContext context, ComponentTypeInferenceMethodIntermediateNode node, bool returnComponentType, bool allowNameof) { if (context == null) { @@ -97,9 +91,9 @@ protected void WriteComponentTypeInferenceMethod(CodeRenderingContext context, C // public static void CreateFoo_0(RenderTreeBuilder __builder, int seq, int __seq0, T1 __arg0, int __seq1, global::System.Collections.Generic.List __arg1, int __seq2, string __arg2) // { // builder.OpenComponent>(); - // builder.AddComponentParameter(__seq0, "Attr0", __arg0); - // builder.AddComponentParameter(__seq1, "Attr1", __arg1); - // builder.AddComponentParameter(__seq2, "Attr2", __arg2); + // builder.AddComponentParameter(__seq0, nameof(Foo.Attr0), __arg0); + // builder.AddComponentParameter(__seq1, nameof(Foo.Attr1), __arg1); + // builder.AddComponentParameter(__seq2, nameof(Foo.Attr2), __arg2); // builder.CloseComponent(); // } // @@ -195,8 +189,7 @@ protected void WriteComponentTypeInferenceMethod(CodeRenderingContext context, C context.CodeWriter.WriteStartInstanceMethodInvocation(ComponentsApi.RenderTreeBuilder.BuilderParameter, GetAddComponentParameterMethodName(context)); context.CodeWriter.Write(parameter.SeqName); context.CodeWriter.Write(", "); - - context.CodeWriter.Write($"\"{attribute.AttributeName}\""); + WriteComponentAttributeName(context, attribute, allowNameof); context.CodeWriter.Write(", "); if (!CanUseAddComponentParameter(context)) @@ -340,6 +333,41 @@ protected void WriteComponentTypeInferenceMethod(CodeRenderingContext context, C } } + protected static void WriteComponentAttributeName(CodeRenderingContext context, ComponentAttributeIntermediateNode attribute, bool allowNameof = true) + { + if (allowNameof && attribute.BoundAttribute?.ContainingType is string containingType) + { + containingType = attribute.Annotations[ComponentMetadata.Component.ConcreteContainingType] as string ?? containingType; + + // nameof(containingType.PropertyName) + // This allows things like Find All References to work in the IDE as we have an actual reference to the parameter + context.CodeWriter.Write("nameof("); + TypeNameHelper.WriteGloballyQualifiedName(context.CodeWriter, containingType); + context.CodeWriter.Write("."); + + var isSynthesized = attribute.Annotations.TryGetValue(ComponentMetadata.Bind.IsSynthesized, out string synthesizedString) && synthesizedString == bool.TrueString; + if (!isSynthesized) + { + var attributeSourceSpan = (SourceSpan)(attribute.Annotations[ComponentMetadata.Bind.PropertySpan] ?? attribute.Annotations[ComponentMetadata.Common.OriginalAttributeSpan]); + var requiresEscaping = attribute.PropertyName.IdentifierRequiresEscaping(); + using (context.CodeWriter.BuildEnhancedLinePragma(attributeSourceSpan, context, characterOffset: requiresEscaping ? 1 : 0)) + { + context.CodeWriter.WriteIdentifierEscapeIfNeeded(attribute.PropertyName); + context.CodeWriter.WriteLine(attribute.PropertyName); + } + } + else + { + context.CodeWriter.Write(attribute.PropertyName); + } + context.CodeWriter.Write(")"); + } + else + { + context.CodeWriter.WriteStringLiteral(attribute.AttributeName); + } + } + protected List GetTypeInferenceMethodParameters(ComponentTypeInferenceMethodIntermediateNode node) { var p = new List(); diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/Components/ComponentRuntimeNodeWriter.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/Components/ComponentRuntimeNodeWriter.cs index a575ba49bb8..bd0b77cab0f 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/Components/ComponentRuntimeNodeWriter.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/Components/ComponentRuntimeNodeWriter.cs @@ -530,6 +530,11 @@ public override void WriteComponent(CodeRenderingContext context, ComponentInter } } + public override void WriteComponentTypeInferenceMethod(CodeRenderingContext context, ComponentTypeInferenceMethodIntermediateNode node) + { + WriteComponentTypeInferenceMethod(context, node, returnComponentType: false, allowNameof: true); + } + private void WriteTypeInferenceMethodParameterInnards(CodeRenderingContext context, TypeInferenceMethodParameter parameter) { switch (parameter.Source) @@ -593,14 +598,15 @@ public override void WriteComponentAttribute(CodeRenderingContext context, Compo var addAttributeMethod = node.Annotations[ComponentMetadata.Common.AddAttributeMethodName] as string ?? GetAddComponentParameterMethodName(context); - // _builder.AddComponentParameter(1, "Foo", 42); + // _builder.AddComponentParameter(1, nameof(Component.Property), 42); context.CodeWriter.Write(_scopeStack.BuilderVarName); context.CodeWriter.Write("."); context.CodeWriter.Write(addAttributeMethod); context.CodeWriter.Write("("); context.CodeWriter.Write((_sourceSequence++).ToString(CultureInfo.InvariantCulture)); context.CodeWriter.Write(", "); - context.CodeWriter.WriteStringLiteral(node.AttributeName); + + WriteComponentAttributeName(context, node); context.CodeWriter.Write(", "); if (addAttributeMethod == ComponentsApi.RenderTreeBuilder.AddAttribute) diff --git a/src/Razor/benchmarks/Microsoft.AspNetCore.Razor.Microbenchmarks/Resources/Telerik/Kendo.Mvc.Examples.project.razor.json b/src/Razor/benchmarks/Microsoft.AspNetCore.Razor.Microbenchmarks/Resources/Telerik/Kendo.Mvc.Examples.project.razor.json index 7de7f1df1a3..00ca3271787 100644 --- a/src/Razor/benchmarks/Microsoft.AspNetCore.Razor.Microbenchmarks/Resources/Telerik/Kendo.Mvc.Examples.project.razor.json +++ b/src/Razor/benchmarks/Microsoft.AspNetCore.Razor.Microbenchmarks/Resources/Telerik/Kendo.Mvc.Examples.project.razor.json @@ -1,5 +1,5 @@ { - "__Version": 4, + "__Version": 5, "ProjectKey": "C:\\Users\\admin\\location\\Kendo.Mvc.Examples\\obj\\Debug\\net7.0\\", "FilePath": "C:\\Users\\admin\\location\\Kendo.Mvc.Examples\\Kendo.Mvc.Examples.csproj", "Configuration": { diff --git a/src/Razor/benchmarks/Microsoft.AspNetCore.Razor.Microbenchmarks/Resources/project.razor.bin b/src/Razor/benchmarks/Microsoft.AspNetCore.Razor.Microbenchmarks/Resources/project.razor.bin index 797443558032826b4ce937a56a9463a13d0b9d39..81821a1dbd87d063f73d84b74b7df7a6b3d62fd3 100644 GIT binary patch delta 16679 zcmbVyc{o*F8+U7)iBv==DnpZbNR+8mGM7vlGiHnkNyk(qA^Wf!6cwqI2I-WPQ<@zu zS`A30c{Vj_;9GkidY%w>^U2i zeOA$fuh0Z&_jzpdp67_W{|hkMooyy>dr1g&jI$K8kFUPRMn&Rp zUYAH-Foq$)6VJ|5ICu!^ehZtR*(I!kt`+B{w~2@Va!|n521a;*7rK|s8qg6v#i9JU zFc&?Y-KANt|F#i*-zDA61tVrjryfRF7gJ1_MjF?;iI$Ge%QlC#}0ko8E;g%8@-#c^Re_N@ieIM zuDWBEJVXIM2pz#T3IL_**?M=U>m)Yp7edEKOzREM9(sLj2 z-Cxb?5IaD6p7^C7CQ$cgUTyd@%{gS9P!S6iE_ORD7uQ(^*JQm9P;2n0g1$x1^ZKG% z;!vl_m?!Cywkm8?5>uoUyXx{=XsCTg&HJZ=20EQRx$<$VjyXE0+Pt~Ux#0*KJuUKU zU0^(A5SqTTF6<2sNr$Rm7ESWBmgFHaU}ya*;|5bUdge7KbR2wm47F~h+<&~1wY~{; zqEx*lU9Ey>#|_Se$)B3Xvr)h9!}sTYR186dYyn|nPm*dJVj(6=}0ioMms zZ1kBb$~)k-u@)|>Fx~q~vs(u}dNaeddc8#4=67WLr460u%bn5M5v6WD{acyMdRmGpA zxG2uj?)2J(IGKV>l=aK?jFx181xhWiEh$l-kO(6Kb6p<1H>+f$ec|frQMuBE(0yRD zRM(!mQ|P9b@}8T?`sdMUfq@UJ&Ub{f(VH{W&H#zDlTgE8hi!U)Q5RhJSTP~KdsYqF zdo@Yd$fRs08@+rv_(d!0emBZ~kT?1Z!J1|V17F0664kk}F#3kc&9iDB%h~8c)m@QM z9Sz0kLF~n=BDwAlp|oJ#-24F25}jAhNDJ%n6=uWG-oPhgy>{53Urs@u9(8rXFsc9c zzW%A1-_U^zE+yVxftGBj=^Y5%rM?uRdzxw)+T+C6BHlEgM|UP($GPxo#c$T>0Zuy` zdd;4rw2Ws`0F&Cfw2frCV^EGsxcX;{l~1A1n8XVYHhuGEqwW2|(|c<)kE2^X>P}Z) zeSU-X%X=TqVb@K9qHblUXA50~Y$yfS7g!p#?MC^%5#v|w8`OhKO8fMkzb{sYRzHK5 z@Af{4ll}Uh0;8$#!neT1=vmkFWtWxmAVS_ zeUeZvV?)_>K|>2>TbiKqG4YjCigT(_MpQQn?*6U-i7lfzoz-g)=_!sQTId<|V$w~& zd1zpUclopu{YaEsu*~?}x?md^c6rsN570f44V5;Wo1EXRUytfPRf#7?nx&)M`$@v# zrVDgoq~Y!)n|T}6*=Xqb^4}BgO=v@DBH!}bcBR^*a~b+im6YOp&@<6Qr=?dqMzK+6 z;X%n|I(O!vOD|$J-~8@V83;{Ot!IckR$oPBm*YZBf1q2(=TsONjG2OVD|=oU49!VL`&vX| zD4YH}WV(bMtLkL!mZ3pS6I9!FTxL?Qfh(dY`C*?b|sP8U>bBeXx%6hG_GsYa+T)n<091P<->6)s-`_ zv*zqJ9@}Es2}R~CDEq9QJ0F@>b4M?&NHj%Rg_lgc59Qag(a-f6QBMf*gV1qZ=z8AA z)17eTY+sF#B-tS-`FOz9reR$Hd1N#WVur!91E;%+22k^Yp8~7agh-$#hXv~%Z(n*B zhI*R)RKE#>rd>YQHm(+aPm22%WO34j=z@ zNREy6yLDFf){04?&Zp507q-{^Kp%R04Qz^w)nUTr%&4>5e(U0XA!c^U?&_8hC?hJi z?&tZ=A-FWNPwmmADOND_tLz1q?WRJKjrt7tpAHX_+koH!{c}^RH|>MO?(Tuy*iK70 zY94!~@GF4?HWa>^c)O(e!gw@;24z_>;z$sNY&Km zZ_o{3vp?m;f(_75@cd)zn=eJtuN=`BjfrOFY?v_4!(HgsmmcWJI{Zyn+oJptoP9Ol z^O-@!6x3haXt#d8?<+R?W%ey!Po_H=j!%1CeU@xff#%aRYRtA&u7t7by)sAZPD!$% z_$;O88`WhAnDWtlyV$Oak#H_p(mUGq6$i$6?i#0m_Dvldng~ufTUo2B2p2yR7TFs9 zHWXD!@7eDI<}0&M7ZI>xK4-;aHcAaDe>%PH_zoC2)m6Vdd)p-hpFWr|WqF4lYN8tU z{klJO7w!-Q_e33WvnFB4?PovLR0_-Cl!a->gCmaXL&JbiCC$dNVQeTSub{ZX^?@VG z(>Q&`;?q@e=vpY8n7Xx53B8K0I>!T*m)TIn#i1{iHFk6`6gZ&yv`gxk42<%x7=Ozy zD*>9Obf@)H-6>?Ft&Zw5yR~F0P}3_d?Xizdm7vf3f^gXhLiuoFsNR>hdM9}{Of=Ao zoH^IX7vLsR+QCH9r`+F-VG@{>Bug*LXv4?EL;?ZH?%r!O9>#}0wK$a&%<_ZIs_#ej zxHR2B`+EImPI6pm$woaf3yVGo33Q+rQ(B3jc%5TVoYnJsl~+In%JbDKxh66(gpCS# zJNyChHMV&;qy-N_d?h9jC_`)hbQlc#xf?6Y4Z=GCT zKy=XRQNk^Q!((uFr*~kwz;k&il-n*Je^DUV1l?Ty=rDP#=|1X?wZ3#szd)bf&b9>d za#uzouBxt>Bg@bNx=#&%?Qdj13c7r&X?$h6?mipFe*<>q=2COu*sig?N&aVD&;!qi zdcnz>dlBn-z}&GSQb8PC59^*yz89-bq2jRS?eAQ>vQYKX9ggDL<2z9KON)5LPBU4& zC&z)ymH0Eh-H=5IiYB%TX)0gW7i0vA- zT$TGBXSz;E%=|pb8WtR{%Hz~u7M+5!H{CaQJnESf)O>j2S?OlYv$%^N6QoWYC{9NM z2PgNfIrVf4+Ir-`cNgxm7`Rx;Nb;yuPcR$$hwkl>Hr&mH8`Lg1-;s*Ag)UuNU(FJK z>hJ>UKG>-y8|Z@lS^Kecb2L<0in`49xS35{Y6RDpzY3pl?~5S}e7{S?aq<{^G0KrB z8F0_wxuRnmvZ*RP#a#5s!K$@A-?Rih49XBw60JVQMwHLFlc9Tc%b@EhWBDlRW+$S8 zUynVx>cB-9;@EH?&cyj38_KcTmkBkW*<+9Lx!Y8yhknvS?RxEg>lm5TK zC2VM&AF(iD>G)SrIV&f>QS$W*)M$FSdz(>oB9vW}F|LJ0#o_~ZeC1b>mu=;Wy)5xJXBa8t_b$jD63PJRw`XH`G8irHz%LdBWsb@n#q?@-#u zFI4s<`r=n3erT7OMtd@Jou;@>e%qw4P}2F~ELpAmyQuO&On_gNP&!WHgLV&1R>f4H z{*ytMi>H0AM7Qk<>f&;m)lt*E+Mll5>icked)Ify%#avSbZ*&;F{j^U44|6XuKjXa zGb^E`Os2`$`7DReZ1e+|BlVi)Lr~qcYT>wUsqIjydb3pdeEYHJh^5iqQuW!=cw-dV z&)YgG7eMPZ0&^#p7~hBbZXP>xrhGmG1=YX4^pXge%0>^f+Z4*9a~jcZx3%5}MGu$9id-Qb^1N0=SMU|paF^>D$lmZ{b1Gj>05H5G6$=aUXQ=;kmA>E$dl%(7?`9pfG7j4}IsXm?GQSxfm|_eEqDyz)BA` zYJOC^=X}!wHB_8%t^R1`S{7>9BfIog+*B7-;k@?UUrY!D z$2UU@@9vk2v%U1#=&BNn7`H`{IFDL?n7C%%>YNQ-q%SA-*Hp>gpO81mPBEq+~Z3Vwc*T`n2YD? zB=_StA)C>y7K3+Q!EyJdJ9d|}PQ%xojm6xZmm*M)Cv-hCs^ktE#tKeYt#;5u3%yve zFlg@sBY(Idb6g!LdFTRlW2-X6e=d|_Ln1nJV}+2pJk-;h_v!AU{0_KILu_C)x!xMu z5N~fhgG*Vs2dK~>=B^H|*Fs%iL*MTTKH~)gmo3wqbHvpLHN4`+Wo3E1XTv!mo>~#1 zw_~B(We3A1A|@O?b1(aC7L)N9`jt4?8O}D3$8Q@84#gBMGD|?^j<=`P)Sgv|6omPDx*r?^a@rTPBy&s_cDWB8E%2D2Eb8^3ES^~NS6(+HI zex91_5sM%HWF;t4cS9RGA|7jZ*!am+DBanft6+5DHhyQ{z8Q+B z^W5bh3kvs}!XOJ#-*;|R16qmC&(Dr z>79`4l!0T&=N)>~nKv-e^h9Ux-Z=qqhIC-r!FB;#0fJB!#X{tT9@Vq!Wi; z7ahGB{y|<6-J059*rZ!F2AEB?0 zH^r+Sr-boCp4$ahlE*vF7C7H8F4uc)jR1^4lfC7l=iSX{Z@0jp`?tj@_!%-mV!YGZ zM~>+DmQOZ*JGFkn*}>_x>$hsfqr2gY3}cpEoWe$12FI*5^l0#g$@}zbE_~`LgDVZb z^+_AQDuFUqh88cUKgBh(Y@NR2=7cZ(P(@>lW9PD#C#aSc^YHU_ZSxFtdwsIK_X4jc zxbI>Yo9?7s_3b1v>sv3~vpD!zE9axmrGBz%28r!LZ~6}SX77)4LF&6}o;zB_ox zWV?QjfTFH)MQqN*`S=2L%5DcWXk~%E_lt$)utLLyprS`~(>UF@Td1<`m1*@0rKfCk zbMubc)+45^aNY^)hhx*1C_o>ZxC4C}ED>lj>-n#l`$O^FPvm0fjM}3mZ=rJLhu!Z^ z&m2HEr#7v!=;8RF$Ja*ndl64s*r;-+@5QB)I}Fi@irI@z^wZ{|cJs*bgsg4`bgY~x zWIpiO%8=|((qQ>zr(bXQ6*(Wu#>iJ6D)POF8r4n4e7}Ldqk@h@Pj~ILBiK+k&|#H} z^?^y~RwYsN{oTiEgq*H4==H=@!)b~3xsewZTeG2lQp6J8p#z)YtoQlHv|eo53|A+0 zk%w3)SvBs}wa|J)HVtSxYKP#@h=%>!M8+ z-yAowPAiJRTRwk7xk;{qLw@szuu>AD)3#X7 zkcQI-C)BJ7xU&k8>Yw2o!MmSP+at*bFnT>q^u=K|#P&(@7Fe%S0Mc zOVlLr&7!|r;&P}C8&1~TP;E)Yn*MuwqW}Y&Lp6 zJk-DmWL zInW}%Fg`5dSQ{dd=D#{x1E?HzUwh=OKkzYvu40+7H72aC7J7Wzb&l zwBO>gguRIRy`?`hPx1#8Yup~Qpb15@p|9zexqD*o20`P3m$`S0x7VXS^HV)jjD0K6 zm#CD@kKZgDi?{xJQ;Mv7S?ccS>Pnv(Ig37~L+^;_5ZgNUSoC}C&!vKnk+7dMT}#+-`gth_aj#L@FpOg&`&L(D8w^-}s%>C@u@rQ8 z&(Xbd!sRd<&SHhLO`Qi{NyA8OZoiGgX+f;`~SIs)I^P*|`PHpsl>cSRw@d;b>wDNVu zj!vZjC@bkTjXa%p9j8l$s zcnOtz+e`DIkh@UUgN(eHsQ1(1*yHJJVYtvLNVVrvvMU>%_IsH>J?hzQ^eps6weO4b zp{T9rwzhr!DRcDdq@L)W<6GNt6Fynw#QF{05ZV^JmdO9OY&NtSJ@r#*^3zIaw|&=q zpLk+{CAofzKPV+Tr`V9HQv<|H1x3X!U*>Yfxn#jq7M_rvmIt`x-f6XXYP<|RCCjbx zQVj=q?uMG}Om5@lfk_F@(8sK$bV?WKZKr_rlaxizNh z)dXJkZh8RbXg^~w{{3M_7Q8aU-nV#DY>mV@C727%{d(KPchVule#jF>ZqTVTWzBT5*t(x+(_aBISJGH7Aly3v436(2v9BSLL4L%U(2_Kac<+?vA%8)=5qjXVIiCe3IwJrFhC ziG8up_!nO4!Vs>&OI`6&4XlfsJFSZcm*mXt#l(k9USVR#WLgtxQaEKI`PeiO<8JdZ zFdk!OOpco$ipRU_VUak5!q4Raq54BY_wR!pLll1c%T_C`MLeL=z)njKjk*5`hsd zj6^c-jpC9nmb8d!OFJfTi^x=qDP)U_5UFZqDPAhaCyV9QL|IJ}z;uPyKNz}dDyA72 zkRmBIq~u~_0qk9B$__AbIddjcwFC)mgE~6#2 zMl8VzVm}-yXNi$0@pf{_St~wcFRQrj#qPi8T7`dyxh=-OPr7}@zYn>$G7d|mqo+@v z@NmK)@O;RC8);CN9J?~kcEm@#y|jX*SV7uJR!oiZ%4lpK#;j;l_VW%fc9+v=1x6Rp z=s{j3gC4@MTDg!8{8;bhjFk1H^9*;A>#c#YH{MYUmP3~*ndjq!v5!9cCH^Lq-05r2 zjA?;>Q-2dUyvy)vXlz(0ZRKgko?05Etz5#l@(hD=X!I~fZ3+r@)VQqL1Mu$5 zSEAjHG&7n_>VzmrxVZX9#0O#0_6>{=bV4SQ^?}mZ=H@^j8JfjE)oR~Oa!r&-&mh)6 z9I`#!l$;za^AD%Y3(jK3!vk4jsD9SmuYmw8Kh?Dwg2=5*IR--v07@h)_*#LKQS3Q1g_qQ^|zQlvat)19vPA( z8Rm$2@niPKIbJj`GAmK`Kb++F9}bG3>EyMT7%T|&j|vH*cgzv>vB#nqMm8bRSh7gu z-#mAnrn@ohIsVDTyGdiWFh=ha!&%fsWB=he9*zCWam_UPFUQ@c(Gkauu6Y=_nywq? zv~^ThA~A-%75z^W-$q-H8R5>a#CCG5*%XSK1Z2smI1w^w4NH1N5Wgtf&B#lB+T{9} zF{E`&Cbsit%=Eu%{Vq-XM}K~`-20~l-hC$DAN-RouZ=<5xukLI53I6^YZ~=Fkq{#< ztd)`c2UF_g3}RYgoa&$0V8uzTxNK%jI|S=Va^tpP)$HT{rrM)_aN(==_`j<5(HudZrG3g05{YM;^}PaXAq%HS|mtQDb9olc{@dz5%`ALI!AA8oAM_QduYDB zBYa0rt3Gax0Ly^pYni(5HkamNy;i#Xnlx9Z5?~4RUzNUtPiEZCb&lg3UmfX_A_O2wvF? zMDbdGytWyLH3M-v!_%w_=+?GI>-On7d8W_e@Sl!W4JZPwyDq|xSbcw z80+w-+w#eG8$EK4H-mB98g9M-5Gxft=oB5XIv|PC>cOo**-i}!{upy_&*t~oi?@e~ zmI_uZi;f6dOZ^Tcv={?ZcSwmd5KXz2?vG}Xa|%~u+4~BcahDZEE&{@Qqp6fc+&p!$ zT}NZuKX#LrMOPUeQ~w^26_`Om@eMxZuph_(${PoVOQkWL7t^#zmrN(~cL-y+XonU) zgqndIlP=9bo)Iz;yKpt*T!mp=k-?QP9>(C4{y2RyGoy@W!kL+oFsb}qT|whN^ivpo zDyFAX4TsO<&(t(#Y9xNmK$YLhH3KzfLLIM(z-##F(hM}XWZcdKZ1RVlK8!DH|HLb9 zm&@PcHG^A&cFEC^eZSie8*N*n`?pz5E}2!5@~4?@cmI=yI7;NB5=qi$k0@RhyvN{g ztF*af#U2u~oVzz4Pg-m>Ab;&m9zAl8!Ij9ZNiSWBuW&WZ`=sg4`O$tk0g=*XVAu>C z$kzC&^iiNp&O4Y+x8Db2=*ynY;q7>E>F^?An9z^f9tBd!$+g1b0nuxc7&rJ*)rUYB zsdGe_3_m78?T7|WH9^Oi(+F1Q((QXQ2%#=%^J!{Yj=!cYKYNnItZh#@(sFj6&g0W1 zkf}EqR)uFqQ}3<7cyi3m`87Xk*Wx8LQ5-SACu5PYBdq4t+3z%`Cv`b|bPLtG0fg1G zoqqy`)h#3~dQwQ!i&A`o?PN<&7_#Q07+(;h^%T7n>Q?tXW2a?^OSq-idnZ!M$FLY^?a&i3}O%?*srHH%;i zt)*P+QOvHfbqP%~`tC9QN=TIftn&1GO(QC|F&>r(4Dt_%TfNRdE(qT+A6Sm)(ADlo z>UQ{%vpPyKw_6=qG`D4ss_@|VBbSjV^^-o&_X`K%TMWL54RyKGMDEXrMGo-QihJ>b zR?FknQAQI2@HL5h%|yrREuWeY<5MTTV~nu*a0pB4`@k4s(nBXlQ_q}XvBXp=Dj%eX z21TxkTaDYLnr;2cwB%!-v-u)skUCexYRbRd9=4Uxqc4Fj5&xvrz`@qL)sT11I>pWHHX=7|VkP zv5I0}O*PfssLR{(=5+{&YwN2UO2&dq7y5v^FI z8aU3EaGa?n&Q*2rhMuUN4o+grd}n|yw8n2|fpd7ce>MoGhf><08V~EWfd@UDpa-h? zTp*o2(Hvua&_#2ZXb6VW>H*&&hDLn$lZ_b$JYzs_2b7ZOh(liU)tEC6ydSZrmq{8b z#SGN)h4e7a;OsL8Dug&ws>F|GaE?;e10!{6D7?mhEiNU_8Y`ekOUPXa_(>@M=oI5* zSmP*TeAZ%+#c&l6V?r@y2{=70SYRAK>}w+YlU7HCa5;WUK?KdK*$&g-gt7;b^svVf z;0FxOJ|_@G52crb8a~Gv)CX4(Lv=d?5srlm_(aPya0NB=QPC_wrhOmJ8FU47c2kZX zfQ@-P_uxx#@&Y8Ehb2F$?STlz^~Ql)?F~NCeB6A&DL#b_y@OJ{n1aLd1Kspw)G8); z$^jsRW}X!^LhJDt?eSpnmZseqI-Iit{!HcbIW?>XPwClx;Q()n9Onoym*%uJ3T)#` zjo~Ncn`m4>1+ic}HSaK(&%wjI5$~;M%JWCeaCr(O(Ux$MVsWZtPV?eM;*rM0Lq8s? z%-_TXa;OWrV54wAY;;5fmlKr$rqZ&vCxIP#$m}n@gr z&Ufci+MVIl=3*dC9;s!#X~w}LHfF$4+ySJ)aMFOs<4KEJcdEA(2ysexg6XvA8@q?g zOyCn!X7sEG=Y0uyHR94=#fL!o@BzU|D+PYTE)*1GCL)6T*WqH>z8|cl`F$)Ou4h4s z;hdnQjX4P3(f0hPWb8S72+*ej)qe!w{)3ZN1@uRls`3jb!GCoe6BzSqU`dmvoxmRD za%PS(SE{!g@8Zd4fDvs4Zr}vXDgV*<49UL) zq=hVFgZ#OiK@N}`nYEyN&4y?3KQ{3_+W|cP@EXl2I|qzMs4dA8meZ)zOF&t2QLKMR zBtAT`>~;@6xyyNAIV{xbFQH;fqSrE1&U`A#dSEzAwSZ6M+X!T^N%{4laYWEUN(J{~ z6g@+gUIZe16EFTvt;ZL^9@-xpxWI{NBNOHKxX22iq}HaUJj<-t+1EAflVNt6sVzFAPV!sPt;UJ6Ih24B_3FYS4HtaDIQ5R17AFfY{sE2 zrQ~k|U%r9IM=pcHl)4o$o^$;+mW3%SS{VA$7QAVeQp;Kaz8g@-Tk-i=N_pP_-i!t% z^kN%I1c4w7M+5OeU445Cvbg^^ChJ_Ptx zlxlnk+~|v4vtaDy%LTm81*MdFCkW$12{iNtLnWOck`Ha5p|2Q{eFP%-P$~_5!_c-z zz?~0e($IGd^*sVUd?=fS1~9bpG4SR?xis_xLsuS;P!-V7PYh{28KGj+&@T*8f1n*S z^t+(6xC?mVeDUl83-R5WDt!(-_)*(J-vsAVID~X(&%t7*_W=ABL2c{-p~F%vsj`QKu`mkZ8lxH7s!^}_ifiOH$>Icr)qR4(ge>$MrKLPxChZFl5DA2=gUw|Fo z_xOdYfQR*`UVZ`V_)c@fvZrw}zJf(G>8)>IDW4QSdlm5BVp5gwz=;oa(9k;!ZTJox z=og4)!A=@_KkSeN^oI$Hu}=OWbjmdgKBgx>V*1$wz?sjYi-x)}v}FL;@)dAl6!)>#ku|y&<#Iz^fz6uoWb8fn;vQnfu)Q`8kt3QnD)Uj1gGLjV=oBj&LnLFprKJgFI!ATJ6FzvD zH=dX_T%LU)DKz;%mq;iQ zVvJV^dA?S=ln67xZfFwpvEr#kEMrz6zI_k0 zh?9SU&YW1?vxu>Oc2Im@$6tNvb6uDc(INaXht)a+-bkp6Iz%@f9n&RlGyIOxwy04{ z?t!V4jwmsfnx#jKjJKV?;<(rE>@g`bA{A2IX`f zh*Iryh_!f?y)og*_iR1QJ%Um)CnTxV3B)hz&oXMB31Kb8q^(de^YYYgPk}RF)?Xx| zHcNFuNXunOGNARD2hI8-WJYqA3HRltyj4}6^`0k&NbH0@FFe8@nwMb^P z;9xE2H$Q5=1wq$oz6C*mVGYcg4{GhpsFsId2490VOJX9X>a!%`=qwCgNNk{=5}SpD z@V0=T5b?gyvyk|~mmo?@(4b@&5g-3Vh3TN+LPC1D6diFk(>`@xN^Ja3PMu4M;f@U7 z4u>N*nras(5M^qEgHk6!?BP7OBO+=2ogIiQ#@tk#RMR+<~eQ^-iEkT^eUodY-zL5#b%*< z!!L3|_qh}|oWTD!&A<=&uY^LKT&gsNkfj;}h@<~y1uKvU$86sR;@sm>c0t4;Jo*wu zJD$Qakl_|ic>K>Ylp_eo{|_015yZ0pSw=%7VgEl9Cr1$p|IZ2~|Ih4g*AS-v zZ|uMPwc>wD&dX!?Df@%}VZ1$oa^3(8NgWR>oP@7qiM7Mxhv%DxesZa>wS*(i)Vj5} zEVz_u+#i4a;D2{+7W&PlcEmA6Z{i62KP6On{J)6?xzvq#hDd%LL$rI{zlnyp)c17^ z(UJrr6?3|g@HZmn17EZ7C@!Uz$PmRR68K9YHIVpkA`H7G5$#xUo%O^#Jc?LP;Qv0L P{FCVsXHPOAA^3j)aA#`3 delta 15966 zcmb7pc|29y`+sYjLWWYIRA?|HiUwpBsmzsm%n*?wQxqqf5QV*KH>#+VjGc6vP`Ztr z7Oid}p;?*~l@$Hf-iLed=W~C5e7=92*XykJdgkX@&l+}3n#Aef;sh<6OYG$Iek^$P z)<741$lPM|ixMh=p<~~TKK04p096|f#OqXh+ft}>ae%Yw{die4s6P5p!OeT?p`Y$v z6Q6fm-@=HJirTKZn$IWeS#Zk;(%`BUW3c?w$HZ9`yv$jn;kFEcN4CG8%5v69eB@o zgGuMBBWM?3`+ z!0G6mLzO*f`xdyItDLeA&hjh^%Y5W^8a>!nF_0l6Hj^9@TCoh>h#pYCXoITWRY`qc?e375MfP&wN*^atooOehqsz4&6UJ|RE&*pI28r#^ z7;uOFVPm(M9UuFMf)ho;g*0!DQ$$r26PAdoym$+zzOsJdEVAVaG~DGZHmYDwAB7sf ztjY0J6)HiGyvoLwjkfPa@6_cf_rVVhC?i1Ma&XxRJqn$>beB3bDrqtdb&o{3i#Y1l z=$(#6+C=j;P3WlWl3$?jmM;azy{_q5|1NwqYC5kf=f0rzIy(6|Kl4T4ntD{SMdtKj z*JeKo-CO7MHT!&~3rg?wPSO~)r56>LU z0u)_kH{*?z{A&uz5nWujd0jbZ`{6|Cq z;o@sMe0?I}yjgDz_Z{iP`t)C}iGIfInufZ*(prtLx{kvnKVg?F`KG5(L*j0#WJA$$ zQerf&(y$dur7zV~bYa+1j_9?XIg-$2>(l8%g`v|?Q^CNA1A52pD9HILYdvw#pG~Mz zHnOhBN4^nC1zcGYqN>n`-Z!b;o1y)w+^WR#x zp?n*~Pv5~NK83o=N)wk{dAk`d8|<^qs^gq#M33TWJKb|4j%dp@ah0UZjBpCI6eCxo zp3OO^Uv5RcXhXLgdUm*ZnPF|xA{b-C?JRiEv@txMk5}#>Ao4)Y-Y56UCRl zQ|Lh7^}ZV?2m)$teWwlb4;P}JYdbVUqz!k&*;=WN%d!uBr{KE2V=jExs1g{Rsj<9F zqJIo}Gi%OhZNGa{p`LYKbeZJwaTNM=B57^Rw#YMRTkL7gJduO>=-U2wjd%OL*gvS}RVB7|;_K*pam!STrO%n>W;s;0%37pZX_WaE| zQmdpS8 zKH+4*RFrpYprQB13PYH@_(^8M_2423+Bkn{uKFO|0z;!hCby0+FM-AyD^`mf)Qm;c z!4>OVmfpWXrb*gznkMl42X1KHLai6Jv>&AnoM4Jg{f2RJM(XHy`*WWcSsg}roosU5 zBOKXz9>(MjpcTDAQ7HY}k6WhBdctu0-hI_3h4nuu^kkLg*Eh>}qUc4UNp5!*Uf~6| z;%t|E80tgSnQyjV-FD#(h00G>fH$JOG3e8mqi2p?)Aw$L#9~_|2;NH_K3#Tra4kt?# zl^cRkPitO3umv}Hq)c#R~tI(^NRj-MpK1C-=;o|tM#Z`i1q~r<*RSv z2pvLn!Of*6yV}#x%d_cPM)?n}Q7|&~u%!0m{kzb?@e6LhP+hNq+GmEj$a51`qM;{0 z$X{K}rzun&<#uS2h0Q}$bB1mYTbkyL8qYZ?I{B~YiKd;i1qgv`A)=JUDB}AWz=unza3G>*_5*#}pnP7}H+=h(cHT!%VlIF>ir3&w>jz60HrOaPZsuYwP2dBWm}T$Z4N+ zQYcip)jpUmSL}vy?Qsul#bY|qISZkrAH`Sppz~W~i}n>QvZUbngLZdvjuAVcNBmjO zs-YXbknk-YcOX0@fdh3nNmyN2qL4|U){Cu@ErmsYpi5`f4RUpk|ANK=C7V5!U3Wo~ zb0?PEJ!kxzLf`M4NZt5yo;eJ8Cfm`hQ#=;BsrwYU=QnFXvxqag)slanpb(00McU3& zB;b4zqoGxzu|nv@1tULuF_rnKIr7_KG!&IVq58?u-Um5Pqm*IN_ivS&+)X{`Qp|;S zzIo1a(0#kQN>yrTI0a|6puL@5CGP0gs1IgmCR!YVV<%gRm+chNhRdSXc(^{QkEYN` zD)=VP=k#7E-?z%;K(gBjC}Xs<(Dk&Q4NSUKJ1MQ>WEuq>`MRTTMgEzM_CdD|#Fh_s zXnRaP$1i18sWPfw8809EZam(Jzv_D{=pG( zE!6mY7V+O-$)A)IIu#1JKG3OCyI+p?yCvnhM|>^t9(eJa_Ono>*5~Nwmj><=1M{m; z%(X>k;3R#Hg7L)e!SYi=dZ*E2Yhva}b^XF8o^03_}X~ zygH`4gV0lhUTFocH|)Efz=(IfrDc7ppP-S&#yNdYRP-sBq@4cfjj?1Lx~=!@OuUne z9J;aer3W`yBN3h6xtp-yteCTyg5D8zk~wcCcS4gzNre)1zf;hYeYdnu7YnDriL%F} zoW5OnLE+7?pyFq}sy;fo@YNMLZPh#I`L}FMDG~MYP(83Ps(oGiQwrK%JojQp;&m>J zIxlBwrW0(63d}0JXTMc+g+$Ay=TeteE~8KfEj*~!xY`vxc*!v?N^g>IgA>Mh?SH>D zA`m?}>?K+6dh8p8-f;MegJKddP_dShvMRZ@3*EPU_~`e0g>(Jq&-~kql_EX1m_NsC|^#G0(u`JH12l1bsnl3tcmWpdjC1p zoYGjYIzY8j=;gXZ>8}HG+tBZ-^LNXVJVKz!+%_>;*IE0~Sq<>qE6lVVAAO{Ddwfo; zn>cJ7mD-F0#SFjQ&1_=16tdz)ZV)71?%m+c(! z%DNlB>Tbc1oa?WikquU$dicvPs zNl`D`@RcFDgF7=KY$=qSbai%drco43u2OJ!8XFT2IWD}E*N0-Hr3^tdIP zFO~5$2s#ZlblgfHxM(o1o8#O(D-{~9SQ78Lav?sN*vWaeOb*cuhLe>p)!aOyk&fQ` z4k_(&xwQr+7iXI}+~geR)z>ymFqyCP`xI1H^O4lfkMA7PHPH;li`?q%XKXcI^ z8`L$Pv_}O{P$4N<=V({0HmW~1zI1b5MgeNjdJ$Vy1e{U9(;I5pa_L$Wj50TKY&Ta= zfj%=D!xK<;G}LK-e)X76Z6%Cr398+5P4)u?$6g-%BipmR7HU2^+xhwW>~i#K_Y7l| zjzJ@6!10lt*!?5pByKOsrncHG{`JGKsxpcHRM@=%9dAU4bXfu3Wn@8 zs>nNMp^0i=c0Ksf)O-Wt0XrC#IfE$H24Pob_vrG`Rdzfq{9L#`Cxi1kqZ z+XoVlIA1SAlQk`?UsY=T!pGFSY|RB#(VS7}?BPRSbO|C4-Px>JcIk4+UAW1JHL5LLkht>ml1#)eUVUQ?2d>qE zE{jX{J+@5=rl3^N2J50ZA{(GCK6AWW`ydN?%g&R3{YSkBTsEu1d+(wN^C@&9ul(WG zas4i+*nIZY{`mowP`QoTxwC#p6r5qbIxKf=W(kE(=cu^VpG=_8-LYmE<@QyDTaeB zn)Bd_w1_l&NvBsR)k}3{;`37$xbmLl&lW$nWjA_c5}NX<>4-VvwBO7eQuLMCfNrR# z&+np+=2Ph4>rR&io|in(tA$p74)A1GL)ZF^FAHOA%Fs4%*=N?Ho@P)`eboJHKkq-l z-LqtVQJ#A5Da3PazFA+#I|E(n#GXoz{yv(5=8t8+&E9yf1J&@Y4OgEnz6e7d&hG8L zd}Shfv2DEjb+Il^90iwGUEa5JV3`Wa*k~+zQsZnaoR<{Rv8%IO2HhAuq8y`mOqzn> z-6t64qLv&y05_ptZM1)v*s!+(}mX0dp`U&*dT_Jd{i&j-)f~P+HZL)(Aq2L z6MFpdONHltk!ZhXGlu^l2;p2~?QU|fVrOI2nDSTzfIJW<_gFM=^ zI^(RNgwk}BEhcl~VSi6L9Od(PE&rZ4zSR86*El}w$gDOf`HH z3)OaV{DaH7j=!OxxP87=)x zTitd-n;TE8%YOvmb3y=pSv6(pS0nU0!e^P#C=o|! z5|!thI1n%y6*Lx6i_iUW7rzd8Cw!0>Pjlm-lM^#SMLyjLfij|;$wM2DIY6DM1v@@* zAN1mD$fQa~5jQFoE_Yt~)b!b5W%MHDz1+MRU)-Up=%T`kxb}7mU3$7eC-^#b3st0D zbnuZPXf;DGc}bbH*x zkR8*r-B3#>f779j89@}vM1Gu81COj9Lci=3e)*tJRYoXgu$<#?>#>C&_N1%eIaht8T{;m zOAiMNT~h{<=#fV6)%m+}XTtef`PXIKa`01tDy4TZYnPN1)SkQ6%KGlJ>CmF+fLObV z-zqp^wRW|Etce*1udMLO`m>7sAdhC+Nf6Y9Xh|>x$cCyxGVal z6e}yMF8UT7Ts6DkBXw~v1@-2Jz3tS9T88eo9rFLg*=2qLefcJ8D_PH3j_)zeq{prG z`0Y*HefRt?USb+o)9iFU_9Nsn5va z=%y|=7*uStOQ>;qCAy|%8D-{mC6z*-_xNhU@3Qt@8#B+_6E4UPXN$S97L9)xJ!#9dvOX+SRm5QD^t> zS_)1wI$pwa`koK9j!s`bS*FAk>Q)5J*|=fhZuI-1mh(_xO(+E;Y(1jN`>x2N%a-Gv z_p5Cji|X=s8Ha`hY(-B!O!K$8dE-NB@Wtf@imfY^;KIQA4K~+~roc&Cv%7CL4(x*7 zV|?tVaa^uy;2mj9!2N5p{I8+CVvd)eep%KIjnCRBn)bSgpsqZdYQL2tvJ_mU`F$w; z#Y`utU3IxDfBv?gh-=U(TA|ohgepgkwqI(Nl0v~)zM=EGsR0+zeY?v^rG}z^pie%p z-%B0LR6;EeCq0~=)6+pgwG(#tZ@S)_2u<}k3Y7eKuOHC0^#15jx3JUb_lJ&GzZ80I zVWV!-5yf=|`=RyY7HQGKywRO$wDfG-zs`ah~u@UT|$;zi;(5aAAA$i>PMHdvN@iEXkLBLDdwxT;cgd^WeMy zXgcreqoc+N0jTtZl4PaS>+OiY%KZ9n!}9U?aX4OmPtyyPM(kJbu(JuSzj&hXVDyzB^yaIG7iXe#k^{5~ zM*(iyCioH7R8HRMb6mg#xN!B|=uHl1tWcNM1@WzR!4}XdaNpPY!csN(As{>D#nZqL z38<&vZMs3x2EO+2k|#A-1ft4t`Y}zs~ZND4JaAGh0lLn z_v9rv;X7%etF3BAP6)Jm5YtuBb;=QXn|-=?p?h;W%8h(rx;wtxn1UwV(j3v}FFc@1 z^_{FHkMN1;^N??|Z9v*rDE001sy|#yeDDV0>Dl$5B)bJQWWRXU`TgQz^t0SPSh%L- z1$tPbhZhRbVM`{d_=9}1O=TH5OLdKSzVK-Ay1HxEB*;8f4j!Gbhzv|@(I!=9E0cbv z(xlCFH}d%ODm)`Mo}rt-^_vj}uz-e{D@cV|)9{4qbY@}(*L+qPfhT&@1BCNHOCtF+ z!HulYu)t8S#!f6mjU395BFi=HF*2m-&-I(##t1T=D53@XAjsYbMSm-enmfWPd zTN&X)^CHOz-6;I8L)Vt8r56V#jfh>52W*GM+Odl5xz+Pi7$&2I?jm`h6(o`K^o+QV z7g{mk6#WB?hmSEfpZui%2bQynWm}yGT(BH9tlZU&QSMGcgC5Lr&G0qDQH?p~l1I{% z$nT3cVmQiZE4`%w=#yH;Arkq*C#@snA_807nc(N`(;<7Z#K~{Qdj%vNrV3=6i8JQX zF->5E?PJw307+A-~I4lo@V?Y}N>)DV-kn!g3SV^O~Ejh&^Ogvv+fN$XDSxgra$`?LQ zjtw49HdwtRE3Gey;GnknkGS9$EK1HzkR;*K6J+E9H9BfGAwizB$&$_&K5G>i8fzID z5gW8ImcI5C$dkt$l*kRsHn0JYA^mlxbETHMF#!)=;liz6u@e8~j5I9LmI}mVvMP?hHVYoS#SpicVf_h0n-~YSTGZVyD(_TfLRUMEVvtk zdoZ||0dt4JJPeW;G-5!iVUmD!FGlxa)EJ|Js5a1~#;P?!ILLJF7cf1~eiFHU)tJ%R z!;vC8SH(+=WT4>y>A$)UJ9Q)`l^paCCp%rnGyWC~*V%lsB6%Vi<2nbE9CuwxPjw>H zNLe?Chn;Rs4CO|a^0oU)3>kVnVW1QiTJ9OQbR*XpV1z#NR5(R$n`rVRchjbuA0X<5Ak=F+VXf+;7XcVXgZlu^~AMRth=!bu}X|B#h9QN8qQ(pFHhP2(ZIzJ^Etwg-lNk;xB$d`?k!RL={_WgVJXwtu|I@jezom~jSBs(la_$<2 z{^i_t4F1cxIt>2p+$HQBnGtf0_05c|2$vCE<>DV67lhs1F3j{*x-5a1g|`qL(l1z& zAt3L}9m6C#i%s;?b>5gaH7J#xst+6gpYAWlFbn-1f^ZB?{?9N(FjQpzS_v{>z32MB za(x?{dS^Hsf_jv6JuFPHLRv^CI~7vaeFFI?Y6nxzj7Y&cX)z(q{dLHWXc@9NdK;;;LH+NQ z_YhP5Wu%~L|NIZR4UgE;d;A{~8=6_Lg)G=GfNeYylRxI4a%eD{m`-*EPb86+>tbZrN=qzz z-0R6&C7uU7uo88gcl&HNvM5{IKVO&+MA?G@AK)#P4@P4Ge{3rsi1UF2Q)ql3$xMvF z6Kn8<;4H)kQva=o5Ad28mOs4P@qr9?@or@%q+WZ186WKN8Dt5{sZIQ+EBeEZv|JXPTMp7Dj(DdW%9u{dX33DAltSLhi9$H^5r0xL zfBrvabjTI?B%bNW--BzjTyo?P&Ih_&&11_6@q9j5zz2pcfpo402qa(EyOE8@$I^r0 zU?I7sP=vdqP@bvz{8M-FNs$liX!G@89rtk&L5K-h-AK@rOb(Tcj`k0T4UPAY4dR9u zTaV28(PhejnHCd@j7sF1ml`m)mQCeZthBY{^=IqIic&FdO2uo&wV-n(_s2O0hGtpS zZfV1tg z%a=<=7q8>4t9_37xOUe?m_sdQyq*l?X#3s3jayeYb|e%h@Oe75-kI#YBSRYBJkIU7 zd6Y4SbEkqk_pS|NPGbF7z}?jl$G`w)ad$&g=I{Nc67Hr4HiU#AE{%LpL_RBU!-AGb z1+EDX2oDViW7I-H2%r5~&v;S#IGek;*_@G^+$tt;vx9ZB?}-8%&{xX#$SC zddDkvg?h z(8=AUEGmxE5WzKi*T8_{A5OF2Sk?%Yk1Y)N^HVN2yJyj`IzpAcS_YEEg4RdHh6V+4 z9ebxSmPUO|=l=L=JRC?ucQ}yc-=)c;{ROPhdF0U7Fz&e@V~3+e81cbY@>stc*?w_} zNN{98Tnsnz*HT6rZ%AOWrND3W`xy{Kmat`bn8;!tDV8TPE|&3b1?wH}0Ri4&qv;x9 zK(bm_l0)a#(U(U930}Pjc+bpT6a#s@6{A5eR>gZN0VV-nza-d?M|7?B&fSJs| zcPz+cWyG;&@Z86N4$RLp7!Sq)p6vv1kfC}b4=PxyodOHQ6v1OgOUEQo%FCV%7BfV5 zrvQORG!t3gtEr%lp*gJ#vRU4vq*?PiT2vK`C2iixk@uU8X|riSm?xnMwlIXdrh{DG zlo`N_5tcLyl(Ssr0=o{Vfv%DGT;u~2+9v?GlZ^#q>7j72Ksr3qKQJcNe*+sP9<%Cr zg_>XzBdJCUT;gq<1Hwj2Peb>BNHN+px&mB>w!r6zBUl$NzG%ur$6X|GTvc5 zu!<4zc>#9v=tAJi48H4wGS;pRmW?;b5Ih;NtBY9?%5T^eF=l;aTue}06rv7D?m8IUTO!J8!BIj%eZ$>FNRyu83Qp6&-6c~kvtoX>_VISQ8_F-TxkYp?AFBdSfb2u47Yxu-kxFcRAhY)6;bfE#^4h=0V|ASR&Etc8gYU<} zz6CfjvTD+B6L8uJ?3lsP?O-=gdk2`u4E)js%U$ z-UX&I^rhLuR^4T+3gZ>+20X@e-<)ANO~dUY7cU^e7A4e5Z9rM4-)h*p%wv= z8wKt#%qsgpHm`gi2paCFLfwLnN}Ck|89L^R9w$ z{6GIHuw{;2PRz-Yo>&bQV9>UDSO`}j#P$%WKvw3e)53MY2j^K>pD%39+yHgyxjZ0CPrHc2S6K(-n3OV;CM`>ttJo5H>`jox z%fAVBGqUE~23Hwb?2U(ZXa(}L!5xr6tV=l^?-xHu?--CdDtw&|8@AlnIYKC+>YoAe1M-cY1R9{mjOu@{P_SV((pdO zj|TJ{2z=>1wuCyFlO~h5U6fY(6X^4ZM!-A}(k@K`zC(ZW2|WNocqa4#U=Qo`$V?&z zpgYEc#Knvh9 z=H@X3JRBb`v#6MOa%ry~piBEa1CvJE`>zkeM9HkO-E9Cr=hDyGfGfV9^MyCm)#Wtw z<>b>=Pr*7CNnnt#7`gfstY?wU4Dt;l3)?|Bi)>+#?-(g>2X6Rk#~0qlApJQ4?K|jC z9l&{V7Rh0dpBP!yIZQ(_$S;i4j3E0N zWDq0j&wvMS>oc$fAIj-FFM;5}JcGH1@oZm#4NOvMUkhMj5d+g0Hsz(g!R;KMpM>>K zM&Pi-(8tYjO&)!VtNHRL-vnsh6d-?*&f0W4*XuG0B*(-~jK`SA1^6gX`abEgMSw7LwC|?V~4s z2l2ez?;rwC@B0Ckv$Ob}CZ~Zh%k>9vWRus*Al<|MnA1ZSfG+l3nC|%j#<47I48c3h zA~OJ%vn=fl@?n@|3B7wJ@fV8(T`~Y9S*lKk>fe!bE}4a8i%cN}utXP?jN-n5HNs%yc>4snNt|W_J{<8pcAp zQIe2j+hz$Hc%IT2g842(ACe**SiAsp&f!gwCay5cv_+QK#9KXGNZ39A_=1e4FhKVN8vlR(jF{_OM;c%|9v`_up=v0tI?4>d?fUmNBCo~ zW*%DwEl(J+^kQA&HU@?Ci2L|?PmT6_1ZL1tdc<^|*?dBXF=NRh!jCa-h)J3UEu>GJ z#b~)c!G1i*Vgkox3cpOyrwj-W9xxk;2vaLo|BOFVKx5Vi(5*35-7wQM)gH( zrH(ZrD=yeDT0yCx@8I%B%!C}TaT)P~QFDF;k@8=X&1?yK9^M~kG2y)6K3tBEn@_t1 z6aMt&VB$260b|a45~S#mvUi2)>HtE9KD(BX5ZKYMmIwwi|D}a43nx_QfKbBg-wGJ3 z{zX4`9pO4m`hLWL4~zl@x?&xn|1Wx0zG4^=^gqh~6h_$pALS?gkD?E(CmjBdqE+am z2*UY)ly4kK*!_>BKO>2R|FbE=(S*nUC?7@>i~le3H*NTf{=drdUkO!8MyDW?0RD;6o-~S5eJk#-m<$L$0P;l!=^61X#i;}$5`Wl}5n(^1 z(EaiMrX8YP5=LmZ(wZCpP4Syf-^fxlZzQ(R?uq}PV85pDMMu%RM3zD(options); var caseSensitive = reader.ReadBoolean(); var isEditorRequired = reader.ReadBoolean(); @@ -38,13 +39,13 @@ public override BoundAttributeDescriptor Deserialize(ref MessagePackReader reade return new BoundAttributeDescriptor( kind, name!, typeName, isEnum, hasIndexer, indexerNamePrefix, indexerTypeName, - documentationObject, displayName, caseSensitive, isEditorRequired, + documentationObject, displayName, containingType, caseSensitive, isEditorRequired, parameters, metadata, diagnostics); } public override void Serialize(ref MessagePackWriter writer, BoundAttributeDescriptor value, SerializerCachingOptions options) { - writer.WriteArrayHeader(14); + writer.WriteArrayHeader(15); CachedStringFormatter.Instance.Serialize(ref writer, value.Kind, options); CachedStringFormatter.Instance.Serialize(ref writer, value.Name, options); @@ -54,6 +55,7 @@ public override void Serialize(ref MessagePackWriter writer, BoundAttributeDescr CachedStringFormatter.Instance.Serialize(ref writer, value.IndexerNamePrefix, options); CachedStringFormatter.Instance.Serialize(ref writer, value.IndexerTypeName, options); CachedStringFormatter.Instance.Serialize(ref writer, value.DisplayName, options); + CachedStringFormatter.Instance.Serialize(ref writer, value.ContainingType, options); writer.Serialize(value.DocumentationObject, options); writer.Write(value.CaseSensitive); writer.Write(value.IsEditorRequired); @@ -65,7 +67,7 @@ public override void Serialize(ref MessagePackWriter writer, BoundAttributeDescr public override void Skim(ref MessagePackReader reader, SerializerCachingOptions options) { - reader.ReadArrayHeaderAndVerify(14); + reader.ReadArrayHeaderAndVerify(15); CachedStringFormatter.Instance.Skim(ref reader, options); // Kind; CachedStringFormatter.Instance.Skim(ref reader, options); // Name @@ -75,8 +77,9 @@ public override void Skim(ref MessagePackReader reader, SerializerCachingOptions CachedStringFormatter.Instance.Skim(ref reader, options); // IndexerNamePrefix CachedStringFormatter.Instance.Skim(ref reader, options); // IndexerTypeName CachedStringFormatter.Instance.Skim(ref reader, options); // DisplayName + CachedStringFormatter.Instance.Skim(ref reader, options); // ContainingType DocumentationObjectFormatter.Instance.Skim(ref reader, options); // DocumentationObject - reader.Skip(); // CaseSenstive + reader.Skip(); // CaseSensitive reader.Skip(); // IsEditorRequired BoundAttributeParameterFormatter.Instance.SkimArray(ref reader, options); // BoundAttributeParameters diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Serialization/MessagePack/SerializationFormat.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Serialization/MessagePack/SerializationFormat.cs index c8e31d27b6a..bb550776606 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Serialization/MessagePack/SerializationFormat.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Serialization/MessagePack/SerializationFormat.cs @@ -9,5 +9,5 @@ internal static class SerializationFormat // or any of the types that compose it changes. This includes: RazorConfiguration, // ProjectWorkspaceState, TagHelperDescriptor, and DocumentSnapshotHandle. // NOTE: If this version is changed, a coordinated insertion is required between Roslyn and Razor for the C# extension. - public const int Version = 4; + public const int Version = 5; } diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Serialization.Json/ObjectReaders.cs b/src/Shared/Microsoft.AspNetCore.Razor.Serialization.Json/ObjectReaders.cs index 9dadbcc5cf8..3ccdbf6a994 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Serialization.Json/ObjectReaders.cs +++ b/src/Shared/Microsoft.AspNetCore.Razor.Serialization.Json/ObjectReaders.cs @@ -215,6 +215,7 @@ static BoundAttributeDescriptor ReadFromProperties(JsonDataReader reader) var indexerNamePrefix = reader.ReadStringOrNull(nameof(BoundAttributeDescriptor.IndexerNamePrefix)); var indexerTypeName = reader.ReadStringOrNull(nameof(BoundAttributeDescriptor.IndexerTypeName)); var displayName = reader.ReadNonNullString(nameof(BoundAttributeDescriptor.DisplayName)); + var containingType = reader.ReadStringOrNull(nameof(BoundAttributeDescriptor.ContainingType)); var documentationObject = ReadDocumentationObject(reader, nameof(BoundAttributeDescriptor.Documentation)); var caseSensitive = reader.ReadBooleanOrTrue(nameof(BoundAttributeDescriptor.CaseSensitive)); var isEditorRequired = reader.ReadBooleanOrFalse(nameof(BoundAttributeDescriptor.IsEditorRequired)); @@ -226,8 +227,8 @@ static BoundAttributeDescriptor ReadFromProperties(JsonDataReader reader) return new BoundAttributeDescriptor( Cached(kind), Cached(name)!, Cached(typeName), isEnum, hasIndexer, Cached(indexerNamePrefix), Cached(indexerTypeName), - documentationObject, Cached(displayName), caseSensitive, isEditorRequired, - parameters, metadata, diagnostics); + documentationObject, Cached(displayName), Cached(containingType), + caseSensitive, isEditorRequired, parameters, metadata, diagnostics); } } diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Serialization.Json/ObjectWriters.cs b/src/Shared/Microsoft.AspNetCore.Razor.Serialization.Json/ObjectWriters.cs index 9387490630c..c8998ca6fc9 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Serialization.Json/ObjectWriters.cs +++ b/src/Shared/Microsoft.AspNetCore.Razor.Serialization.Json/ObjectWriters.cs @@ -174,6 +174,7 @@ static void WriteBoundAttribute(JsonDataWriter writer, BoundAttributeDescriptor writer.WriteIfNotNull(nameof(value.IndexerNamePrefix), value.IndexerNamePrefix); writer.WriteIfNotNull(nameof(value.IndexerTypeName), value.IndexerTypeName); writer.WriteIfNotNull(nameof(value.DisplayName), value.DisplayName); + writer.WriteIfNotNull(nameof(value.ContainingType), value.ContainingType); WriteDocumentationObject(writer, nameof(value.Documentation), value.DocumentationObject); writer.WriteIfNotTrue(nameof(value.CaseSensitive), value.CaseSensitive); writer.WriteIfNotFalse(nameof(value.IsEditorRequired), value.IsEditorRequired); diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Serialization.Json/SerializationFormat.cs b/src/Shared/Microsoft.AspNetCore.Razor.Serialization.Json/SerializationFormat.cs index 09658a27efb..1be32b7f927 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Serialization.Json/SerializationFormat.cs +++ b/src/Shared/Microsoft.AspNetCore.Razor.Serialization.Json/SerializationFormat.cs @@ -9,5 +9,5 @@ internal static class SerializationFormat // or any of the types that compose it changes. This includes: RazorConfiguration, // ProjectWorkspaceState, TagHelperDescriptor, and DocumentSnapshotHandle. // NOTE: If this version is changed, a coordinated insertion is required between Roslyn and Razor for the C# extension. - public const int Version = 4; + public const int Version = 5; } From d1d03fb21d89a522cbb17ec8ffdb29ac76eb9e06 Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Tue, 16 Jul 2024 10:44:03 -0700 Subject: [PATCH 110/176] Inline brokered service factories into the services --- .../RemoteFoldingRangeService.Factory.cs | 15 --------------- .../FoldingRanges/RemoteFoldingRangeService.cs | 8 +++++++- .../RemoteHtmlDocumentService.Factory.cs | 15 --------------- .../HtmlDocuments/RemoteHtmlDocumentService.cs | 8 +++++++- .../RemoteClientInitializationService.Factory.cs | 15 --------------- .../RemoteClientInitializationService.cs | 8 +++++++- .../RemoteLinkedEditingRangeService.Factory.cs | 15 --------------- .../RemoteLinkedEditingRangeService.cs | 8 +++++++- .../RemoteSemanticTokensService.Factory.cs | 15 --------------- .../SemanticTokens/RemoteSemanticTokensService.cs | 5 +++++ .../RemoteTagHelperProviderService.Factory.cs | 15 --------------- .../TagHelpers/RemoteTagHelperProviderService.cs | 6 ++++++ .../RemoteUriPresentationService.Factory.cs | 15 --------------- .../RemoteUriPresentationService.cs | 6 ++++++ 14 files changed, 45 insertions(+), 109 deletions(-) delete mode 100644 src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/FoldingRanges/RemoteFoldingRangeService.Factory.cs delete mode 100644 src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/HtmlDocuments/RemoteHtmlDocumentService.Factory.cs delete mode 100644 src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Initialization/RemoteClientInitializationService.Factory.cs delete mode 100644 src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/LinkedEditingRange/RemoteLinkedEditingRangeService.Factory.cs delete mode 100644 src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/SemanticTokens/RemoteSemanticTokensService.Factory.cs delete mode 100644 src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/TagHelpers/RemoteTagHelperProviderService.Factory.cs delete mode 100644 src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/UriPresentation/RemoteUriPresentationService.Factory.cs diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/FoldingRanges/RemoteFoldingRangeService.Factory.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/FoldingRanges/RemoteFoldingRangeService.Factory.cs deleted file mode 100644 index 34abbcf45cf..00000000000 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/FoldingRanges/RemoteFoldingRangeService.Factory.cs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the MIT license. See License.txt in the project root for license information. - -using Microsoft.CodeAnalysis.Razor.Remote; - -namespace Microsoft.CodeAnalysis.Remote.Razor; - -internal sealed partial class RemoteFoldingRangeService -{ - internal sealed class Factory : FactoryBase - { - protected override IRemoteFoldingRangeService CreateService(in ServiceArgs args) - => new RemoteFoldingRangeService(in args); - } -} diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/FoldingRanges/RemoteFoldingRangeService.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/FoldingRanges/RemoteFoldingRangeService.cs index 6331b182b60..92c114a5816 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/FoldingRanges/RemoteFoldingRangeService.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/FoldingRanges/RemoteFoldingRangeService.cs @@ -16,8 +16,14 @@ namespace Microsoft.CodeAnalysis.Remote.Razor; -internal sealed partial class RemoteFoldingRangeService(in ServiceArgs args) : RazorDocumentServiceBase(in args), IRemoteFoldingRangeService +internal sealed class RemoteFoldingRangeService(in ServiceArgs args) : RazorDocumentServiceBase(in args), IRemoteFoldingRangeService { + internal sealed class Factory : FactoryBase + { + protected override IRemoteFoldingRangeService CreateService(in ServiceArgs args) + => new RemoteFoldingRangeService(in args); + } + private readonly IFoldingRangeService _foldingRangeService = args.ExportProvider.GetExportedValue(); private readonly IFilePathService _filePathService = args.ExportProvider.GetExportedValue(); diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/HtmlDocuments/RemoteHtmlDocumentService.Factory.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/HtmlDocuments/RemoteHtmlDocumentService.Factory.cs deleted file mode 100644 index 91db19d8774..00000000000 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/HtmlDocuments/RemoteHtmlDocumentService.Factory.cs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the MIT license. See License.txt in the project root for license information. - -using Microsoft.CodeAnalysis.Razor.Remote; - -namespace Microsoft.CodeAnalysis.Remote.Razor; - -internal sealed partial class RemoteHtmlDocumentService -{ - internal sealed class Factory : FactoryBase - { - protected override IRemoteHtmlDocumentService CreateService(in ServiceArgs args) - => new RemoteHtmlDocumentService(in args); - } -} diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/HtmlDocuments/RemoteHtmlDocumentService.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/HtmlDocuments/RemoteHtmlDocumentService.cs index a2c32ea5df4..c8492edc1df 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/HtmlDocuments/RemoteHtmlDocumentService.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/HtmlDocuments/RemoteHtmlDocumentService.cs @@ -10,8 +10,14 @@ namespace Microsoft.CodeAnalysis.Remote.Razor; -internal sealed partial class RemoteHtmlDocumentService(in ServiceArgs args) : RazorDocumentServiceBase(in args), IRemoteHtmlDocumentService +internal sealed class RemoteHtmlDocumentService(in ServiceArgs args) : RazorDocumentServiceBase(in args), IRemoteHtmlDocumentService { + internal sealed class Factory : FactoryBase + { + protected override IRemoteHtmlDocumentService CreateService(in ServiceArgs args) + => new RemoteHtmlDocumentService(in args); + } + public ValueTask GetHtmlDocumentTextAsync( RazorPinnedSolutionInfoWrapper solutionInfo, DocumentId razorDocumentId, diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Initialization/RemoteClientInitializationService.Factory.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Initialization/RemoteClientInitializationService.Factory.cs deleted file mode 100644 index 2fbdc9ff968..00000000000 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Initialization/RemoteClientInitializationService.Factory.cs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the MIT license. See License.txt in the project root for license information. - -using Microsoft.CodeAnalysis.Razor.Remote; - -namespace Microsoft.CodeAnalysis.Remote.Razor; - -internal sealed partial class RemoteClientInitializationService -{ - internal sealed class Factory : FactoryBase - { - protected override IRemoteClientInitializationService CreateService(in ServiceArgs args) - => new RemoteClientInitializationService(in args); - } -} diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Initialization/RemoteClientInitializationService.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Initialization/RemoteClientInitializationService.cs index 8bca0800e63..b7e23789f5c 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Initialization/RemoteClientInitializationService.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Initialization/RemoteClientInitializationService.cs @@ -8,8 +8,14 @@ namespace Microsoft.CodeAnalysis.Remote.Razor; -internal sealed partial class RemoteClientInitializationService(in ServiceArgs args) : RazorBrokeredServiceBase(in args), IRemoteClientInitializationService +internal sealed class RemoteClientInitializationService(in ServiceArgs args) : RazorBrokeredServiceBase(in args), IRemoteClientInitializationService { + internal sealed class Factory : FactoryBase + { + protected override IRemoteClientInitializationService CreateService(in ServiceArgs args) + => new RemoteClientInitializationService(in args); + } + public ValueTask InitializeAsync(RemoteClientInitializationOptions options, CancellationToken cancellationToken) => RunServiceAsync(ct => { diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/LinkedEditingRange/RemoteLinkedEditingRangeService.Factory.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/LinkedEditingRange/RemoteLinkedEditingRangeService.Factory.cs deleted file mode 100644 index aceaf61116f..00000000000 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/LinkedEditingRange/RemoteLinkedEditingRangeService.Factory.cs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the MIT license. See License.txt in the project root for license information. - -using Microsoft.CodeAnalysis.Razor.Remote; - -namespace Microsoft.CodeAnalysis.Remote.Razor; - -internal sealed partial class RemoteLinkedEditingRangeService -{ - internal sealed class Factory : FactoryBase - { - protected override IRemoteLinkedEditingRangeService CreateService(in ServiceArgs args) - => new RemoteLinkedEditingRangeService(in args); - } -} diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/LinkedEditingRange/RemoteLinkedEditingRangeService.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/LinkedEditingRange/RemoteLinkedEditingRangeService.cs index 3afc7fe1cf6..d27a11f7ce3 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/LinkedEditingRange/RemoteLinkedEditingRangeService.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/LinkedEditingRange/RemoteLinkedEditingRangeService.cs @@ -11,8 +11,14 @@ namespace Microsoft.CodeAnalysis.Remote.Razor; -internal sealed partial class RemoteLinkedEditingRangeService(in ServiceArgs args) : RazorDocumentServiceBase(in args), IRemoteLinkedEditingRangeService +internal sealed class RemoteLinkedEditingRangeService(in ServiceArgs args) : RazorDocumentServiceBase(in args), IRemoteLinkedEditingRangeService { + internal sealed class Factory : FactoryBase + { + protected override IRemoteLinkedEditingRangeService CreateService(in ServiceArgs args) + => new RemoteLinkedEditingRangeService(in args); + } + public ValueTask GetRangesAsync( RazorPinnedSolutionInfoWrapper solutionInfo, DocumentId razorDocumentId, diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/SemanticTokens/RemoteSemanticTokensService.Factory.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/SemanticTokens/RemoteSemanticTokensService.Factory.cs deleted file mode 100644 index 9658e0e35fc..00000000000 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/SemanticTokens/RemoteSemanticTokensService.Factory.cs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the MIT license. See License.txt in the project root for license information. - -using Microsoft.CodeAnalysis.Razor.Remote; - -namespace Microsoft.CodeAnalysis.Remote.Razor; - -internal sealed partial class RemoteSemanticTokensService -{ - internal sealed class Factory : FactoryBase - { - protected override IRemoteSemanticTokensService CreateService(in ServiceArgs args) - => new RemoteSemanticTokensService(in args); - } -} diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/SemanticTokens/RemoteSemanticTokensService.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/SemanticTokens/RemoteSemanticTokensService.cs index 5db2f30a61c..a570bcca9ae 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/SemanticTokens/RemoteSemanticTokensService.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/SemanticTokens/RemoteSemanticTokensService.cs @@ -14,6 +14,11 @@ namespace Microsoft.CodeAnalysis.Remote.Razor; internal sealed partial class RemoteSemanticTokensService(in ServiceArgs args) : RazorDocumentServiceBase(in args), IRemoteSemanticTokensService { + internal sealed class Factory : FactoryBase + { + protected override IRemoteSemanticTokensService CreateService(in ServiceArgs args) + => new RemoteSemanticTokensService(in args); + } private readonly IRazorSemanticTokensInfoService _semanticTokensInfoService = args.ExportProvider.GetExportedValue(); diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/TagHelpers/RemoteTagHelperProviderService.Factory.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/TagHelpers/RemoteTagHelperProviderService.Factory.cs deleted file mode 100644 index c88fa2eef9a..00000000000 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/TagHelpers/RemoteTagHelperProviderService.Factory.cs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the MIT license. See License.txt in the project root for license information. - -using Microsoft.CodeAnalysis.Razor.Remote; - -namespace Microsoft.CodeAnalysis.Remote.Razor; - -internal sealed partial class RemoteTagHelperProviderService -{ - internal sealed class Factory : FactoryBase - { - protected override IRemoteTagHelperProviderService CreateService(in ServiceArgs args) - => new RemoteTagHelperProviderService(in args); - } -} diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/TagHelpers/RemoteTagHelperProviderService.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/TagHelpers/RemoteTagHelperProviderService.cs index 59aced6d0d4..93cca215f5d 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/TagHelpers/RemoteTagHelperProviderService.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/TagHelpers/RemoteTagHelperProviderService.cs @@ -15,6 +15,12 @@ namespace Microsoft.CodeAnalysis.Remote.Razor; internal sealed partial class RemoteTagHelperProviderService(in ServiceArgs args) : RazorBrokeredServiceBase(in args), IRemoteTagHelperProviderService { + internal sealed class Factory : FactoryBase + { + protected override IRemoteTagHelperProviderService CreateService(in ServiceArgs args) + => new RemoteTagHelperProviderService(in args); + } + private readonly RemoteTagHelperResolver _tagHelperResolver = args.ExportProvider.GetExportedValue(); private readonly RemoteTagHelperDeltaProvider _tagHelperDeltaProvider = args.ExportProvider.GetExportedValue(); diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/UriPresentation/RemoteUriPresentationService.Factory.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/UriPresentation/RemoteUriPresentationService.Factory.cs deleted file mode 100644 index e6fc5fb26e9..00000000000 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/UriPresentation/RemoteUriPresentationService.Factory.cs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the MIT license. See License.txt in the project root for license information. - -using Microsoft.CodeAnalysis.Razor.Remote; - -namespace Microsoft.CodeAnalysis.Remote.Razor; - -internal sealed partial class RemoteUriPresentationService -{ - internal sealed class Factory : FactoryBase - { - protected override IRemoteUriPresentationService CreateService(in ServiceArgs args) - => new RemoteUriPresentationService(in args); - } -} diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/UriPresentation/RemoteUriPresentationService.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/UriPresentation/RemoteUriPresentationService.cs index d6957346f78..a63f4c961e5 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/UriPresentation/RemoteUriPresentationService.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/UriPresentation/RemoteUriPresentationService.cs @@ -17,6 +17,12 @@ namespace Microsoft.CodeAnalysis.Remote.Razor; internal sealed partial class RemoteUriPresentationService(in ServiceArgs args) : RazorDocumentServiceBase(in args), IRemoteUriPresentationService { + internal sealed class Factory : FactoryBase + { + protected override IRemoteUriPresentationService CreateService(in ServiceArgs args) + => new RemoteUriPresentationService(in args); + } + private readonly IRazorDocumentMappingService _documentMappingService = args.ExportProvider.GetExportedValue(); public ValueTask GetPresentationAsync( From 94a614ec517f91f6683b122f56f151a9b1e9ec6f Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Tue, 16 Jul 2024 11:36:02 -0700 Subject: [PATCH 111/176] Clean up RemoteMefComposition a bit --- .../RazorBrokeredServiceBase.FactoryBase`1.cs | 3 +- .../RemoteMefComposition.cs | 42 +++++++++++++------ .../Cohost/CohostTestBase.cs | 10 ++--- 3 files changed, 35 insertions(+), 20 deletions(-) diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorBrokeredServiceBase.FactoryBase`1.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorBrokeredServiceBase.FactoryBase`1.cs index c41d4f74f19..f55eed26614 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorBrokeredServiceBase.FactoryBase`1.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorBrokeredServiceBase.FactoryBase`1.cs @@ -4,6 +4,7 @@ using System; using System.Diagnostics; using System.IO; +using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.Razor.Remote; using Microsoft.CodeAnalysis.Remote.Razor.Logging; @@ -40,7 +41,7 @@ public async Task CreateAsync( var brokeredServiceData = (RazorBrokeredServiceData?)hostProvidedServices.GetService(typeof(RazorBrokeredServiceData)); var exportProvider = brokeredServiceData?.ExportProvider - ?? await RemoteMefComposition.GetExportProviderAsync().ConfigureAwait(false); + ?? await RemoteMefComposition.GetSharedExportProviderAsync(CancellationToken.None).ConfigureAwait(false); // There are three logging cases: // diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RemoteMefComposition.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RemoteMefComposition.cs index d031f2ec34d..a1e91636a0f 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RemoteMefComposition.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RemoteMefComposition.cs @@ -10,35 +10,53 @@ namespace Microsoft.CodeAnalysis.Remote.Razor; -internal static class RemoteMefComposition +// Inspired by https://github.com/dotnet/roslyn/blob/25aa74d725e801b8232dbb3e5abcda0fa72da8c5/src/Workspaces/Remote/ServiceHub/Host/RemoteWorkspaceManager.cs#L77 + +internal sealed class RemoteMefComposition { - internal static readonly ImmutableArray RemoteHostAssemblies = [typeof(RemoteMefComposition).Assembly]; + public static readonly ImmutableArray Assemblies = [typeof(RemoteMefComposition).Assembly]; - private static readonly AsyncLazy s_lazyConfiguration = new(CreateConfigurationAsync, joinableTaskFactory: null); + private static readonly AsyncLazy s_lazyConfiguration = new( + static () => CreateConfigurationAsync(CancellationToken.None), + joinableTaskFactory: null); - private static readonly AsyncLazy s_lazyExportProvider = new(CreateExportProviderAsync, joinableTaskFactory: null); + private static readonly AsyncLazy s_lazyExportProvider = new( + static () => CreateExportProviderAsync(CancellationToken.None), + joinableTaskFactory: null); - public static Task GetConfigurationAsync(CancellationToken cancellationToken = default) + /// + /// Gets a built from . Note that the + /// same instance is returned for subsequent calls to this method. + /// + public static Task GetConfigurationAsync(CancellationToken cancellationToken) => s_lazyConfiguration.GetValueAsync(cancellationToken); - public static Task GetExportProviderAsync(CancellationToken cancellationToken = default) + /// + /// Gets an for the shared MEF composition. Note that the + /// same instance is returned for subsequent calls to this method. + /// + public static Task GetSharedExportProviderAsync(CancellationToken cancellationToken) => s_lazyExportProvider.GetValueAsync(cancellationToken); - private static async Task CreateConfigurationAsync() + private static async Task CreateConfigurationAsync(CancellationToken cancellationToken) { var resolver = new Resolver(SimpleAssemblyLoader.Instance); var discovery = new AttributedPartDiscovery(resolver, isNonPublicSupported: true); // MEFv2 only - var parts = await discovery.CreatePartsAsync(RemoteHostAssemblies).ConfigureAwait(false); + var parts = await discovery.CreatePartsAsync(Assemblies, cancellationToken: cancellationToken).ConfigureAwait(false); var catalog = ComposableCatalog.Create(resolver).AddParts(parts); return CompositionConfiguration.Create(catalog).ThrowOnErrors(); } - // Internal for testing - // Inspired by https://github.com/dotnet/roslyn/blob/25aa74d725e801b8232dbb3e5abcda0fa72da8c5/src/Workspaces/Remote/ServiceHub/Host/RemoteWorkspaceManager.cs#L77 - private static async Task CreateExportProviderAsync() + /// + /// Creates a new MEF composition and returns an . The catalog and configuration + /// are reused for subsequent calls to this method. + /// + public static async Task CreateExportProviderAsync(CancellationToken cancellationToken) { - var configuration = await s_lazyConfiguration.GetValueAsync(); + var configuration = await s_lazyConfiguration.GetValueAsync(cancellationToken); + cancellationToken.ThrowIfCancellationRequested(); + var runtimeComposition = RuntimeComposition.CreateRuntimeComposition(configuration); var exportProviderFactory = runtimeComposition.CreateExportProviderFactory(); diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostTestBase.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostTestBase.cs index 16fa2ab3516..ed375852db0 100644 --- a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostTestBase.cs +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostTestBase.cs @@ -11,7 +11,6 @@ using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Remote.Razor; using Microsoft.CodeAnalysis.Text; -using Microsoft.VisualStudio.Composition; using Xunit.Abstractions; namespace Microsoft.VisualStudio.Razor.LanguageClient.Cohost; @@ -26,12 +25,9 @@ protected override async Task InitializeAsync() { await base.InitializeAsync(); - // Create a new isolated MEF composition but use the cached configuration for performance. - var configuration = await RemoteMefComposition.GetConfigurationAsync(DisposalToken); - var runtimeComposition = RuntimeComposition.CreateRuntimeComposition(configuration); - var exportProviderFactory = runtimeComposition.CreateExportProviderFactory(); - var exportProvider = exportProviderFactory.CreateExportProvider(); - + // Create a new isolated MEF composition. + // Note that this uses a cached catalog and configuration for performance. + var exportProvider = await RemoteMefComposition.CreateExportProviderAsync(DisposalToken); AddDisposable(exportProvider); _remoteServiceInvoker = new TestRemoteServiceInvoker(JoinableTaskContext, exportProvider, LoggerFactory); From 00a11a3ff72132c755d44f2c3333aed38278e9d4 Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Tue, 16 Jul 2024 11:41:04 -0700 Subject: [PATCH 112/176] Don't inherit EmptyLoggerFactory from AbstractLoggerFactory --- .../Logging/EmptyLoggerFactory.cs | 31 +++++++++++++++++-- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Logging/EmptyLoggerFactory.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Logging/EmptyLoggerFactory.cs index d52a222626d..6ae7e3fcbc7 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Logging/EmptyLoggerFactory.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Logging/EmptyLoggerFactory.cs @@ -1,17 +1,42 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT license. See License.txt in the project root for license information. -using System.Collections.Immutable; +using System; using Microsoft.CodeAnalysis.Razor.Logging; namespace Microsoft.CodeAnalysis.Remote.Razor.Logging; -internal sealed class EmptyLoggerFactory : AbstractLoggerFactory +internal sealed class EmptyLoggerFactory : ILoggerFactory { public static ILoggerFactory Instance { get; } = new EmptyLoggerFactory(); private EmptyLoggerFactory() - : base(ImmutableArray.Empty) { } + + public void AddLoggerProvider(ILoggerProvider provider) + { + // This is an empty logger factory. Do nothing. + } + + public ILogger GetOrCreateLogger(string categoryName) + { + return Logger.Instance; + } + + private sealed class Logger : ILogger + { + public static readonly ILogger Instance = new Logger(); + + private Logger() + { + } + + public bool IsEnabled(LogLevel logLevel) => false; + + public void Log(LogLevel logLevel, string message, Exception? exception) + { + // This is an empty logger. Do nothing. + } + } } From 323e74cae665c306175cf486c4a40426cbd0c732 Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Tue, 16 Jul 2024 12:03:36 -0700 Subject: [PATCH 113/176] Prefer mock for IServiceBroker --- .../RazorBrokeredServiceBase.FactoryBase`1.cs | 2 +- .../Cohost/BrokeredServiceFactory.cs | 7 +-- .../Cohost/TestBrokeredServiceInterceptor.cs | 33 ++++++++++++++ .../Cohost/TestRemoteServiceInvoker.cs | 6 +-- .../Cohost/TestServiceBroker.cs | 43 ------------------- 5 files changed, 41 insertions(+), 50 deletions(-) create mode 100644 src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/TestBrokeredServiceInterceptor.cs delete mode 100644 src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/TestServiceBroker.cs diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorBrokeredServiceBase.FactoryBase`1.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorBrokeredServiceBase.FactoryBase`1.cs index f55eed26614..f3c1b31d6db 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorBrokeredServiceBase.FactoryBase`1.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorBrokeredServiceBase.FactoryBase`1.cs @@ -54,7 +54,7 @@ public async Task CreateAsync( ? new TraceSourceLoggerFactory(traceSource) : EmptyLoggerFactory.Instance); - // Update the MEF composition's ILoggerFactory the target ILoggerFactory. + // Update the MEF composition's ILoggerFactory to the target ILoggerFactory. // Note that this means that the first non-empty ILoggerFactory that we use // will be used for MEF component logging for the lifetime of all services. var remoteLoggerFactory = exportProvider.GetExportedValue(); diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/BrokeredServiceFactory.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/BrokeredServiceFactory.cs index 849d87876f7..1284f6785bf 100644 --- a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/BrokeredServiceFactory.cs +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/BrokeredServiceFactory.cs @@ -6,6 +6,7 @@ using System.Diagnostics; using System.Linq; using System.Threading.Tasks; +using Microsoft.AspNetCore.Razor.Test.Common; using Microsoft.AspNetCore.Razor.Test.Common.VisualStudio; using Microsoft.CodeAnalysis.Razor.Logging; using Microsoft.CodeAnalysis.Remote.Razor; @@ -52,13 +53,13 @@ private static Dictionary BuildFactoryMap() } public static async Task CreateServiceAsync( - TestServiceBroker serviceBroker, ExportProvider exportProvider, ILoggerFactory loggerFactory) + TestBrokeredServiceInterceptor brokeredServiceInterceptor, ExportProvider exportProvider, ILoggerFactory loggerFactory) where TService : class { Assert.True(s_factoryMap.TryGetValue(typeof(TService), out var factory)); var (clientStream, serverStream) = FullDuplexStream.CreatePair(); - var brokeredServiceData = new RazorBrokeredServiceData(exportProvider, loggerFactory, serviceBroker); + var brokeredServiceData = new RazorBrokeredServiceData(exportProvider, loggerFactory, brokeredServiceInterceptor); var hostProvidedServices = VsMocks.CreateServiceProvider(b => { b.AddService(brokeredServiceData); @@ -71,7 +72,7 @@ public static async Task CreateServiceAsync( serverStream, hostProvidedServices, serviceActivationOptions: default, - serviceBroker, + StrictMock.Of(), authorizationServiceClient: default!); } } diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/TestBrokeredServiceInterceptor.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/TestBrokeredServiceInterceptor.cs new file mode 100644 index 00000000000..4c8e70ed2ea --- /dev/null +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/TestBrokeredServiceInterceptor.cs @@ -0,0 +1,33 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT license. See License.txt in the project root for license information. + +using System; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Razor; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.ExternalAccess.Razor; +using Microsoft.CodeAnalysis.Remote.Razor; + +namespace Microsoft.VisualStudio.Razor.LanguageClient.Cohost; + +internal sealed class TestBrokeredServiceInterceptor : IRazorBrokeredServiceInterceptor +{ + private Solution? _solution; + + public void UpdateSolution(Solution solution) + { + _solution = solution; + } + + public ValueTask RunServiceAsync( + Func implementation, + CancellationToken cancellationToken) + => implementation(cancellationToken); + + public ValueTask RunServiceAsync( + RazorPinnedSolutionInfoWrapper solutionInfo, + Func> implementation, + CancellationToken cancellationToken) + => implementation(_solution.AssumeNotNull()); +} diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/TestRemoteServiceInvoker.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/TestRemoteServiceInvoker.cs index 5e4c7f05b47..52f5af1e270 100644 --- a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/TestRemoteServiceInvoker.cs +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/TestRemoteServiceInvoker.cs @@ -24,7 +24,7 @@ internal sealed class TestRemoteServiceInvoker( ExportProvider exportProvider, ILoggerFactory loggerFactory) : IRemoteServiceInvoker, IDisposable { - private readonly TestServiceBroker _serviceBroker = new(); + private readonly TestBrokeredServiceInterceptor _serviceInterceptor = new(); private readonly Dictionary _services = []; private readonly ReentrantSemaphore _reentrantSemaphore = ReentrantSemaphore.Create(initialCount: 1, joinableTaskContext); @@ -35,7 +35,7 @@ private async Task GetOrCreateServiceAsync() { if (!_services.TryGetValue(typeof(TService), out var service)) { - service = await BrokeredServiceFactory.CreateServiceAsync(_serviceBroker, exportProvider, loggerFactory); + service = await BrokeredServiceFactory.CreateServiceAsync(_serviceInterceptor, exportProvider, loggerFactory); _services.Add(typeof(TService), service); } @@ -57,7 +57,7 @@ private async Task GetOrCreateServiceAsync() // the RazorPinnedSolutionInfoWrapper properly, but we need Roslyn changes for that. For now, this works fine // as we don't have any code that makes multiple parallel calls to TryInvokeAsync in the same test. var solutionInfo = new RazorPinnedSolutionInfoWrapper(); - _serviceBroker.UpdateSolution(solution); + _serviceInterceptor.UpdateSolution(solution); return await invocation(service, solutionInfo, cancellationToken); } diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/TestServiceBroker.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/TestServiceBroker.cs deleted file mode 100644 index fd5925588eb..00000000000 --- a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/TestServiceBroker.cs +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the MIT license. See License.txt in the project root for license information. - -using System; -using System.IO.Pipelines; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Razor; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.ExternalAccess.Razor; -using Microsoft.CodeAnalysis.Remote.Razor; -using Microsoft.ServiceHub.Framework; - -namespace Microsoft.VisualStudio.Razor.LanguageClient.Cohost; - -internal sealed class TestServiceBroker : IServiceBroker, IRazorBrokeredServiceInterceptor -{ - private Solution? _solution; - - public event EventHandler? AvailabilityChanged { add { } remove { } } - - public void UpdateSolution(Solution solution) - { - _solution = solution; - } - - public ValueTask RunServiceAsync(Func implementation, CancellationToken cancellationToken) - { - return implementation(cancellationToken); - } - - public ValueTask RunServiceAsync(RazorPinnedSolutionInfoWrapper solutionInfo, Func> implementation, CancellationToken cancellationToken) - { - return implementation(_solution.AssumeNotNull()); - } - - public ValueTask GetPipeAsync(ServiceMoniker serviceMoniker, ServiceActivationOptions options = default, CancellationToken cancellationToken = default) - => throw new NotImplementedException(); - - public ValueTask GetProxyAsync(ServiceRpcDescriptor serviceDescriptor, ServiceActivationOptions options = default, CancellationToken cancellationToken = default) - where T : class - => throw new NotImplementedException(); -} From 55fee1ecb73baa230c869dcb9a64cef7d7d7e0d0 Mon Sep 17 00:00:00 2001 From: David Wengier Date: Wed, 17 Jul 2024 07:42:52 +1000 Subject: [PATCH 114/176] Post merge updates, and rejig of client initialization options --- .../CohostSemanticTokensRangeEndpointTest.cs | 6 +++--- .../Cohost/CohostTestBase.cs | 17 ++++++++++++----- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostSemanticTokensRangeEndpointTest.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostSemanticTokensRangeEndpointTest.cs index 02d79678d91..760defdd871 100644 --- a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostSemanticTokensRangeEndpointTest.cs +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostSemanticTokensRangeEndpointTest.cs @@ -101,13 +101,13 @@ private async Task VerifySemanticTokensAsync(string input, bool colorBackground, var legendService = OOPExportProvider.GetExportedValue(); legendService.SetLegend(legend.TokenTypes.All, legend.TokenModifiers.All); - var featureOptions = OOPExportProvider.GetExportedValue(); - featureOptions.SetOptions(_clientInitializationOptions with { UsePreciseSemanticTokenRanges = precise }); + // Update the client initialization options to control the precise ranges option + UpdateClientInitializationOptions(c => c with { UsePreciseSemanticTokenRanges = precise }); var clientSettingsManager = new ClientSettingsManager([], null, null); clientSettingsManager.Update(ClientAdvancedSettings.Default with { ColorBackground = colorBackground }); - var endpoint = new CohostSemanticTokensRangeEndpoint(RemoteServiceProvider, clientSettingsManager, legend, NoOpTelemetryReporter.Instance, LoggerFactory); + var endpoint = new CohostSemanticTokensRangeEndpoint(RemoteServiceInvoker, clientSettingsManager, legend, NoOpTelemetryReporter.Instance, LoggerFactory); var span = new LinePositionSpan(new(0, 0), new(sourceText.Lines.Count, 0)); diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostTestBase.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostTestBase.cs index 139a7fa3e5b..47cd7bd476a 100644 --- a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostTestBase.cs +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostTestBase.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT license. See License.txt in the project root for license information. +using System; using System.IO; using System.Linq; using System.Threading.Tasks; @@ -10,6 +11,7 @@ using Microsoft.AspNetCore.Razor.Test.Common; using Microsoft.AspNetCore.Razor.Test.Common.Workspaces; using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Razor.Remote; using Microsoft.CodeAnalysis.Remote.Razor; using Microsoft.CodeAnalysis.Text; using Microsoft.VisualStudio.Composition; @@ -22,8 +24,8 @@ public abstract class CohostTestBase(ITestOutputHelper testOutputHelper) : Works private const string CSharpVirtualDocumentSuffix = ".g.cs"; private ExportProvider? _exportProvider; private TestRemoteServiceInvoker? _remoteServiceInvoker; + private RemoteClientInitializationOptions _clientInitializationOptions; - private protected RemoteClientInitializationOptions _clientInitializationOptions; private protected TestRemoteServiceInvoker RemoteServiceInvoker => _remoteServiceInvoker.AssumeNotNull(); /// @@ -37,13 +39,12 @@ protected override async Task InitializeAsync() // Create a new isolated MEF composition. // Note that this uses a cached catalog and configuration for performance. - var exportProvider = await RemoteMefComposition.CreateExportProviderAsync(DisposalToken); - AddDisposable(exportProvider); + _exportProvider = await RemoteMefComposition.CreateExportProviderAsync(DisposalToken); + AddDisposable(_exportProvider); - _remoteServiceInvoker = new TestRemoteServiceInvoker(JoinableTaskContext, exportProvider, LoggerFactory); + _remoteServiceInvoker = new TestRemoteServiceInvoker(JoinableTaskContext, _exportProvider, LoggerFactory); AddDisposable(_remoteServiceInvoker); - var featureOptions = OOPExportProvider.GetExportedValue(); _clientInitializationOptions = new() { CSharpVirtualDocumentSuffix = CSharpVirtualDocumentSuffix, @@ -52,7 +53,13 @@ protected override async Task InitializeAsync() UsePreciseSemanticTokenRanges = false, UseRazorCohostServer = true }; + UpdateClientInitializationOptions(c => c); + } + private protected void UpdateClientInitializationOptions(Func mutation) + { + _clientInitializationOptions = mutation(_clientInitializationOptions); + var featureOptions = OOPExportProvider.GetExportedValue(); featureOptions.SetOptions(_clientInitializationOptions); } From e67fab8002fc552c3adf008abc0fb0dddd5646ba Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Tue, 16 Jul 2024 14:13:24 -0700 Subject: [PATCH 115/176] Add missing `ReturnAsync` for mock --- .../Documents/VisualStudioFileChangeTrackerTest.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Documents/VisualStudioFileChangeTrackerTest.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Documents/VisualStudioFileChangeTrackerTest.cs index 2b75b031509..b708a37e657 100644 --- a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Documents/VisualStudioFileChangeTrackerTest.cs +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Documents/VisualStudioFileChangeTrackerTest.cs @@ -79,6 +79,7 @@ public async Task StopListening_UnadvisesForFileChange() .Verifiable(); fileChangeService .Setup(f => f.UnadviseFileChangeAsync(123, It.IsAny())) + .ReturnsAsync(TestProjectData.SomeProjectImportFile.FilePath) .Verifiable(); var tracker = new VisualStudioFileChangeTracker( TestProjectData.SomeProjectImportFile.FilePath, From 2edc20169db3a0d42f710a7b9900cfc076640636 Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Tue, 16 Jul 2024 14:28:18 -0700 Subject: [PATCH 116/176] Move CreateTextLoader helper to TestMocks class --- .../TagHelperTooltipFactoryBaseTest.cs | 15 +++++----- .../DocumentContextFactoryTest.cs | 6 ++-- .../LanguageServer/LanguageServerTestBase.cs | 18 ------------ .../TestMocks.cs | 29 +++++++++++++++++++ .../RazorProjectInfoDriverTest.cs | 13 +++++---- 5 files changed, 47 insertions(+), 34 deletions(-) create mode 100644 src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/TestMocks.cs diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Completion/TagHelperTooltipFactoryBaseTest.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Completion/TagHelperTooltipFactoryBaseTest.cs index 7a635a05f7a..e5ccc0e268d 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Completion/TagHelperTooltipFactoryBaseTest.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Completion/TagHelperTooltipFactoryBaseTest.cs @@ -10,6 +10,7 @@ using Microsoft.AspNetCore.Razor.Language.Components; using Microsoft.AspNetCore.Razor.LanguageServer.Tooltip; using Microsoft.AspNetCore.Razor.ProjectSystem; +using Microsoft.AspNetCore.Razor.Test.Common; using Microsoft.AspNetCore.Razor.Test.Common.LanguageServer; using Microsoft.CodeAnalysis.Razor.ProjectSystem; using Roslyn.Test.Utilities; @@ -374,7 +375,7 @@ await projectManager.UpdateAsync(updater => { updater.ProjectAdded(hostProject); updater.ProjectWorkspaceStateChanged(hostProject.Key, projectWorkspaceState); - updater.DocumentAdded(hostProject.Key, hostDocument, CreateTextLoader(hostDocument.FilePath, text: "")); + updater.DocumentAdded(hostProject.Key, hostDocument, TestMocks.CreateTextLoader(hostDocument.FilePath, text: "")); }); var service = new TestTagHelperToolTipFactory(projectManager); @@ -419,11 +420,11 @@ await projectManager.UpdateAsync(updater => { updater.ProjectAdded(hostProject1); updater.ProjectWorkspaceStateChanged(hostProject1.Key, projectWorkspaceState); - updater.DocumentAdded(hostProject1.Key, hostDocument, CreateTextLoader(hostDocument.FilePath, text: "")); + updater.DocumentAdded(hostProject1.Key, hostDocument, TestMocks.CreateTextLoader(hostDocument.FilePath, text: "")); updater.ProjectAdded(hostProject2); updater.ProjectWorkspaceStateChanged(hostProject2.Key, projectWorkspaceState); - updater.DocumentAdded(hostProject2.Key, hostDocument, CreateTextLoader(hostDocument.FilePath, text: "")); + updater.DocumentAdded(hostProject2.Key, hostDocument, TestMocks.CreateTextLoader(hostDocument.FilePath, text: "")); }); var service = new TestTagHelperToolTipFactory(projectManager); @@ -468,10 +469,10 @@ await projectManager.UpdateAsync(updater => { updater.ProjectAdded(hostProject1); updater.ProjectWorkspaceStateChanged(hostProject1.Key, projectWorkspaceState); - updater.DocumentAdded(hostProject1.Key, hostDocument, CreateTextLoader(hostDocument.FilePath, text: "")); + updater.DocumentAdded(hostProject1.Key, hostDocument, TestMocks.CreateTextLoader(hostDocument.FilePath, text: "")); updater.ProjectAdded(hostProject2); - updater.DocumentAdded(hostProject2.Key, hostDocument, CreateTextLoader(hostDocument.FilePath, text: "")); + updater.DocumentAdded(hostProject2.Key, hostDocument, TestMocks.CreateTextLoader(hostDocument.FilePath, text: "")); }); var service = new TestTagHelperToolTipFactory(projectManager); @@ -512,10 +513,10 @@ public async Task GetAvailableProjects_NotAvailableInAnyProject_ReturnsText() await projectManager.UpdateAsync(updater => { updater.ProjectAdded(hostProject1); - updater.DocumentAdded(hostProject1.Key, hostDocument, CreateTextLoader(hostDocument.FilePath, text: "")); + updater.DocumentAdded(hostProject1.Key, hostDocument, TestMocks.CreateTextLoader(hostDocument.FilePath, text: "")); updater.ProjectAdded(hostProject2); - updater.DocumentAdded(hostProject2.Key, hostDocument, CreateTextLoader(hostDocument.FilePath, text: "")); + updater.DocumentAdded(hostProject2.Key, hostDocument, TestMocks.CreateTextLoader(hostDocument.FilePath, text: "")); }); var service = new TestTagHelperToolTipFactory(projectManager); diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/DocumentContextFactoryTest.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/DocumentContextFactoryTest.cs index 3c549217fe2..31394f347d2 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/DocumentContextFactoryTest.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/DocumentContextFactoryTest.cs @@ -67,7 +67,7 @@ public async Task TryCreateForOpenDocumentAsync_CanNotResolveVersion_ReturnsNull await _projectManager.UpdateAsync(updater => { - updater.DocumentAdded(MiscFilesHostProject.Instance.Key, hostDocument, CreateTextLoader(filePath, "")); + updater.DocumentAdded(MiscFilesHostProject.Instance.Key, hostDocument, TestMocks.CreateTextLoader(filePath, "")); }); var factory = new DocumentContextFactory(_projectManager, _documentVersionCache, LoggerFactory); @@ -87,7 +87,7 @@ public async Task TryCreateAsync_ResolvesContent() await _projectManager.UpdateAsync(updater => { - updater.DocumentAdded(MiscFilesHostProject.Instance.Key, hostDocument, CreateTextLoader(filePath, "")); + updater.DocumentAdded(MiscFilesHostProject.Instance.Key, hostDocument, TestMocks.CreateTextLoader(filePath, "")); }); var miscFilesProject = _projectManager.GetMiscellaneousProject(); @@ -142,7 +142,7 @@ public async Task TryCreateForOpenDocumentAsync_ResolvesContent() await _projectManager.UpdateAsync(updater => { - updater.DocumentAdded(MiscFilesHostProject.Instance.Key, hostDocument, CreateTextLoader(filePath, "")); + updater.DocumentAdded(MiscFilesHostProject.Instance.Key, hostDocument, TestMocks.CreateTextLoader(filePath, "")); }); var miscFilesProject = _projectManager.GetMiscellaneousProject(); diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/LanguageServer/LanguageServerTestBase.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/LanguageServer/LanguageServerTestBase.cs index b8a4e215aad..e7e0f6e87e2 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/LanguageServer/LanguageServerTestBase.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/LanguageServer/LanguageServerTestBase.cs @@ -24,7 +24,6 @@ using Microsoft.CodeAnalysis.Text; using Microsoft.CommonLanguageServerProtocol.Framework; using Microsoft.VisualStudio.LanguageServer.Protocol; -using Moq; using Xunit.Abstractions; namespace Microsoft.AspNetCore.Razor.Test.Common.LanguageServer; @@ -131,23 +130,6 @@ private protected static VersionedDocumentContext CreateDocumentContext(Uri uri, return new VersionedDocumentContext(uri, snapshot, projectContext: null, version: 0); } - protected static TextLoader CreateTextLoader(string filePath, string text) - { - return CreateTextLoader(filePath, SourceText.From(text)); - } - - protected static TextLoader CreateTextLoader(string filePath, SourceText text) - { - var mock = new StrictMock(); - - var textAndVersion = TextAndVersion.Create(text, VersionStamp.Create(), filePath); - - mock.Setup(x => x.LoadTextAndVersionAsync(It.IsAny(), It.IsAny())) - .ReturnsAsync(textAndVersion); - - return mock.Object; - } - private protected static RazorLSPOptionsMonitor GetOptionsMonitor(bool enableFormatting = true, bool autoShowCompletion = true, bool autoListParams = true, bool formatOnType = true, bool autoInsertAttributeQuotes = true, bool colorBackground = false, bool codeBlockBraceOnNextLine = false, bool commitElementsWithSpace = true) { var configService = StrictMock.Of(); diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/TestMocks.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/TestMocks.cs new file mode 100644 index 00000000000..1e0a3dbd2e7 --- /dev/null +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/TestMocks.cs @@ -0,0 +1,29 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT license. See License.txt in the project root for license information. + +using System.Threading; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Text; +using Moq; + +namespace Microsoft.AspNetCore.Razor.Test.Common; + +internal static class TestMocks +{ + public static TextLoader CreateTextLoader(string filePath, string text) + { + return CreateTextLoader(filePath, SourceText.From(text)); + } + + public static TextLoader CreateTextLoader(string filePath, SourceText text) + { + var mock = new StrictMock(); + + var textAndVersion = TextAndVersion.Create(text, VersionStamp.Create(), filePath); + + mock.Setup(x => x.LoadTextAndVersionAsync(It.IsAny(), It.IsAny())) + .ReturnsAsync(textAndVersion); + + return mock.Object; + } +} diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/LanguageClient/ProjectSystem/RazorProjectInfoDriverTest.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/LanguageClient/ProjectSystem/RazorProjectInfoDriverTest.cs index 6ff9e9b0675..1cf6ee0b788 100644 --- a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/LanguageClient/ProjectSystem/RazorProjectInfoDriverTest.cs +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/LanguageClient/ProjectSystem/RazorProjectInfoDriverTest.cs @@ -8,6 +8,7 @@ using Microsoft.AspNetCore.Razor.Language; using Microsoft.AspNetCore.Razor.LanguageServer.ProjectSystem; using Microsoft.AspNetCore.Razor.ProjectSystem; +using Microsoft.AspNetCore.Razor.Test.Common; using Microsoft.AspNetCore.Razor.Test.Common.LanguageServer; using Microsoft.CodeAnalysis.Razor.ProjectSystem; using Xunit; @@ -41,10 +42,10 @@ public async Task ProcessesExistingProjectsDuringInitialization() await projectManager.UpdateAsync(static updater => { updater.ProjectAdded(s_hostProject1); - updater.DocumentAdded(s_hostProject1.Key, s_hostDocument1, CreateTextLoader(s_hostDocument1.FilePath, "

Hello World

")); + updater.DocumentAdded(s_hostProject1.Key, s_hostDocument1, TestMocks.CreateTextLoader(s_hostDocument1.FilePath, "

Hello World

")); updater.ProjectAdded(s_hostProject2); - updater.DocumentAdded(s_hostProject2.Key, s_hostDocument2, CreateTextLoader(s_hostDocument2.FilePath, "

Hello World

")); + updater.DocumentAdded(s_hostProject2.Key, s_hostDocument2, TestMocks.CreateTextLoader(s_hostDocument2.FilePath, "

Hello World

")); }); var (driver, testAccessor) = await CreateDriverAndInitializeAsync(projectManager); @@ -93,10 +94,10 @@ public async Task ProcessesProjectsAddedAfterInitialization() await projectManager.UpdateAsync(static updater => { updater.ProjectAdded(s_hostProject1); - updater.DocumentAdded(s_hostProject1.Key, s_hostDocument1, CreateTextLoader(s_hostDocument1.FilePath, "

Hello World

")); + updater.DocumentAdded(s_hostProject1.Key, s_hostDocument1, TestMocks.CreateTextLoader(s_hostDocument1.FilePath, "

Hello World

")); updater.ProjectAdded(s_hostProject2); - updater.DocumentAdded(s_hostProject2.Key, s_hostDocument2, CreateTextLoader(s_hostDocument2.FilePath, "

Hello World

")); + updater.DocumentAdded(s_hostProject2.Key, s_hostDocument2, TestMocks.CreateTextLoader(s_hostDocument2.FilePath, "

Hello World

")); }); await testAccessor.WaitUntilCurrentBatchCompletesAsync(); @@ -134,7 +135,7 @@ await projectManager.UpdateAsync(static updater => await projectManager.UpdateAsync(static updater => { - updater.DocumentAdded(s_hostProject1.Key, s_hostDocument1, CreateTextLoader(s_hostDocument1.FilePath, "

Hello World

")); + updater.DocumentAdded(s_hostProject1.Key, s_hostDocument1, TestMocks.CreateTextLoader(s_hostDocument1.FilePath, "

Hello World

")); }); await testAccessor.WaitUntilCurrentBatchCompletesAsync(); @@ -204,7 +205,7 @@ await projectManager.UpdateAsync(static updater => await projectManager.UpdateAsync(static updater => { - updater.DocumentAdded(s_hostProject1.Key, s_hostDocument1, CreateTextLoader(s_hostDocument1.FilePath, "

Hello World

")); + updater.DocumentAdded(s_hostProject1.Key, s_hostDocument1, TestMocks.CreateTextLoader(s_hostDocument1.FilePath, "

Hello World

")); }); await testAccessor.WaitUntilCurrentBatchCompletesAsync(); From d96c004800d2336f85371647369993e86f30fe8b Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Tue, 16 Jul 2024 15:27:39 -0700 Subject: [PATCH 117/176] Fix BackgroundDocumentGeneratorTest that was throwing exception The ProcessWorkAndRestart test was throwing an exception and swallowing it because a document was added to a project when the document's file path was outside of the project's. --- .../BackgroundDocumentGeneratorTest.cs | 32 ++++++++++++------- 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/DocumentGenerator/BackgroundDocumentGeneratorTest.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/DocumentGenerator/BackgroundDocumentGeneratorTest.cs index 45628cfe6af..67a071ed8a7 100644 --- a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/DocumentGenerator/BackgroundDocumentGeneratorTest.cs +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/DocumentGenerator/BackgroundDocumentGeneratorTest.cs @@ -14,14 +14,17 @@ using Microsoft.AspNetCore.Razor.ProjectSystem; using Microsoft.AspNetCore.Razor.Test.Common; using Microsoft.AspNetCore.Razor.Test.Common.VisualStudio; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Razor; using Microsoft.CodeAnalysis.Razor.Logging; +using Microsoft.CodeAnalysis.Razor.ProjectSystem; using Microsoft.CodeAnalysis.Text; using Microsoft.VisualStudio.Razor.DynamicFiles; using Moq; using Xunit; using Xunit.Abstractions; -namespace Microsoft.CodeAnalysis.Razor.ProjectSystem; +namespace Microsoft.VisualStudio.Razor.ProjectSystem; // These tests are really integration tests. There isn't a good way to unit test this functionality since // the only thing in here is threading. @@ -219,27 +222,32 @@ await projectManager.UpdateAsync(updater => [UIFact] public async Task ProcessWorkAndRestart() { + var hostProject1 = TestProjectData.SomeProject; + var hostProject2 = TestProjectData.AnotherProject; + var hostDocument1 = TestProjectData.SomeProjectFile1; + var hostDocument2 = TestProjectData.SomeProjectFile2; + // Arrange var projectManager = CreateProjectSnapshotManager(); await projectManager.UpdateAsync(updater => { - updater.ProjectAdded(s_hostProject1); - updater.ProjectAdded(s_hostProject2); - updater.DocumentAdded(s_hostProject1.Key, s_documents[0], null!); - updater.DocumentAdded(s_hostProject1.Key, s_documents[1], null!); + updater.ProjectAdded(hostProject1); + updater.ProjectAdded(hostProject2); + updater.DocumentAdded(hostProject1.Key, hostDocument1, null!); + updater.DocumentAdded(hostProject1.Key, hostDocument2, null!); }); - var project = projectManager.GetLoadedProject(s_hostProject1.Key); - var documentKey1 = new DocumentKey(project.Key, s_documents[0].FilePath); - var documentKey2 = new DocumentKey(project.Key, s_documents[1].FilePath); + var project = projectManager.GetLoadedProject(hostProject1.Key); + var documentKey1 = new DocumentKey(project.Key, hostDocument1.FilePath); + var documentKey2 = new DocumentKey(project.Key, hostDocument2.FilePath); using var generator = new TestBackgroundDocumentGenerator(projectManager, _dynamicFileInfoProvider, LoggerFactory); // Act & Assert // First, enqueue some work. - generator.Enqueue(project, project.GetDocument(s_documents[0].FilePath).AssumeNotNull()); + generator.Enqueue(project, project.GetDocument(hostDocument1.FilePath).AssumeNotNull()); // Wait for the work to complete. await generator.WaitUntilCurrentBatchCompletesAsync(); @@ -248,14 +256,14 @@ await projectManager.UpdateAsync(updater => Assert.Single(generator.CompletedWork, documentKey1); // Enqueue more work. - generator.Enqueue(project, project.GetDocument(s_documents[1].FilePath).AssumeNotNull()); + generator.Enqueue(project, project.GetDocument(hostDocument2.FilePath).AssumeNotNull()); // Wait for the work to complete. await generator.WaitUntilCurrentBatchCompletesAsync(); Assert.Collection(generator.CompletedWork.OrderBy(key => key.DocumentFilePath), - key => Assert.Equal(documentKey2, key), - key => Assert.Equal(documentKey1, key)); + key => Assert.Equal(documentKey1, key), + key => Assert.Equal(documentKey2, key)); } [UIFact] From 3138fb0be600b4b86a64cb21b9cd9deae8341162 Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Tue, 16 Jul 2024 15:38:43 -0700 Subject: [PATCH 118/176] Do not swallow test logging errors that occur outside of tests --- .../Logging/TestOutputLogger.cs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/Logging/TestOutputLogger.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/Logging/TestOutputLogger.cs index f0cc8891511..ac0cfbee1de 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/Logging/TestOutputLogger.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/Logging/TestOutputLogger.cs @@ -74,10 +74,6 @@ public void Log(LogLevel logLevel, string message, Exception? exception) { _provider.TestOutputHelper.WriteLine(finalMessage); } - catch (InvalidOperationException iex) when (iex.Message == "There is no currently active test.") - { - // Ignore, something is logging a message outside of a test. Other loggers will capture it. - } catch (Exception ex) { // If an exception is thrown while writing a message, throw an AggregateException that includes From 214d921112a0516a1d0a98a65dd0c1ecd32387df Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Tue, 16 Jul 2024 15:41:19 -0700 Subject: [PATCH 119/176] Ensure that we log exceptions during tests --- .../Logging/TestOutputLogger.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/Logging/TestOutputLogger.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/Logging/TestOutputLogger.cs index ac0cfbee1de..3db5c90b6f4 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/Logging/TestOutputLogger.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/Logging/TestOutputLogger.cs @@ -73,6 +73,11 @@ public void Log(LogLevel logLevel, string message, Exception? exception) try { _provider.TestOutputHelper.WriteLine(finalMessage); + + if (exception is not null) + { + _provider.TestOutputHelper.WriteLine(exception.ToString()); + } } catch (Exception ex) { From 59aa56d3962f7f4e29a249a3b3581ff3bb20a4c8 Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Tue, 16 Jul 2024 17:11:34 -0700 Subject: [PATCH 120/176] Don't read past end of span in NormalizeAndDedupeSlashes --- .../Utilities/FilePathNormalizer.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Utilities/FilePathNormalizer.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Utilities/FilePathNormalizer.cs index 54bd1ac5c91..2fa1426795d 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Utilities/FilePathNormalizer.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Utilities/FilePathNormalizer.cs @@ -253,7 +253,8 @@ private static void NormalizeAndDedupeSlashes(Span span, ref int charsWrit { writeSlot = '/'; - if (Unsafe.Add(ref readSlot, 1) is '/' or '\\') + // Be careful not to read past the end of the span. + if (read < charsWritten - 1 && Unsafe.Add(ref readSlot, 1) is '/' or '\\') { // We found two slashes in a row. If we are at the start of the path, // we we are at '\\network' paths, so want to leave them alone. Otherwise From 6d76c6d52f629cfc2151dcbcdaecb2639ded1d2e Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Tue, 16 Jul 2024 17:13:05 -0700 Subject: [PATCH 121/176] Add "/" as special case when normalizing directories --- .../Utilities/FilePathNormalizer.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Utilities/FilePathNormalizer.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Utilities/FilePathNormalizer.cs index 2fa1426795d..e632c7c5add 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Utilities/FilePathNormalizer.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Utilities/FilePathNormalizer.cs @@ -18,7 +18,7 @@ internal static class FilePathNormalizer public static string NormalizeDirectory(string? directoryFilePath) { - if (directoryFilePath.IsNullOrEmpty()) + if (directoryFilePath.IsNullOrEmpty() || directoryFilePath == "/") { return "/"; } @@ -76,7 +76,7 @@ public static string Normalize(string? filePath) ///
public static string GetNormalizedDirectoryName(string? filePath) { - if (filePath.IsNullOrEmpty()) + if (filePath.IsNullOrEmpty() || filePath == "/") { return "/"; } From b8f14d39bffd11f65b4fc140a69d5413b7c53d8d Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Mon, 15 Jul 2024 18:18:59 -0700 Subject: [PATCH 122/176] Fix issue with cancelling AsyncBatchingWorkQueue This was simply a mistake on my part. We should not assume that code is unreachable when it is reached because an OperationCanceledException is caught. --- .../Utilities/AsyncBatchingWorkQueue`2.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Utilities/AsyncBatchingWorkQueue`2.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Utilities/AsyncBatchingWorkQueue`2.cs index 2565ce36abc..23fb11979b7 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Utilities/AsyncBatchingWorkQueue`2.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Utilities/AsyncBatchingWorkQueue`2.cs @@ -271,9 +271,8 @@ void AddItemsToBatch(IEnumerable items) catch (OperationCanceledException) { // Silently continue to allow the next batch to be processed. + return default; } - - return Assumed.Unreachable(); } private (ImmutableArray items, CancellationToken batchCancellationToken) GetNextBatchAndResetQueue() From 0ded205cd40bfef9466e84a60066700cb199c3e1 Mon Sep 17 00:00:00 2001 From: Andrew Hall Date: Tue, 16 Jul 2024 18:06:54 -0700 Subject: [PATCH 123/176] Move StreamExtensions to netcore only (#10634) --- Directory.Build.targets | 2 +- ...ensions.cs => StreamExtensions.NetCore.cs} | 60 +------------------ ...sts.cs => StreamExtensionTests.NetCore.cs} | 2 - 3 files changed, 4 insertions(+), 60 deletions(-) rename src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Utilities/{StreamExtensions.cs => StreamExtensions.NetCore.cs} (65%) rename src/Razor/test/Microsoft.AspNetCore.Razor.ProjectEngineHost.Test/{StreamExtensionTests.cs => StreamExtensionTests.NetCore.cs} (98%) diff --git a/Directory.Build.targets b/Directory.Build.targets index 8fdc2c28558..a9f5c800796 100644 --- a/Directory.Build.targets +++ b/Directory.Build.targets @@ -54,7 +54,7 @@ If a C# file should only be compiled under NetCore, it can be named with a ".NetCore.cs" extension. Or, the file can be included in a folder called "NetCore" or has a name that ends in "_NetCore". --> - + diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Utilities/StreamExtensions.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Utilities/StreamExtensions.NetCore.cs similarity index 65% rename from src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Utilities/StreamExtensions.cs rename to src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Utilities/StreamExtensions.NetCore.cs index c792e4a25b8..81abc7a2a16 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Utilities/StreamExtensions.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Utilities/StreamExtensions.NetCore.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT license. See License.txt in the project root for license information. +using Microsoft.AspNetCore.Razor.ProjectSystem; using System; using System.Buffers; using System.Diagnostics; @@ -8,12 +9,6 @@ using System.Text; using System.Threading; using System.Threading.Tasks; -using Microsoft.AspNetCore.Razor.ProjectSystem; - -#if !NET -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -#endif namespace Microsoft.AspNetCore.Razor.Utilities; @@ -27,25 +22,10 @@ public static Task WriteStringAsync(this Stream stream, string text, Encoding? e var byteCount = encoding.GetMaxByteCount(text.Length); using var _ = ArrayPool.Shared.GetPooledArray(byteCount, out var byteArray); -#if NET var usedBytes = encoding.GetBytes(text, byteArray); -#else - var usedBytes = GetBytes(text, encoding, byteArray); -#endif WriteSize(stream, usedBytes); return stream.WriteAsync(byteArray, 0, usedBytes, cancellationToken); - -#if !NET - static unsafe int GetBytes(string text, Encoding encoding, byte[] byteArray) - { - fixed (char* c = text) - fixed (byte* b = byteArray) - { - return encoding.GetBytes(c, text.Length, b, byteArray.Length); - } - } -#endif } public static async Task ReadStringAsync(this Stream stream, Encoding? encoding, CancellationToken cancellationToken) @@ -57,7 +37,7 @@ public static async Task ReadStringAsync(this Stream stream, Encoding? e using var _ = ArrayPool.Shared.GetPooledArray(length, out var encodedBytes); - await ReadExactlyAsync(stream, encodedBytes, length, cancellationToken).ConfigureAwait(false); + await stream.ReadExactlyAsync(encodedBytes, 0, length, cancellationToken).ConfigureAwait(false); return encoding.GetString(encodedBytes, 0, length); } @@ -105,7 +85,7 @@ public static async Task WriteProjectInfoAsync(this Stream stream, RazorProjectI var sizeToRead = ReadSize(stream); using var _ = ArrayPool.Shared.GetPooledArray(sizeToRead, out var projectInfoBytes); - await ReadExactlyAsync(stream, projectInfoBytes, sizeToRead, cancellationToken).ConfigureAwait(false); + await stream.ReadExactlyAsync(projectInfoBytes, 0, sizeToRead, cancellationToken).ConfigureAwait(false); // The array may be larger than the bytes read so make sure to trim accordingly. var projectInfoMemory = projectInfoBytes.AsMemory(0, sizeToRead); @@ -115,49 +95,15 @@ public static async Task WriteProjectInfoAsync(this Stream stream, RazorProjectI public static void WriteSize(this Stream stream, int length) { -#if NET Span sizeBytes = stackalloc byte[4]; BitConverter.TryWriteBytes(sizeBytes, length); stream.Write(sizeBytes); -#else - using var _ = ArrayPool.Shared.GetPooledArray(4, out var sizeBytes); - // Pulled from https://github.com/dotnet/runtime/blob/4b9a1b2d956f4a10a28b8f5f3f725e76eb6fb826/src/libraries/System.Private.CoreLib/src/System/BitConverter.cs#L158C13-L158C87 - Unsafe.WriteUnaligned(ref MemoryMarshal.GetReference(sizeBytes.AsSpan()), length); - stream.Write(sizeBytes, 0, 4); -#endif - } public unsafe static int ReadSize(this Stream stream) { -#if NET Span bytes = stackalloc byte[4]; stream.Read(bytes); return BitConverter.ToInt32(bytes); -#else - using var _ = ArrayPool.Shared.GetPooledArray(4, out var bytes); - stream.Read(bytes, 0, 4); - return BitConverter.ToInt32(bytes, 0); -#endif - } - -#if NET - private static ValueTask ReadExactlyAsync(Stream stream, byte[] buffer, int length, CancellationToken cancellationToken) - => stream.ReadExactlyAsync(buffer, 0, length, cancellationToken); -#else - private static async ValueTask ReadExactlyAsync(Stream stream, byte[] buffer, int length, CancellationToken cancellationToken) - { - var bytesRead = 0; - while (bytesRead < length) - { - var read = await stream.ReadAsync(buffer, bytesRead, length - bytesRead, cancellationToken); - if (read == 0) - { - throw new EndOfStreamException(); - } - - bytesRead += read; - } } -#endif } diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.ProjectEngineHost.Test/StreamExtensionTests.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.ProjectEngineHost.Test/StreamExtensionTests.NetCore.cs similarity index 98% rename from src/Razor/test/Microsoft.AspNetCore.Razor.ProjectEngineHost.Test/StreamExtensionTests.cs rename to src/Razor/test/Microsoft.AspNetCore.Razor.ProjectEngineHost.Test/StreamExtensionTests.NetCore.cs index c0f0d50f200..8895137d798 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.ProjectEngineHost.Test/StreamExtensionTests.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.ProjectEngineHost.Test/StreamExtensionTests.NetCore.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; using System.Collections.Immutable; -using System.Drawing; using System.IO; using System.Linq; using System.Text; @@ -13,7 +12,6 @@ using Microsoft.AspNetCore.Razor.ProjectSystem; using Microsoft.AspNetCore.Razor.Serialization; using Microsoft.AspNetCore.Razor.Utilities; -using Microsoft.CodeAnalysis; using Xunit; namespace Microsoft.AspNetCore.Razor.ProjectEngineHost.Test; From 93440cc65c20847db0dd6bf53e0ee324b8c4153f Mon Sep 17 00:00:00 2001 From: dotnet bot Date: Tue, 16 Jul 2024 18:26:40 -0700 Subject: [PATCH 124/176] Localized file check-in by OneLocBuild Task: Build definition ID 262: Build ID 2496558 --- .../xlf/SyntaxVisualizerMenu.vsct.cs.xlf | 6 +++--- .../xlf/SyntaxVisualizerMenu.vsct.de.xlf | 6 +++--- .../xlf/SyntaxVisualizerMenu.vsct.es.xlf | 6 +++--- .../xlf/SyntaxVisualizerMenu.vsct.fr.xlf | 6 +++--- .../xlf/SyntaxVisualizerMenu.vsct.it.xlf | 6 +++--- .../xlf/SyntaxVisualizerMenu.vsct.ja.xlf | 6 +++--- .../xlf/SyntaxVisualizerMenu.vsct.ko.xlf | 6 +++--- .../xlf/SyntaxVisualizerMenu.vsct.pl.xlf | 6 +++--- .../xlf/SyntaxVisualizerMenu.vsct.pt-BR.xlf | 6 +++--- .../xlf/SyntaxVisualizerMenu.vsct.ru.xlf | 6 +++--- .../xlf/SyntaxVisualizerMenu.vsct.tr.xlf | 6 +++--- .../xlf/SyntaxVisualizerMenu.vsct.zh-Hans.xlf | 6 +++--- .../xlf/SyntaxVisualizerMenu.vsct.zh-Hant.xlf | 6 +++--- 13 files changed, 39 insertions(+), 39 deletions(-) diff --git a/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/SyntaxVisualizerMenu.vsct.cs.xlf b/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/SyntaxVisualizerMenu.vsct.cs.xlf index 29a6553cb02..3d2ab48842c 100644 --- a/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/SyntaxVisualizerMenu.vsct.cs.xlf +++ b/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/SyntaxVisualizerMenu.vsct.cs.xlf @@ -4,17 +4,17 @@ Show All Tag Helpers - Show All Tag Helpers + Zobrazit všechny pomocné elementy značek Show In Scope Tag Helpers - Show In Scope Tag Helpers + Zobrazit pomocné elementy značek v oboru Show Referenced Tag Helpers - Show Referenced Tag Helpers + Zobrazit odkazované pomocné elementy značek diff --git a/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/SyntaxVisualizerMenu.vsct.de.xlf b/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/SyntaxVisualizerMenu.vsct.de.xlf index ec6699b5552..bd6b9db7023 100644 --- a/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/SyntaxVisualizerMenu.vsct.de.xlf +++ b/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/SyntaxVisualizerMenu.vsct.de.xlf @@ -4,17 +4,17 @@ Show All Tag Helpers - Show All Tag Helpers + Alle Tag-Hilfsprogramme anzeigen Show In Scope Tag Helpers - Show In Scope Tag Helpers + Tag-Hilfsprogramme im Bereich anzeigen Show Referenced Tag Helpers - Show Referenced Tag Helpers + Referenzierte Tag-Hilfsprogramme anzeigen diff --git a/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/SyntaxVisualizerMenu.vsct.es.xlf b/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/SyntaxVisualizerMenu.vsct.es.xlf index 4913464cdef..e5e805992bf 100644 --- a/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/SyntaxVisualizerMenu.vsct.es.xlf +++ b/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/SyntaxVisualizerMenu.vsct.es.xlf @@ -4,17 +4,17 @@ Show All Tag Helpers - Show All Tag Helpers + Mostrar todos los asistentes de etiquetas Show In Scope Tag Helpers - Show In Scope Tag Helpers + Mostrar asistentes de etiquetas de ámbito Show Referenced Tag Helpers - Show Referenced Tag Helpers + Mostrar asistentes de etiquetas a los que se hace referencia diff --git a/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/SyntaxVisualizerMenu.vsct.fr.xlf b/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/SyntaxVisualizerMenu.vsct.fr.xlf index 0ac6d04f980..302cda4e10b 100644 --- a/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/SyntaxVisualizerMenu.vsct.fr.xlf +++ b/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/SyntaxVisualizerMenu.vsct.fr.xlf @@ -4,17 +4,17 @@ Show All Tag Helpers - Show All Tag Helpers + Afficher toutes les balises d’assistance Show In Scope Tag Helpers - Show In Scope Tag Helpers + Afficher les application d’assistance des balises dans l’étendue Show Referenced Tag Helpers - Show Referenced Tag Helpers + Afficher les application d’assistance de balise référencée diff --git a/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/SyntaxVisualizerMenu.vsct.it.xlf b/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/SyntaxVisualizerMenu.vsct.it.xlf index 7991519b447..f5229517266 100644 --- a/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/SyntaxVisualizerMenu.vsct.it.xlf +++ b/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/SyntaxVisualizerMenu.vsct.it.xlf @@ -4,17 +4,17 @@ Show All Tag Helpers - Show All Tag Helpers + Mostra tutti gli helper tag Show In Scope Tag Helpers - Show In Scope Tag Helpers + Mostra gli helper tag nell’ambito Show Referenced Tag Helpers - Show Referenced Tag Helpers + Mostra gli helper tag di riferimento diff --git a/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/SyntaxVisualizerMenu.vsct.ja.xlf b/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/SyntaxVisualizerMenu.vsct.ja.xlf index b34b800eb97..a6fe1c12caf 100644 --- a/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/SyntaxVisualizerMenu.vsct.ja.xlf +++ b/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/SyntaxVisualizerMenu.vsct.ja.xlf @@ -4,17 +4,17 @@ Show All Tag Helpers - Show All Tag Helpers + すべてのタグ ヘルパーの表示 Show In Scope Tag Helpers - Show In Scope Tag Helpers + スコープ内のタグ ヘルパーの表示 Show Referenced Tag Helpers - Show Referenced Tag Helpers + 参照タグ ヘルパーの表示 diff --git a/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/SyntaxVisualizerMenu.vsct.ko.xlf b/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/SyntaxVisualizerMenu.vsct.ko.xlf index 957dc166bb8..c59d78f6fc7 100644 --- a/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/SyntaxVisualizerMenu.vsct.ko.xlf +++ b/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/SyntaxVisualizerMenu.vsct.ko.xlf @@ -4,17 +4,17 @@ Show All Tag Helpers - Show All Tag Helpers + 모든 태그 도우미 표시 Show In Scope Tag Helpers - Show In Scope Tag Helpers + 범위 태그 도우미에서 표시 Show Referenced Tag Helpers - Show Referenced Tag Helpers + 참조된 태그 도우미 표시 diff --git a/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/SyntaxVisualizerMenu.vsct.pl.xlf b/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/SyntaxVisualizerMenu.vsct.pl.xlf index 220ce6f0e7f..6bce1739e6f 100644 --- a/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/SyntaxVisualizerMenu.vsct.pl.xlf +++ b/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/SyntaxVisualizerMenu.vsct.pl.xlf @@ -4,17 +4,17 @@ Show All Tag Helpers - Show All Tag Helpers + Pokaż wszystkich pomocników tagów Show In Scope Tag Helpers - Show In Scope Tag Helpers + Pokaż pomocników tagów objętych zakresem Show Referenced Tag Helpers - Show Referenced Tag Helpers + Pokaż pomocników tagów, których dotyczy odwołanie diff --git a/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/SyntaxVisualizerMenu.vsct.pt-BR.xlf b/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/SyntaxVisualizerMenu.vsct.pt-BR.xlf index d5c60d71dff..94644f378c3 100644 --- a/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/SyntaxVisualizerMenu.vsct.pt-BR.xlf +++ b/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/SyntaxVisualizerMenu.vsct.pt-BR.xlf @@ -4,17 +4,17 @@ Show All Tag Helpers - Show All Tag Helpers + Mostrar todos os auxiliares de marcas Show In Scope Tag Helpers - Show In Scope Tag Helpers + Mostrar auxiliares de marcas no escopo Show Referenced Tag Helpers - Show Referenced Tag Helpers + Mostrar auxiliares de marcas referenciados diff --git a/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/SyntaxVisualizerMenu.vsct.ru.xlf b/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/SyntaxVisualizerMenu.vsct.ru.xlf index f2ed58bba1b..1c65fc0abb8 100644 --- a/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/SyntaxVisualizerMenu.vsct.ru.xlf +++ b/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/SyntaxVisualizerMenu.vsct.ru.xlf @@ -4,17 +4,17 @@ Show All Tag Helpers - Show All Tag Helpers + Показать все тег-хелперы Show In Scope Tag Helpers - Show In Scope Tag Helpers + Показать тег-хелперы в области Show Referenced Tag Helpers - Show Referenced Tag Helpers + Показать указанные тег-хелперы diff --git a/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/SyntaxVisualizerMenu.vsct.tr.xlf b/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/SyntaxVisualizerMenu.vsct.tr.xlf index 220661012dc..e627082bc6c 100644 --- a/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/SyntaxVisualizerMenu.vsct.tr.xlf +++ b/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/SyntaxVisualizerMenu.vsct.tr.xlf @@ -4,17 +4,17 @@ Show All Tag Helpers - Show All Tag Helpers + Tüm Etiket Yardımcılarını Göster Show In Scope Tag Helpers - Show In Scope Tag Helpers + Kapsam Etiketi Yardımcılarında Göster Show Referenced Tag Helpers - Show Referenced Tag Helpers + Başvurulan Etiket Yardımcılarını Göster diff --git a/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/SyntaxVisualizerMenu.vsct.zh-Hans.xlf b/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/SyntaxVisualizerMenu.vsct.zh-Hans.xlf index 626942aeda5..241de9a0e51 100644 --- a/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/SyntaxVisualizerMenu.vsct.zh-Hans.xlf +++ b/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/SyntaxVisualizerMenu.vsct.zh-Hans.xlf @@ -4,17 +4,17 @@ Show All Tag Helpers - Show All Tag Helpers + 显示所有标记帮助程序 Show In Scope Tag Helpers - Show In Scope Tag Helpers + 显示作用域内标记帮助程序 Show Referenced Tag Helpers - Show Referenced Tag Helpers + 显示引用的标记帮助程序 diff --git a/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/SyntaxVisualizerMenu.vsct.zh-Hant.xlf b/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/SyntaxVisualizerMenu.vsct.zh-Hant.xlf index a59c8089762..fef0e18063a 100644 --- a/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/SyntaxVisualizerMenu.vsct.zh-Hant.xlf +++ b/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/SyntaxVisualizerMenu.vsct.zh-Hant.xlf @@ -4,17 +4,17 @@ Show All Tag Helpers - Show All Tag Helpers + 顯示所有標籤協助程式 Show In Scope Tag Helpers - Show In Scope Tag Helpers + 顯示涵蓋在範圍內的標籤協助程式 Show Referenced Tag Helpers - Show Referenced Tag Helpers + 顯示參照的標籤協助程式 From 096f1fbfc8d34324edac952d78e161bc762e3064 Mon Sep 17 00:00:00 2001 From: David Wengier Date: Wed, 17 Jul 2024 11:02:24 +1000 Subject: [PATCH 125/176] Create cohosting folding range tests --- .../Cohost/CohostFoldingRangeEndpoint.cs | 15 +- .../Workspaces/WorkspaceTestBase.cs | 18 +- .../Cohost/CohostFoldingRangeEndpointTest.cs | 236 ++++++++++++++++++ .../Cohost/TestHtmlDocumentSynchronizer.cs | 25 ++ .../LanguageClient/TestLSPRequestInvoker.cs | 12 + 5 files changed, 287 insertions(+), 19 deletions(-) create mode 100644 src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostFoldingRangeEndpointTest.cs create mode 100644 src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/TestHtmlDocumentSynchronizer.cs diff --git a/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/CohostFoldingRangeEndpoint.cs b/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/CohostFoldingRangeEndpoint.cs index 963b975ba39..41741514926 100644 --- a/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/CohostFoldingRangeEndpoint.cs +++ b/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/CohostFoldingRangeEndpoint.cs @@ -62,10 +62,11 @@ internal class CohostFoldingRangeEndpoint( protected override RazorTextDocumentIdentifier? GetRazorTextDocumentIdentifier(FoldingRangeParams request) => request.TextDocument.ToRazorTextDocumentIdentifier(); - protected override async Task HandleRequestAsync(FoldingRangeParams request, RazorCohostRequestContext context, CancellationToken cancellationToken) - { - var razorDocument = context.TextDocument.AssumeNotNull(); + protected override Task HandleRequestAsync(FoldingRangeParams request, RazorCohostRequestContext context, CancellationToken cancellationToken) + => HandleRequestAsync(context.TextDocument.AssumeNotNull(), cancellationToken); + private async Task HandleRequestAsync(TextDocument razorDocument, CancellationToken cancellationToken) + { _logger.LogDebug($"Getting folding ranges for {razorDocument.FilePath}"); // TODO: Should we have a separate method/service for getting C# ranges, so we can kick off both tasks in parallel? Or are we better off transition to OOP once? var htmlRangesResult = await GetHtmlFoldingRangesAsync(razorDocument, cancellationToken).ConfigureAwait(false); @@ -123,5 +124,13 @@ internal class CohostFoldingRangeEndpoint( return result.Response.SelectAsArray(RemoteFoldingRange.FromLspFoldingRange); } + + internal TestAccessor GetTestAccessor() => new(this); + + internal readonly struct TestAccessor(CohostFoldingRangeEndpoint instance) + { + public Task HandleRequestAsync(TextDocument razorDocument, CancellationToken cancellationToken) + => instance.HandleRequestAsync(razorDocument, cancellationToken); + } } diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/Workspaces/WorkspaceTestBase.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/Workspaces/WorkspaceTestBase.cs index 112533b804a..a30b8c69a59 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/Workspaces/WorkspaceTestBase.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/Workspaces/WorkspaceTestBase.cs @@ -1,13 +1,13 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT license. See License.txt in the project root for license information. -using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using Microsoft.AspNetCore.Razor.Language; using Microsoft.AspNetCore.Razor.ProjectEngineHost; using Microsoft.AspNetCore.Razor.Test.Common.ProjectSystem; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Host; +using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.Razor.Workspaces; using Xunit.Abstractions; @@ -63,14 +63,6 @@ private protected TestProjectSnapshotManager CreateProjectSnapshotManager() private protected TestProjectSnapshotManager CreateProjectSnapshotManager(IProjectEngineFactoryProvider projectEngineFactoryProvider) => new(projectEngineFactoryProvider, LoggerFactory, DisposalToken); - protected virtual void ConfigureWorkspaceServices(List services) - { - } - - protected virtual void ConfigureLanguageServices(List services) - { - } - protected virtual void ConfigureWorkspace(AdhocWorkspace workspace) { } @@ -96,13 +88,7 @@ private void EnsureInitialized() Configure = ConfigureProjectEngine, }; - var workspaceServices = new List(); - ConfigureWorkspaceServices(workspaceServices); - - var languageServices = new List(); - ConfigureLanguageServices(languageServices); - - _hostServices = TestServices.Create(workspaceServices, languageServices); + _hostServices = MefHostServices.DefaultHost; _workspace = TestWorkspace.Create(_hostServices, ConfigureWorkspace); AddDisposable(_workspace); _workspaceProvider = new TestWorkspaceProvider(_workspace); diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostFoldingRangeEndpointTest.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostFoldingRangeEndpointTest.cs new file mode 100644 index 00000000000..8b95d0e5bd3 --- /dev/null +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostFoldingRangeEndpointTest.cs @@ -0,0 +1,236 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT license. See License.txt in the project root for license information. + +using System; +using System.Collections.Immutable; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Razor; +using Microsoft.AspNetCore.Razor.Language; +using Microsoft.CodeAnalysis.Razor.Workspaces; +using Microsoft.CodeAnalysis.Testing; +using Microsoft.CodeAnalysis.Text; +using Microsoft.VisualStudio.LanguageServer.Protocol; +using Roslyn.Test.Utilities; +using Xunit; +using Xunit.Abstractions; + +namespace Microsoft.VisualStudio.Razor.LanguageClient.Cohost; + +public class CohostFoldingRangeEndpointTest(ITestOutputHelper testOutputHelper) : CohostTestBase(testOutputHelper) +{ + [Fact] + public Task IfStatements() + => VerifyFoldingRangesAsync(""" +
+ @if (true) {[| +
+ Hello World +
+ }|] +
+ + @if (true) {[| +
+ Hello World +
+ }|] + + @if (true) {[| + }|] + """); + + [Fact] + public Task LockStatement() + => VerifyFoldingRangesAsync(""" + @lock (new object()) {[| + }|] + """); + + [Fact] + public Task UsingStatement() + => VerifyFoldingRangesAsync(""" + @using (new object()) {[| + }|] + """); + + [Fact] + public Task IfElseStatements() + => VerifyFoldingRangesAsync(""" +
+ @if (true) {[| +
+ Hello World +
+ else {[| +
+ Goodbye World +
+ }|] + }|] +
+ """); + + [Fact] + public Task Usings() + => VerifyFoldingRangesAsync(""" + @using System[| + @using System.Text|] + +

hello!

+ + @using System.Buffers[| + @using System.Drawing + @using System.CodeDom|] + +

hello!

+ """); + + [Fact] + public Task CSharpStatement() + => VerifyFoldingRangesAsync(""" +

hello!

+ + @{[| + var helloWorld = ""; + }|] + + @(DateTime + .Now) + +

hello!

+ """); + + [Fact] + public Task CSharpStatement_Nested() + => VerifyFoldingRangesAsync(""" +

hello!

+ +
+ + @{[| + var helloWorld = ""; + }|] + +
+ + @(DateTime + .Now) + +

hello!

+ """); + + [Fact] + public Task CSharpStatement_NotSingleLine() + => VerifyFoldingRangesAsync(""" +

hello!

+ + @{ var helloWorld = ""; } + +

hello!

+ """); + + [Fact] + public Task CodeBlock() + => VerifyFoldingRangesAsync(""" +

hello!

+ + @code {[| + var helloWorld = ""; + }|] + +

hello!

+ """); + + [Fact] + public Task CodeBlock_Mvc() + => VerifyFoldingRangesAsync(""" +

hello!

+ + @functions {[| + var helloWorld = ""; + }|] + +

hello!

+ """, + fileKind: FileKinds.Legacy); + + [Fact] + public Task Section() + => VerifyFoldingRangesAsync(""" +

hello!

+ + @section Hello {[| +

Hello

+ }|] + +

hello!

+ """, + fileKind: FileKinds.Legacy); + + [Fact] + public Task Section_Invalid() + => VerifyFoldingRangesAsync(""" +

hello!

+ + @section { +

Hello

+ } + +

hello!

+ """, + fileKind: FileKinds.Legacy); + + [Fact] + public Task CSharpCodeInCodeBlocks() + => VerifyFoldingRangesAsync(""" +
+ Hello @_name +
+ + @code {[| + private string _name = "Dave"; + + public void M() {[| + }|] + }|] + """); + + private async Task VerifyFoldingRangesAsync(string input, string? fileKind = null) + { + TestFileMarkupParser.GetSpans(input, out var source, out ImmutableArray expected); + var document = CreateProjectAndRazorDocument(source, fileKind); + + var requestInvoker = new TestLSPRequestInvoker([(Methods.TextDocumentFoldingRangeName, Array.Empty())]); + + var endpoint = new CohostFoldingRangeEndpoint(RemoteServiceInvoker, TestHtmlDocumentSynchronizer.Instance, requestInvoker, LoggerFactory); + + var result = await endpoint.GetTestAccessor().HandleRequestAsync(document, DisposalToken); + + if (expected.Length == 0) + { + Assert.Null(result); + return; + } + + // Rather than comparing numbers and spans, its nicer to reconstruct the test input data and use string comparisons so we can + // more easily understand what went wrong. + + var inputText = SourceText.From(source); + var markerPositions = result + .SelectMany(r => + new[] { + (index: inputText.GetRequiredAbsoluteIndex(r.StartLine, r.StartCharacter.AssumeNotNull()), isStart: true), + (index: inputText.GetRequiredAbsoluteIndex(r.EndLine, r.EndCharacter.AssumeNotNull()), isStart: false) + }); + + var actual = new StringBuilder(source); + foreach (var marker in markerPositions.OrderByDescending(p => p.index)) + { + actual.Insert(marker.index, marker.isStart ? "[|" : "|]"); + } + + AssertEx.EqualOrDiff(input, actual.ToString()); + } +} diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/TestHtmlDocumentSynchronizer.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/TestHtmlDocumentSynchronizer.cs new file mode 100644 index 00000000000..5198fbc2035 --- /dev/null +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/TestHtmlDocumentSynchronizer.cs @@ -0,0 +1,25 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT license. See License.txt in the project root for license information. + +using System.Threading; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Razor.Test.Common.VisualStudio; +using Microsoft.CodeAnalysis; + +namespace Microsoft.VisualStudio.Razor.LanguageClient.Cohost; + +internal sealed class TestHtmlDocumentSynchronizer : IHtmlDocumentSynchronizer +{ + public static TestHtmlDocumentSynchronizer Instance = new(); + + public Task TryGetSynchronizedHtmlDocumentAsync(TextDocument razorDocument, CancellationToken cancellationToken) + { + var filePath = razorDocument.FilePath + ".g.html"; + return Task.FromResult(new HtmlDocumentResult(new System.Uri(filePath), VsMocks.CreateTextBuffer(core: false))); + } + + public Task TrySynchronizeAsync(TextDocument document, CancellationToken cancellationToken) + { + throw new System.NotImplementedException(); + } +} diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/LanguageClient/TestLSPRequestInvoker.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/LanguageClient/TestLSPRequestInvoker.cs index 27bb265f77d..3bbf1c56ee0 100644 --- a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/LanguageClient/TestLSPRequestInvoker.cs +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/LanguageClient/TestLSPRequestInvoker.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.Razor.Test.Common.LanguageServer; @@ -17,9 +18,15 @@ namespace Microsoft.VisualStudio.Razor.LanguageClient; internal class TestLSPRequestInvoker : LSPRequestInvoker { private readonly CSharpTestLspServer _csharpServer; + private readonly Dictionary _htmlResponses; public TestLSPRequestInvoker() { } + public TestLSPRequestInvoker(List<(string method, object response)> htmlResponses) + { + _htmlResponses = htmlResponses.ToDictionary(kvp => kvp.method, kvp => kvp.response); + } + public TestLSPRequestInvoker(CSharpTestLspServer csharpServer) { if (csharpServer is null) @@ -104,6 +111,11 @@ public async override Task> ReinvokeRequestOnServerAs return new ReinvocationResponse(languageClientName: RazorLSPConstants.RazorCSharpLanguageServerName, result); } + if (_htmlResponses.TryGetValue(method, out var response)) + { + return new ReinvocationResponse(languageClientName: "html", (TOut)response); + } + return default; } From d636a6f66e73c8cdc90186aee2a92ac8f467a6a6 Mon Sep 17 00:00:00 2001 From: David Wengier Date: Wed, 17 Jul 2024 11:30:42 +1000 Subject: [PATCH 126/176] Rename base class --- .../Cohost/{CohostTestBase.cs => CohostEndpointTestBase.cs} | 2 +- .../Cohost/CohostFoldingRangeEndpointTest.cs | 2 +- .../Cohost/CohostLinkedEditingRangeEndpointTest.cs | 2 +- .../Cohost/CohostSemanticTokensRangeEndpointTest.cs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) rename src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/{CohostTestBase.cs => CohostEndpointTestBase.cs} (97%) diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostTestBase.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostEndpointTestBase.cs similarity index 97% rename from src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostTestBase.cs rename to src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostEndpointTestBase.cs index 47cd7bd476a..3a6e17f38fc 100644 --- a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostTestBase.cs +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostEndpointTestBase.cs @@ -19,7 +19,7 @@ namespace Microsoft.VisualStudio.Razor.LanguageClient.Cohost; -public abstract class CohostTestBase(ITestOutputHelper testOutputHelper) : WorkspaceTestBase(testOutputHelper) +public abstract class CohostEndpointTestBase(ITestOutputHelper testOutputHelper) : WorkspaceTestBase(testOutputHelper) { private const string CSharpVirtualDocumentSuffix = ".g.cs"; private ExportProvider? _exportProvider; diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostFoldingRangeEndpointTest.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostFoldingRangeEndpointTest.cs index 8b95d0e5bd3..c6bad120876 100644 --- a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostFoldingRangeEndpointTest.cs +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostFoldingRangeEndpointTest.cs @@ -18,7 +18,7 @@ namespace Microsoft.VisualStudio.Razor.LanguageClient.Cohost; -public class CohostFoldingRangeEndpointTest(ITestOutputHelper testOutputHelper) : CohostTestBase(testOutputHelper) +public class CohostFoldingRangeEndpointTest(ITestOutputHelper testOutputHelper) : CohostEndpointTestBase(testOutputHelper) { [Fact] public Task IfStatements() diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostLinkedEditingRangeEndpointTest.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostLinkedEditingRangeEndpointTest.cs index 3b31488b882..2f100059fb8 100644 --- a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostLinkedEditingRangeEndpointTest.cs +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostLinkedEditingRangeEndpointTest.cs @@ -14,7 +14,7 @@ namespace Microsoft.VisualStudio.Razor.LanguageClient.Cohost; -public class CohostLinkedEditingRangeEndpointTest(ITestOutputHelper testOutputHelper) : CohostTestBase(testOutputHelper) +public class CohostLinkedEditingRangeEndpointTest(ITestOutputHelper testOutputHelper) : CohostEndpointTestBase(testOutputHelper) { [Theory] [InlineData("$$PageTitle", "PageTitle")] diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostSemanticTokensRangeEndpointTest.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostSemanticTokensRangeEndpointTest.cs index 760defdd871..8f688ce3712 100644 --- a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostSemanticTokensRangeEndpointTest.cs +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostSemanticTokensRangeEndpointTest.cs @@ -21,7 +21,7 @@ namespace Microsoft.VisualStudio.Razor.LanguageClient.Cohost; -public class CohostSemanticTokensRangeEndpointTest(ITestOutputHelper testOutputHelper) : CohostTestBase(testOutputHelper) +public class CohostSemanticTokensRangeEndpointTest(ITestOutputHelper testOutputHelper) : CohostEndpointTestBase(testOutputHelper) { [Theory] [CombinatorialData] From e2549ad1e65857cdf8342a0bde1cdc7ee0dc3f05 Mon Sep 17 00:00:00 2001 From: David Wengier Date: Wed, 17 Jul 2024 11:55:56 +1000 Subject: [PATCH 127/176] Add some html coverage --- .../Cohost/CohostFoldingRangeEndpointTest.cs | 75 ++++++++++++++++--- 1 file changed, 64 insertions(+), 11 deletions(-) diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostFoldingRangeEndpointTest.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostFoldingRangeEndpointTest.cs index c6bad120876..f63d412c10e 100644 --- a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostFoldingRangeEndpointTest.cs +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostFoldingRangeEndpointTest.cs @@ -1,13 +1,13 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT license. See License.txt in the project root for license information. -using System; using System.Collections.Immutable; using System.Linq; using System.Text; using System.Threading.Tasks; using Microsoft.AspNetCore.Razor; using Microsoft.AspNetCore.Razor.Language; +using Microsoft.AspNetCore.Razor.PooledObjects; using Microsoft.CodeAnalysis.Razor.Workspaces; using Microsoft.CodeAnalysis.Testing; using Microsoft.CodeAnalysis.Text; @@ -197,27 +197,66 @@ public void M() {[| }|] """); + [Fact] + public Task HtmlAndCSharp() + => VerifyFoldingRangesAsync(""" +
{|html: + Hello @_name + +
{|html: + Nests aren't just for birds! +
|} +
|} + + @code {[| + private string _name = "Dave"; + + public void M() {[| + }|] + }|] + """); + private async Task VerifyFoldingRangesAsync(string input, string? fileKind = null) { - TestFileMarkupParser.GetSpans(input, out var source, out ImmutableArray expected); + TestFileMarkupParser.GetSpans(input, out var source, out ImmutableDictionary> spans); var document = CreateProjectAndRazorDocument(source, fileKind); - - var requestInvoker = new TestLSPRequestInvoker([(Methods.TextDocumentFoldingRangeName, Array.Empty())]); + var inputText = await document.GetTextAsync(DisposalToken); + + var htmlSpans = spans.GetValueOrDefault("html").NullToEmpty(); + var htmlRanges = htmlSpans + .Select(span => + { + inputText.GetLineAndOffset(span.Start, out var startLine, out var startCharacter); + inputText.GetLineAndOffset(span.End, out var endLine, out var endCharacter); + return new FoldingRange() + { + StartLine = startLine, + StartCharacter = startCharacter, + EndLine = endLine, + EndCharacter = endCharacter + }; + }) + .ToArray(); + + var requestInvoker = new TestLSPRequestInvoker([(Methods.TextDocumentFoldingRangeName, htmlRanges)]); var endpoint = new CohostFoldingRangeEndpoint(RemoteServiceInvoker, TestHtmlDocumentSynchronizer.Instance, requestInvoker, LoggerFactory); var result = await endpoint.GetTestAccessor().HandleRequestAsync(document, DisposalToken); - if (expected.Length == 0) + if (spans.Count == 0) { Assert.Null(result); return; } - // Rather than comparing numbers and spans, its nicer to reconstruct the test input data and use string comparisons so we can - // more easily understand what went wrong. + var actual = GenerateTestInput(inputText, htmlSpans, result.AssumeNotNull()); - var inputText = SourceText.From(source); + AssertEx.EqualOrDiff(input, actual); + } + + private static string GenerateTestInput(SourceText inputText, ImmutableArray htmlSpans, FoldingRange[] result) + { var markerPositions = result .SelectMany(r => new[] { @@ -225,12 +264,26 @@ private async Task VerifyFoldingRangesAsync(string input, string? fileKind = nul (index: inputText.GetRequiredAbsoluteIndex(r.EndLine, r.EndCharacter.AssumeNotNull()), isStart: false) }); - var actual = new StringBuilder(source); + var actual = new StringBuilder(inputText.ToString()); foreach (var marker in markerPositions.OrderByDescending(p => p.index)) { - actual.Insert(marker.index, marker.isStart ? "[|" : "|]"); + actual.Insert(marker.index, GetMarker(marker.index, marker.isStart, htmlSpans)); + } + + static string GetMarker(int index, bool isStart, ImmutableArray htmlSpans) + { + if (isStart) + { + return htmlSpans.Any(r => r.Start == index) + ? "{|html:" + : "[|"; + } + + return htmlSpans.Any(r => r.End == index) + ? "|}" + : "|]"; } - AssertEx.EqualOrDiff(input, actual.ToString()); + return actual.ToString(); } } From 78859c75f201e39b0708cb49e2c1ed3dcaf5b732 Mon Sep 17 00:00:00 2001 From: David Wengier Date: Tue, 16 Jul 2024 14:59:01 +1000 Subject: [PATCH 128/176] Fix bad assumption in tests --- .../Cohost/HtmlDocumentSynchronizerTest.cs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/HtmlDocumentSynchronizerTest.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/HtmlDocumentSynchronizerTest.cs index e6683df3ac7..6e31aeef793 100644 --- a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/HtmlDocumentSynchronizerTest.cs +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/HtmlDocumentSynchronizerTest.cs @@ -40,10 +40,6 @@ public async Task TrySynchronize_NewDocument_Generates() Assert.True(await synchronizer.TrySynchronizeAsync(document, DisposalToken)); - var version = await RazorDocumentVersion.CreateAsync(document, DisposalToken); - - Assert.Equal(1, version.WorkspaceVersion); - Assert.Collection(publisher.Publishes, i => { From 2b28abc90695abe064bf8a1c7c86d1916ccc6150 Mon Sep 17 00:00:00 2001 From: David Wengier Date: Tue, 16 Jul 2024 14:59:07 +1000 Subject: [PATCH 129/176] Remove statics --- .../ProjectSystem/DocumentSnapshotFactory.cs | 2 +- .../ProjectSystem/ProjectSnapshotFactory.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/ProjectSystem/DocumentSnapshotFactory.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/ProjectSystem/DocumentSnapshotFactory.cs index 241458f1efc..d5c6adac062 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/ProjectSystem/DocumentSnapshotFactory.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/ProjectSystem/DocumentSnapshotFactory.cs @@ -11,7 +11,7 @@ namespace Microsoft.CodeAnalysis.Remote.Razor.ProjectSystem; [method: ImportingConstructor] internal class DocumentSnapshotFactory(Lazy projectSnapshotFactory) { - private static readonly ConditionalWeakTable _documentSnapshots = new(); + private readonly ConditionalWeakTable _documentSnapshots = new(); private readonly Lazy _projectSnapshotFactory = projectSnapshotFactory; diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/ProjectSystem/ProjectSnapshotFactory.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/ProjectSystem/ProjectSnapshotFactory.cs index f5b16a49e51..e57436af364 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/ProjectSystem/ProjectSnapshotFactory.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/ProjectSystem/ProjectSnapshotFactory.cs @@ -11,7 +11,7 @@ namespace Microsoft.CodeAnalysis.Remote.Razor.ProjectSystem; [method: ImportingConstructor] internal class ProjectSnapshotFactory(DocumentSnapshotFactory documentSnapshotFactory, ITelemetryReporter telemetryReporter) { - private static readonly ConditionalWeakTable _projectSnapshots = new(); + private readonly ConditionalWeakTable _projectSnapshots = new(); private readonly DocumentSnapshotFactory _documentSnapshotFactory = documentSnapshotFactory; private readonly ITelemetryReporter _telemetryReporter = telemetryReporter; From 98c64945f0af082f6ee99e95d3b4c155c6f8f9f4 Mon Sep 17 00:00:00 2001 From: David Wengier Date: Tue, 16 Jul 2024 14:59:33 +1000 Subject: [PATCH 130/176] Use the test solution store to actual map solution infos to solutions --- .../Cohost/TestBrokeredServiceInterceptor.cs | 23 +++++++++++++------ .../Cohost/TestRemoteServiceInvoker.cs | 6 +---- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/TestBrokeredServiceInterceptor.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/TestBrokeredServiceInterceptor.cs index 4c8e70ed2ea..c4a9b8d411e 100644 --- a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/TestBrokeredServiceInterceptor.cs +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/TestBrokeredServiceInterceptor.cs @@ -4,21 +4,20 @@ using System; using System.Threading; using System.Threading.Tasks; -using Microsoft.AspNetCore.Razor; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.ExternalAccess.Razor; +using Microsoft.CodeAnalysis.ExternalAccess.Razor.Testing; using Microsoft.CodeAnalysis.Remote.Razor; +using Xunit; namespace Microsoft.VisualStudio.Razor.LanguageClient.Cohost; internal sealed class TestBrokeredServiceInterceptor : IRazorBrokeredServiceInterceptor { - private Solution? _solution; + private readonly TestSolutionStore _solutionStore = new(); - public void UpdateSolution(Solution solution) - { - _solution = solution; - } + public Task GetSolutionInfoAsync(Solution solution, CancellationToken cancellationToken) + => _solutionStore.AddAsync(solution, cancellationToken); public ValueTask RunServiceAsync( Func implementation, @@ -29,5 +28,15 @@ public ValueTask RunServiceAsync( RazorPinnedSolutionInfoWrapper solutionInfo, Func> implementation, CancellationToken cancellationToken) - => implementation(_solution.AssumeNotNull()); + { + var solution = _solutionStore.Get(solutionInfo); + + Assert.NotNull(solution); + + return implementation(solution); + } + + public void Dispose() + { + } } diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/TestRemoteServiceInvoker.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/TestRemoteServiceInvoker.cs index 52f5af1e270..9e5c8651aac 100644 --- a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/TestRemoteServiceInvoker.cs +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/TestRemoteServiceInvoker.cs @@ -53,11 +53,7 @@ private async Task GetOrCreateServiceAsync() { var service = await GetOrCreateServiceAsync(); - // In an ideal world we'd be able to maintain a dictionary of solution checksums in TestServiceBroker, and use - // the RazorPinnedSolutionInfoWrapper properly, but we need Roslyn changes for that. For now, this works fine - // as we don't have any code that makes multiple parallel calls to TryInvokeAsync in the same test. - var solutionInfo = new RazorPinnedSolutionInfoWrapper(); - _serviceInterceptor.UpdateSolution(solution); + var solutionInfo = await _serviceInterceptor.GetSolutionInfoAsync(solution, cancellationToken); return await invocation(service, solutionInfo, cancellationToken); } From 19f2329629679877d0b0f9137b19ef2f936ba0d5 Mon Sep 17 00:00:00 2001 From: David Wengier Date: Tue, 16 Jul 2024 14:59:42 +1000 Subject: [PATCH 131/176] Respond to CLaSP changes --- .../RazorLanguageServerTest.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/RazorLanguageServerTest.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/RazorLanguageServerTest.cs index 70477b6bb44..9db1b0b0868 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/RazorLanguageServerTest.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/RazorLanguageServerTest.cs @@ -40,14 +40,14 @@ public async Task LocaleIsSetCorrectly() Locale = "de-DE" }; - await queue.ExecuteAsync(initializeParams, Methods.InitializeName, LanguageServerConstants.DefaultLanguageName, server.GetLspServices(), DisposalToken); + await queue.ExecuteAsync(initializeParams, Methods.InitializeName, server.GetLspServices(), DisposalToken); // We have to send one more request, because culture is set before any request starts, but the first initialize request has to // be started in order to set the culture. // The request isn't actually valid, so we wrap it in a try catch, but we don't care for this test try { - await queue.ExecuteAsync(new(), VSInternalMethods.DocumentPullDiagnosticName, LanguageServerConstants.DefaultLanguageName, server.GetLspServices(), DisposalToken); + await queue.ExecuteAsync(new(), VSInternalMethods.DocumentPullDiagnosticName, server.GetLspServices(), DisposalToken); } catch { } From 43f12e84252979d073ba17112b9cc978dc622889 Mon Sep 17 00:00:00 2001 From: David Wengier Date: Wed, 17 Jul 2024 07:26:24 +1000 Subject: [PATCH 132/176] Apply suggestions from code review --- .../ProjectSystem/DocumentSnapshotFactory.cs | 2 +- .../ProjectSystem/ProjectSnapshotFactory.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/ProjectSystem/DocumentSnapshotFactory.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/ProjectSystem/DocumentSnapshotFactory.cs index d5c6adac062..241458f1efc 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/ProjectSystem/DocumentSnapshotFactory.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/ProjectSystem/DocumentSnapshotFactory.cs @@ -11,7 +11,7 @@ namespace Microsoft.CodeAnalysis.Remote.Razor.ProjectSystem; [method: ImportingConstructor] internal class DocumentSnapshotFactory(Lazy projectSnapshotFactory) { - private readonly ConditionalWeakTable _documentSnapshots = new(); + private static readonly ConditionalWeakTable _documentSnapshots = new(); private readonly Lazy _projectSnapshotFactory = projectSnapshotFactory; diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/ProjectSystem/ProjectSnapshotFactory.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/ProjectSystem/ProjectSnapshotFactory.cs index e57436af364..f5b16a49e51 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/ProjectSystem/ProjectSnapshotFactory.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/ProjectSystem/ProjectSnapshotFactory.cs @@ -11,7 +11,7 @@ namespace Microsoft.CodeAnalysis.Remote.Razor.ProjectSystem; [method: ImportingConstructor] internal class ProjectSnapshotFactory(DocumentSnapshotFactory documentSnapshotFactory, ITelemetryReporter telemetryReporter) { - private readonly ConditionalWeakTable _projectSnapshots = new(); + private static readonly ConditionalWeakTable _projectSnapshots = new(); private readonly DocumentSnapshotFactory _documentSnapshotFactory = documentSnapshotFactory; private readonly ITelemetryReporter _telemetryReporter = telemetryReporter; From e1b7bc982a6f0ae171a09e3d8b93d93f7c95ce30 Mon Sep 17 00:00:00 2001 From: David Wengier Date: Wed, 17 Jul 2024 12:02:43 +1000 Subject: [PATCH 133/176] Bump Roslyn --- eng/Versions.props | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/eng/Versions.props b/eng/Versions.props index ab3d814a8d8..898101a3ff1 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -53,25 +53,25 @@ 9.0.0-beta.24352.2 1.0.0-beta.23475.1 1.0.0-beta.23475.1 - 4.11.0-3.24303.3 - 4.11.0-3.24303.3 - 4.11.0-3.24303.3 - 4.11.0-3.24303.3 - 4.11.0-3.24303.3 - 4.11.0-3.24303.3 - 4.11.0-3.24303.3 - 4.11.0-3.24303.3 - 4.11.0-3.24303.3 - 4.11.0-3.24303.3 - 4.11.0-3.24303.3 - 4.11.0-3.24303.3 - 4.11.0-3.24303.3 - 4.11.0-3.24303.3 - 4.11.0-3.24303.3 - 4.11.0-3.24303.3 - 4.11.0-3.24303.3 - 4.11.0-3.24303.3 - 4.11.0-3.24303.3 + 4.12.0-1.24366.3 + 4.12.0-1.24366.3 + 4.12.0-1.24366.3 + 4.12.0-1.24366.3 + 4.12.0-1.24366.3 + 4.12.0-1.24366.3 + 4.12.0-1.24366.3 + 4.12.0-1.24366.3 + 4.12.0-1.24366.3 + 4.12.0-1.24366.3 + 4.12.0-1.24366.3 + 4.12.0-1.24366.3 + 4.12.0-1.24366.3 + 4.12.0-1.24366.3 + 4.12.0-1.24366.3 + 4.12.0-1.24366.3 + 4.12.0-1.24366.3 + 4.12.0-1.24366.3 + 4.12.0-1.24366.3 - + https://github.com/dotnet/roslyn - ec443fac0dcc4e9ce2f83b9202f689dc2872b9f3 + 5866fabb8ffe6cbdb17e46902d6b96900ab5937b From 0884b799fb8c86e13354107c7db7dd8888274605 Mon Sep 17 00:00:00 2001 From: David Wengier Date: Wed, 17 Jul 2024 14:20:35 +1000 Subject: [PATCH 140/176] Fix test --- .../RazorLanguageServerTest.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/RazorLanguageServerTest.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/RazorLanguageServerTest.cs index 9db1b0b0868..3fc2585b22d 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/RazorLanguageServerTest.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/RazorLanguageServerTest.cs @@ -6,6 +6,7 @@ using System.IO; using System.Linq; using System.Reflection; +using System.Text.Json; using System.Threading.Tasks; using Microsoft.AspNetCore.Razor.LanguageServer.Extensions; using Microsoft.AspNetCore.Razor.LanguageServer.Hosting; @@ -34,11 +35,11 @@ public async Task LocaleIsSetCorrectly() server.Initialize(); var queue = server.GetTestAccessor().GetRequestExecutionQueue(); - var initializeParams = new InitializeParams + var initializeParams = JsonSerializer.SerializeToElement(new InitializeParams { Capabilities = new(), Locale = "de-DE" - }; + }); await queue.ExecuteAsync(initializeParams, Methods.InitializeName, server.GetLspServices(), DisposalToken); @@ -47,7 +48,7 @@ public async Task LocaleIsSetCorrectly() // The request isn't actually valid, so we wrap it in a try catch, but we don't care for this test try { - await queue.ExecuteAsync(new(), VSInternalMethods.DocumentPullDiagnosticName, server.GetLspServices(), DisposalToken); + await queue.ExecuteAsync(JsonSerializer.SerializeToElement(new object()), VSInternalMethods.DocumentPullDiagnosticName, server.GetLspServices(), DisposalToken); } catch { } From d184cae5e69caab19319ed94cf92b90620ad9387 Mon Sep 17 00:00:00 2001 From: David Wengier Date: Wed, 17 Jul 2024 14:50:38 +1000 Subject: [PATCH 141/176] Initial test commit but not working because I need to merge main --- .../Cohost/CohostSignatureHelpEndpoint.cs | 36 +++++- .../RazorLanguageServerTest.cs | 9 +- .../Cohost/CohostSignatureHelpEndpointTest.cs | 120 ++++++++++++++++++ 3 files changed, 158 insertions(+), 7 deletions(-) create mode 100644 src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostSignatureHelpEndpointTest.cs diff --git a/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/CohostSignatureHelpEndpoint.cs b/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/CohostSignatureHelpEndpoint.cs index 8c563089d8d..8d4a5a59e1a 100644 --- a/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/CohostSignatureHelpEndpoint.cs +++ b/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/CohostSignatureHelpEndpoint.cs @@ -2,10 +2,12 @@ // Licensed under the MIT license. See License.txt in the project root for license information. using System.Composition; +using System.Linq; using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.Razor; using Microsoft.AspNetCore.Razor.LanguageServer.Hosting; +using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.ExternalAccess.Razor.Cohost; using Microsoft.CodeAnalysis.Razor.Logging; using Microsoft.CodeAnalysis.Razor.Remote; @@ -67,7 +69,10 @@ internal class CohostSignatureHelpEndpoint( // NOTE: The use of SumType here is a little odd, but it allows us to return Roslyn LSP types from the Roslyn call, and VS LSP types from the Html // call. It works because both sets of types are attributed the right way, so the Json ends up looking the same and the client doesn't // care. Ideally eventually we will be able to move all of this to just Roslyn LSP types, but we might have to wait for Web Tools - protected async override Task?> HandleRequestAsync(SignatureHelpParams request, RazorCohostRequestContext context, CancellationToken cancellationToken) + protected override Task?> HandleRequestAsync(SignatureHelpParams request, RazorCohostRequestContext context, CancellationToken cancellationToken) + => HandleRequestAsync(request, context.TextDocument.AssumeNotNull(), cancellationToken); + + private async Task?> HandleRequestAsync(SignatureHelpParams request, TextDocument razorDocument, CancellationToken cancellationToken) { // Return nothing if "Parameter Information" option is disabled unless signature help is invoked explicitly via command as opposed to typing or content change if (request.Context is { TriggerKind: not SignatureHelpTriggerKind.Invoked } && @@ -76,8 +81,6 @@ internal class CohostSignatureHelpEndpoint( return null; } - var razorDocument = context.TextDocument.AssumeNotNull(); - var data = await _remoteServiceInvoker.TryInvokeAsync( razorDocument.Project.Solution, (service, solutionInfo, cancellationToken) => service.GetSignatureHelpAsync(solutionInfo, razorDocument.Id, new RLSP.Position(request.Position.Line, request.Position.Character), cancellationToken), @@ -109,4 +112,31 @@ internal class CohostSignatureHelpEndpoint( return result?.Response; } + + internal TestAccessor GetTestAccessor() => new(this); + + internal readonly struct TestAccessor(CohostSignatureHelpEndpoint instance) + { + internal async Task HandleRequestAndGetLabelsAsync(SignatureHelpParams request, TextDocument document, CancellationToken cancellationToken) + { + var result = await instance.HandleRequestAsync(request, document, cancellationToken); + + if (result is not { } signatureHelp) + { + return null; + } + + if (signatureHelp.TryGetFirst(out var sigHelp1)) + { + return sigHelp1.Signatures.Select(s => s.Label).ToArray(); + } + else if (signatureHelp.TryGetSecond(out var sigHelp2)) + { + return sigHelp2.Signatures.Select(s => s.Label).ToArray(); + } + + Assumed.Unreachable(); + return null; + } + } } diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/RazorLanguageServerTest.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/RazorLanguageServerTest.cs index 70477b6bb44..3fc2585b22d 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/RazorLanguageServerTest.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/RazorLanguageServerTest.cs @@ -6,6 +6,7 @@ using System.IO; using System.Linq; using System.Reflection; +using System.Text.Json; using System.Threading.Tasks; using Microsoft.AspNetCore.Razor.LanguageServer.Extensions; using Microsoft.AspNetCore.Razor.LanguageServer.Hosting; @@ -34,20 +35,20 @@ public async Task LocaleIsSetCorrectly() server.Initialize(); var queue = server.GetTestAccessor().GetRequestExecutionQueue(); - var initializeParams = new InitializeParams + var initializeParams = JsonSerializer.SerializeToElement(new InitializeParams { Capabilities = new(), Locale = "de-DE" - }; + }); - await queue.ExecuteAsync(initializeParams, Methods.InitializeName, LanguageServerConstants.DefaultLanguageName, server.GetLspServices(), DisposalToken); + await queue.ExecuteAsync(initializeParams, Methods.InitializeName, server.GetLspServices(), DisposalToken); // We have to send one more request, because culture is set before any request starts, but the first initialize request has to // be started in order to set the culture. // The request isn't actually valid, so we wrap it in a try catch, but we don't care for this test try { - await queue.ExecuteAsync(new(), VSInternalMethods.DocumentPullDiagnosticName, LanguageServerConstants.DefaultLanguageName, server.GetLspServices(), DisposalToken); + await queue.ExecuteAsync(JsonSerializer.SerializeToElement(new object()), VSInternalMethods.DocumentPullDiagnosticName, server.GetLspServices(), DisposalToken); } catch { } diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostSignatureHelpEndpointTest.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostSignatureHelpEndpointTest.cs new file mode 100644 index 00000000000..3ac6d1bae73 --- /dev/null +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostSignatureHelpEndpointTest.cs @@ -0,0 +1,120 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT license. See License.txt in the project root for license information. + +using System.Threading.Tasks; +using Microsoft.AspNetCore.Razor; +using Microsoft.CodeAnalysis.ExternalAccess.Razor; +using Microsoft.CodeAnalysis.Razor.Settings; +using Microsoft.CodeAnalysis.Razor.Workspaces; +using Microsoft.CodeAnalysis.Testing; +using Microsoft.VisualStudio.LanguageServer.Protocol; +using Microsoft.VisualStudio.LanguageServices.Razor.LanguageClient.Cohost; +using Microsoft.VisualStudio.Razor.Settings; +using Xunit; +using Xunit.Abstractions; + +namespace Microsoft.VisualStudio.Razor.LanguageClient.Cohost; + +public class CohostSignatureHelpEndpointTest(ITestOutputHelper testOutputHelper) : CohostTestBase(testOutputHelper) +{ + [Fact] + public async Task CSharpMethod() + { + var input = """ +
+ + @{ + string M1(int i) => throw new NotImplementedException(); + + void Act() + { + M1($$); + } + } + """; + + await VerifySignatureHelpAsync(input, "string M1(int i)"); + } + + [Fact] + public async Task AutoListParamsOff() + { + var input = """ +
+ + @{ + string M1(int i) => throw new NotImplementedException(); + + void Act() + { + M1($$); + } + } + """; + + await VerifySignatureHelpAsync(input, "", autoListParams: false); + } + + [Fact] + public async Task TriggerKind() + { + var input = """ +
+ + @{ + string M1(int i) => throw new NotImplementedException(); + + void Act() + { + M1($$); + } + } + """; + + await VerifySignatureHelpAsync(input, "", triggerKind: SignatureHelpTriggerKind.TriggerCharacter); + } + + private async Task VerifySignatureHelpAsync(string input, string expected, bool autoListParams = true, SignatureHelpTriggerKind? triggerKind = null) + { + TestFileMarkupParser.GetPosition(input, out input, out var cursorPosition); + var document = CreateProjectAndRazorDocument(input); + var sourceText = await document.GetTextAsync(DisposalToken); + sourceText.GetLineAndOffset(cursorPosition, out var lineIndex, out var characterIndex); + + var clientSettingsManager = new ClientSettingsManager([], null, null); + clientSettingsManager.Update(ClientCompletionSettings.Default with { AutoListParams = autoListParams }); + + var endpoint = new CohostSignatureHelpEndpoint(RemoteServiceInvoker, clientSettingsManager, htmlDocumentSynchronizer, requestInvoker, LoggerFactory); + + var signatureHelpContext = new SignatureHelpContext() + { + TriggerKind = triggerKind ?? SignatureHelpTriggerKind.Invoked + }; + + var request = new SignatureHelpParams() + { + TextDocument = new TextDocumentIdentifier() + { + Uri = document.CreateUri() + }, + Position = new Position() + { + Line = lineIndex, + Character = characterIndex + }, + Context = signatureHelpContext + }; + + var result = await endpoint.GetTestAccessor().HandleRequestAndGetLabelsAsync(request, document, DisposalToken); + + // Assert + if (expected.Length == 0) + { + Assert.Null(result); + return; + } + + var actual = Assert.Single(result.AssumeNotNull()); + Assert.Equal(expected, actual); + } +} From 5a0a0b0de7325abc3a48a849ade939df87407689 Mon Sep 17 00:00:00 2001 From: David Wengier Date: Wed, 17 Jul 2024 15:13:16 +1000 Subject: [PATCH 142/176] Updates after merge --- .../RazorBrokeredServiceBase.FactoryBase`1.cs | 4 +++- .../Cohost/CohostFoldingRangeEndpointTest.cs | 1 - .../Cohost/CohostSignatureHelpEndpointTest.cs | 14 ++++++++------ 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorBrokeredServiceBase.FactoryBase`1.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorBrokeredServiceBase.FactoryBase`1.cs index f3c1b31d6db..f9cd31f160e 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorBrokeredServiceBase.FactoryBase`1.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RazorBrokeredServiceBase.FactoryBase`1.cs @@ -62,7 +62,9 @@ public async Task CreateAsync( var pipe = stream.UsePipe(); - var descriptor = RazorServices.Descriptors.GetDescriptorForServiceFactory(typeof(TService)); + var descriptor = typeof(IRemoteJsonService).IsAssignableFrom(typeof(TService)) + ? RazorServices.JsonDescriptors.GetDescriptorForServiceFactory(typeof(TService)) + : RazorServices.Descriptors.GetDescriptorForServiceFactory(typeof(TService)); var serverConnection = descriptor.WithTraceSource(traceSource).ConstructRpcConnection(pipe); var args = new ServiceArgs(serviceBroker, exportProvider, targetLoggerFactory, serverConnection, brokeredServiceData?.Interceptor); diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostFoldingRangeEndpointTest.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostFoldingRangeEndpointTest.cs index f63d412c10e..2f8a9be3573 100644 --- a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostFoldingRangeEndpointTest.cs +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostFoldingRangeEndpointTest.cs @@ -7,7 +7,6 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Razor; using Microsoft.AspNetCore.Razor.Language; -using Microsoft.AspNetCore.Razor.PooledObjects; using Microsoft.CodeAnalysis.Razor.Workspaces; using Microsoft.CodeAnalysis.Testing; using Microsoft.CodeAnalysis.Text; diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostSignatureHelpEndpointTest.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostSignatureHelpEndpointTest.cs index 3ac6d1bae73..74d3f80299a 100644 --- a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostSignatureHelpEndpointTest.cs +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostSignatureHelpEndpointTest.cs @@ -15,7 +15,7 @@ namespace Microsoft.VisualStudio.Razor.LanguageClient.Cohost; -public class CohostSignatureHelpEndpointTest(ITestOutputHelper testOutputHelper) : CohostTestBase(testOutputHelper) +public class CohostSignatureHelpEndpointTest(ITestOutputHelper testOutputHelper) : CohostEndpointTestBase(testOutputHelper) { [Fact] public async Task CSharpMethod() @@ -37,7 +37,7 @@ void Act() } [Fact] - public async Task AutoListParamsOff() + public async Task AutoListParamsOff_Invoked_ReturnsResult() { var input = """
@@ -52,11 +52,11 @@ void Act() } """; - await VerifySignatureHelpAsync(input, "", autoListParams: false); + await VerifySignatureHelpAsync(input, "", autoListParams: false, triggerKind: SignatureHelpTriggerKind.Invoked); } [Fact] - public async Task TriggerKind() + public async Task AutoListParamsOff_NotInvoked_ReturnsNoResult() { var input = """
@@ -71,7 +71,7 @@ void Act() } """; - await VerifySignatureHelpAsync(input, "", triggerKind: SignatureHelpTriggerKind.TriggerCharacter); + await VerifySignatureHelpAsync(input, "", autoListParams: false, triggerKind: SignatureHelpTriggerKind.ContentChange); } private async Task VerifySignatureHelpAsync(string input, string expected, bool autoListParams = true, SignatureHelpTriggerKind? triggerKind = null) @@ -84,7 +84,9 @@ private async Task VerifySignatureHelpAsync(string input, string expected, bool var clientSettingsManager = new ClientSettingsManager([], null, null); clientSettingsManager.Update(ClientCompletionSettings.Default with { AutoListParams = autoListParams }); - var endpoint = new CohostSignatureHelpEndpoint(RemoteServiceInvoker, clientSettingsManager, htmlDocumentSynchronizer, requestInvoker, LoggerFactory); + var requestInvoker = new TestLSPRequestInvoker([(Methods.TextDocumentSignatureHelpName, null)]); + + var endpoint = new CohostSignatureHelpEndpoint(RemoteServiceInvoker, clientSettingsManager, TestHtmlDocumentSynchronizer.Instance, requestInvoker, LoggerFactory); var signatureHelpContext = new SignatureHelpContext() { From 0a42f3cfd9c966eedc5883bc44e71c09ddb46852 Mon Sep 17 00:00:00 2001 From: David Wengier Date: Wed, 17 Jul 2024 17:18:34 +1000 Subject: [PATCH 143/176] Fail in a more interesting way --- .../Workspaces/WorkspaceTestBase.cs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/Workspaces/WorkspaceTestBase.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/Workspaces/WorkspaceTestBase.cs index a30b8c69a59..f992616c8a1 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/Workspaces/WorkspaceTestBase.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/Workspaces/WorkspaceTestBase.cs @@ -88,7 +88,17 @@ private void EnsureInitialized() Configure = ConfigureProjectEngine, }; - _hostServices = MefHostServices.DefaultHost; + var assemblies = MefHostServices.DefaultAssemblies + // Uncomment to fail on JoinableTaskContext instead of a Lazy! + //.AddRange( + // Assembly.LoadFrom("Microsoft.CodeAnalysis.dll"), + // Assembly.LoadFrom("Microsoft.CodeAnalysis.CSharp.EditorFeatures.dll"), + // Assembly.LoadFrom("Microsoft.CodeAnalysis.EditorFeatures.dll"), + // Assembly.LoadFrom("Microsoft.CodeAnalysis.ExternalAccess.Razor.dll"), + // Assembly.LoadFrom("Microsoft.CodeAnalysis.LanguageServer.Protocol.dll")) + ; + + _hostServices = MefHostServices.Create(assemblies); _workspace = TestWorkspace.Create(_hostServices, ConfigureWorkspace); AddDisposable(_workspace); _workspaceProvider = new TestWorkspaceProvider(_workspace); From c0b9aa27c6ef613ae1a367ef1d26950e4f0cb626 Mon Sep 17 00:00:00 2001 From: Jan Jones Date: Wed, 17 Jul 2024 10:06:30 +0200 Subject: [PATCH 144/176] Handle `:get`/`:set` in `EditorRequired` checking (#10628) * Add utility for verifying razor diagnostics * Handle `:get`/`:set` in `EditorRequired` checking * Simplify code --- .../ComponentCodeGenerationTestBase.cs | 90 +++++++++++++++++++ .../Components/ComponentLoweringPass.cs | 9 +- .../DiagnosticExtensions.cs | 20 +++++ 3 files changed, 118 insertions(+), 1 deletion(-) create mode 100644 src/Shared/Microsoft.AspNetCore.Razor.Test.Common/DiagnosticExtensions.cs diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/IntegrationTests/ComponentCodeGenerationTestBase.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/IntegrationTests/ComponentCodeGenerationTestBase.cs index 364e9b87341..84f21cea83b 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/IntegrationTests/ComponentCodeGenerationTestBase.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/IntegrationTests/ComponentCodeGenerationTestBase.cs @@ -1198,6 +1198,96 @@ public class ComponentWithEditorRequiredParameters : ComponentBase Assert.Empty(generated.RazorDiagnostics); } + [IntegrationTestFact, WorkItem("https://github.com/dotnet/razor/issues/10553")] + public void Component_WithEditorRequiredParameter_ValueSpecifiedUsingBindGetSet() + { + AdditionalSyntaxTrees.Add(Parse(""" + using System; + using Microsoft.AspNetCore.Components; + + namespace Test; + + public class ComponentWithEditorRequiredParameters : ComponentBase + { + [Parameter] + [EditorRequired] + public string Property1 { get; set; } + } + """)); + + var generated = CompileToCSharp(""" + + + @code { + private string myField = "Some Value"; + private void OnFieldChanged(string value) { } + } + """); + + CompileToAssembly(generated); + Assert.Empty(generated.RazorDiagnostics); + } + + [IntegrationTestFact, WorkItem("https://github.com/dotnet/razor/issues/10553")] + public void Component_WithEditorRequiredParameter_ValueSpecifiedUsingBindGet() + { + AdditionalSyntaxTrees.Add(Parse(""" + using System; + using Microsoft.AspNetCore.Components; + + namespace Test; + + public class ComponentWithEditorRequiredParameters : ComponentBase + { + [Parameter] + [EditorRequired] + public string Property1 { get; set; } + } + """)); + + var generated = CompileToCSharp(""" + + + @code { + private string myField = "Some Value"; + } + """); + + CompileToAssembly(generated); + Assert.Empty(generated.RazorDiagnostics); + } + + [IntegrationTestFact, WorkItem("https://github.com/dotnet/razor/issues/10553")] + public void Component_WithEditorRequiredParameter_ValueSpecifiedUsingBindSet() + { + AdditionalSyntaxTrees.Add(Parse(""" + using System; + using Microsoft.AspNetCore.Components; + + namespace Test; + + public class ComponentWithEditorRequiredParameters : ComponentBase + { + [Parameter] + [EditorRequired] + public string Property1 { get; set; } + } + """)); + + var generated = CompileToCSharp(""" + + + @code { + private void OnFieldChanged(string value) { } + } + """); + + var compiled = CompileToAssembly(generated); + generated.RazorDiagnostics.Verify( + // x:\dir\subdir\Test\TestComponent.cshtml(1,61): error RZ10016: Attribute 'bind-Property1:set' was used but no attribute 'bind-Property1:get' was found. + Diagnostic("RZ10016").WithLocation(1, 61)); + } + [IntegrationTestFact] public void Component_WithEditorRequiredChildContent_NoValueSpecified() { diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/Components/ComponentLoweringPass.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/Components/ComponentLoweringPass.cs index e01340e82cf..8d809696490 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/Components/ComponentLoweringPass.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/Components/ComponentLoweringPass.cs @@ -203,10 +203,17 @@ static bool IsPresentAsAttribute(string attributeName, ComponentIntermediateNode const string bindPrefix = "@bind-"; if (child is TagHelperDirectiveAttributeIntermediateNode { OriginalAttributeName: { } originalAttributeName } && originalAttributeName.StartsWith(bindPrefix, StringComparison.Ordinal) && - originalAttributeName.AsSpan()[bindPrefix.Length..].Equals(attributeName.AsSpan(), StringComparison.Ordinal)) + originalAttributeName.AsSpan(start: bindPrefix.Length).Equals(attributeName.AsSpan(), StringComparison.Ordinal)) { return true; } + if (child is TagHelperDirectiveAttributeParameterIntermediateNode { OriginalAttributeName: { } originalName, AttributeNameWithoutParameter: { } nameWithoutParameter } && + originalName.StartsWith(bindPrefix, StringComparison.Ordinal) && + nameWithoutParameter.AsSpan(start: bindPrefix.Length - 1).Equals(attributeName.AsSpan(), StringComparison.Ordinal)) + { + // `@bind-Value:get` or `@bind-Value:set` is specified. + return true; + } } return false; diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Test.Common/DiagnosticExtensions.cs b/src/Shared/Microsoft.AspNetCore.Razor.Test.Common/DiagnosticExtensions.cs new file mode 100644 index 00000000000..54f800e718d --- /dev/null +++ b/src/Shared/Microsoft.AspNetCore.Razor.Test.Common/DiagnosticExtensions.cs @@ -0,0 +1,20 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Generic; +using System.Linq; +using Microsoft.AspNetCore.Razor.Language; +using Microsoft.CodeAnalysis.Test.Utilities; +using Microsoft.NET.Sdk.Razor.SourceGenerators; + +namespace Microsoft.CodeAnalysis; + +public static class RazorDiagnosticExtensions +{ + public static void Verify( + this IEnumerable diagnostics, + params DiagnosticDescription[] expected) + { + diagnostics.Select(d => d.AsDiagnostic()).Verify(expected); + } +} From 32fed2e24ee15f4b04c45c4b5b3bf3fd22a1e21b Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Wed, 17 Jul 2024 15:07:06 -0700 Subject: [PATCH 145/176] Add StringExtensions.CreateString(...) helper --- .../StringExtensions.cs | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/StringExtensions.cs b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/StringExtensions.cs index 9dde4e4b539..5741c8ea5d8 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/StringExtensions.cs +++ b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/StringExtensions.cs @@ -4,6 +4,7 @@ using System.Diagnostics.CodeAnalysis; #if !NET +using ArgHelper = Microsoft.AspNetCore.Razor.ArgHelper; using ThrowHelper = Microsoft.AspNetCore.Razor.Utilities.ThrowHelper; #endif @@ -552,6 +553,31 @@ public static bool EndsWith(this string text, char value) return text.EndsWith(value); #else return text.Length > 0 && text[^1] == value; +#endif + } + + public delegate void SpanAction(Span span, TArg arg); + + public unsafe static string CreateString(int length, TState state, SpanAction action) + { +#if NET + return string.Create(length, (action, state), (span, state) => state.action(span, state.state)); +#else + ArgHelper.ThrowIfNegative(length); + + if (length == 0) + { + return string.Empty; + } + + var result = new string('\0', length); + + fixed (char* ptr = result) + { + action(new Span(ptr, length), state); + } + + return result; #endif } } From 6f3fcc1a801b6b2d55eb6ad5e8662be8651effb8 Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Wed, 17 Jul 2024 15:17:22 -0700 Subject: [PATCH 146/176] Use CreateString helper in CodeWriter --- .../src/Language/CodeGeneration/CodeWriter.cs | 49 +++++-------------- ...crosoft.CodeAnalysis.Razor.Compiler.csproj | 3 +- 2 files changed, 14 insertions(+), 38 deletions(-) diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/CodeWriter.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/CodeWriter.cs index b0d4dcae50a..e9f11be5f1c 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/CodeWriter.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/CodeWriter.cs @@ -8,6 +8,7 @@ using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; using Microsoft.AspNetCore.Razor.PooledObjects; +using static System.StringExtensions; namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration; @@ -259,7 +260,7 @@ public CodeWriter Write([InterpolatedStringHandlerArgument("")] ref WriteInterpo => this; [MethodImpl(MethodImplOptions.AggressiveInlining)] - private unsafe CodeWriter WriteCore(ReadOnlyMemory value, bool allowIndent = true) + private CodeWriter WriteCore(ReadOnlyMemory value, bool allowIndent = true) { if (value.IsEmpty) { @@ -336,50 +337,26 @@ public CodeWriter WriteLine([InterpolatedStringHandlerArgument("")] ref WriteInt public string GenerateCode() { - unsafe + return CreateString(Length, _pages, static (span, pages) => { - // This might look a bit scary, but it's pretty simple. We allocate our string - // with the correct length up front and then use simple pointer math to copy - // the pages of ReadOnlyMemory directly into it. - - // Eventually, we need to remove this and not return a giant string, which can - // easily be allocated on the LOH. The work to remove this is tracked by - // https://github.com/dotnet/razor/issues/8076. - - var length = Length; - var result = new string('\0', length); - - fixed (char* stringPtr = result) + foreach (var page in pages) { - var destination = stringPtr; - - // destinationSize and sourceSize track the number of bytes (not chars). - var destinationSize = length * sizeof(char); - - foreach (var page in _pages) + foreach (var chars in page) { - foreach (var chars in page) + if (chars.IsEmpty) { - var source = chars.Span; - var sourceSize = source.Length * sizeof(char); - - fixed (char* srcPtr = source) - { - Buffer.MemoryCopy(srcPtr, destination, destinationSize, sourceSize); - } + return; + } - destination += source.Length; - destinationSize -= sourceSize; + chars.Span.CopyTo(span); + span = span[chars.Length..]; - Debug.Assert(destinationSize >= 0); - } + Debug.Assert(span.Length >= 0); } - - Debug.Assert(destinationSize == 0, "We didn't exhaust our destination pointer!"); } - return result; - } + Debug.Assert(span.Length == 0, "We didn't fill the whole span!"); + }); } public void Dispose() diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Microsoft.CodeAnalysis.Razor.Compiler.csproj b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Microsoft.CodeAnalysis.Razor.Compiler.csproj index c98fe2ddf61..deca9b6930d 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Microsoft.CodeAnalysis.Razor.Compiler.csproj +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Microsoft.CodeAnalysis.Razor.Compiler.csproj @@ -1,10 +1,9 @@ - + Razor is a markup syntax for adding server-side logic to web pages. This package contains the Razor compiler. $(DefaultNetCoreTargetFramework);netstandard2.0 false - true - + https://github.com/dotnet/roslyn - 5866fabb8ffe6cbdb17e46902d6b96900ab5937b + 30edd04fd41dec9e8f9f48e698ebd5b80d9f7677 diff --git a/eng/Versions.props b/eng/Versions.props index 898101a3ff1..6aa6e7cad14 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -53,25 +53,25 @@ 9.0.0-beta.24352.2 1.0.0-beta.23475.1 1.0.0-beta.23475.1 - 4.12.0-1.24366.3 - 4.12.0-1.24366.3 - 4.12.0-1.24366.3 - 4.12.0-1.24366.3 - 4.12.0-1.24366.3 - 4.12.0-1.24366.3 - 4.12.0-1.24366.3 - 4.12.0-1.24366.3 - 4.12.0-1.24366.3 - 4.12.0-1.24366.3 - 4.12.0-1.24366.3 - 4.12.0-1.24366.3 - 4.12.0-1.24366.3 - 4.12.0-1.24366.3 - 4.12.0-1.24366.3 - 4.12.0-1.24366.3 - 4.12.0-1.24366.3 - 4.12.0-1.24366.3 - 4.12.0-1.24366.3 + 4.12.0-1.24366.6 + 4.12.0-1.24366.6 + 4.12.0-1.24366.6 + 4.12.0-1.24366.6 + 4.12.0-1.24366.6 + 4.12.0-1.24366.6 + 4.12.0-1.24366.6 + 4.12.0-1.24366.6 + 4.12.0-1.24366.6 + 4.12.0-1.24366.6 + 4.12.0-1.24366.6 + 4.12.0-1.24366.6 + 4.12.0-1.24366.6 + 4.12.0-1.24366.6 + 4.12.0-1.24366.6 + 4.12.0-1.24366.6 + 4.12.0-1.24366.6 + 4.12.0-1.24366.6 + 4.12.0-1.24366.6 - + diff --git a/BuildAnalyzers.sln b/eng/BuildAnalyzers.sln similarity index 87% rename from BuildAnalyzers.sln rename to eng/BuildAnalyzers.sln index 4661086786d..3d7b70b797e 100644 --- a/BuildAnalyzers.sln +++ b/eng/BuildAnalyzers.sln @@ -3,7 +3,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.8.34117.57 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Razor.Diagnostics.Analyzers", "src\Analyzers\Razor.Diagnostics.Analyzers\Razor.Diagnostics.Analyzers.csproj", "{42438A8F-6284-443A-A518-9AAD5371A403}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Razor.Diagnostics.Analyzers", "..\src\Analyzers\Razor.Diagnostics.Analyzers\Razor.Diagnostics.Analyzers.csproj", "{42438A8F-6284-443A-A518-9AAD5371A403}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution From 4af4e6f7f03f8f1cc471f42b867a98e0a5dab947 Mon Sep 17 00:00:00 2001 From: Jan Jones Date: Fri, 19 Jul 2024 11:13:50 +0200 Subject: [PATCH 174/176] Fix attribute parsing recovery (#10620) * Add tests * Fix attribute parsing recovery * Update new baselines * Fix expected missing source mapping * Update pre-existing baselines * Simplify code --- .../Legacy/TagHelperParseTreeRewriterTest.cs | 4 +- .../RazorCommentInOpeningTagBlock.stree.txt | 17 +- ...enSwapCharacterEncounteredMidTag.stree.txt | 3 +- ...s_DirectiveAttribute_SelfClosing.stree.txt | 3 +- ...ructures_DirectiveAttribute_Void.stree.txt | 3 +- ...formedTagHelpersWithAttributes13.stree.txt | 15 +- ...formedTagHelpersWithAttributes14.stree.txt | 3 +- ...TreeRewriter_AllowsInvalidHtml10.stree.txt | 3 +- .../CodeGenerationIntegrationTest.cs | 16 + .../test/Legacy/HtmlAttributeTest.cs | 73 +++ .../Legacy/TagHelperParseTreeRewriterTest.cs | 4 +- .../ConditionalAttributes.cshtml | 3 +- .../ConditionalAttributes2.cshtml | 22 + ...nditionalAttributes2_DesignTime.codegen.cs | 406 +++++++++++++++++ ...itionalAttributes2_DesignTime.codegen.html | 22 + ...onalAttributes2_DesignTime.diagnostics.txt | 1 + ...alAttributes2_DesignTime.html.mappings.txt | 222 ++++++++++ .../ConditionalAttributes2_DesignTime.ir.txt | 252 +++++++++++ ...itionalAttributes2_DesignTime.mappings.txt | 272 ++++++++++++ .../ConditionalAttributes2_Runtime.codegen.cs | 414 ++++++++++++++++++ ...itionalAttributes2_Runtime.diagnostics.txt | 1 + .../ConditionalAttributes2_Runtime.ir.txt | 229 ++++++++++ ...onditionalAttributes_DesignTime.codegen.cs | 15 + ...ditionalAttributes_DesignTime.codegen.html | 3 +- ...nalAttributes_DesignTime.html.mappings.txt | 17 + .../ConditionalAttributes_DesignTime.ir.txt | 14 +- ...ditionalAttributes_DesignTime.mappings.txt | 16 +- .../ConditionalAttributes_Runtime.codegen.cs | 18 +- .../ConditionalAttributes_Runtime.ir.txt | 15 +- .../RazorComments_DesignTime.ir.txt | 3 +- .../RazorComments_Runtime.ir.txt | 3 +- .../EscapedIdentifiers_08.cspans.txt | 3 +- .../EscapedIdentifiers_08.stree.txt | 8 +- .../RazorCommentInOpeningTagBlock.stree.txt | 17 +- ...nditionalAttribute_CommentAfter.cspans.txt | 12 + ...onditionalAttribute_CommentAfter.stree.txt | 41 ++ ...ditionalAttribute_CommentBefore.cspans.txt | 11 + ...nditionalAttribute_CommentBefore.stree.txt | 41 ++ ...alAttribute_DynamicContentAfter.cspans.txt | 9 + ...nalAttribute_DynamicContentAfter.stree.txt | 44 ++ ...lAttribute_DynamicContentBefore.cspans.txt | 8 + ...alAttribute_DynamicContentBefore.stree.txt | 44 ++ ...tribute_DynamicContentBefore_02.cspans.txt | 10 + ...ttribute_DynamicContentBefore_02.stree.txt | 52 +++ ...tribute_DynamicContentBefore_03.cspans.txt | 13 + ...ttribute_DynamicContentBefore_03.stree.txt | 66 +++ ...tribute_DynamicContentBefore_04.cspans.txt | 8 + ...ttribute_DynamicContentBefore_04.stree.txt | 41 ++ ...lAttribute_InvalidContentBefore.cspans.txt | 4 + ...alAttribute_InvalidContentBefore.stree.txt | 30 ++ .../EscapedAttributeName_Eof.cspans.txt | 3 + .../EscapedAttributeName_Eof.stree.txt | 15 + ...scapedAttributeName_InvalidName.cspans.txt | 4 + ...EscapedAttributeName_InvalidName.stree.txt | 22 + .../EscapedAttributeName_Minimized.cspans.txt | 4 + .../EscapedAttributeName_Minimized.stree.txt | 20 + .../EscapedAttributeName_WithValue.cspans.txt | 6 + .../EscapedAttributeName_WithValue.stree.txt | 29 ++ ...enSwapCharacterEncounteredMidTag.stree.txt | 3 +- ...s_DirectiveAttribute_SelfClosing.stree.txt | 3 +- ...ructures_DirectiveAttribute_Void.stree.txt | 3 +- ...formedTagHelpersWithAttributes13.stree.txt | 15 +- ...formedTagHelpersWithAttributes14.stree.txt | 3 +- ...TreeRewriter_AllowsInvalidHtml10.stree.txt | 3 +- .../src/Language/Legacy/HtmlMarkupParser.cs | 85 +++- .../RazorSourceGeneratorCshtmlTests.cs | 48 ++ .../RazorSourceGeneratorTestsBase.cs | 3 +- .../ConditionalAttributes/Pages_Index.html | 17 + .../IntegrationTests/IntegrationTestBase.cs | 26 +- 69 files changed, 2795 insertions(+), 71 deletions(-) create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2_DesignTime.codegen.cs create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2_DesignTime.codegen.html create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2_DesignTime.diagnostics.txt create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2_DesignTime.html.mappings.txt create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2_DesignTime.ir.txt create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2_DesignTime.mappings.txt create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2_Runtime.codegen.cs create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2_Runtime.diagnostics.txt create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2_Runtime.ir.txt create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/ConditionalAttribute_CommentAfter.cspans.txt create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/ConditionalAttribute_CommentAfter.stree.txt create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/ConditionalAttribute_CommentBefore.cspans.txt create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/ConditionalAttribute_CommentBefore.stree.txt create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/ConditionalAttribute_DynamicContentAfter.cspans.txt create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/ConditionalAttribute_DynamicContentAfter.stree.txt create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/ConditionalAttribute_DynamicContentBefore.cspans.txt create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/ConditionalAttribute_DynamicContentBefore.stree.txt create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/ConditionalAttribute_DynamicContentBefore_02.cspans.txt create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/ConditionalAttribute_DynamicContentBefore_02.stree.txt create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/ConditionalAttribute_DynamicContentBefore_03.cspans.txt create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/ConditionalAttribute_DynamicContentBefore_03.stree.txt create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/ConditionalAttribute_DynamicContentBefore_04.cspans.txt create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/ConditionalAttribute_DynamicContentBefore_04.stree.txt create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/ConditionalAttribute_InvalidContentBefore.cspans.txt create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/ConditionalAttribute_InvalidContentBefore.stree.txt create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/EscapedAttributeName_Eof.cspans.txt create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/EscapedAttributeName_Eof.stree.txt create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/EscapedAttributeName_InvalidName.cspans.txt create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/EscapedAttributeName_InvalidName.stree.txt create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/EscapedAttributeName_Minimized.cspans.txt create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/EscapedAttributeName_Minimized.stree.txt create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/EscapedAttributeName_WithValue.cspans.txt create mode 100644 src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/EscapedAttributeName_WithValue.stree.txt create mode 100644 src/Compiler/test/Microsoft.NET.Sdk.Razor.SourceGenerators.Tests/TestFiles/RazorSourceGeneratorCshtmlTests/ConditionalAttributes/Pages_Index.html diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/legacyTest/Legacy/TagHelperParseTreeRewriterTest.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/legacyTest/Legacy/TagHelperParseTreeRewriterTest.cs index 1fedb472c67..bb63bdf4da3 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/legacyTest/Legacy/TagHelperParseTreeRewriterTest.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/legacyTest/Legacy/TagHelperParseTreeRewriterTest.cs @@ -29,11 +29,11 @@ public static TheoryData GetAttributeNameValuePairsData return new TheoryData>> { { "", empty }, - { "", empty }, + { "", new[] { kvp("href", "~/home") } }, { "", new[] { kvp("href", csharp) } }, { "", new[] { kvp("href", $"prefix{csharp} suffix") } }, { "", new[] { kvp("href", "~/home") } }, - { "", new[] { kvp("href", "~/home") } }, + { "", new[] { kvp("href", "~/home"), kvp("nothing", "something") } }, { "", new[] { kvp("href", $"{csharp}::0"), kvp("class", "btn btn-success"), kvp("random", "") } diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/legacyTest/TestFiles/ParserTests/CSharpRazorCommentsTest/RazorCommentInOpeningTagBlock.stree.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/legacyTest/TestFiles/ParserTests/CSharpRazorCommentsTest/RazorCommentInOpeningTagBlock.stree.txt index bb67bbf202d..361dda76243 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/legacyTest/TestFiles/ParserTests/CSharpRazorCommentsTest/RazorCommentInOpeningTagBlock.stree.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/legacyTest/TestFiles/ParserTests/CSharpRazorCommentsTest/RazorCommentInOpeningTagBlock.stree.txt @@ -4,15 +4,14 @@ MarkupStartTag - [0..26)::26 - [] - Gen - SpanEditHandler;Accepts:Any OpenAngle;[<]; Text;[text]; - MarkupMiscAttributeContent - [5..25)::20 - MarkupTextLiteral - [5..6)::1 - [ ] - Gen - SpanEditHandler;Accepts:Any - Whitespace;[ ]; - RazorComment - [6..25)::19 - RazorCommentTransition;[@]; - RazorCommentStar;[*]; - RazorCommentLiteral;[ razor comment ]; - RazorCommentStar;[*]; - RazorCommentTransition;[@]; + MarkupTextLiteral - [5..6)::1 - [ ] - Gen - SpanEditHandler;Accepts:Any + Whitespace;[ ]; + RazorComment - [6..25)::19 + RazorCommentTransition;[@]; + RazorCommentStar;[*]; + RazorCommentLiteral;[ razor comment ]; + RazorCommentStar;[*]; + RazorCommentTransition;[@]; CloseAngle;[>]; MarkupEndTag - [26..33)::7 - [] - Gen - SpanEditHandler;Accepts:Any OpenAngle;[<]; diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/legacyTest/TestFiles/ParserTests/HtmlToCodeSwitchTest/SwitchesToCodeWhenSwapCharacterEncounteredMidTag.stree.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/legacyTest/TestFiles/ParserTests/HtmlToCodeSwitchTest/SwitchesToCodeWhenSwapCharacterEncounteredMidTag.stree.txt index 0be9f018ecd..66183567582 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/legacyTest/TestFiles/ParserTests/HtmlToCodeSwitchTest/SwitchesToCodeWhenSwapCharacterEncounteredMidTag.stree.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/legacyTest/TestFiles/ParserTests/HtmlToCodeSwitchTest/SwitchesToCodeWhenSwapCharacterEncounteredMidTag.stree.txt @@ -15,7 +15,7 @@ MarkupStartTag - [2..14)::12 - [] - Gen - SpanEditHandler;Accepts:None OpenAngle;[<]; Text;[foo]; - MarkupMiscAttributeContent - [6..12)::6 + MarkupMiscAttributeContent - [6..11)::5 MarkupTextLiteral - [6..7)::1 - [ ] - Gen - SpanEditHandler;Accepts:Any Whitespace;[ ]; CSharpCodeBlock - [7..11)::4 @@ -26,6 +26,7 @@ CSharpCodeBlock - [8..11)::3 CSharpExpressionLiteral - [8..11)::3 - [bar] - Gen - ImplicitExpressionEditHandler;Accepts:NonWhitespace;ImplicitExpression[RTD];K14 Identifier;[bar]; + MarkupMiscAttributeContent - [11..12)::1 MarkupTextLiteral - [11..12)::1 - [ ] - Gen - SpanEditHandler;Accepts:Any Whitespace;[ ]; ForwardSlash;[/]; diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/legacyTest/TestFiles/ParserTests/TagHelperBlockRewriterTest/AllowsCompatibleTagStructures_DirectiveAttribute_SelfClosing.stree.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/legacyTest/TestFiles/ParserTests/TagHelperBlockRewriterTest/AllowsCompatibleTagStructures_DirectiveAttribute_SelfClosing.stree.txt index f69a6c78f6f..d836d334261 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/legacyTest/TestFiles/ParserTests/TagHelperBlockRewriterTest/AllowsCompatibleTagStructures_DirectiveAttribute_SelfClosing.stree.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/legacyTest/TestFiles/ParserTests/TagHelperBlockRewriterTest/AllowsCompatibleTagStructures_DirectiveAttribute_SelfClosing.stree.txt @@ -4,7 +4,7 @@ MarkupStartTag - [0..25)::25 - [] - Gen - SpanEditHandler;Accepts:Any OpenAngle;[<]; Text;[input]; - MarkupMiscAttributeContent - [6..23)::17 + MarkupMiscAttributeContent - [6..15)::9 MarkupTextLiteral - [6..7)::1 - [ ] - Gen - SpanEditHandler;Accepts:Any Whitespace;[ ]; CSharpCodeBlock - [7..15)::8 @@ -15,6 +15,7 @@ CSharpCodeBlock - [8..15)::7 CSharpExpressionLiteral - [8..15)::7 - [onclick] - Gen - ImplicitExpressionEditHandler;Accepts:NonWhitespace;ImplicitExpression[RTD];K14 Identifier;[onclick]; + MarkupMiscAttributeContent - [15..23)::8 MarkupTextLiteral - [15..17)::2 - [="] - Gen - SpanEditHandler;Accepts:Any Equals;[=]; DoubleQuote;["]; diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/legacyTest/TestFiles/ParserTests/TagHelperBlockRewriterTest/AllowsCompatibleTagStructures_DirectiveAttribute_Void.stree.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/legacyTest/TestFiles/ParserTests/TagHelperBlockRewriterTest/AllowsCompatibleTagStructures_DirectiveAttribute_Void.stree.txt index 07c9c76aa94..21a272664e2 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/legacyTest/TestFiles/ParserTests/TagHelperBlockRewriterTest/AllowsCompatibleTagStructures_DirectiveAttribute_Void.stree.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/legacyTest/TestFiles/ParserTests/TagHelperBlockRewriterTest/AllowsCompatibleTagStructures_DirectiveAttribute_Void.stree.txt @@ -4,7 +4,7 @@ MarkupStartTag - [0..24)::24 - [] - Gen - SpanEditHandler;Accepts:Any OpenAngle;[<]; Text;[input]; - MarkupMiscAttributeContent - [6..23)::17 + MarkupMiscAttributeContent - [6..15)::9 MarkupTextLiteral - [6..7)::1 - [ ] - Gen - SpanEditHandler;Accepts:Any Whitespace;[ ]; CSharpCodeBlock - [7..15)::8 @@ -15,6 +15,7 @@ CSharpCodeBlock - [8..15)::7 CSharpExpressionLiteral - [8..15)::7 - [onclick] - Gen - ImplicitExpressionEditHandler;Accepts:NonWhitespace;ImplicitExpression[RTD];K14 Identifier;[onclick]; + MarkupMiscAttributeContent - [15..23)::8 MarkupTextLiteral - [15..17)::2 - [="] - Gen - SpanEditHandler;Accepts:Any Equals;[=]; DoubleQuote;["]; diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/legacyTest/TestFiles/ParserTests/TagHelperBlockRewriterTest/CreatesErrorForMalformedTagHelpersWithAttributes13.stree.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/legacyTest/TestFiles/ParserTests/TagHelperBlockRewriterTest/CreatesErrorForMalformedTagHelpersWithAttributes13.stree.txt index afc0314011c..404cbe29e05 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/legacyTest/TestFiles/ParserTests/TagHelperBlockRewriterTest/CreatesErrorForMalformedTagHelpersWithAttributes13.stree.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/legacyTest/TestFiles/ParserTests/TagHelperBlockRewriterTest/CreatesErrorForMalformedTagHelpersWithAttributes13.stree.txt @@ -4,7 +4,7 @@ MarkupTagHelperStartTag - [0..29)::29 - [

] - Gen - SpanEditHandler;Accepts:Any OpenAngle;[<]; Text;[p]; - MarkupMiscAttributeContent - [2..28)::26 + MarkupMiscAttributeContent - [2..16)::14 MarkupTextLiteral - [2..3)::1 - [ ] - Gen - SpanEditHandler;Accepts:Any Whitespace;[ ]; CSharpCodeBlock - [3..16)::13 @@ -17,12 +17,19 @@ Identifier;[DateTime]; Dot;[.]; Identifier;[Now]; - MarkupTextLiteral - [16..28)::12 - [ class="btn"] - Gen - SpanEditHandler;Accepts:Any + MarkupAttributeBlock - [16..28)::12 - [ class="btn"] + MarkupTextLiteral - [16..17)::1 - [ ] - Gen - SpanEditHandler;Accepts:Any Whitespace;[ ]; + MarkupTextLiteral - [17..22)::5 - [class] - Gen - SpanEditHandler;Accepts:Any Text;[class]; - Equals;[=]; + Equals;[=]; + MarkupTextLiteral - [23..24)::1 - ["] - Gen - SpanEditHandler;Accepts:Any DoubleQuote;["]; - Text;[btn]; + GenericBlock - [24..27)::3 + MarkupLiteralAttributeValue - [24..27)::3 - [btn] + MarkupTextLiteral - [24..27)::3 - [btn] - Gen - SpanEditHandler;Accepts:Any + Text;[btn]; + MarkupTextLiteral - [27..28)::1 - ["] - Gen - SpanEditHandler;Accepts:Any DoubleQuote;["]; CloseAngle;[>]; MarkupTagHelperEndTag - [29..33)::4 - [

] diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/legacyTest/TestFiles/ParserTests/TagHelperBlockRewriterTest/CreatesErrorForMalformedTagHelpersWithAttributes14.stree.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/legacyTest/TestFiles/ParserTests/TagHelperBlockRewriterTest/CreatesErrorForMalformedTagHelpersWithAttributes14.stree.txt index 63c75731d4b..01079836e50 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/legacyTest/TestFiles/ParserTests/TagHelperBlockRewriterTest/CreatesErrorForMalformedTagHelpersWithAttributes14.stree.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/legacyTest/TestFiles/ParserTests/TagHelperBlockRewriterTest/CreatesErrorForMalformedTagHelpersWithAttributes14.stree.txt @@ -4,7 +4,7 @@ MarkupTagHelperStartTag - [0..23)::23 - [

] - Gen - SpanEditHandler;Accepts:Any OpenAngle;[<]; Text;[p]; - MarkupMiscAttributeContent - [2..22)::20 + MarkupMiscAttributeContent - [2..16)::14 MarkupTextLiteral - [2..3)::1 - [ ] - Gen - SpanEditHandler;Accepts:Any Whitespace;[ ]; CSharpCodeBlock - [3..16)::13 @@ -17,6 +17,7 @@ Identifier;[DateTime]; Dot;[.]; Identifier;[Now]; + MarkupMiscAttributeContent - [16..22)::6 MarkupTextLiteral - [16..22)::6 - [="btn"] - Gen - SpanEditHandler;Accepts:Any Equals;[=]; DoubleQuote;["]; diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/legacyTest/TestFiles/ParserTests/TagHelperBlockRewriterTest/TagHelperParseTreeRewriter_AllowsInvalidHtml10.stree.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/legacyTest/TestFiles/ParserTests/TagHelperBlockRewriterTest/TagHelperParseTreeRewriter_AllowsInvalidHtml10.stree.txt index 9511e116c22..4cb70e1e687 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/legacyTest/TestFiles/ParserTests/TagHelperBlockRewriterTest/TagHelperParseTreeRewriter_AllowsInvalidHtml10.stree.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/legacyTest/TestFiles/ParserTests/TagHelperBlockRewriterTest/TagHelperParseTreeRewriter_AllowsInvalidHtml10.stree.txt @@ -9,7 +9,7 @@ MarkupStartTag - [3..20)::17 - [< @DateTime.Now >] - Gen - SpanEditHandler;Accepts:Any OpenAngle;[<]; Text;[]; - MarkupMiscAttributeContent - [4..19)::15 + MarkupMiscAttributeContent - [4..18)::14 MarkupTextLiteral - [4..5)::1 - [ ] - Gen - SpanEditHandler;Accepts:Any Whitespace;[ ]; CSharpCodeBlock - [5..18)::13 @@ -22,6 +22,7 @@ Identifier;[DateTime]; Dot;[.]; Identifier;[Now]; + MarkupMiscAttributeContent - [18..19)::1 MarkupTextLiteral - [18..19)::1 - [ ] - Gen - SpanEditHandler;Accepts:Any Whitespace;[ ]; CloseAngle;[>]; diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/IntegrationTests/CodeGenerationIntegrationTest.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/IntegrationTests/CodeGenerationIntegrationTest.cs index 6fd02bb233d..6156e55f838 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/IntegrationTests/CodeGenerationIntegrationTest.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/IntegrationTests/CodeGenerationIntegrationTest.cs @@ -155,6 +155,22 @@ public void CSharp8() [IntegrationTestFact] public void ConditionalAttributes() => RunTest(); + [IntegrationTestFact, WorkItem("https://github.com/dotnet/razor/issues/10586")] + public void ConditionalAttributes2() + { + if (designTime) + { + // An error scenario: tag helper + C# dynamic content (a razor error is reported, + // so it is fine there is a missing mapping for the C# dynamic content). + ExpectedMissingSourceMappings = new() + { + { new(base.GetTestFileName() + ".cshtml", 328, 11, 8), "s" } + }; + } + + RunTest(); + } + [IntegrationTestFact] public void CodeBlockWithTextElement() => RunTest(); diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/Legacy/HtmlAttributeTest.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/Legacy/HtmlAttributeTest.cs index 9d9ecc3c6b4..222cb123d6f 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/Legacy/HtmlAttributeTest.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/Legacy/HtmlAttributeTest.cs @@ -5,6 +5,7 @@ using System; using System.Linq; +using Roslyn.Test.Utilities; using Xunit; namespace Microsoft.AspNetCore.Razor.Language.Legacy; @@ -299,6 +300,78 @@ public void ConditionalAttributesWithWeirdSpacingAreDisabledForDataAttributesInD ParseDocumentTest("@{}"); } + [Fact, WorkItem("https://github.com/dotnet/razor/issues/10586")] + public void ConditionalAttribute_DynamicContentAfter() + { + ParseDocumentTest("""

"""); + } + + [Fact, WorkItem("https://github.com/dotnet/razor/issues/10586")] + public void ConditionalAttribute_DynamicContentBefore() + { + ParseDocumentTest("""

"""); + } + + [Fact, WorkItem("https://github.com/dotnet/razor/issues/10586")] + public void ConditionalAttribute_DynamicContentBefore_02() + { + ParseDocumentTest("""

"""); + } + + [Fact, WorkItem("https://github.com/dotnet/razor/issues/10586")] + public void ConditionalAttribute_DynamicContentBefore_03() + { + ParseDocumentTest("""

"""); + } + + [Fact, WorkItem("https://github.com/dotnet/razor/issues/10586")] + public void ConditionalAttribute_DynamicContentBefore_04() + { + ParseDocumentTest("""

"""); + } + + [Fact, WorkItem("https://github.com/dotnet/razor/issues/10586")] + public void ConditionalAttribute_InvalidContentBefore() + { + ParseDocumentTest("""

"""); + } + + [Fact, WorkItem("https://github.com/dotnet/razor/issues/10586")] + public void ConditionalAttribute_CommentAfter() + { + ParseDocumentTest("""

"""); + } + + [Fact, WorkItem("https://github.com/dotnet/razor/issues/10586")] + public void ConditionalAttribute_CommentBefore() + { + ParseDocumentTest("""

"""); + } + + [Fact] + public void EscapedAttributeName_WithValue() + { + ParseDocumentTest("""

"""); + } + + [Fact] + public void EscapedAttributeName_Minimized() + { + ParseDocumentTest("""

"""); + } + + [Fact] + public void EscapedAttributeName_Eof() + { + ParseDocumentTest("""

"""); + } + [Fact] public void ComponentFileKind_ParsesDirectiveAttributesAsMarkup() { diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/Legacy/TagHelperParseTreeRewriterTest.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/Legacy/TagHelperParseTreeRewriterTest.cs index d1a7aa1166b..27296791cc6 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/Legacy/TagHelperParseTreeRewriterTest.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/Legacy/TagHelperParseTreeRewriterTest.cs @@ -29,11 +29,11 @@ public static TheoryData GetAttributeNameValuePairsData return new TheoryData>> { { "", empty }, - { "", empty }, + { "", new[] { kvp("href", "~/home") } }, { "", new[] { kvp("href", csharp) } }, { "", new[] { kvp("href", $"prefix{csharp} suffix") } }, { "", new[] { kvp("href", "~/home") } }, - { "", new[] { kvp("href", "~/home") } }, + { "", new[] { kvp("href", "~/home"), kvp("nothing", "something") } }, { "", new[] { kvp("href", $"{csharp}::0"), kvp("class", "btn btn-success"), kvp("random", "") } diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes.cshtml b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes.cshtml index be1a9c20797..bf825a8f3c8 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes.cshtml +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes.cshtml @@ -12,4 +12,5 @@ -} \ No newline at end of file +

+} diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml new file mode 100644 index 00000000000..25842336be3 --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml @@ -0,0 +1,22 @@ +@{ + var ch = true; + var cls = "bar"; + var s = "str"; + +

+

+

+ + +

+ + +

+

+ +

x

+ +

x

+

x

+

x

+} diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2_DesignTime.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2_DesignTime.codegen.cs new file mode 100644 index 00000000000..d91b68b31f0 --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2_DesignTime.codegen.cs @@ -0,0 +1,406 @@ +// +#pragma warning disable 1591 +namespace AspNetCore +{ + #line default + using TModel = global::System.Object; + using global::System; + using global::System.Collections.Generic; + using global::System.Linq; + using global::System.Threading.Tasks; + using global::Microsoft.AspNetCore.Mvc; + using global::Microsoft.AspNetCore.Mvc.Rendering; + using global::Microsoft.AspNetCore.Mvc.ViewFeatures; + #line default + #line hidden + [global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemMetadataAttribute("Identifier", "/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml")] + [global::System.Runtime.CompilerServices.CreateNewOnMetadataUpdateAttribute] + #nullable restore + public class TestFiles_IntegrationTests_CodeGenerationIntegrationTest_ConditionalAttributes2 : global::Microsoft.AspNetCore.Mvc.Razor.RazorPage + #nullable disable + { + #line hidden + #pragma warning disable 0649 + private global::Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperExecutionContext __tagHelperExecutionContext; + #pragma warning restore 0649 + private global::Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperRunner __tagHelperRunner = new global::Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperRunner(); + private global::Microsoft.AspNetCore.Mvc.Razor.TagHelpers.UrlResolutionTagHelper __Microsoft_AspNetCore_Mvc_Razor_TagHelpers_UrlResolutionTagHelper; + #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 + public async override global::System.Threading.Tasks.Task ExecuteAsync() + { +#nullable restore +#line 1 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml" + + var ch = true; + var cls = "bar"; + var s = "str"; + + +#line default +#line hidden +#nullable disable +#nullable restore +#line 5 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml" + __o = s; + +#line default +#line hidden +#nullable disable +#nullable restore +#line 5 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml" + + + +#line default +#line hidden +#nullable disable +#nullable restore +#line 6 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml" + __o = s; + +#line default +#line hidden +#nullable disable +#nullable restore +#line 6 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml" + __o = cls; + +#line default +#line hidden +#nullable disable +#nullable restore +#line 6 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml" + + + +#line default +#line hidden +#nullable disable +#nullable restore +#line 7 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml" + __o = s; + +#line default +#line hidden +#nullable disable +#nullable restore +#line 7 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml" + __o = cls; + +#line default +#line hidden +#nullable disable +#nullable restore +#line 7 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml" + + + +#line default +#line hidden +#nullable disable +#nullable restore +#line 8 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml" + __o = s; + +#line default +#line hidden +#nullable disable +#nullable restore +#line 8 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml" + __o = cls; + +#line default +#line hidden +#nullable disable +#nullable restore +#line 8 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml" + + + +#line default +#line hidden +#nullable disable +#nullable restore +#line 9 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml" + __o = s; + +#line default +#line hidden +#nullable disable +#nullable restore +#line 9 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml" + __o = ch; + +#line default +#line hidden +#nullable disable +#nullable restore +#line 9 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml" + + + +#line default +#line hidden +#nullable disable +#nullable restore +#line 10 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml" + __o = s; + +#line default +#line hidden +#nullable disable +#nullable restore +#line 10 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml" + __o = ch; + +#line default +#line hidden +#nullable disable +#nullable restore +#line 10 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml" + + + +#line default +#line hidden +#nullable disable +#nullable restore +#line 11 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml" + __o = s; + +#line default +#line hidden +#nullable disable +#nullable restore +#line 11 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml" + if(cls != null) { + +#line default +#line hidden +#nullable disable +#nullable restore +#line 11 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml" + __o = cls; + +#line default +#line hidden +#nullable disable +#nullable restore +#line 11 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml" + } + +#line default +#line hidden +#nullable disable +#nullable restore +#line 11 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml" + + + +#line default +#line hidden +#nullable disable + __Microsoft_AspNetCore_Mvc_Razor_TagHelpers_UrlResolutionTagHelper = CreateTagHelper(); + await __tagHelperRunner.RunAsync(__tagHelperExecutionContext); +#nullable restore +#line 12 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml" + + + +#line default +#line hidden +#nullable disable +#nullable restore +#line 13 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml" + __o = s; + +#line default +#line hidden +#nullable disable +#nullable restore +#line 13 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml" + __o = Url.Content("~/Scripts/jquery-1.6.2.min.js"); + +#line default +#line hidden +#nullable disable +#nullable restore +#line 13 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml" + + + +#line default +#line hidden +#nullable disable +#nullable restore +#line 14 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml" + __o = s; + +#line default +#line hidden +#nullable disable +#nullable restore +#line 14 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml" + __o = null; + +#line default +#line hidden +#nullable disable +#nullable restore +#line 14 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml" + + + +#line default +#line hidden +#nullable disable +#nullable restore +#line 15 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml" + __o = null; + +#line default +#line hidden +#nullable disable +#nullable restore +#line 15 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml" + __o = s; + +#line default +#line hidden +#nullable disable +#nullable restore +#line 15 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml" + + + + +#line default +#line hidden +#nullable disable +#nullable restore +#line 17 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml" + __o = s; + +#line default +#line hidden +#nullable disable +#nullable restore +#line 17 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml" + __o = null; + +#line default +#line hidden +#nullable disable +#nullable restore +#line 17 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml" + + + + +#line default +#line hidden +#nullable disable +#nullable restore +#line 19 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml" + __o = s + s; + +#line default +#line hidden +#nullable disable +#nullable restore +#line 19 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml" + __o = null; + +#line default +#line hidden +#nullable disable +#nullable restore +#line 19 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml" + + + +#line default +#line hidden +#nullable disable +#nullable restore +#line 20 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml" + if (s.Length != 0) { + +#line default +#line hidden +#nullable disable +#nullable restore +#line 20 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml" + __o = s; + +#line default +#line hidden +#nullable disable +#nullable restore +#line 20 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml" + } + +#line default +#line hidden +#nullable disable +#nullable restore +#line 20 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml" + __o = null; + +#line default +#line hidden +#nullable disable +#nullable restore +#line 20 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml" + + + +#line default +#line hidden +#nullable disable +#nullable restore +#line 21 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml" + __o = null; + +#line default +#line hidden +#nullable disable +#nullable restore +#line 21 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml" + + +#line default +#line hidden +#nullable disable + } + #pragma warning restore 1998 + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.ViewFeatures.IModelExpressionProvider ModelExpressionProvider { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.IUrlHelper Url { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.IViewComponentHelper Component { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.Rendering.IJsonHelper Json { get; private set; } = default!; + #nullable disable + #nullable restore + [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute] + public global::Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper Html { get; private set; } = default!; + #nullable disable + } +} +#pragma warning restore 1591 diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2_DesignTime.codegen.html b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2_DesignTime.codegen.html new file mode 100644 index 00000000000..3981b69f586 --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2_DesignTime.codegen.html @@ -0,0 +1,22 @@ +~~ + ~~~ ~~ ~ ~~~~~ + ~~~ ~~~ ~ ~~~~~~ + ~~~ ~ ~ ~~~~~~ +
+

+

+

+ + +

+ + +

+

+ +

x

+ +

x

+

x

+

x

+~ diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2_DesignTime.diagnostics.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2_DesignTime.diagnostics.txt new file mode 100644 index 00000000000..b26658f13b4 --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2_DesignTime.diagnostics.txt @@ -0,0 +1 @@ +TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml(12,8): Error RZ1031: The tag helper 'a' must not have C# in the element's attribute declaration area. diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2_DesignTime.html.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2_DesignTime.html.mappings.txt new file mode 100644 index 00000000000..0a8f373f817 --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2_DesignTime.html.mappings.txt @@ -0,0 +1,222 @@ +Source Location: (70:4,4 [3] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml) +|
| +Generated Location: (75:4,9 [12] ) +| href="x" />| + +Source Location: (93:5,4 [3] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml) +|

| +Generated Location: (110:5,21 [4] ) +|" />| + +Source Location: (120:6,4 [3] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml) +|

| +Generated Location: (139:6,23 [4] ) +|" />| + +Source Location: (149:7,4 [3] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml) +|

| +Generated Location: (166:7,21 [6] ) +| x" />| + +Source Location: (178:8,4 [23] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml) +|| +Generated Location: (216:8,42 [4] ) +|" />| + +Source Location: (226:9,4 [23] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml) +|| +Generated Location: (266:9,44 [4] ) +|" />| + +Source Location: (276:10,4 [3] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml) +|

| +Generated Location: (314:10,42 [4] ) +|" />| + +Source Location: (324:11,4 [3] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml) +|| +Generated Location: (329:11,9 [14] ) +| href="~/x" />| + +Source Location: (349:12,4 [8] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml) +|| +Generated Location: (410:12,65 [34] ) +|" type="text/javascript">| + +Source Location: (450:13,4 [3] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml) +|

| +Generated Location: (468:13,22 [4] ) +|" />| + +Source Location: (478:14,4 [10] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml) +|

| +Generated Location: (497:14,23 [3] ) +| />| + +Source Location: (508:16,4 [3] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml) +|

x

| +Generated Location: (540:16,36 [7] ) +|">x

| + +Source Location: (555:18,4 [3] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml) +|

x

| +Generated Location: (579:18,28 [7] ) +|">x

| + +Source Location: (592:19,4 [3] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml) +|

x

| +Generated Location: (636:19,48 [7] ) +|">x

| + +Source Location: (649:20,4 [14] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml) +|

x

| +Generated Location: (668:20,23 [7] ) +|">x

| + +Source Location: (678:21,1 [2] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml) +| +| +Generated Location: (678:21,1 [2] ) +| +| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2_DesignTime.ir.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2_DesignTime.ir.txt new file mode 100644 index 00000000000..1e6a91531c1 --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2_DesignTime.ir.txt @@ -0,0 +1,252 @@ +Document - + NamespaceDeclaration - - AspNetCore + UsingDirective - - TModel = global::System.Object + UsingDirective - (1:0,1 [20] ) - global::System + UsingDirective - (24:1,1 [40] ) - global::System.Collections.Generic + UsingDirective - (67:2,1 [25] ) - global::System.Linq + UsingDirective - (95:3,1 [36] ) - global::System.Threading.Tasks + UsingDirective - (134:4,1 [38] ) - global::Microsoft.AspNetCore.Mvc + UsingDirective - (175:5,1 [48] ) - global::Microsoft.AspNetCore.Mvc.Rendering + UsingDirective - (226:6,1 [51] ) - global::Microsoft.AspNetCore.Mvc.ViewFeatures + RazorCompiledItemMetadataAttribute - + CreateNewOnMetadataUpdateAttribute - + ClassDeclaration - - public - TestFiles_IntegrationTests_CodeGenerationIntegrationTest_ConditionalAttributes2 - global::Microsoft.AspNetCore.Mvc.Razor.RazorPage - + DefaultTagHelperRuntime - + FieldDeclaration - - private - global::Microsoft.AspNetCore.Mvc.Razor.TagHelpers.UrlResolutionTagHelper - __Microsoft_AspNetCore_Mvc_Razor_TagHelpers_UrlResolutionTagHelper + DesignTimeDirective - + DirectiveToken - (287:7,8 [62] ) - global::Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper + DirectiveToken - (350:7,71 [4] ) - Html + DirectiveToken - (364:8,8 [54] ) - global::Microsoft.AspNetCore.Mvc.Rendering.IJsonHelper + DirectiveToken - (419:8,63 [4] ) - Json + DirectiveToken - (433:9,8 [53] ) - global::Microsoft.AspNetCore.Mvc.IViewComponentHelper + DirectiveToken - (487:9,62 [9] ) - Component + DirectiveToken - (506:10,8 [43] ) - global::Microsoft.AspNetCore.Mvc.IUrlHelper + DirectiveToken - (550:10,52 [3] ) - Url + DirectiveToken - (563:11,8 [70] ) - global::Microsoft.AspNetCore.Mvc.ViewFeatures.IModelExpressionProvider + DirectiveToken - (634:11,79 [23] ) - ModelExpressionProvider + DirectiveToken - (673:12,14 [104] ) - global::Microsoft.AspNetCore.Mvc.Razor.TagHelpers.UrlResolutionTagHelper, Microsoft.AspNetCore.Mvc.Razor + DirectiveToken - (793:13,14 [95] ) - global::Microsoft.AspNetCore.Mvc.Razor.TagHelpers.HeadTagHelper, Microsoft.AspNetCore.Mvc.Razor + DirectiveToken - (904:14,14 [95] ) - global::Microsoft.AspNetCore.Mvc.Razor.TagHelpers.BodyTagHelper, Microsoft.AspNetCore.Mvc.Razor + CSharpCode - + IntermediateToken - - CSharp - #pragma warning disable 0414 + CSharpCode - + IntermediateToken - - CSharp - private static object __o = null; + CSharpCode - + IntermediateToken - - CSharp - #pragma warning restore 0414 + MethodDeclaration - - public async override - global::System.Threading.Tasks.Task - ExecuteAsync + CSharpCode - (2:0,2 [68] ConditionalAttributes2.cshtml) + LazyIntermediateToken - (2:0,2 [68] ConditionalAttributes2.cshtml) - CSharp - \n var ch = true;\n var cls = "bar";\n var s = "str";\n + HtmlContent - (70:4,4 [3] ConditionalAttributes2.cshtml) + LazyIntermediateToken - (70:4,4 [2] ConditionalAttributes2.cshtml) - Html -
+ CSharpCode - (87:4,21 [6] ConditionalAttributes2.cshtml) + LazyIntermediateToken - (87:4,21 [6] ConditionalAttributes2.cshtml) - CSharp - \n + HtmlContent - (93:5,4 [3] ConditionalAttributes2.cshtml) + LazyIntermediateToken - (93:5,4 [2] ConditionalAttributes2.cshtml) - Html -

+ CSharpCode - (114:5,25 [6] ConditionalAttributes2.cshtml) + LazyIntermediateToken - (114:5,25 [6] ConditionalAttributes2.cshtml) - CSharp - \n + HtmlContent - (120:6,4 [3] ConditionalAttributes2.cshtml) + LazyIntermediateToken - (120:6,4 [2] ConditionalAttributes2.cshtml) - Html -

+ CSharpCode - (143:6,27 [6] ConditionalAttributes2.cshtml) + LazyIntermediateToken - (143:6,27 [6] ConditionalAttributes2.cshtml) - CSharp - \n + HtmlContent - (149:7,4 [3] ConditionalAttributes2.cshtml) + LazyIntermediateToken - (149:7,4 [2] ConditionalAttributes2.cshtml) - Html -

+ CSharpCode - (172:7,27 [6] ConditionalAttributes2.cshtml) + LazyIntermediateToken - (172:7,27 [6] ConditionalAttributes2.cshtml) - CSharp - \n + HtmlContent - (178:8,4 [23] ConditionalAttributes2.cshtml) + LazyIntermediateToken - (178:8,4 [6] ConditionalAttributes2.cshtml) - Html - + CSharpCode - (220:8,46 [6] ConditionalAttributes2.cshtml) + LazyIntermediateToken - (220:8,46 [6] ConditionalAttributes2.cshtml) - CSharp - \n + HtmlContent - (226:9,4 [23] ConditionalAttributes2.cshtml) + LazyIntermediateToken - (226:9,4 [6] ConditionalAttributes2.cshtml) - Html - + CSharpCode - (270:9,48 [6] ConditionalAttributes2.cshtml) + LazyIntermediateToken - (270:9,48 [6] ConditionalAttributes2.cshtml) - CSharp - \n + HtmlContent - (276:10,4 [3] ConditionalAttributes2.cshtml) + LazyIntermediateToken - (276:10,4 [2] ConditionalAttributes2.cshtml) - Html -

+ CSharpCode - (318:10,46 [6] ConditionalAttributes2.cshtml) + LazyIntermediateToken - (318:10,46 [6] ConditionalAttributes2.cshtml) - CSharp - \n + TagHelper - (324:11,4 [19] ConditionalAttributes2.cshtml) - a - TagMode.SelfClosing + DefaultTagHelperBody - + DefaultTagHelperCreate - - Microsoft.AspNetCore.Mvc.Razor.TagHelpers.UrlResolutionTagHelper + DefaultTagHelperExecute - + CSharpCode - (343:11,23 [6] ConditionalAttributes2.cshtml) + LazyIntermediateToken - (343:11,23 [6] ConditionalAttributes2.cshtml) - CSharp - \n + HtmlContent - (349:12,4 [8] ConditionalAttributes2.cshtml) + LazyIntermediateToken - (349:12,4 [7] ConditionalAttributes2.cshtml) - Html - + CSharpCode - (444:12,99 [6] ConditionalAttributes2.cshtml) + LazyIntermediateToken - (444:12,99 [6] ConditionalAttributes2.cshtml) - CSharp - \n + HtmlContent - (450:13,4 [3] ConditionalAttributes2.cshtml) + LazyIntermediateToken - (450:13,4 [2] ConditionalAttributes2.cshtml) - Html -

+ CSharpCode - (472:13,26 [6] ConditionalAttributes2.cshtml) + LazyIntermediateToken - (472:13,26 [6] ConditionalAttributes2.cshtml) - CSharp - \n + HtmlContent - (478:14,4 [2] ConditionalAttributes2.cshtml) + LazyIntermediateToken - (478:14,4 [2] ConditionalAttributes2.cshtml) - Html -

+ CSharpCode - (500:14,26 [8] ConditionalAttributes2.cshtml) + LazyIntermediateToken - (500:14,26 [8] ConditionalAttributes2.cshtml) - CSharp - \n\n + HtmlContent - (508:16,4 [3] ConditionalAttributes2.cshtml) + LazyIntermediateToken - (508:16,4 [2] ConditionalAttributes2.cshtml) - Html -

+ LazyIntermediateToken - (542:16,38 [1] ConditionalAttributes2.cshtml) - Html - x + LazyIntermediateToken - (543:16,39 [4] ConditionalAttributes2.cshtml) - Html -

+ CSharpCode - (547:16,43 [8] ConditionalAttributes2.cshtml) + LazyIntermediateToken - (547:16,43 [8] ConditionalAttributes2.cshtml) - CSharp - \n\n + HtmlContent - (555:18,4 [3] ConditionalAttributes2.cshtml) + LazyIntermediateToken - (555:18,4 [2] ConditionalAttributes2.cshtml) - Html -

+ LazyIntermediateToken - (581:18,30 [1] ConditionalAttributes2.cshtml) - Html - x + LazyIntermediateToken - (582:18,31 [4] ConditionalAttributes2.cshtml) - Html -

+ CSharpCode - (586:18,35 [6] ConditionalAttributes2.cshtml) + LazyIntermediateToken - (586:18,35 [6] ConditionalAttributes2.cshtml) - CSharp - \n + HtmlContent - (592:19,4 [3] ConditionalAttributes2.cshtml) + LazyIntermediateToken - (592:19,4 [2] ConditionalAttributes2.cshtml) - Html -

+ LazyIntermediateToken - (638:19,50 [1] ConditionalAttributes2.cshtml) - Html - x + LazyIntermediateToken - (639:19,51 [4] ConditionalAttributes2.cshtml) - Html -

+ CSharpCode - (643:19,55 [6] ConditionalAttributes2.cshtml) + LazyIntermediateToken - (643:19,55 [6] ConditionalAttributes2.cshtml) - CSharp - \n + HtmlContent - (649:20,4 [3] ConditionalAttributes2.cshtml) + LazyIntermediateToken - (649:20,4 [2] ConditionalAttributes2.cshtml) - Html -

+ LazyIntermediateToken - (670:20,25 [1] ConditionalAttributes2.cshtml) - Html - x + LazyIntermediateToken - (671:20,26 [4] ConditionalAttributes2.cshtml) - Html -

+ CSharpCode - (675:20,30 [2] ConditionalAttributes2.cshtml) + LazyIntermediateToken - (675:20,30 [2] ConditionalAttributes2.cshtml) - CSharp - \n + Inject - + Inject - + Inject - + Inject - + Inject - diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2_DesignTime.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2_DesignTime.mappings.txt new file mode 100644 index 00000000000..6351ea88ec2 --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2_DesignTime.mappings.txt @@ -0,0 +1,272 @@ +Source Location: (2:0,2 [68] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml) +| + var ch = true; + var cls = "bar"; + var s = "str"; + | +Generated Location: (2043:39,2 [68] ) +| + var ch = true; + var cls = "bar"; + var s = "str"; + | + +Source Location: (74:4,8 [1] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml) +|s| +Generated Location: (2288:50,8 [1] ) +|s| + +Source Location: (87:4,21 [6] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml) +| + | +Generated Location: (2480:57,21 [6] ) +| + | + +Source Location: (97:5,8 [1] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml) +|s| +Generated Location: (2663:65,8 [1] ) +|s| + +Source Location: (107:5,18 [3] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml) +|cls| +Generated Location: (2852:72,18 [3] ) +|cls| + +Source Location: (114:5,25 [6] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml) +| + | +Generated Location: (3050:79,25 [6] ) +| + | + +Source Location: (124:6,8 [1] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml) +|s| +Generated Location: (3233:87,8 [1] ) +|s| + +Source Location: (136:6,20 [3] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml) +|cls| +Generated Location: (3424:94,20 [3] ) +|cls| + +Source Location: (143:6,27 [6] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml) +| + | +Generated Location: (3624:101,27 [6] ) +| + | + +Source Location: (153:7,8 [1] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml) +|s| +Generated Location: (3807:109,8 [1] ) +|s| + +Source Location: (163:7,18 [3] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml) +|cls| +Generated Location: (3996:116,18 [3] ) +|cls| + +Source Location: (172:7,27 [6] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml) +| + | +Generated Location: (4196:123,27 [6] ) +| + | + +Source Location: (202:8,28 [1] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml) +|s| +Generated Location: (4399:131,28 [1] ) +|s| + +Source Location: (214:8,40 [2] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml) +|ch| +Generated Location: (4610:138,40 [2] ) +|ch| + +Source Location: (220:8,46 [6] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml) +| + | +Generated Location: (4828:145,46 [6] ) +| + | + +Source Location: (250:9,28 [1] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml) +|s| +Generated Location: (5032:153,28 [1] ) +|s| + +Source Location: (264:9,42 [2] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml) +|ch| +Generated Location: (5246:160,42 [2] ) +|ch| + +Source Location: (270:9,48 [6] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml) +| + | +Generated Location: (5467:167,48 [6] ) +| + | + +Source Location: (280:10,8 [1] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml) +|s| +Generated Location: (5651:175,8 [1] ) +|s| + +Source Location: (290:10,18 [18] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml) +|if(cls != null) { | +Generated Location: (5841:182,18 [18] ) +|if(cls != null) { | + +Source Location: (309:10,37 [3] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml) +|cls| +Generated Location: (6066:189,37 [3] ) +|cls| + +Source Location: (312:10,40 [2] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml) +| }| +Generated Location: (6280:196,40 [2] ) +| }| + +Source Location: (318:10,46 [6] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml) +| + | +Generated Location: (6498:203,46 [6] ) +| + | + +Source Location: (343:11,23 [6] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml) +| + | +Generated Location: (6948:213,23 [6] ) +| + | + +Source Location: (358:12,13 [1] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml) +|s| +Generated Location: (7137:221,13 [1] ) +|s| + +Source Location: (366:12,21 [44] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml) +|Url.Content("~/Scripts/jquery-1.6.2.min.js")| +Generated Location: (7330:228,21 [44] ) +|Url.Content("~/Scripts/jquery-1.6.2.min.js")| + +Source Location: (444:12,99 [6] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml) +| + | +Generated Location: (7644:235,99 [6] ) +| + | + +Source Location: (454:13,8 [1] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml) +|s| +Generated Location: (7828:243,8 [1] ) +|s| + +Source Location: (464:13,18 [4] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml) +|null| +Generated Location: (8018:250,18 [4] ) +|null| + +Source Location: (472:13,26 [6] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml) +| + | +Generated Location: (8219:257,26 [6] ) +| + | + +Source Location: (489:14,15 [4] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml) +|null| +Generated Location: (8410:265,15 [4] ) +|null| + +Source Location: (496:14,22 [1] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml) +|s| +Generated Location: (8607:272,22 [1] ) +|s| + +Source Location: (500:14,26 [8] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml) +| + + | +Generated Location: (8805:279,26 [8] ) +| + + | + +Source Location: (526:16,22 [1] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml) +|s| +Generated Location: (9005:288,22 [1] ) +|s| + +Source Location: (536:16,32 [4] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml) +|null| +Generated Location: (9209:295,32 [4] ) +|null| + +Source Location: (547:16,43 [8] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml) +| + + | +Generated Location: (9427:302,43 [8] ) +| + + | + +Source Location: (560:18,9 [5] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml) +|s + s| +Generated Location: (9614:311,9 [5] ) +|s + s| + +Source Location: (575:18,24 [4] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml) +|null| +Generated Location: (9814:318,24 [4] ) +|null| + +Source Location: (586:18,35 [6] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml) +| + | +Generated Location: (10024:325,35 [6] ) +| + | + +Source Location: (597:19,9 [21] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml) +|if (s.Length != 0) { | +Generated Location: (10209:333,9 [21] ) +|if (s.Length != 0) { | + +Source Location: (619:19,31 [1] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml) +|s| +Generated Location: (10431:340,31 [1] ) +|s| + +Source Location: (620:19,32 [2] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml) +| }| +Generated Location: (10635:347,32 [2] ) +| }| + +Source Location: (632:19,44 [4] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml) +|null| +Generated Location: (10851:354,44 [4] ) +|null| + +Source Location: (643:19,55 [6] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml) +| + | +Generated Location: (11081:361,55 [6] ) +| + | + +Source Location: (664:20,19 [4] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml) +|null| +Generated Location: (11276:369,19 [4] ) +|null| + +Source Location: (675:20,30 [2] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml) +| +| +Generated Location: (11481:376,30 [2] ) +| +| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2_Runtime.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2_Runtime.codegen.cs new file mode 100644 index 00000000000..bfdfcbda387 --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2_Runtime.codegen.cs @@ -0,0 +1,414 @@ +#pragma checksum "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml" "{8829d00f-11b8-4213-878b-770e8597ac16}" "ee976c57374bafda343bd6b2086b223381f842016566d5a83498a6d0cbec2f54" +// +#pragma warning disable 1591 +[assembly: global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemAttribute(typeof(AspNetCore.TestFiles_IntegrationTests_CodeGenerationIntegrationTest_ConditionalAttributes2), @"mvc.1.0.view", @"/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml")] +namespace AspNetCore +{ + #line default + using global::System; + using global::System.Collections.Generic; + using global::System.Linq; + using global::System.Threading.Tasks; + using global::Microsoft.AspNetCore.Mvc; + using global::Microsoft.AspNetCore.Mvc.Rendering; + using global::Microsoft.AspNetCore.Mvc.ViewFeatures; + #line default + #line hidden + [global::Microsoft.AspNetCore.Razor.Hosting.RazorSourceChecksumAttribute(@"Sha256", @"ee976c57374bafda343bd6b2086b223381f842016566d5a83498a6d0cbec2f54", @"/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml")] + [global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemMetadataAttribute("Identifier", "/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml")] + [global::System.Runtime.CompilerServices.CreateNewOnMetadataUpdateAttribute] + #nullable restore + public class TestFiles_IntegrationTests_CodeGenerationIntegrationTest_ConditionalAttributes2 : global::Microsoft.AspNetCore.Mvc.Razor.RazorPage + #nullable disable + { + #line hidden + #pragma warning disable 0649 + private global::Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperExecutionContext __tagHelperExecutionContext; + #pragma warning restore 0649 + private global::Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperRunner __tagHelperRunner = new global::Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperRunner(); + #pragma warning disable 0169 + private string __tagHelperStringValueBuffer; + #pragma warning restore 0169 + private global::Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperScopeManager __backed__tagHelperScopeManager = null; + private global::Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperScopeManager __tagHelperScopeManager + { + get + { + if (__backed__tagHelperScopeManager == null) + { + __backed__tagHelperScopeManager = new global::Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperScopeManager(StartTagHelperWritingScope, EndTagHelperWritingScope); + } + return __backed__tagHelperScopeManager; + } + } + private global::Microsoft.AspNetCore.Mvc.Razor.TagHelpers.UrlResolutionTagHelper __Microsoft_AspNetCore_Mvc_Razor_TagHelpers_UrlResolutionTagHelper; + #pragma warning disable 1998 + public async override global::System.Threading.Tasks.Task ExecuteAsync() + { +#nullable restore +#line (1,3)-(5,1) "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes2.cshtml" + + var ch = true; + var cls = "bar"; + var s = "str"; + +#line default +#line hidden +#nullable disable + + WriteLiteral("
+ LazyIntermediateToken - (87:4,21 [2] ConditionalAttributes2.cshtml) - Html - \n + LazyIntermediateToken - (89:5,0 [4] ConditionalAttributes2.cshtml) - Html - + LazyIntermediateToken - (93:5,4 [2] ConditionalAttributes2.cshtml) - Html -

+ LazyIntermediateToken - (114:5,25 [2] ConditionalAttributes2.cshtml) - Html - \n + LazyIntermediateToken - (116:6,0 [4] ConditionalAttributes2.cshtml) - Html - + LazyIntermediateToken - (120:6,4 [2] ConditionalAttributes2.cshtml) - Html -

+ LazyIntermediateToken - (143:6,27 [2] ConditionalAttributes2.cshtml) - Html - \n + LazyIntermediateToken - (145:7,0 [4] ConditionalAttributes2.cshtml) - Html - + LazyIntermediateToken - (149:7,4 [2] ConditionalAttributes2.cshtml) - Html -

+ LazyIntermediateToken - (172:7,27 [2] ConditionalAttributes2.cshtml) - Html - \n + LazyIntermediateToken - (174:8,0 [4] ConditionalAttributes2.cshtml) - Html - + LazyIntermediateToken - (178:8,4 [6] ConditionalAttributes2.cshtml) - Html - + LazyIntermediateToken - (220:8,46 [2] ConditionalAttributes2.cshtml) - Html - \n + LazyIntermediateToken - (222:9,0 [4] ConditionalAttributes2.cshtml) - Html - + LazyIntermediateToken - (226:9,4 [6] ConditionalAttributes2.cshtml) - Html - + LazyIntermediateToken - (270:9,48 [2] ConditionalAttributes2.cshtml) - Html - \n + LazyIntermediateToken - (272:10,0 [4] ConditionalAttributes2.cshtml) - Html - + LazyIntermediateToken - (276:10,4 [2] ConditionalAttributes2.cshtml) - Html -

+ LazyIntermediateToken - (318:10,46 [2] ConditionalAttributes2.cshtml) - Html - \n + LazyIntermediateToken - (320:11,0 [4] ConditionalAttributes2.cshtml) - Html - + TagHelper - (324:11,4 [19] ConditionalAttributes2.cshtml) - a - TagMode.SelfClosing + DefaultTagHelperBody - + DefaultTagHelperCreate - - Microsoft.AspNetCore.Mvc.Razor.TagHelpers.UrlResolutionTagHelper + DefaultTagHelperExecute - + HtmlContent - (343:11,23 [14] ConditionalAttributes2.cshtml) + LazyIntermediateToken - (343:11,23 [2] ConditionalAttributes2.cshtml) - Html - \n + LazyIntermediateToken - (345:12,0 [4] ConditionalAttributes2.cshtml) - Html - + LazyIntermediateToken - (349:12,4 [7] ConditionalAttributes2.cshtml) - Html - + LazyIntermediateToken - (444:12,99 [2] ConditionalAttributes2.cshtml) - Html - \n + LazyIntermediateToken - (446:13,0 [4] ConditionalAttributes2.cshtml) - Html - + LazyIntermediateToken - (450:13,4 [2] ConditionalAttributes2.cshtml) - Html -

+ LazyIntermediateToken - (472:13,26 [2] ConditionalAttributes2.cshtml) - Html - \n + LazyIntermediateToken - (474:14,0 [4] ConditionalAttributes2.cshtml) - Html - + LazyIntermediateToken - (478:14,4 [2] ConditionalAttributes2.cshtml) - Html -

+ LazyIntermediateToken - (500:14,26 [2] ConditionalAttributes2.cshtml) - Html - \n + CSharpCode - (502:15,0 [2] ConditionalAttributes2.cshtml) + LazyIntermediateToken - (502:15,0 [2] ConditionalAttributes2.cshtml) - CSharp - \n + HtmlContent - (504:16,0 [7] ConditionalAttributes2.cshtml) + LazyIntermediateToken - (504:16,0 [4] ConditionalAttributes2.cshtml) - Html - + LazyIntermediateToken - (508:16,4 [2] ConditionalAttributes2.cshtml) - Html -

+ LazyIntermediateToken - (542:16,38 [1] ConditionalAttributes2.cshtml) - Html - x + LazyIntermediateToken - (543:16,39 [4] ConditionalAttributes2.cshtml) - Html -

+ LazyIntermediateToken - (547:16,43 [2] ConditionalAttributes2.cshtml) - Html - \n + CSharpCode - (549:17,0 [2] ConditionalAttributes2.cshtml) + LazyIntermediateToken - (549:17,0 [2] ConditionalAttributes2.cshtml) - CSharp - \n + HtmlContent - (551:18,0 [7] ConditionalAttributes2.cshtml) + LazyIntermediateToken - (551:18,0 [4] ConditionalAttributes2.cshtml) - Html - + LazyIntermediateToken - (555:18,4 [2] ConditionalAttributes2.cshtml) - Html -

+ LazyIntermediateToken - (581:18,30 [1] ConditionalAttributes2.cshtml) - Html - x + LazyIntermediateToken - (582:18,31 [4] ConditionalAttributes2.cshtml) - Html -

+ LazyIntermediateToken - (586:18,35 [2] ConditionalAttributes2.cshtml) - Html - \n + LazyIntermediateToken - (588:19,0 [4] ConditionalAttributes2.cshtml) - Html - + LazyIntermediateToken - (592:19,4 [2] ConditionalAttributes2.cshtml) - Html -

+ LazyIntermediateToken - (638:19,50 [1] ConditionalAttributes2.cshtml) - Html - x + LazyIntermediateToken - (639:19,51 [4] ConditionalAttributes2.cshtml) - Html -

+ LazyIntermediateToken - (643:19,55 [2] ConditionalAttributes2.cshtml) - Html - \n + LazyIntermediateToken - (645:20,0 [4] ConditionalAttributes2.cshtml) - Html - + LazyIntermediateToken - (649:20,4 [2] ConditionalAttributes2.cshtml) - Html -

+ LazyIntermediateToken - (670:20,25 [1] ConditionalAttributes2.cshtml) - Html - x + LazyIntermediateToken - (671:20,26 [4] ConditionalAttributes2.cshtml) - Html -

+ LazyIntermediateToken - (675:20,30 [2] ConditionalAttributes2.cshtml) - Html - \n + CSharpCode - (677:21,0 [0] ConditionalAttributes2.cshtml) + LazyIntermediateToken - (677:21,0 [0] ConditionalAttributes2.cshtml) - CSharp - + Inject - + Inject - + Inject - + Inject - + Inject - diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes_DesignTime.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes_DesignTime.codegen.cs index ff574f914a5..569b502fc05 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes_DesignTime.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes_DesignTime.codegen.cs @@ -200,6 +200,21 @@ private void __RazorDirectiveTokenHelpers__() { #nullable restore #line 14 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes.cshtml" + + +#line default +#line hidden +#nullable disable +#nullable restore +#line 15 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes.cshtml" + __o = null; + +#line default +#line hidden +#nullable disable +#nullable restore +#line 15 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes.cshtml" + #line default #line hidden diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes_DesignTime.codegen.html b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes_DesignTime.codegen.html index 34c5024a53f..323da7fe613 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes_DesignTime.codegen.html +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes_DesignTime.codegen.html @@ -12,4 +12,5 @@ -~ \ No newline at end of file +

+~ diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes_DesignTime.html.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes_DesignTime.html.mappings.txt index 25185818f66..5630f45dd41 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes_DesignTime.html.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes_DesignTime.html.mappings.txt @@ -93,3 +93,20 @@ Source Location: (527:13,4 [111] TestFiles/IntegrationTests/CodeGenerationIntegr Generated Location: (527:13,4 [111] ) || +Source Location: (644:14,4 [10] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes.cshtml) +|

| +Generated Location: (659:14,19 [4] ) +|" />| + +Source Location: (666:15,1 [2] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes.cshtml) +| +| +Generated Location: (666:15,1 [2] ) +| +| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes_DesignTime.ir.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes_DesignTime.ir.txt index 1281fd038c2..bcdf748d694 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes_DesignTime.ir.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes_DesignTime.ir.txt @@ -151,8 +151,18 @@ LazyIntermediateToken - (605:13,82 [23] ConditionalAttributes.cshtml) - Html - type="text/javascript" LazyIntermediateToken - (628:13,105 [1] ConditionalAttributes.cshtml) - Html - > LazyIntermediateToken - (629:13,106 [9] ConditionalAttributes.cshtml) - Html - - CSharpCode - (638:13,115 [2] ConditionalAttributes.cshtml) - LazyIntermediateToken - (638:13,115 [2] ConditionalAttributes.cshtml) - CSharp - \n + CSharpCode - (638:13,115 [6] ConditionalAttributes.cshtml) + LazyIntermediateToken - (638:13,115 [6] ConditionalAttributes.cshtml) - CSharp - \n + HtmlContent - (644:14,4 [2] ConditionalAttributes.cshtml) + LazyIntermediateToken - (644:14,4 [2] ConditionalAttributes.cshtml) - Html -

+ CSharpCode - (663:14,23 [2] ConditionalAttributes.cshtml) + LazyIntermediateToken - (663:14,23 [2] ConditionalAttributes.cshtml) - CSharp - \n Inject - Inject - Inject - diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes_DesignTime.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes_DesignTime.mappings.txt index 06a436ff701..46e2d14236f 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes_DesignTime.mappings.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes_DesignTime.mappings.txt @@ -129,10 +129,22 @@ Generated Location: (6616:193,112 [6] ) | | -Source Location: (638:13,115 [2] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes.cshtml) +Source Location: (638:13,115 [6] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes.cshtml) +| + | +Generated Location: (6906:201,115 [6] ) +| + | + +Source Location: (655:14,15 [4] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes.cshtml) +|null| +Generated Location: (7096:209,15 [4] ) +|null| + +Source Location: (663:14,23 [2] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes.cshtml) | | -Generated Location: (6906:201,115 [2] ) +Generated Location: (7293:216,23 [2] ) | | diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes_Runtime.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes_Runtime.codegen.cs index a6735c47762..c1bbb67fd09 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes_Runtime.codegen.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes_Runtime.codegen.cs @@ -1,4 +1,4 @@ -#pragma checksum "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes.cshtml" "{8829d00f-11b8-4213-878b-770e8597ac16}" "06e553c9dddd22392e81b4db3d16d097612b3552ffeaa58d015a2e3dedcf6c3a" +#pragma checksum "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes.cshtml" "{8829d00f-11b8-4213-878b-770e8597ac16}" "ea68cb71b106404af0072bb70c04f6d73d165cf4aabc5d838b668d681625b53c" // #pragma warning disable 1591 [assembly: global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemAttribute(typeof(AspNetCore.TestFiles_IntegrationTests_CodeGenerationIntegrationTest_ConditionalAttributes), @"mvc.1.0.view", @"/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes.cshtml")] @@ -14,7 +14,7 @@ namespace AspNetCore using global::Microsoft.AspNetCore.Mvc.ViewFeatures; #line default #line hidden - [global::Microsoft.AspNetCore.Razor.Hosting.RazorSourceChecksumAttribute(@"Sha256", @"06e553c9dddd22392e81b4db3d16d097612b3552ffeaa58d015a2e3dedcf6c3a", @"/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes.cshtml")] + [global::Microsoft.AspNetCore.Razor.Hosting.RazorSourceChecksumAttribute(@"Sha256", @"ea68cb71b106404af0072bb70c04f6d73d165cf4aabc5d838b668d681625b53c", @"/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes.cshtml")] [global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemMetadataAttribute("Identifier", "/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes.cshtml")] [global::System.Runtime.CompilerServices.CreateNewOnMetadataUpdateAttribute] #nullable restore @@ -188,7 +188,19 @@ public class TestFiles_IntegrationTests_CodeGenerationIntegrationTest_Conditiona #nullable disable , 426, 61, false); EndWriteAttribute(); - WriteLiteral(" type=\"text/javascript\">\r\n \r\n"); + WriteLiteral(" type=\"text/javascript\">\r\n \r\n

+ LazyIntermediateToken - (663:14,23 [2] ConditionalAttributes.cshtml) - Html - \n + CSharpCode - (665:15,0 [0] ConditionalAttributes.cshtml) + LazyIntermediateToken - (665:15,0 [0] ConditionalAttributes.cshtml) - CSharp - Inject - Inject - Inject - diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/RazorComments_DesignTime.ir.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/RazorComments_DesignTime.ir.txt index ddcf25c76ea..e1680c41e3d 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/RazorComments_DesignTime.ir.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/RazorComments_DesignTime.ir.txt @@ -73,7 +73,8 @@ LazyIntermediateToken - (408:17,0 [6] RazorComments.cshtml) - Html - LazyIntermediateToken - (473:17,65 [2] RazorComments.cshtml) - Html - \n Inject - diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/RazorComments_Runtime.ir.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/RazorComments_Runtime.ir.txt index 290deed1310..931613bfaf4 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/RazorComments_Runtime.ir.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/RazorComments_Runtime.ir.txt @@ -54,7 +54,8 @@ LazyIntermediateToken - (408:17,0 [6] RazorComments.cshtml) - Html - LazyIntermediateToken - (473:17,65 [2] RazorComments.cshtml) - Html - \n Inject - diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpBlockTest/EscapedIdentifiers_08.cspans.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpBlockTest/EscapedIdentifiers_08.cspans.txt index aa6ae7948c7..208b6b6fbb1 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpBlockTest/EscapedIdentifiers_08.cspans.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpBlockTest/EscapedIdentifiers_08.cspans.txt @@ -9,4 +9,5 @@ Markup span at (51:2,25 [45] ) - Parent: Markup block at (0:0,0 [110] ) Markup span at (96:2,70 [2] ) - Parent: Tag block at (96:2,70 [14] ) Transition span at (98:2,72 [1] ) - Parent: Expression block at (98:2,72 [8] ) Code span at (99:2,73 [7] ) - Parent: Expression block at (98:2,72 [8] ) -Markup span at (106:2,80 [4] ) - Parent: Tag block at (96:2,70 [14] ) +Markup span at (106:2,80 [1] ) - Parent: Markup block at (106:2,80 [1] ) +Markup span at (107:2,81 [3] ) - Parent: Markup block at (107:2,81 [3] ) diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpBlockTest/EscapedIdentifiers_08.stree.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpBlockTest/EscapedIdentifiers_08.stree.txt index 484eb659c35..9104e3483f3 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpBlockTest/EscapedIdentifiers_08.stree.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpBlockTest/EscapedIdentifiers_08.stree.txt @@ -58,7 +58,7 @@ MarkupStartTag - [96..110)::14 - [< @context;LF}] - Gen OpenAngle;[<]; Text;[]; - MarkupMiscAttributeContent - [97..110)::13 + MarkupMiscAttributeContent - [97..106)::9 MarkupTextLiteral - [97..98)::1 - [ ] - Gen Whitespace;[ ]; CSharpCodeBlock - [98..106)::8 @@ -69,9 +69,13 @@ CSharpCodeBlock - [99..106)::7 CSharpExpressionLiteral - [99..106)::7 - [context] - Gen Identifier;[context]; - MarkupTextLiteral - [106..110)::4 - [;LF}] - Gen + MarkupMinimizedAttributeBlock - [106..107)::1 - [;] + MarkupTextLiteral - [106..107)::1 - [;] - Gen Text;[;]; + MarkupMinimizedAttributeBlock - [107..110)::3 - [LF}] + MarkupTextLiteral - [107..109)::2 - [LF] - Gen NewLine;[LF]; + MarkupTextLiteral - [109..110)::1 - [}] - Gen Text;[}]; CloseAngle;[]; EndOfFile;[]; diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpRazorCommentsTest/RazorCommentInOpeningTagBlock.stree.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpRazorCommentsTest/RazorCommentInOpeningTagBlock.stree.txt index c44a546575b..46591bf7c95 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpRazorCommentsTest/RazorCommentInOpeningTagBlock.stree.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/CSharpRazorCommentsTest/RazorCommentInOpeningTagBlock.stree.txt @@ -4,15 +4,14 @@ MarkupStartTag - [0..26)::26 - [] - Gen OpenAngle;[<]; Text;[text]; - MarkupMiscAttributeContent - [5..25)::20 - MarkupTextLiteral - [5..6)::1 - [ ] - Gen - Whitespace;[ ]; - RazorComment - [6..25)::19 - RazorCommentTransition;[@]; - RazorCommentStar;[*]; - RazorCommentLiteral;[ razor comment ]; - RazorCommentStar;[*]; - RazorCommentTransition;[@]; + MarkupTextLiteral - [5..6)::1 - [ ] - Gen + Whitespace;[ ]; + RazorComment - [6..25)::19 + RazorCommentTransition;[@]; + RazorCommentStar;[*]; + RazorCommentLiteral;[ razor comment ]; + RazorCommentStar;[*]; + RazorCommentTransition;[@]; CloseAngle;[>]; MarkupEndTag - [26..33)::7 - [] - Gen OpenAngle;[<]; diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/ConditionalAttribute_CommentAfter.cspans.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/ConditionalAttribute_CommentAfter.cspans.txt new file mode 100644 index 00000000000..361925fdb9f --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/ConditionalAttribute_CommentAfter.cspans.txt @@ -0,0 +1,12 @@ +Markup span at (0:0,0 [2] ) - Parent: Tag block at (0:0,0 [30] ) +Markup span at (2:0,2 [8] ) - Parent: Markup block at (2:0,2 [11] ) +Transition span at (10:0,10 [1] ) - Parent: Expression block at (10:0,10 [2] ) +Code span at (11:0,11 [1] ) - Parent: Expression block at (10:0,10 [2] ) +Markup span at (12:0,12 [1] ) - Parent: Markup block at (2:0,2 [11] ) +Markup span at (13:0,13 [1] ) - Parent: Tag block at (0:0,0 [30] ) +Transition span at (14:0,14 [1] ) - Parent: Comment block at (14:0,14 [13] ) +MetaCode span at (15:0,15 [1] ) - Parent: Comment block at (14:0,14 [13] ) +Comment span at (16:0,16 [9] ) - Parent: Comment block at (14:0,14 [13] ) +MetaCode span at (25:0,25 [1] ) - Parent: Comment block at (14:0,14 [13] ) +Transition span at (26:0,26 [1] ) - Parent: Comment block at (14:0,14 [13] ) +Markup span at (27:0,27 [3] ) - Parent: Tag block at (0:0,0 [30] ) diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/ConditionalAttribute_CommentAfter.stree.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/ConditionalAttribute_CommentAfter.stree.txt new file mode 100644 index 00000000000..99d7738a6c7 --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/ConditionalAttribute_CommentAfter.stree.txt @@ -0,0 +1,41 @@ +RazorDocument - [0..30)::30 - [

] + MarkupBlock - [0..30)::30 + MarkupElement - [0..30)::30 + MarkupStartTag - [0..30)::30 - [

] - Gen + OpenAngle;[<]; + Text;[p]; + MarkupAttributeBlock - [2..13)::11 - [ class="@c"] + MarkupTextLiteral - [2..3)::1 - [ ] - Gen + Whitespace;[ ]; + MarkupTextLiteral - [3..8)::5 - [class] - Gen + Text;[class]; + Equals;[=]; + MarkupTextLiteral - [9..10)::1 - ["] - Gen + DoubleQuote;["]; + GenericBlock - [10..12)::2 + MarkupDynamicAttributeValue - [10..12)::2 - [@c] + GenericBlock - [10..12)::2 + CSharpCodeBlock - [10..12)::2 + CSharpImplicitExpression - [10..12)::2 + CSharpTransition - [10..11)::1 - Gen + Transition;[@]; + CSharpImplicitExpressionBody - [11..12)::1 + CSharpCodeBlock - [11..12)::1 + CSharpExpressionLiteral - [11..12)::1 - [c] - Gen + Identifier;[c]; + MarkupTextLiteral - [12..13)::1 - ["] - Gen + DoubleQuote;["]; + MarkupTextLiteral - [13..14)::1 - [ ] - Gen + Whitespace;[ ]; + RazorComment - [14..27)::13 + RazorCommentTransition;[@]; + RazorCommentStar;[*]; + RazorCommentLiteral;[ comment ]; + RazorCommentStar;[*]; + RazorCommentTransition;[@]; + MarkupMiscAttributeContent - [27..28)::1 + MarkupTextLiteral - [27..28)::1 - [ ] - Gen + Whitespace;[ ]; + ForwardSlash;[/]; + CloseAngle;[>]; + EndOfFile;[]; diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/ConditionalAttribute_CommentBefore.cspans.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/ConditionalAttribute_CommentBefore.cspans.txt new file mode 100644 index 00000000000..601a400d623 --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/ConditionalAttribute_CommentBefore.cspans.txt @@ -0,0 +1,11 @@ +Markup span at (0:0,0 [3] ) - Parent: Tag block at (0:0,0 [30] ) +Transition span at (3:0,3 [1] ) - Parent: Comment block at (3:0,3 [13] ) +MetaCode span at (4:0,4 [1] ) - Parent: Comment block at (3:0,3 [13] ) +Comment span at (5:0,5 [9] ) - Parent: Comment block at (3:0,3 [13] ) +MetaCode span at (14:0,14 [1] ) - Parent: Comment block at (3:0,3 [13] ) +Transition span at (15:0,15 [1] ) - Parent: Comment block at (3:0,3 [13] ) +Markup span at (16:0,16 [8] ) - Parent: Markup block at (16:0,16 [11] ) +Transition span at (24:0,24 [1] ) - Parent: Expression block at (24:0,24 [2] ) +Code span at (25:0,25 [1] ) - Parent: Expression block at (24:0,24 [2] ) +Markup span at (26:0,26 [1] ) - Parent: Markup block at (16:0,16 [11] ) +Markup span at (27:0,27 [3] ) - Parent: Tag block at (0:0,0 [30] ) diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/ConditionalAttribute_CommentBefore.stree.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/ConditionalAttribute_CommentBefore.stree.txt new file mode 100644 index 00000000000..a8aee7debe0 --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/ConditionalAttribute_CommentBefore.stree.txt @@ -0,0 +1,41 @@ +RazorDocument - [0..30)::30 - [

] + MarkupBlock - [0..30)::30 + MarkupElement - [0..30)::30 + MarkupStartTag - [0..30)::30 - [

] - Gen + OpenAngle;[<]; + Text;[p]; + MarkupTextLiteral - [2..3)::1 - [ ] - Gen + Whitespace;[ ]; + RazorComment - [3..16)::13 + RazorCommentTransition;[@]; + RazorCommentStar;[*]; + RazorCommentLiteral;[ comment ]; + RazorCommentStar;[*]; + RazorCommentTransition;[@]; + MarkupAttributeBlock - [16..27)::11 - [ class="@c"] + MarkupTextLiteral - [16..17)::1 - [ ] - Gen + Whitespace;[ ]; + MarkupTextLiteral - [17..22)::5 - [class] - Gen + Text;[class]; + Equals;[=]; + MarkupTextLiteral - [23..24)::1 - ["] - Gen + DoubleQuote;["]; + GenericBlock - [24..26)::2 + MarkupDynamicAttributeValue - [24..26)::2 - [@c] + GenericBlock - [24..26)::2 + CSharpCodeBlock - [24..26)::2 + CSharpImplicitExpression - [24..26)::2 + CSharpTransition - [24..25)::1 - Gen + Transition;[@]; + CSharpImplicitExpressionBody - [25..26)::1 + CSharpCodeBlock - [25..26)::1 + CSharpExpressionLiteral - [25..26)::1 - [c] - Gen + Identifier;[c]; + MarkupTextLiteral - [26..27)::1 - ["] - Gen + DoubleQuote;["]; + MarkupMiscAttributeContent - [27..28)::1 + MarkupTextLiteral - [27..28)::1 - [ ] - Gen + Whitespace;[ ]; + ForwardSlash;[/]; + CloseAngle;[>]; + EndOfFile;[]; diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/ConditionalAttribute_DynamicContentAfter.cspans.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/ConditionalAttribute_DynamicContentAfter.cspans.txt new file mode 100644 index 00000000000..1afcd2567c6 --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/ConditionalAttribute_DynamicContentAfter.cspans.txt @@ -0,0 +1,9 @@ +Markup span at (0:0,0 [2] ) - Parent: Tag block at (0:0,0 [19] ) +Markup span at (2:0,2 [8] ) - Parent: Markup block at (2:0,2 [11] ) +Transition span at (10:0,10 [1] ) - Parent: Expression block at (10:0,10 [2] ) +Code span at (11:0,11 [1] ) - Parent: Expression block at (10:0,10 [2] ) +Markup span at (12:0,12 [1] ) - Parent: Markup block at (2:0,2 [11] ) +Markup span at (13:0,13 [1] ) - Parent: Tag block at (0:0,0 [19] ) +Transition span at (14:0,14 [1] ) - Parent: Expression block at (14:0,14 [2] ) +Code span at (15:0,15 [1] ) - Parent: Expression block at (14:0,14 [2] ) +Markup span at (16:0,16 [3] ) - Parent: Tag block at (0:0,0 [19] ) diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/ConditionalAttribute_DynamicContentAfter.stree.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/ConditionalAttribute_DynamicContentAfter.stree.txt new file mode 100644 index 00000000000..4e4b3cb53aa --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/ConditionalAttribute_DynamicContentAfter.stree.txt @@ -0,0 +1,44 @@ +RazorDocument - [0..19)::19 - [

] + MarkupBlock - [0..19)::19 + MarkupElement - [0..19)::19 + MarkupStartTag - [0..19)::19 - [

] - Gen + OpenAngle;[<]; + Text;[p]; + MarkupAttributeBlock - [2..13)::11 - [ class="@c"] + MarkupTextLiteral - [2..3)::1 - [ ] - Gen + Whitespace;[ ]; + MarkupTextLiteral - [3..8)::5 - [class] - Gen + Text;[class]; + Equals;[=]; + MarkupTextLiteral - [9..10)::1 - ["] - Gen + DoubleQuote;["]; + GenericBlock - [10..12)::2 + MarkupDynamicAttributeValue - [10..12)::2 - [@c] + GenericBlock - [10..12)::2 + CSharpCodeBlock - [10..12)::2 + CSharpImplicitExpression - [10..12)::2 + CSharpTransition - [10..11)::1 - Gen + Transition;[@]; + CSharpImplicitExpressionBody - [11..12)::1 + CSharpCodeBlock - [11..12)::1 + CSharpExpressionLiteral - [11..12)::1 - [c] - Gen + Identifier;[c]; + MarkupTextLiteral - [12..13)::1 - ["] - Gen + DoubleQuote;["]; + MarkupMiscAttributeContent - [13..16)::3 + MarkupTextLiteral - [13..14)::1 - [ ] - Gen + Whitespace;[ ]; + CSharpCodeBlock - [14..16)::2 + CSharpImplicitExpression - [14..16)::2 + CSharpTransition - [14..15)::1 - Gen + Transition;[@]; + CSharpImplicitExpressionBody - [15..16)::1 + CSharpCodeBlock - [15..16)::1 + CSharpExpressionLiteral - [15..16)::1 - [x] - Gen + Identifier;[x]; + MarkupMiscAttributeContent - [16..17)::1 + MarkupTextLiteral - [16..17)::1 - [ ] - Gen + Whitespace;[ ]; + ForwardSlash;[/]; + CloseAngle;[>]; + EndOfFile;[]; diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/ConditionalAttribute_DynamicContentBefore.cspans.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/ConditionalAttribute_DynamicContentBefore.cspans.txt new file mode 100644 index 00000000000..a17d0422e53 --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/ConditionalAttribute_DynamicContentBefore.cspans.txt @@ -0,0 +1,8 @@ +Markup span at (0:0,0 [3] ) - Parent: Tag block at (0:0,0 [19] ) +Transition span at (3:0,3 [1] ) - Parent: Expression block at (3:0,3 [2] ) +Code span at (4:0,4 [1] ) - Parent: Expression block at (3:0,3 [2] ) +Markup span at (5:0,5 [8] ) - Parent: Markup block at (5:0,5 [11] ) +Transition span at (13:0,13 [1] ) - Parent: Expression block at (13:0,13 [2] ) +Code span at (14:0,14 [1] ) - Parent: Expression block at (13:0,13 [2] ) +Markup span at (15:0,15 [1] ) - Parent: Markup block at (5:0,5 [11] ) +Markup span at (16:0,16 [3] ) - Parent: Tag block at (0:0,0 [19] ) diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/ConditionalAttribute_DynamicContentBefore.stree.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/ConditionalAttribute_DynamicContentBefore.stree.txt new file mode 100644 index 00000000000..48d0f66ca4b --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/ConditionalAttribute_DynamicContentBefore.stree.txt @@ -0,0 +1,44 @@ +RazorDocument - [0..19)::19 - [

] + MarkupBlock - [0..19)::19 + MarkupElement - [0..19)::19 + MarkupStartTag - [0..19)::19 - [

] - Gen + OpenAngle;[<]; + Text;[p]; + MarkupMiscAttributeContent - [2..5)::3 + MarkupTextLiteral - [2..3)::1 - [ ] - Gen + Whitespace;[ ]; + CSharpCodeBlock - [3..5)::2 + CSharpImplicitExpression - [3..5)::2 + CSharpTransition - [3..4)::1 - Gen + Transition;[@]; + CSharpImplicitExpressionBody - [4..5)::1 + CSharpCodeBlock - [4..5)::1 + CSharpExpressionLiteral - [4..5)::1 - [x] - Gen + Identifier;[x]; + MarkupAttributeBlock - [5..16)::11 - [ class="@c"] + MarkupTextLiteral - [5..6)::1 - [ ] - Gen + Whitespace;[ ]; + MarkupTextLiteral - [6..11)::5 - [class] - Gen + Text;[class]; + Equals;[=]; + MarkupTextLiteral - [12..13)::1 - ["] - Gen + DoubleQuote;["]; + GenericBlock - [13..15)::2 + MarkupDynamicAttributeValue - [13..15)::2 - [@c] + GenericBlock - [13..15)::2 + CSharpCodeBlock - [13..15)::2 + CSharpImplicitExpression - [13..15)::2 + CSharpTransition - [13..14)::1 - Gen + Transition;[@]; + CSharpImplicitExpressionBody - [14..15)::1 + CSharpCodeBlock - [14..15)::1 + CSharpExpressionLiteral - [14..15)::1 - [c] - Gen + Identifier;[c]; + MarkupTextLiteral - [15..16)::1 - ["] - Gen + DoubleQuote;["]; + MarkupMiscAttributeContent - [16..17)::1 + MarkupTextLiteral - [16..17)::1 - [ ] - Gen + Whitespace;[ ]; + ForwardSlash;[/]; + CloseAngle;[>]; + EndOfFile;[]; diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/ConditionalAttribute_DynamicContentBefore_02.cspans.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/ConditionalAttribute_DynamicContentBefore_02.cspans.txt new file mode 100644 index 00000000000..3360fe43295 --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/ConditionalAttribute_DynamicContentBefore_02.cspans.txt @@ -0,0 +1,10 @@ +Markup span at (0:0,0 [3] ) - Parent: Tag block at (0:0,0 [25] ) +Transition span at (3:0,3 [1] ) - Parent: Expression block at (3:0,3 [8] ) +MetaCode span at (4:0,4 [1] ) - Parent: Expression block at (3:0,3 [8] ) +Code span at (5:0,5 [5] ) - Parent: Expression block at (3:0,3 [8] ) +MetaCode span at (10:0,10 [1] ) - Parent: Expression block at (3:0,3 [8] ) +Markup span at (11:0,11 [8] ) - Parent: Markup block at (11:0,11 [11] ) +Transition span at (19:0,19 [1] ) - Parent: Expression block at (19:0,19 [2] ) +Code span at (20:0,20 [1] ) - Parent: Expression block at (19:0,19 [2] ) +Markup span at (21:0,21 [1] ) - Parent: Markup block at (11:0,11 [11] ) +Markup span at (22:0,22 [3] ) - Parent: Tag block at (0:0,0 [25] ) diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/ConditionalAttribute_DynamicContentBefore_02.stree.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/ConditionalAttribute_DynamicContentBefore_02.stree.txt new file mode 100644 index 00000000000..0bfb01eb951 --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/ConditionalAttribute_DynamicContentBefore_02.stree.txt @@ -0,0 +1,52 @@ +RazorDocument - [0..25)::25 - [

] + MarkupBlock - [0..25)::25 + MarkupElement - [0..25)::25 + MarkupStartTag - [0..25)::25 - [

] - Gen + OpenAngle;[<]; + Text;[p]; + MarkupMiscAttributeContent - [2..11)::9 + MarkupTextLiteral - [2..3)::1 - [ ] - Gen + Whitespace;[ ]; + CSharpCodeBlock - [3..11)::8 + CSharpExplicitExpression - [3..11)::8 + CSharpTransition - [3..4)::1 - Gen + Transition;[@]; + CSharpExplicitExpressionBody - [4..11)::7 + RazorMetaCode - [4..5)::1 - Gen + LeftParenthesis;[(]; + CSharpCodeBlock - [5..10)::5 + CSharpExpressionLiteral - [5..10)::5 - [x + y] - Gen + Identifier;[x]; + Whitespace;[ ]; + Plus;[+]; + Whitespace;[ ]; + Identifier;[y]; + RazorMetaCode - [10..11)::1 - Gen + RightParenthesis;[)]; + MarkupAttributeBlock - [11..22)::11 - [ class="@c"] + MarkupTextLiteral - [11..12)::1 - [ ] - Gen + Whitespace;[ ]; + MarkupTextLiteral - [12..17)::5 - [class] - Gen + Text;[class]; + Equals;[=]; + MarkupTextLiteral - [18..19)::1 - ["] - Gen + DoubleQuote;["]; + GenericBlock - [19..21)::2 + MarkupDynamicAttributeValue - [19..21)::2 - [@c] + GenericBlock - [19..21)::2 + CSharpCodeBlock - [19..21)::2 + CSharpImplicitExpression - [19..21)::2 + CSharpTransition - [19..20)::1 - Gen + Transition;[@]; + CSharpImplicitExpressionBody - [20..21)::1 + CSharpCodeBlock - [20..21)::1 + CSharpExpressionLiteral - [20..21)::1 - [c] - Gen + Identifier;[c]; + MarkupTextLiteral - [21..22)::1 - ["] - Gen + DoubleQuote;["]; + MarkupMiscAttributeContent - [22..23)::1 + MarkupTextLiteral - [22..23)::1 - [ ] - Gen + Whitespace;[ ]; + ForwardSlash;[/]; + CloseAngle;[>]; + EndOfFile;[]; diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/ConditionalAttribute_DynamicContentBefore_03.cspans.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/ConditionalAttribute_DynamicContentBefore_03.cspans.txt new file mode 100644 index 00000000000..72a255eca54 --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/ConditionalAttribute_DynamicContentBefore_03.cspans.txt @@ -0,0 +1,13 @@ +Markup span at (0:0,0 [3] ) - Parent: Tag block at (0:0,0 [33] ) +Transition span at (3:0,3 [1] ) - Parent: Statement block at (3:0,3 [16] ) +MetaCode span at (4:0,4 [1] ) - Parent: Statement block at (3:0,3 [16] ) +Code span at (5:0,5 [9] ) - Parent: Statement block at (3:0,3 [16] ) +Transition span at (14:0,14 [1] ) - Parent: Expression block at (14:0,14 [2] ) +Code span at (15:0,15 [1] ) - Parent: Expression block at (14:0,14 [2] ) +Code span at (16:0,16 [2] ) - Parent: Statement block at (3:0,3 [16] ) +MetaCode span at (18:0,18 [1] ) - Parent: Statement block at (3:0,3 [16] ) +Markup span at (19:0,19 [8] ) - Parent: Markup block at (19:0,19 [11] ) +Transition span at (27:0,27 [1] ) - Parent: Expression block at (27:0,27 [2] ) +Code span at (28:0,28 [1] ) - Parent: Expression block at (27:0,27 [2] ) +Markup span at (29:0,29 [1] ) - Parent: Markup block at (19:0,19 [11] ) +Markup span at (30:0,30 [3] ) - Parent: Tag block at (0:0,0 [33] ) diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/ConditionalAttribute_DynamicContentBefore_03.stree.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/ConditionalAttribute_DynamicContentBefore_03.stree.txt new file mode 100644 index 00000000000..c9f30d10b3b --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/ConditionalAttribute_DynamicContentBefore_03.stree.txt @@ -0,0 +1,66 @@ +RazorDocument - [0..33)::33 - [

] + MarkupBlock - [0..33)::33 + MarkupElement - [0..33)::33 + MarkupStartTag - [0..33)::33 - [

] - Gen + OpenAngle;[<]; + Text;[p]; + MarkupMiscAttributeContent - [2..19)::17 + MarkupTextLiteral - [2..3)::1 - [ ] - Gen + Whitespace;[ ]; + CSharpCodeBlock - [3..19)::16 + CSharpStatement - [3..19)::16 + CSharpTransition - [3..4)::1 - Gen + Transition;[@]; + CSharpStatementBody - [4..19)::15 + RazorMetaCode - [4..5)::1 - Gen + LeftBrace;[{]; + CSharpCodeBlock - [5..18)::13 + CSharpStatementLiteral - [5..14)::9 - [if (x) { ] - Gen + Keyword;[if]; + Whitespace;[ ]; + LeftParenthesis;[(]; + Identifier;[x]; + RightParenthesis;[)]; + Whitespace;[ ]; + LeftBrace;[{]; + Whitespace;[ ]; + CSharpCodeBlock - [14..16)::2 + CSharpImplicitExpression - [14..16)::2 + CSharpTransition - [14..15)::1 - Gen + Transition;[@]; + CSharpImplicitExpressionBody - [15..16)::1 + CSharpCodeBlock - [15..16)::1 + CSharpExpressionLiteral - [15..16)::1 - [x] - Gen + Identifier;[x]; + CSharpStatementLiteral - [16..18)::2 - [ }] - Gen + Whitespace;[ ]; + RightBrace;[}]; + RazorMetaCode - [18..19)::1 - Gen + RightBrace;[}]; + MarkupAttributeBlock - [19..30)::11 - [ class="@c"] + MarkupTextLiteral - [19..20)::1 - [ ] - Gen + Whitespace;[ ]; + MarkupTextLiteral - [20..25)::5 - [class] - Gen + Text;[class]; + Equals;[=]; + MarkupTextLiteral - [26..27)::1 - ["] - Gen + DoubleQuote;["]; + GenericBlock - [27..29)::2 + MarkupDynamicAttributeValue - [27..29)::2 - [@c] + GenericBlock - [27..29)::2 + CSharpCodeBlock - [27..29)::2 + CSharpImplicitExpression - [27..29)::2 + CSharpTransition - [27..28)::1 - Gen + Transition;[@]; + CSharpImplicitExpressionBody - [28..29)::1 + CSharpCodeBlock - [28..29)::1 + CSharpExpressionLiteral - [28..29)::1 - [c] - Gen + Identifier;[c]; + MarkupTextLiteral - [29..30)::1 - ["] - Gen + DoubleQuote;["]; + MarkupMiscAttributeContent - [30..31)::1 + MarkupTextLiteral - [30..31)::1 - [ ] - Gen + Whitespace;[ ]; + ForwardSlash;[/]; + CloseAngle;[>]; + EndOfFile;[]; diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/ConditionalAttribute_DynamicContentBefore_04.cspans.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/ConditionalAttribute_DynamicContentBefore_04.cspans.txt new file mode 100644 index 00000000000..7e28da18a1f --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/ConditionalAttribute_DynamicContentBefore_04.cspans.txt @@ -0,0 +1,8 @@ +Markup span at (0:0,0 [3] ) - Parent: Tag block at (0:0,0 [20] ) +Markup span at (3:0,3 [1] ) - Parent: Tag block at (0:0,0 [20] ) +Markup span at (4:0,4 [2] ) - Parent: Markup block at (4:0,4 [2] ) +Markup span at (6:0,6 [8] ) - Parent: Markup block at (6:0,6 [11] ) +Transition span at (14:0,14 [1] ) - Parent: Expression block at (14:0,14 [2] ) +Code span at (15:0,15 [1] ) - Parent: Expression block at (14:0,14 [2] ) +Markup span at (16:0,16 [1] ) - Parent: Markup block at (6:0,6 [11] ) +Markup span at (17:0,17 [3] ) - Parent: Tag block at (0:0,0 [20] ) diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/ConditionalAttribute_DynamicContentBefore_04.stree.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/ConditionalAttribute_DynamicContentBefore_04.stree.txt new file mode 100644 index 00000000000..136a533f762 --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/ConditionalAttribute_DynamicContentBefore_04.stree.txt @@ -0,0 +1,41 @@ +RazorDocument - [0..20)::20 - [

] + MarkupBlock - [0..20)::20 + MarkupElement - [0..20)::20 + MarkupStartTag - [0..20)::20 - [

] - Gen + OpenAngle;[<]; + Text;[p]; + MarkupTextLiteral - [2..3)::1 - [ ] - Gen + Whitespace;[ ]; + MarkupEphemeralTextLiteral - [3..4)::1 - [@] - Gen + Transition;[@]; + MarkupMinimizedAttributeBlock - [4..6)::2 - [@x] + MarkupTextLiteral - [4..6)::2 - [@x] - Gen + Transition;[@]; + Text;[x]; + MarkupAttributeBlock - [6..17)::11 - [ class="@c"] + MarkupTextLiteral - [6..7)::1 - [ ] - Gen + Whitespace;[ ]; + MarkupTextLiteral - [7..12)::5 - [class] - Gen + Text;[class]; + Equals;[=]; + MarkupTextLiteral - [13..14)::1 - ["] - Gen + DoubleQuote;["]; + GenericBlock - [14..16)::2 + MarkupDynamicAttributeValue - [14..16)::2 - [@c] + GenericBlock - [14..16)::2 + CSharpCodeBlock - [14..16)::2 + CSharpImplicitExpression - [14..16)::2 + CSharpTransition - [14..15)::1 - Gen + Transition;[@]; + CSharpImplicitExpressionBody - [15..16)::1 + CSharpCodeBlock - [15..16)::1 + CSharpExpressionLiteral - [15..16)::1 - [c] - Gen + Identifier;[c]; + MarkupTextLiteral - [16..17)::1 - ["] - Gen + DoubleQuote;["]; + MarkupMiscAttributeContent - [17..18)::1 + MarkupTextLiteral - [17..18)::1 - [ ] - Gen + Whitespace;[ ]; + ForwardSlash;[/]; + CloseAngle;[>]; + EndOfFile;[]; diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/ConditionalAttribute_InvalidContentBefore.cspans.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/ConditionalAttribute_InvalidContentBefore.cspans.txt new file mode 100644 index 00000000000..f3b1e46a965 --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/ConditionalAttribute_InvalidContentBefore.cspans.txt @@ -0,0 +1,4 @@ +Markup span at (0:0,0 [15] ) - Parent: Tag block at (0:0,0 [21] ) +Transition span at (15:0,15 [1] ) - Parent: Expression block at (15:0,15 [2] ) +Code span at (16:0,16 [1] ) - Parent: Expression block at (15:0,15 [2] ) +Markup span at (17:0,17 [4] ) - Parent: Tag block at (0:0,0 [21] ) diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/ConditionalAttribute_InvalidContentBefore.stree.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/ConditionalAttribute_InvalidContentBefore.stree.txt new file mode 100644 index 00000000000..28ae108fc51 --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/ConditionalAttribute_InvalidContentBefore.stree.txt @@ -0,0 +1,30 @@ +RazorDocument - [0..21)::21 - [

] + MarkupBlock - [0..21)::21 + MarkupElement - [0..21)::21 + MarkupStartTag - [0..21)::21 - [

] - Gen + OpenAngle;[<]; + Text;[p]; + MarkupMiscAttributeContent - [2..19)::17 + MarkupTextLiteral - [2..15)::13 - [ "ab" class="] - Gen + Whitespace;[ ]; + DoubleQuote;["]; + Text;[ab]; + DoubleQuote;["]; + Whitespace;[ ]; + Text;[class]; + Equals;[=]; + DoubleQuote;["]; + CSharpCodeBlock - [15..17)::2 + CSharpImplicitExpression - [15..17)::2 + CSharpTransition - [15..16)::1 - Gen + Transition;[@]; + CSharpImplicitExpressionBody - [16..17)::1 + CSharpCodeBlock - [16..17)::1 + CSharpExpressionLiteral - [16..17)::1 - [c] - Gen + Identifier;[c]; + MarkupTextLiteral - [17..19)::2 - [" ] - Gen + DoubleQuote;["]; + Whitespace;[ ]; + ForwardSlash;[/]; + CloseAngle;[>]; + EndOfFile;[]; diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/EscapedAttributeName_Eof.cspans.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/EscapedAttributeName_Eof.cspans.txt new file mode 100644 index 00000000000..f56e27cddc5 --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/EscapedAttributeName_Eof.cspans.txt @@ -0,0 +1,3 @@ +Markup span at (0:0,0 [3] ) - Parent: Tag block at (0:0,0 [5] ) +Markup span at (3:0,3 [1] ) - Parent: Tag block at (0:0,0 [5] ) +Markup span at (4:0,4 [1] ) - Parent: Markup block at (4:0,4 [1] ) diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/EscapedAttributeName_Eof.stree.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/EscapedAttributeName_Eof.stree.txt new file mode 100644 index 00000000000..c33f401ff88 --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/EscapedAttributeName_Eof.stree.txt @@ -0,0 +1,15 @@ +RazorDocument - [0..5)::5 - [

+ OpenAngle;[<]; + Text;[p]; + MarkupTextLiteral - [2..3)::1 - [ ] - Gen + Whitespace;[ ]; + MarkupEphemeralTextLiteral - [3..4)::1 - [@] - Gen + Transition;[@]; + MarkupMinimizedAttributeBlock - [4..5)::1 - [@] + MarkupTextLiteral - [4..5)::1 - [@] - Gen + Transition;[@]; + CloseAngle;[]; + EndOfFile;[]; diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/EscapedAttributeName_InvalidName.cspans.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/EscapedAttributeName_InvalidName.cspans.txt new file mode 100644 index 00000000000..768edf20f10 --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/EscapedAttributeName_InvalidName.cspans.txt @@ -0,0 +1,4 @@ +Markup span at (0:0,0 [3] ) - Parent: Tag block at (0:0,0 [17] ) +Markup span at (3:0,3 [1] ) - Parent: Tag block at (0:0,0 [17] ) +Markup span at (4:0,4 [10] ) - Parent: Markup block at (4:0,4 [10] ) +Markup span at (14:0,14 [3] ) - Parent: Tag block at (0:0,0 [17] ) diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/EscapedAttributeName_InvalidName.stree.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/EscapedAttributeName_InvalidName.stree.txt new file mode 100644 index 00000000000..b3a855fdc03 --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/EscapedAttributeName_InvalidName.stree.txt @@ -0,0 +1,22 @@ +RazorDocument - [0..17)::17 - [

] + MarkupBlock - [0..17)::17 + MarkupElement - [0..17)::17 + MarkupStartTag - [0..17)::17 - [

] - Gen + OpenAngle;[<]; + Text;[p]; + MarkupTextLiteral - [2..3)::1 - [ ] - Gen + Whitespace;[ ]; + MarkupEphemeralTextLiteral - [3..4)::1 - [@] - Gen + Transition;[@]; + MarkupMinimizedAttributeBlock - [4..14)::10 - [@"invalid"] + MarkupTextLiteral - [4..14)::10 - [@"invalid"] - Gen + Transition;[@]; + DoubleQuote;["]; + Text;[invalid]; + DoubleQuote;["]; + MarkupMiscAttributeContent - [14..15)::1 + MarkupTextLiteral - [14..15)::1 - [ ] - Gen + Whitespace;[ ]; + ForwardSlash;[/]; + CloseAngle;[>]; + EndOfFile;[]; diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/EscapedAttributeName_Minimized.cspans.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/EscapedAttributeName_Minimized.cspans.txt new file mode 100644 index 00000000000..65a083eaf48 --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/EscapedAttributeName_Minimized.cspans.txt @@ -0,0 +1,4 @@ +Markup span at (0:0,0 [3] ) - Parent: Tag block at (0:0,0 [12] ) +Markup span at (3:0,3 [1] ) - Parent: Tag block at (0:0,0 [12] ) +Markup span at (4:0,4 [5] ) - Parent: Markup block at (4:0,4 [5] ) +Markup span at (9:0,9 [3] ) - Parent: Tag block at (0:0,0 [12] ) diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/EscapedAttributeName_Minimized.stree.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/EscapedAttributeName_Minimized.stree.txt new file mode 100644 index 00000000000..e995535e191 --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/EscapedAttributeName_Minimized.stree.txt @@ -0,0 +1,20 @@ +RazorDocument - [0..12)::12 - [

] + MarkupBlock - [0..12)::12 + MarkupElement - [0..12)::12 + MarkupStartTag - [0..12)::12 - [

] - Gen + OpenAngle;[<]; + Text;[p]; + MarkupTextLiteral - [2..3)::1 - [ ] - Gen + Whitespace;[ ]; + MarkupEphemeralTextLiteral - [3..4)::1 - [@] - Gen + Transition;[@]; + MarkupMinimizedAttributeBlock - [4..9)::5 - [@attr] + MarkupTextLiteral - [4..9)::5 - [@attr] - Gen + Transition;[@]; + Text;[attr]; + MarkupMiscAttributeContent - [9..10)::1 + MarkupTextLiteral - [9..10)::1 - [ ] - Gen + Whitespace;[ ]; + ForwardSlash;[/]; + CloseAngle;[>]; + EndOfFile;[]; diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/EscapedAttributeName_WithValue.cspans.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/EscapedAttributeName_WithValue.cspans.txt new file mode 100644 index 00000000000..1007a00e136 --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/EscapedAttributeName_WithValue.cspans.txt @@ -0,0 +1,6 @@ +Markup span at (0:0,0 [3] ) - Parent: Tag block at (0:0,0 [20] ) +Markup span at (3:0,3 [1] ) - Parent: Tag block at (0:0,0 [20] ) +Markup span at (4:0,4 [7] ) - Parent: Markup block at (4:0,4 [13] ) +Markup span at (11:0,11 [5] ) - Parent: Markup block at (4:0,4 [13] ) +Markup span at (16:0,16 [1] ) - Parent: Markup block at (4:0,4 [13] ) +Markup span at (17:0,17 [3] ) - Parent: Tag block at (0:0,0 [20] ) diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/EscapedAttributeName_WithValue.stree.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/EscapedAttributeName_WithValue.stree.txt new file mode 100644 index 00000000000..12c5fb8ca0b --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlAttributeTest/EscapedAttributeName_WithValue.stree.txt @@ -0,0 +1,29 @@ +RazorDocument - [0..20)::20 - [

] + MarkupBlock - [0..20)::20 + MarkupElement - [0..20)::20 + MarkupStartTag - [0..20)::20 - [

] - Gen + OpenAngle;[<]; + Text;[p]; + MarkupTextLiteral - [2..3)::1 - [ ] - Gen + Whitespace;[ ]; + MarkupEphemeralTextLiteral - [3..4)::1 - [@] - Gen + Transition;[@]; + MarkupAttributeBlock - [4..17)::13 - [@attr="value"] + MarkupTextLiteral - [4..9)::5 - [@attr] - Gen + Transition;[@]; + Text;[attr]; + Equals;[=]; + MarkupTextLiteral - [10..11)::1 - ["] - Gen + DoubleQuote;["]; + GenericBlock - [11..16)::5 + MarkupLiteralAttributeValue - [11..16)::5 - [value] + MarkupTextLiteral - [11..16)::5 - [value] - Gen + Text;[value]; + MarkupTextLiteral - [16..17)::1 - ["] - Gen + DoubleQuote;["]; + MarkupMiscAttributeContent - [17..18)::1 + MarkupTextLiteral - [17..18)::1 - [ ] - Gen + Whitespace;[ ]; + ForwardSlash;[/]; + CloseAngle;[>]; + EndOfFile;[]; diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlToCodeSwitchTest/SwitchesToCodeWhenSwapCharacterEncounteredMidTag.stree.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlToCodeSwitchTest/SwitchesToCodeWhenSwapCharacterEncounteredMidTag.stree.txt index f88861c33a6..90bdb2cbe61 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlToCodeSwitchTest/SwitchesToCodeWhenSwapCharacterEncounteredMidTag.stree.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/HtmlToCodeSwitchTest/SwitchesToCodeWhenSwapCharacterEncounteredMidTag.stree.txt @@ -15,7 +15,7 @@ MarkupStartTag - [2..14)::12 - [] - Gen OpenAngle;[<]; Text;[foo]; - MarkupMiscAttributeContent - [6..12)::6 + MarkupMiscAttributeContent - [6..11)::5 MarkupTextLiteral - [6..7)::1 - [ ] - Gen Whitespace;[ ]; CSharpCodeBlock - [7..11)::4 @@ -26,6 +26,7 @@ CSharpCodeBlock - [8..11)::3 CSharpExpressionLiteral - [8..11)::3 - [bar] - Gen Identifier;[bar]; + MarkupMiscAttributeContent - [11..12)::1 MarkupTextLiteral - [11..12)::1 - [ ] - Gen Whitespace;[ ]; ForwardSlash;[/]; diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/TagHelperBlockRewriterTest/AllowsCompatibleTagStructures_DirectiveAttribute_SelfClosing.stree.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/TagHelperBlockRewriterTest/AllowsCompatibleTagStructures_DirectiveAttribute_SelfClosing.stree.txt index 127a0c96746..17fb8f7a506 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/TagHelperBlockRewriterTest/AllowsCompatibleTagStructures_DirectiveAttribute_SelfClosing.stree.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/TagHelperBlockRewriterTest/AllowsCompatibleTagStructures_DirectiveAttribute_SelfClosing.stree.txt @@ -4,7 +4,7 @@ MarkupStartTag - [0..25)::25 - [] - Gen OpenAngle;[<]; Text;[input]; - MarkupMiscAttributeContent - [6..23)::17 + MarkupMiscAttributeContent - [6..15)::9 MarkupTextLiteral - [6..7)::1 - [ ] - Gen Whitespace;[ ]; CSharpCodeBlock - [7..15)::8 @@ -15,6 +15,7 @@ CSharpCodeBlock - [8..15)::7 CSharpExpressionLiteral - [8..15)::7 - [onclick] - Gen Identifier;[onclick]; + MarkupMiscAttributeContent - [15..23)::8 MarkupTextLiteral - [15..17)::2 - [="] - Gen Equals;[=]; DoubleQuote;["]; diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/TagHelperBlockRewriterTest/AllowsCompatibleTagStructures_DirectiveAttribute_Void.stree.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/TagHelperBlockRewriterTest/AllowsCompatibleTagStructures_DirectiveAttribute_Void.stree.txt index 7d6cb8d775d..ec24da08de9 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/TagHelperBlockRewriterTest/AllowsCompatibleTagStructures_DirectiveAttribute_Void.stree.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/TagHelperBlockRewriterTest/AllowsCompatibleTagStructures_DirectiveAttribute_Void.stree.txt @@ -4,7 +4,7 @@ MarkupStartTag - [0..24)::24 - [] - Gen OpenAngle;[<]; Text;[input]; - MarkupMiscAttributeContent - [6..23)::17 + MarkupMiscAttributeContent - [6..15)::9 MarkupTextLiteral - [6..7)::1 - [ ] - Gen Whitespace;[ ]; CSharpCodeBlock - [7..15)::8 @@ -15,6 +15,7 @@ CSharpCodeBlock - [8..15)::7 CSharpExpressionLiteral - [8..15)::7 - [onclick] - Gen Identifier;[onclick]; + MarkupMiscAttributeContent - [15..23)::8 MarkupTextLiteral - [15..17)::2 - [="] - Gen Equals;[=]; DoubleQuote;["]; diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/TagHelperBlockRewriterTest/CreatesErrorForMalformedTagHelpersWithAttributes13.stree.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/TagHelperBlockRewriterTest/CreatesErrorForMalformedTagHelpersWithAttributes13.stree.txt index e3f29b33746..63b33f86d1d 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/TagHelperBlockRewriterTest/CreatesErrorForMalformedTagHelpersWithAttributes13.stree.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/TagHelperBlockRewriterTest/CreatesErrorForMalformedTagHelpersWithAttributes13.stree.txt @@ -4,7 +4,7 @@ MarkupTagHelperStartTag - [0..29)::29 - [

] - Gen OpenAngle;[<]; Text;[p]; - MarkupMiscAttributeContent - [2..28)::26 + MarkupMiscAttributeContent - [2..16)::14 MarkupTextLiteral - [2..3)::1 - [ ] - Gen Whitespace;[ ]; CSharpCodeBlock - [3..16)::13 @@ -17,12 +17,19 @@ Identifier;[DateTime]; Dot;[.]; Identifier;[Now]; - MarkupTextLiteral - [16..28)::12 - [ class="btn"] - Gen + MarkupAttributeBlock - [16..28)::12 - [ class="btn"] + MarkupTextLiteral - [16..17)::1 - [ ] - Gen Whitespace;[ ]; + MarkupTextLiteral - [17..22)::5 - [class] - Gen Text;[class]; - Equals;[=]; + Equals;[=]; + MarkupTextLiteral - [23..24)::1 - ["] - Gen DoubleQuote;["]; - Text;[btn]; + GenericBlock - [24..27)::3 + MarkupLiteralAttributeValue - [24..27)::3 - [btn] + MarkupTextLiteral - [24..27)::3 - [btn] - Gen + Text;[btn]; + MarkupTextLiteral - [27..28)::1 - ["] - Gen DoubleQuote;["]; CloseAngle;[>]; MarkupTagHelperEndTag - [29..33)::4 - [

] diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/TagHelperBlockRewriterTest/CreatesErrorForMalformedTagHelpersWithAttributes14.stree.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/TagHelperBlockRewriterTest/CreatesErrorForMalformedTagHelpersWithAttributes14.stree.txt index 427584cf397..cef184ddffb 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/TagHelperBlockRewriterTest/CreatesErrorForMalformedTagHelpersWithAttributes14.stree.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/TagHelperBlockRewriterTest/CreatesErrorForMalformedTagHelpersWithAttributes14.stree.txt @@ -4,7 +4,7 @@ MarkupTagHelperStartTag - [0..23)::23 - [

] - Gen OpenAngle;[<]; Text;[p]; - MarkupMiscAttributeContent - [2..22)::20 + MarkupMiscAttributeContent - [2..16)::14 MarkupTextLiteral - [2..3)::1 - [ ] - Gen Whitespace;[ ]; CSharpCodeBlock - [3..16)::13 @@ -17,6 +17,7 @@ Identifier;[DateTime]; Dot;[.]; Identifier;[Now]; + MarkupMiscAttributeContent - [16..22)::6 MarkupTextLiteral - [16..22)::6 - [="btn"] - Gen Equals;[=]; DoubleQuote;["]; diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/TagHelperBlockRewriterTest/TagHelperParseTreeRewriter_AllowsInvalidHtml10.stree.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/TagHelperBlockRewriterTest/TagHelperParseTreeRewriter_AllowsInvalidHtml10.stree.txt index 00a8412278e..ffb0abc8937 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/TagHelperBlockRewriterTest/TagHelperParseTreeRewriter_AllowsInvalidHtml10.stree.txt +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/ParserTests/TagHelperBlockRewriterTest/TagHelperParseTreeRewriter_AllowsInvalidHtml10.stree.txt @@ -9,7 +9,7 @@ MarkupStartTag - [3..20)::17 - [< @DateTime.Now >] - Gen OpenAngle;[<]; Text;[]; - MarkupMiscAttributeContent - [4..19)::15 + MarkupMiscAttributeContent - [4..18)::14 MarkupTextLiteral - [4..5)::1 - [ ] - Gen Whitespace;[ ]; CSharpCodeBlock - [5..18)::13 @@ -22,6 +22,7 @@ Identifier;[DateTime]; Dot;[.]; Identifier;[Now]; + MarkupMiscAttributeContent - [18..19)::1 MarkupTextLiteral - [18..19)::1 - [ ] - Gen Whitespace;[ ]; CloseAngle;[>]; diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/Legacy/HtmlMarkupParser.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/Legacy/HtmlMarkupParser.cs index dace4acf713..a89e708b7b2 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/Legacy/HtmlMarkupParser.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/Legacy/HtmlMarkupParser.cs @@ -1085,16 +1085,53 @@ private void ParseAttribute(in SyntaxListBuilder builder) // http://dev.w3.org/html5/spec/tokenization.html#attribute-name-state // Read the 'name' (i.e. read until the '=' or whitespace/newline) using var nameTokens = new PooledArrayBuilder(); - if (!TryParseAttributeName(ref nameTokens.AsRef())) + var nameParsingResult = TryParseAttributeName(out SyntaxToken? ephemeralToken, ref nameTokens.AsRef()); + + switch (nameParsingResult) { + // Parse C# and return to attribute parsing afterwards. + case AttributeNameParsingResult.CSharp: + { + Accept(in attributePrefixWhitespace); + PutCurrentBack(); + using var pooledResult = Pool.Allocate(); + var dynamicAttributeValueBuilder = pooledResult.Builder; + OtherParserBlock(dynamicAttributeValueBuilder); + var value = SyntaxFactory.MarkupMiscAttributeContent(dynamicAttributeValueBuilder.ToList()); + builder.Add(value); + return; + } + + // Parse razor comment and return to attribute parsing afterwards. + case AttributeNameParsingResult.RazorComment: + { + Accept(in attributePrefixWhitespace); + PutCurrentBack(); + ParseRazorCommentWithLeadingAndTrailingWhitespace(builder); + return; + } + // Unexpected character in tag, enter recovery - Accept(in attributePrefixWhitespace); - ParseMiscAttribute(builder); - return; + case AttributeNameParsingResult.Other: + { + Accept(in attributePrefixWhitespace); + ParseMiscAttribute(builder); + return; + } } + Debug.Assert(nameParsingResult is AttributeNameParsingResult.Success); Accept(in attributePrefixWhitespace); // Whitespace before attribute name var namePrefix = OutputAsMarkupLiteral(); + + if (ephemeralToken is not null) + { + builder.Add(namePrefix); + Accept(ephemeralToken); + builder.Add(OutputAsMarkupEphemeralLiteral()); + namePrefix = null; + } + Accept(in nameTokens); // Attribute name var name = OutputAsMarkupLiteralRequired(); @@ -1113,18 +1150,44 @@ private void ParseAttribute(in SyntaxListBuilder builder) } } - private bool TryParseAttributeName(ref PooledArrayBuilder nameTokens) + private enum AttributeNameParsingResult { + Success, + Other, + CSharp, + RazorComment, + } + + private AttributeNameParsingResult TryParseAttributeName(out SyntaxToken? ephemeralToken, ref PooledArrayBuilder nameTokens) + { + ephemeralToken = null; + // // We are currently here // If we encounter a transition (@) here, it can be parsed as CSharp or Markup depending on the feature flag. // For example, in Components, we want to parse it as Markup so we can support directive attributes. // - if (Context.FeatureFlags.AllowCSharpInMarkupAttributeArea && - (At(SyntaxKind.Transition) || At(SyntaxKind.RazorCommentTransition))) + if (Context.FeatureFlags.AllowCSharpInMarkupAttributeArea) { - // If we get here, there is CSharp in the attribute area. Don't try to parse the name. - return false; + if (At(SyntaxKind.Transition)) + { + if (NextIs(SyntaxKind.Transition)) + { + // The attribute name is escaped (@@), eat the first @ sign. + ephemeralToken = CurrentToken; + NextToken(); + } + else + { + // There is CSharp in the attribute area. Don't try to parse the name. + return AttributeNameParsingResult.CSharp; + } + } + else if (At(SyntaxKind.RazorCommentTransition)) + { + // There is razor comment in the attribute area. Don't try to parse the name. + return AttributeNameParsingResult.RazorComment; + } } if (IsValidAttributeNameToken(CurrentToken)) @@ -1140,10 +1203,10 @@ private bool TryParseAttributeName(ref PooledArrayBuilder nameToken this, ref nameTokens); - return true; + return AttributeNameParsingResult.Success; } - return false; + return AttributeNameParsingResult.Other; } private MarkupAttributeBlockSyntax ParseRemainingAttribute(MarkupTextLiteralSyntax? namePrefix, MarkupTextLiteralSyntax name) diff --git a/src/Compiler/test/Microsoft.NET.Sdk.Razor.SourceGenerators.Tests/RazorSourceGeneratorCshtmlTests.cs b/src/Compiler/test/Microsoft.NET.Sdk.Razor.SourceGenerators.Tests/RazorSourceGeneratorCshtmlTests.cs index bd36e701d94..32db754df10 100644 --- a/src/Compiler/test/Microsoft.NET.Sdk.Razor.SourceGenerators.Tests/RazorSourceGeneratorCshtmlTests.cs +++ b/src/Compiler/test/Microsoft.NET.Sdk.Razor.SourceGenerators.Tests/RazorSourceGeneratorCshtmlTests.cs @@ -2,6 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Threading.Tasks; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; using Roslyn.Test.Utilities; using Xunit; @@ -68,4 +70,50 @@ public async Task CssScoping() Assert.Single(result.GeneratedSources); await VerifyRazorPageMatchesBaselineAsync(compilation, "Pages_Index"); } + + [Theory, CombinatorialData, WorkItem("https://github.com/dotnet/razor/issues/10586")] + public async Task ConditionalAttributes([CombinatorialValues("@null", "@n")] string value) + { + // Arrange + var project = CreateTestProject(new() + { + ["Pages/Index.cshtml"] = $$""" + @page + @{ var s = "str"; string? n = null; } +

x
+
x
+
x
+
x
+
x
+ +
x
+
x
+ +
x
+ +
x
+
x
+
x
+ +
x
+
x
+ """, + }); + var compilation = await project.GetCompilationAsync(); + compilation = compilation.WithOptions(compilation.Options.WithSpecificDiagnosticOptions([.. compilation.Options.SpecificDiagnosticOptions, + // warning CS0219: The variable 'n' is assigned but its value is never used + new("CS0219", ReportDiagnostic.Suppress)])); + var driver = await GetDriverAsync(project); + + // Act + var result = RunGenerator(compilation!, ref driver, out compilation); + + // Assert + Assert.Empty(result.Diagnostics); + Assert.Single(result.GeneratedSources); + var html = await VerifyRazorPageMatchesBaselineAsync(compilation, "Pages_Index"); + + // The style attribute should not be rendered at all. + Assert.DoesNotContain("style", html); + } } diff --git a/src/Compiler/test/Microsoft.NET.Sdk.Razor.SourceGenerators.Tests/RazorSourceGeneratorTestsBase.cs b/src/Compiler/test/Microsoft.NET.Sdk.Razor.SourceGenerators.Tests/RazorSourceGeneratorTestsBase.cs index 1b53d747d68..6d9f8cdef27 100644 --- a/src/Compiler/test/Microsoft.NET.Sdk.Razor.SourceGenerators.Tests/RazorSourceGeneratorTestsBase.cs +++ b/src/Compiler/test/Microsoft.NET.Sdk.Razor.SourceGenerators.Tests/RazorSourceGeneratorTestsBase.cs @@ -209,7 +209,7 @@ static IEnumerable GetViewStartNames(string name) } } - protected static async Task VerifyRazorPageMatchesBaselineAsync(Compilation compilation, string name, + protected static async Task VerifyRazorPageMatchesBaselineAsync(Compilation compilation, string name, [CallerFilePath] string testPath = "", [CallerMemberName] string testName = "", string suffix = "") { var html = await RenderRazorPageAsync(compilation, name); @@ -220,6 +220,7 @@ protected static async Task VerifyRazorPageMatchesBaselineAsync(Compilation comp testPath: testPath, testName: testName, suffix: suffix); + return html; } protected static Project CreateTestProject( diff --git a/src/Compiler/test/Microsoft.NET.Sdk.Razor.SourceGenerators.Tests/TestFiles/RazorSourceGeneratorCshtmlTests/ConditionalAttributes/Pages_Index.html b/src/Compiler/test/Microsoft.NET.Sdk.Razor.SourceGenerators.Tests/TestFiles/RazorSourceGeneratorCshtmlTests/ConditionalAttributes/Pages_Index.html new file mode 100644 index 00000000000..6b2c1d20ecc --- /dev/null +++ b/src/Compiler/test/Microsoft.NET.Sdk.Razor.SourceGenerators.Tests/TestFiles/RazorSourceGeneratorCshtmlTests/ConditionalAttributes/Pages_Index.html @@ -0,0 +1,17 @@ +
x
+
x
+
x
+
x
+
x
+ +
x
+
x
+ +
x
+ +
x
+
x
+
x
+ +
x
+
x
\ No newline at end of file diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Test.Common/Language/IntegrationTests/IntegrationTestBase.cs b/src/Shared/Microsoft.AspNetCore.Razor.Test.Common/Language/IntegrationTests/IntegrationTestBase.cs index 98bfa6e9b26..ae9ba577a3b 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Test.Common/Language/IntegrationTests/IntegrationTestBase.cs +++ b/src/Shared/Microsoft.AspNetCore.Razor.Test.Common/Language/IntegrationTests/IntegrationTestBase.cs @@ -77,6 +77,8 @@ protected IntegrationTestBase(TestProject.Layer layer, string? projectDirectoryH protected bool NullableEnable { get; set; } + protected Dictionary? ExpectedMissingSourceMappings { get; set; } + /// /// Gets the /// @@ -91,7 +93,7 @@ protected IntegrationTestBase(TestProject.Layer layer, string? projectDirectoryH protected string TestProjectRoot { get; } - public virtual string GetTestFileName(string? testName) + public virtual string GetTestFileName([CallerMemberName] string? testName = null) { return $"TestFiles/IntegrationTests/{this.GetType().Name}/{testName}"; } @@ -507,13 +509,33 @@ protected void AssertSourceMappingsMatchBaseline(RazorCodeDocument codeDocument, } } - if (!found) + if (ExpectedMissingSourceMappings?.TryGetValue(SourceLocation.FromSpan(sourceSpan), out var expectedMissingSpan) == true) + { + if (found) + { + throw new XunitException($"Remove {sourceSpan} from {nameof(ExpectedMissingSourceMappings)}."); + } + else if (expectedSpan != expectedMissingSpan) + { + throw new XunitException($"Missing span {sourceSpan} has different content '{EscapeWhitespace(expectedSpan)}' " + + $"than expected '{EscapeWhitespace(expectedMissingSpan)}'."); + } + + ExpectedMissingSourceMappings.Remove(SourceLocation.FromSpan(sourceSpan)); + } + else if (!found) { throw new XunitException( $"Could not find the span {sourceSpan} - containing '{EscapeWhitespace(expectedSpan)}' " + $"in the output."); } } + + if (ExpectedMissingSourceMappings?.Count > 0) + { + throw new XunitException($"Found unused {nameof(ExpectedMissingSourceMappings)} ({ExpectedMissingSourceMappings.Count}), " + + $"for example {ExpectedMissingSourceMappings.First()}."); + } } protected void AssertHtmlSourceMappingsMatchBaseline(RazorCodeDocument codeDocument, [CallerMemberName] string testName = "") From 749ded88f0cb950171f64f31574ef830049b214e Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Fri, 19 Jul 2024 12:15:56 -0700 Subject: [PATCH 175/176] Add XML doc comments for StreamExtensions.CreateString and SpanAction --- .../StringExtensions.cs | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/StringExtensions.cs b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/StringExtensions.cs index b6be700d097..393a2626403 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/StringExtensions.cs +++ b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/StringExtensions.cs @@ -555,8 +555,47 @@ public static bool EndsWith(this string text, char value) #endif } + /// + /// Encapsulates a method that receives a span of objects of type + /// and a state object of type . + /// + /// + /// The type of the objects in the span. + /// + /// + /// The type of the object that represents the state. + /// + /// + /// A span of objects of type . + /// + /// + /// A state object of type . + /// public delegate void SpanAction(Span span, TArg arg); + /// + /// Creates a new string with a specific length and initializes it after creation by using the specified callback. + /// + /// + /// The type of the element to pass to . + /// + /// + /// The length of the string to create. + /// + /// + /// The element to pass to . + /// + /// + /// A callback to initialize the string + /// + /// + /// The created string. + /// + /// + /// The initial content of the destination span passed to is undefined. + /// Therefore, it is the delegate's responsibility to ensure that every element of the span is assigned. + /// Otherwise, the resulting string could contain random characters + /// public unsafe static string CreateString(int length, TState state, SpanAction action) { #if NET From fabbeeb5c0b09fedec189c1ba6009678acbd8bf4 Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Fri, 19 Jul 2024 12:39:26 -0700 Subject: [PATCH 176/176] Clean up MemoryBuilder.Grow when checking again ArrayMaxLength --- .../MemoryBuilder`1.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/MemoryBuilder`1.cs b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/MemoryBuilder`1.cs index a40d40ea5b0..cc9c236f32b 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/MemoryBuilder`1.cs +++ b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/MemoryBuilder`1.cs @@ -118,9 +118,11 @@ private void Grow(int additionalCapacityRequired = 1) // we've grown too large, we want to OOM when Rent is called below. if ((uint)nextCapacity > ArrayMaxLength) { - nextCapacity = Math.Max( - Math.Max(_memory.Length + 1, ArrayMaxLength), - _memory.Length); + // Note: it's not possible for _memory.Length + 1 to overflow because that would mean + // _memory is pointing to an array with length int.MaxValue, which is larger than + // Array.MaxLength. We would have OOM'd before getting here. + + nextCapacity = Math.Max(_memory.Length + 1, ArrayMaxLength); } Debug.Assert(nextCapacity > _memory.Length);