mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-27 18:57:42 +03:00
Support long diff conflict markers
git can be configured to use more than 7 characters for conflict markers, and jj automatically uses longer conflict markers when the text contains any char sequence that could be confused with conflict markers. Ensure that we only point at markers that are consistent with the start marker's length. Ensure that we only consider char sequences at the beginning of a line as a diff marker.
This commit is contained in:
@@ -3037,27 +3037,53 @@ pub(super) fn is_vcs_conflict_marker(
|
||||
long_kind: &TokenKind,
|
||||
short_kind: &TokenKind,
|
||||
) -> bool {
|
||||
(0..3).all(|i| self.look_ahead(i, |tok| tok == long_kind))
|
||||
&& self.look_ahead(3, |tok| tok == short_kind)
|
||||
if long_kind == short_kind {
|
||||
// For conflict marker chars like `%` and `\`.
|
||||
(0..7).all(|i| self.look_ahead(i, |tok| tok == long_kind))
|
||||
} else {
|
||||
// For conflict marker chars like `<` and `|`.
|
||||
(0..3).all(|i| self.look_ahead(i, |tok| tok == long_kind))
|
||||
&& self.look_ahead(3, |tok| tok == short_kind || tok == long_kind)
|
||||
}
|
||||
}
|
||||
|
||||
fn conflict_marker(&mut self, long_kind: &TokenKind, short_kind: &TokenKind) -> Option<Span> {
|
||||
fn conflict_marker(
|
||||
&mut self,
|
||||
long_kind: &TokenKind,
|
||||
short_kind: &TokenKind,
|
||||
expected: Option<usize>,
|
||||
) -> Option<(Span, usize)> {
|
||||
if self.is_vcs_conflict_marker(long_kind, short_kind) {
|
||||
let lo = self.token.span;
|
||||
for _ in 0..4 {
|
||||
self.bump();
|
||||
if self.psess.source_map().span_to_margin(lo) != Some(0) {
|
||||
return None;
|
||||
}
|
||||
return Some(lo.to(self.prev_token.span));
|
||||
let mut len = 0;
|
||||
while self.token.kind == *long_kind || self.token.kind == *short_kind {
|
||||
if self.token.kind.break_two_token_op(1).is_some() {
|
||||
len += 2;
|
||||
} else {
|
||||
len += 1;
|
||||
}
|
||||
self.bump();
|
||||
if expected == Some(len) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if expected.is_some() && expected != Some(len) {
|
||||
return None;
|
||||
}
|
||||
return Some((lo.to(self.prev_token.span), len));
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
pub(super) fn recover_vcs_conflict_marker(&mut self) {
|
||||
// <<<<<<<
|
||||
let Some(start) = self.conflict_marker(&TokenKind::Shl, &TokenKind::Lt) else {
|
||||
let Some((start, len)) = self.conflict_marker(&TokenKind::Shl, &TokenKind::Lt, None) else {
|
||||
return;
|
||||
};
|
||||
let mut spans = Vec::with_capacity(3);
|
||||
let mut spans = Vec::with_capacity(2);
|
||||
spans.push(start);
|
||||
// |||||||
|
||||
let mut middlediff3 = None;
|
||||
@@ -3069,13 +3095,19 @@ pub(super) fn recover_vcs_conflict_marker(&mut self) {
|
||||
if self.token == TokenKind::Eof {
|
||||
break;
|
||||
}
|
||||
if let Some(span) = self.conflict_marker(&TokenKind::OrOr, &TokenKind::Or) {
|
||||
if let Some((span, _)) =
|
||||
self.conflict_marker(&TokenKind::OrOr, &TokenKind::Or, Some(len))
|
||||
{
|
||||
middlediff3 = Some(span);
|
||||
}
|
||||
if let Some(span) = self.conflict_marker(&TokenKind::EqEq, &TokenKind::Eq) {
|
||||
if let Some((span, _)) =
|
||||
self.conflict_marker(&TokenKind::EqEq, &TokenKind::Eq, Some(len))
|
||||
{
|
||||
middle = Some(span);
|
||||
}
|
||||
if let Some(span) = self.conflict_marker(&TokenKind::Shr, &TokenKind::Gt) {
|
||||
if let Some((span, _)) =
|
||||
self.conflict_marker(&TokenKind::Shr, &TokenKind::Gt, Some(len))
|
||||
{
|
||||
spans.push(span);
|
||||
end = Some(span);
|
||||
break;
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
enum E {
|
||||
Foo {
|
||||
<<<<<<<<< HEAD //~ ERROR encountered diff marker
|
||||
x: u8,
|
||||
|||||||
|
||||
z: (),
|
||||
=========
|
||||
y: i8,
|
||||
>>>>>>>>> branch
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
error: encountered diff marker
|
||||
--> $DIR/long-conflict-markers.rs:3:1
|
||||
|
|
||||
LL | <<<<<<<<< HEAD
|
||||
| ^^^^^^^^^ between this marker and `=======` is the code that you are merging into
|
||||
...
|
||||
LL | =========
|
||||
| --------- between this marker and `>>>>>>>` is the incoming code
|
||||
LL | y: i8,
|
||||
LL | >>>>>>>>> branch
|
||||
| ^^^^^^^^^ this marker concludes the conflict region
|
||||
|
|
||||
= note: conflict markers indicate that a merge was started but could not be completed due to merge conflicts
|
||||
to resolve a conflict, keep only the code you want and then delete the lines containing conflict markers
|
||||
= help: if you are in a merge, the top section is the code you already had checked out and the bottom section is the new code
|
||||
if you are in a rebase, the top section is the code being rebased onto and the bottom section is the code you had checked out which is being rebased
|
||||
= note: for an explanation on these markers from the `git` documentation, visit <https://git-scm.com/book/en/v2/Git-Tools-Advanced-Merging#_checking_out_conflicts>
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
Reference in New Issue
Block a user