diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/CodeActions/Razor/ExtractToComponentCodeActionProvider.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/CodeActions/Razor/ExtractToComponentCodeActionProvider.cs
index 9a0a25559c..fefae3c1b7 100644
--- a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/CodeActions/Razor/ExtractToComponentCodeActionProvider.cs
+++ b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/CodeActions/Razor/ExtractToComponentCodeActionProvider.cs
@@ -83,7 +83,7 @@ internal class ExtractToComponentCodeActionProvider() : IRazorCodeActionProvider
private static (SyntaxNode? Start, SyntaxNode? End) GetStartAndEndElements(RazorCodeActionContext context, RazorSyntaxTree syntaxTree)
{
- var owner = syntaxTree.Root.FindInnermostNode(context.StartAbsoluteIndex, includeWhitespace: true);
+ var owner = syntaxTree.Root.FindInnermostNode(context.StartAbsoluteIndex, includeWhitespace: !context.HasSelection);
if (owner is null)
{
return (null, null);
@@ -112,25 +112,13 @@ internal class ExtractToComponentCodeActionProvider() : IRazorCodeActionProvider
private static SyntaxNode? GetEndElementNode(RazorCodeActionContext context, RazorSyntaxTree syntaxTree)
{
- var endOwner = syntaxTree.Root.FindInnermostNode(context.EndAbsoluteIndex, includeWhitespace: true);
+ var endOwner = syntaxTree.Root.FindInnermostNode(context.EndAbsoluteIndex, includeWhitespace: false);
if (endOwner is null)
{
return null;
}
- // Correct selection to include the current node if the selection ends immediately after a closing tag.
- if (endOwner is MarkupTextLiteralSyntax markupTextLiteral
- && SelectionShouldBePrevious(markupTextLiteral, context.EndAbsoluteIndex)
- && endOwner.TryGetPreviousSibling(out var previousSibling))
- {
- endOwner = previousSibling;
- }
-
return GetBlockOrTextNode(endOwner);
-
- static bool SelectionShouldBePrevious(MarkupTextLiteralSyntax markupTextLiteral, int absoluteIndex)
- => markupTextLiteral.Span.Start == absoluteIndex
- || markupTextLiteral.ContainsOnlyWhitespace();
}
private static SyntaxNode? GetBlockOrTextNode(SyntaxNode node)
diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/Razor/ExtractToComponentCodeActionProviderTest.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/Razor/ExtractToComponentCodeActionProviderTest.cs
index 18fed21646..105a561450 100644
--- a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/Razor/ExtractToComponentCodeActionProviderTest.cs
+++ b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/Razor/ExtractToComponentCodeActionProviderTest.cs
@@ -22,8 +22,10 @@ using Microsoft.CodeAnalysis.Testing;
using Microsoft.CodeAnalysis.Text;
using Microsoft.VisualStudio.LanguageServer.Protocol;
using Moq;
+using Roslyn.Test.Utilities;
using Xunit;
using Xunit.Abstractions;
+using WorkItemAttribute = Roslyn.Test.Utilities.WorkItemAttribute;
namespace Microsoft.AspNetCore.Razor.LanguageServer.Test.CodeActions.Razor;
@@ -465,6 +467,144 @@ public class ExtractToComponentCodeActionProviderTest(ITestOutputHelper testOutp
|}
""");
+ [Fact]
+ [WorkItem("https://github.com/dotnet/razor/issues/11261")]
+ public Task Handle_Inside_ElseBlock()
+ => TestAsync("""
+ @page "/weather"
+
+
This component demonstrates showing data.
+ + @if (forecasts == null) + { +Loading...
+ } + else + { + {|selection: {|result:Date | +Temp. (C) | +Temp. (F) | +Summary | +
---|---|---|---|
@forecast.Date.ToShortDateString() | +@forecast.TemperatureC | +@forecast.TemperatureF | +@forecast.Summary | +
This component demonstrates showing data.
+ + @if (forecasts == null) + { +Loading...
+ } + else + { + {|selection:|}Date | +Temp. (C) | +Temp. (F) | +Summary | +
---|---|---|---|
@forecast.Date.ToShortDateString() | +@forecast.TemperatureC | +@forecast.TemperatureF | +@forecast.Summary | +