Add code fix to help choose which piece to take when there is a merge conflict#15853
Conversation
1432ba2 to
a34c2d4
Compare
|
@CyrusNajmabadi The title of this PR is misleading. There's a non-trivial amount of compiler changes too. |
|
This is a branch off of #15850 . That PR contains the compiler changes, and i'm working through getting that reviewed. This PR was around the CodeFixProvider. It would not go in without the other PR being reviewed and going in first. |
| <data name="ERR_OpenEndedComment" xml:space="preserve"> | ||
| <value>End-of-file found, '*/' expected</value> | ||
| </data> | ||
| <data name="ERR_Merge_conflict_marker_encountered" xml:space="preserve"> |
There was a problem hiding this comment.
Can you push the resource down and reuse it instead of duplicating it between C# and VB?
There was a problem hiding this comment.
No. The compilers don't work that way wrt resources.
| ERR_PPDefFollowsToken = 1032, | ||
| //ERR_TooManyLines = 1033, unused in Roslyn. | ||
| //ERR_LineTooLong = 1034, unused in Roslyn. | ||
| ERR_Merge_conflict_marker_encountered = 1034, |
There was a problem hiding this comment.
CS1034 already has meaning, so I wouldn't re-use it like this. https://msdn.microsoft.com/en-us/library/7bb77w7x(v=vs.90).aspx
| return triviaList; | ||
| } | ||
|
|
||
| private void LexConflictMarkerEndOfLine(ref SyntaxListBuilder triviaList) |
There was a problem hiding this comment.
Maybe name this LexConflictMarkerEndLines?
But I don't understand why more than one newline after <<<<<<< would be trailing trivia on it. Any subsequent newlines feel like they belong to the first token in that half of the diff (so that a codefix taking everything in the "mine" side wouldn't also need to worry about extra newlines attached to the <<<<<<< line -- they could just take everything in that half of the diff and know that it's correct.
There was a problem hiding this comment.
Agree, and that is the general heuristic for newline trivia - it is generally attached to the next token, except the first newline which ends a line.
| ch <> "_"c AndAlso | ||
| ch <> "R"c AndAlso | ||
| ch <> "r"c AndAlso | ||
| ch <> "<"c AndAlso |
There was a problem hiding this comment.
The comment above is now incorrect.
| ShouldBeGoodQuickToken("ab$=") | ||
| ShouldBeGoodQuickToken(" a =") | ||
| ShouldBeGoodQuickToken(" =a") | ||
| ShouldBeGoodQuickToken("a,") |
There was a problem hiding this comment.
I don't understand these changes.
| while (true) | ||
| { | ||
| token = token.GetNextToken(includeZeroWidth: true); | ||
| if (token.RawKind == 0) |
There was a problem hiding this comment.
A comment explaining the magic number would be nice
| } | ||
|
|
||
| var index = GetEqualsConflictMarkerIndex(text, token); | ||
| if (index >= 0) |
There was a problem hiding this comment.
Verifying my understanding of the compiler side: the <<<<<<< is only treated as a conflict marker if there exists a ======= and a >>>>>>> to match, right? Otherwise this index would always be -1 and you'd be stuck in a loop either forever or until GetNextToken fails, I'm not sure which.
There was a problem hiding this comment.
and you'd be stuck in a loop either forever or until GetNextToken fails, I'm not sure which.
You're in the loop until there are no more tokens in the file, in which case the above 'if' check breaks out.
| if (index + 3 < token.LeadingTrivia.Count) | ||
| { | ||
| var equalsTrivia = leadingTrivia[index]; | ||
| var endOfLineTrivia = leadingTrivia[index + 1]; |
There was a problem hiding this comment.
If this is actually all of the endlines, then pluralizing here would be better.
| return -1; | ||
| } | ||
|
|
||
| private SyntaxTrivia GetEqualsConflictMarker(SyntaxToken token) |
There was a problem hiding this comment.
What's going on here? I don't see any callers.
|
|
||
| private void ClassifyConflictMarker(SyntaxTrivia trivia) | ||
| { | ||
| AddClassification(trivia, ClassificationTypeNames.Comment); |
There was a problem hiding this comment.
Should we introduce a new color here? I might want to make my conflict markers bright red. 😄
|
In general, it would be nice to see more tests of "broken" scenarios. Almost conflict resolution code, but without the =======, or without the >>>>>>>, or whatever. |
| ERR_PPDefFollowsToken = 1032, | ||
| //ERR_TooManyLines = 1033, unused in Roslyn. | ||
| //ERR_LineTooLong = 1034, unused in Roslyn. | ||
| ERR_Merge_conflict_marker_encountered = 1034, |
There was a problem hiding this comment.
New error codes should please be moved near then end. They are currently approximately segregated by the version of the compiler in which they were introduced.
There was a problem hiding this comment.
Ah, will do.
|
retest windows_release_unit64_prtest please |
|
This is very cool! Should we get the right folks to review the API additions, or wait on that until it's closer to being ready? |
|
|
||
| var startTrivia = root.FindTrivia(context.Span.Start); | ||
|
|
||
| if (!IsConflictMarker(text, startTrivia, '<')) |
There was a problem hiding this comment.
So this only provides a fix on the <<<<<<<, but not the other markers?
There was a problem hiding this comment.
Currently yes.
| } | ||
|
|
||
| return start < TextWindow.Position; | ||
| return start < TextWindow.Position; |
| return triviaList; | ||
| } | ||
|
|
||
| private void LexConflictMarkerEndOfLine(ref SyntaxListBuilder triviaList) |
There was a problem hiding this comment.
Agree, and that is the general heuristic for newline trivia - it is generally attached to the next token, except the first newline which ends a line.
Looks like this: