-
Notifications
You must be signed in to change notification settings - Fork 196
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merge features/extract-to-component to main #11019
Conversation
…o general GenerateUniquePath helper
Merge main into feature/extract-to-component
dotnet#10578) ### Summary of the changes Part of the implementation of the _Extract To Component_ code action. Functional in one of the two cases, when the user is not selecting a certain range of a Razor component, but rather when the cursor is on either the opening or closing tag.
### Summary of the changes Keep feature branch up to date - Fixes:
…10651) ### Summary of the changes Addition to feature wherein razor component dependencies are now identified, and their corresponding `@usings` are now also extracted into the new document. ## **_Important!_** Notes: Some changes in this PR are further rectified in dotnet#10760, such as: `AddComponentDependenciesInRange` does not take actionParams anymore. In general, most (if not all) of the internal methods that take `actionParams` as a parameter were moved to the resolver, where each method returns a collection of appropiate objects.
Clean up some of the extract to component code. Move more work to the resolver, use pooled objects where applicable, and try to make the provider cleaner when creating the ExtractToComponentCodeActionParams
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The only reason I'm not approving is the confirmation around the behaviour when there is C# code inside a selection. I personally think that is really important, but perhaps there was a decision I'm not aware of/remembing.
// Add check for rooted path in the future, currently having issues in platforms other than Windows. | ||
// See: https://github.com/dotnet/razor/issues/10684 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this comment apply? IsPathRooted
isn't used here.
...ft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/ExtractToComponentCodeActionProvider.cs
Outdated
Show resolved
Hide resolved
} | ||
|
||
var startElementNode = owner.FirstAncestorOrSelf<MarkupElementSyntax>(); | ||
if (startElementNode is not { EndTag: not null } || LocationOutsideNode(context.StartLocation, startElementNode)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would be good to comment what this is (not) looking for. The double negative might be confusing me, but does this mean we don't extract self-closing tags?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hmm... that's a good point. I don't believe that check is needed. Maybe if endElement == startElement
then we don't want to extract a single self-closing tag... but it should be a valid start location. I'll remove the check and add a test
...ft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/ExtractToComponentCodeActionProvider.cs
Outdated
Show resolved
Hide resolved
...ft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/ExtractToComponentCodeActionResolver.cs
Outdated
Show resolved
Hide resolved
}; | ||
} | ||
|
||
private static IEnumerable<string> GetUsingsInDocument(RazorSyntaxTree syntaxTree) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there an issue to have this just include the minimum set?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no, I'll create one. There was code to do that but I am not sure it was right and there were no tests so I removed for now.
...t/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/CodeActionEndToEndTest.NetFx.cs
Outdated
Show resolved
Hide resolved
...t/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/CodeActionEndToEndTest.NetFx.cs
Show resolved
Hide resolved
...t/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/CodeActionEndToEndTest.NetFx.cs
Show resolved
Hide resolved
...Core.Razor.LanguageServer.Test/CodeActions/Razor/ExtractToComponentCodeActionProviderTest.cs
Outdated
Show resolved
Hide resolved
…tions/Razor/ExtractToComponentCodeActionResolver.cs Co-authored-by: David Wengier <david.wengier@microsoft.com>
…tions/Razor/ExtractToComponentCodeActionResolver.cs Co-authored-by: David Wengier <david.wengier@microsoft.com>
This is worth a fresh pass @davidwengier . I changed a few things that came up as I added tests :) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Love the extra tests!
Feels like this one will be akin to formatting, in that we'll find weird edge cases and keep building our test collection out over time.
=> node.Kind is | ||
SyntaxKind.MarkupElement or | ||
SyntaxKind.MarkupTagHelperElement or | ||
SyntaxKind.CSharpCodeBlock; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is probably okay for now, but the Razor syntax tree is annoying and CSharpCodeBlock
is pretty ubiquitous. I wonder if it's worth being more explicit with the check here, or at least logging an issue for follow up. I expect this will be a source of future quirks. eg given @attribute [StreamR$$endering]
, the first CSharpCodeBlock
ancestor of the cursor is " [StreamRendering]
" and in <div>@curren$$tCount</div>
it's @currentCount
, though one could argue that is extract-able.
I don't feel super strongly about it, though, because it's very much in the "if it hurts when you do that, don't do that" category IMO. Assuming the editor implements undo correctly anyway :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yea... I wanted to keep it open until we find cases where it's hurting too much. Then add more tests and improve :)
...ft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/ExtractToComponentCodeActionResolver.cs
Show resolved
Hide resolved
// Keep passing characters until either we reach the root indendation level | ||
// or we would consume a character that isn't whitespace. This does make assumptions | ||
// about consistency of tabs or spaces but at least will only fail to unindent correctly |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider extracting all of the de-dent logic (ie, lines 96 - 110) to its own method (maybe even in FormattingUtilities
?) and putting this comment, or at least the 2nd sentence, at the start of it. It really sets the expectations for what otherwise appears to be an surprising algorithmic choice.
} | ||
|
||
var extractedText = text.GetSubTextString(new TextSpan(actionParams.Start, actionParams.End - actionParams.Start)).Trim(); | ||
builder.Append(extractedText); | ||
var indentation = GetIndentation(actionParams.Start, text); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think I understand why this starts at the extract start point. Shouldn't the base indentation be calculated by starting at the 0th character of the line, and count forwards until it hits non-whitespace.
<div> <span>
Hello
</span> [|<span>
World
</span>|]
</div>
Perhaps a pathological example, but pretty sure this would calculate the base indentation as 1, but logically it should be 4.
Also, if the extraction is all on one line, then should probably skip de-denting entirely. eg:
<div>
[|<span> Hello </span>|]
</div>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yea, I might be a bit too naive. The dedent logic should probably be something more like
- If all content on same line, don't dedent
- Find the line with the left most non-whitespace character. Calculate that indentation
- Dedent everything by that indentation
The pathological case will still be wrong but maybe closer to right? Could also take advantage of the syntax tree and make sure paired start/ends match but that gets closer into making a static formatter for razor than I currently have the brain space for
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The other approach could be to get the actual indent string from the first line, and remove it from the start of subsequent lines, if it exists, and simply ignore lines that have a space/tab mix. Of the three, Not sure either is necessarily "right"
New PR because apparently the branch is restricted so I can't handle merge conflicts...
Adding work from @marcarro into main 🥳