diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Rename/RenameService.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Rename/RenameService.cs index aec6df4929c..7bf2b77017d 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Rename/RenameService.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Rename/RenameService.cs @@ -16,7 +16,6 @@ using Microsoft.AspNetCore.Razor.PooledObjects; using Microsoft.CodeAnalysis.Razor.DocumentMapping; using Microsoft.CodeAnalysis.Razor.ProjectSystem; -using Microsoft.CodeAnalysis.Razor.Protocol; using Microsoft.CodeAnalysis.Razor.Workspaces; using RazorSyntaxKind = Microsoft.AspNetCore.Razor.Language.SyntaxKind; using RazorSyntaxNode = Microsoft.AspNetCore.Razor.Language.Syntax.SyntaxNode; @@ -43,12 +42,6 @@ internal class RenameService( return null; } - // If we're in C# then there is no point checking for a component tag, because there won't be one - if (positionInfo.LanguageKind == RazorLanguageKind.CSharp) - { - return null; - } - var codeDocument = await documentContext.GetCodeDocumentAsync(cancellationToken).ConfigureAwait(false); var originTagHelpers = await GetOriginTagHelpersAsync(documentContext, positionInfo.HostDocumentIndex, cancellationToken).ConfigureAwait(false); diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Rename/RemoteRenameService.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Rename/RemoteRenameService.cs index 2579d206493..468d824b511 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Rename/RemoteRenameService.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Rename/RemoteRenameService.cs @@ -45,7 +45,7 @@ protected override IRemoteRenameService CreateService(in ServiceArgs args) { var codeDocument = await context.GetCodeDocumentAsync(cancellationToken).ConfigureAwait(false); - if (!TryGetDocumentPositionInfo(codeDocument, position, out var positionInfo)) + if (!TryGetDocumentPositionInfo(codeDocument, position, preferCSharpOverHtml: true, out var positionInfo)) { return NoFurtherHandling; } diff --git a/src/Razor/test/Microsoft.VisualStudioCode.RazorExtension.Test/Endpoints/Shared/CohostRenameEndpointTest.cs b/src/Razor/test/Microsoft.VisualStudioCode.RazorExtension.Test/Endpoints/Shared/CohostRenameEndpointTest.cs index ad499c0a07a..1e089c54cb8 100644 --- a/src/Razor/test/Microsoft.VisualStudioCode.RazorExtension.Test/Endpoints/Shared/CohostRenameEndpointTest.cs +++ b/src/Razor/test/Microsoft.VisualStudioCode.RazorExtension.Test/Endpoints/Shared/CohostRenameEndpointTest.cs @@ -2,9 +2,12 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Linq; +using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.Razor; using Microsoft.AspNetCore.Razor.Language; +using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.ExternalAccess.Razor; using Microsoft.CodeAnalysis.Razor; using Microsoft.CodeAnalysis.Testing; @@ -148,6 +151,69 @@ The end. """, renames: [("Component.razor", "DifferentName.razor")]); + [Fact] + public Task Component_Attribute() + => VerifyRenamesAsync( + input: $""" + This is a Razor document. + + + +
+ + + +
+ + + +
+
+ + The end. + """, + additionalFiles: [ + (FilePath("Component.razor"), """ +
+ + @code { + [Parameter] + public string Title { get; set; } + } + + """) + ], + newName: "Name", + expected: """ + This is a Razor document. + + + +
+ + + +
+ + + +
+
+ + The end. + """, + additionalExpectedFiles: [ + (FileUri("Component.razor"), """ +
+ + @code { + [Parameter] + public string Name { get; set; } + } + + """) + ]); + [Fact] public Task Mvc() => VerifyRenamesAsync( @@ -171,7 +237,8 @@ private async Task VerifyRenamesAsync( string expected, RazorFileKind? fileKind = null, (string fileName, string contents)[]? additionalFiles = null, - (string oldName, string newName)[]? renames = null) + (string oldName, string newName)[]? renames = null, + (Uri fileUri, string contents)[]? additionalExpectedFiles = null) { TestFileMarkupParser.GetPosition(input, out var source, out var cursorPosition); var document = CreateProjectAndRazorDocument(source, fileKind, additionalFiles: additionalFiles); @@ -215,13 +282,15 @@ private async Task VerifyRenamesAsync( } } - var actual = ProcessRazorDocumentEdits(inputText, document.CreateUri(), result); + await ProcessRazorDocumentEditsAsync(inputText, expected, document, additionalExpectedFiles, result, DisposalToken).ConfigureAwait(false); - AssertEx.EqualOrDiff(expected, actual); } - private static string ProcessRazorDocumentEdits(SourceText inputText, Uri razorDocumentUri, WorkspaceEdit result) + private static async Task ProcessRazorDocumentEditsAsync(SourceText inputText, string expected, TextDocument razorDocument, (Uri fileUri, string contents)[]? additionalExpectedFiles, WorkspaceEdit result, CancellationToken cancellationToken) { + var razorDocumentUri = razorDocument.CreateUri(); + var solution = razorDocument.Project.Solution; + Assert.True(result.TryGetTextDocumentEdits(out var textDocumentEdits)); foreach (var textDocumentEdit in textDocumentEdits) { @@ -232,8 +301,23 @@ private static string ProcessRazorDocumentEdits(SourceText inputText, Uri razorD inputText = inputText.WithChanges(inputText.GetTextChange((TextEdit)edit)); } } + else if (additionalExpectedFiles is not null) + { + foreach (var (uri, contents) in additionalExpectedFiles) + { + var additionalDocument = solution.GetTextDocuments(uri).First(); + var text = await additionalDocument.GetTextAsync(cancellationToken).ConfigureAwait(false); + + foreach (var edit in textDocumentEdit.Edits) + { + text = text.WithChanges(text.GetTextChange((TextEdit)edit)); + } + + AssertEx.EqualOrDiff(contents, text.ToString()); + } + } } - return inputText.ToString(); + AssertEx.EqualOrDiff(expected, inputText.ToString()); } }