-
Notifications
You must be signed in to change notification settings - Fork 1.4k
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
Support preserving formatting when opening a project #1036
Support preserving formatting when opening a project #1036
Conversation
…be preserved when creating project from XmlReader
… preserve formatting is enabled
… likely to fix this
We need to make sure this doesn't conflict with #1004, where @maddin2016 is playing in similar areas. |
@@ -227,6 +227,8 @@ internal ProjectRootElement Get(string projectFile, OpenProjectRootElement openP | |||
// use: it checks the file content as well as the timestamp. That's better than completely disabling | |||
// the cache as we get test coverage of the rest of the cache code. | |||
XmlDocument document = new XmlDocument(); | |||
// TODO: does PreserveWhitespace need to be an option here? | |||
//document.PreserveWhitespace = true; |
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.
Seems like it'd need to match what gets inserted into the cache, which would depend on how it was loaded, right?
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've updated this so that it won't use the cached version if it doesn't match the preserveFormatting setting requested.
{ | ||
var newWhitespaceNode = XmlDocument.CreateWhitespace(reference.XmlElement.PreviousSibling.Value); | ||
XmlElement.InsertAfter(newWhitespaceNode, reference.XmlElement); | ||
} |
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.
It's unfortunate that we have to do this manually. But this seems like a reasonable strategy (and good comment).
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.
But can it be abstracted and reused?
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.
How do you mean abstracted and reused? ProjectElementContainer seems like it is already the generic place to put this logic.
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.
This and below have very similar logic to find, clone, and insert whitespace. Though I guess it's only twice, so the generalization may not be that general.
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.
Yeah, I didn't see an elegant way to unify the different cases that exist within ProjectElementContainer
.
else if (XmlElement.PreviousSibling != null && | ||
XmlElement.PreviousSibling.NodeType == XmlNodeType.Whitespace) | ||
{ | ||
// This container didn't have any whitespace in in. This probably means it didn't have separate open |
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.
in it
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.
Fixed
// So try to match the surrounding formatting and add one indentation level | ||
if (XmlElement.FirstChild.NodeType == XmlNodeType.Whitespace) | ||
{ | ||
// This container had a whitespace node, which should generally be a newline and the indent |
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.
how true is "generally"? Should we bother to validate this assumption?
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 thought about this and it seemed OK to leave it as is. If there's spacing between the elements but not a newline, then we'll still be matching the surrounding formatting, even though the formatting seems weird.
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.
Ok, I buy it. Can you put that in the comment?
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.
Done.
// and close tags. So add a whitespace node before the new child with additional indentation over the | ||
// container's indentation, and add a whitespace node with the same level of indentation as the container | ||
// after the new child so the closing tag will be indented properly. | ||
string whitespace = XmlElement.PreviousSibling.Value; |
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.
rename to parentWhitespace
?
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.
Done.
<ItemGroup> | ||
<ProjectReference Include=`..\CLREXE\CLREXE.vcxproj`> | ||
<!-- Comment --> | ||
<Project>{3699f81b-2d03-46c5-abd7-e88a4c946f28}</Project> |
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'm not sure I prefer this behavior. It can be useful to have both
// Long comments explaining
code;
and
code; // clarified
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 behavior today is that comments are put on separate lines. If you specify the option to preserve formatting, then the location of the comment will be preserved. This test covers both behaviors, which is why you see the reformatted version.
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.
Ohhh. Gotcha.
project.SaveLogicalProject(writer); | ||
|
||
string actual = writer.ToString(); | ||
string expected = @"<?xml version=""1.0"" encoding=""utf-16""?>" + |
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.
attn: @AndyGerlicher
VerifyAssertLineByLine(expected, actual); | ||
} | ||
|
||
[Fact(Skip = "https://github.com/Microsoft/msbuild/issues/362")] |
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.
So the preserve-whitespace flag doesn't fix this? Boo :(
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.
Apparently not... 😞
Yes. The comment is referring to the NextSibling and PreviousSibling properties of |
Ah, now I see that I evidently didn't hit "comment" on my most important comment. Sorry. My instinct is to say that this shouldn't be an option--that is, we should always preserve whitespace. But you've plumbed through an option. Do you think that should be exposed to the user? |
2269a7a
to
e0141a0
Compare
I went with an opt-in option to avoid a compat risk (as suggested by Dave). How much of a compat risk would there be to always preserving formatting? Also note that there's some risk that there are still cases where preserving the formatting will result in ugly formatting when the project is modified, as would be the case without the changes on |
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.
Looks good!
@dsplaisted Where did we land with this? Did we sync with CPS to call this overload? |
@davkean No, AFAIK CPS isn't consuming this yet. I'm not sure if this has made it into a drop of MSBuild that they are using. @AndyGerlicher, can you comment? |
@lifengl have we reacted to this in CPS? |
Fixes #707
Adds the following overloads to
ProjectRootElement
: