Skip to content
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

Merged
merged 73 commits into from
Oct 18, 2024
Merged

Conversation

ryzngard
Copy link
Contributor

@ryzngard ryzngard commented Oct 15, 2024

New PR because apparently the branch is restricted so I can't handle merge conflicts...

Adding work from @marcarro into main 🥳

marcarro and others added 30 commits July 3, 2024 13:28
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:
marcarro and others added 8 commits August 26, 2024 19:47
…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
@ryzngard ryzngard requested review from a team as code owners October 15, 2024 00:33
Copy link
Contributor

@davidwengier davidwengier left a 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.

Comment on lines 21 to 22
// Add check for rooted path in the future, currently having issues in platforms other than Windows.
// See: https://github.com/dotnet/razor/issues/10684
Copy link
Contributor

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.

}

var startElementNode = owner.FirstAncestorOrSelf<MarkupElementSyntax>();
if (startElementNode is not { EndTag: not null } || LocationOutsideNode(context.StartLocation, startElementNode))
Copy link
Contributor

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?

Copy link
Contributor Author

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

};
}

private static IEnumerable<string> GetUsingsInDocument(RazorSyntaxTree syntaxTree)
Copy link
Contributor

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?

Copy link
Contributor Author

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.

#11025

ryzngard and others added 6 commits October 15, 2024 12:17
…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>
@ryzngard
Copy link
Contributor Author

This is worth a fresh pass @davidwengier . I changed a few things that came up as I added tests :)

Copy link
Contributor

@davidwengier davidwengier left a 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;
Copy link
Contributor

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 :)

Copy link
Contributor Author

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 :)

Comment on lines 153 to 155
// 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
Copy link
Contributor

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);
Copy link
Contributor

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>

Copy link
Contributor Author

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

  1. If all content on same line, don't dedent
  2. Find the line with the left most non-whitespace character. Calculate that indentation
  3. 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

Copy link
Contributor

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"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants