Ensure unchanged MatchedPos have the same number on LHS and RHS

Fixes #246
unified_patch
Wilfred Hughes 2022-04-09 21:11:24 +07:00
parent 1c9ae2fbc6
commit 1830d286e0
5 changed files with 157 additions and 22 deletions

@ -4,6 +4,10 @@
Fixed Zig parsing of `@foo` identifiers.
### Display
Fixed a crash when inserting newlines in JSX literals.
## 0.26 (released 9th April 2022)
### Build

@ -139,6 +139,9 @@ c1d8b44875121d81c583dd3a8fb43232 -
sample_files/typing_before.ml sample_files/typing_after.ml
ceba89e4ffc8406454d337638c7d45e6 -
sample_files/whitespace_before.tsx sample_files/whitespace_after.tsx
c4151c5a44b11e04fd11c2594597ed33 -
sample_files/yaml_before.yaml sample_files/yaml_after.yaml
1ae5db1355627f3ca607d76c3e6eed9a -

@ -0,0 +1,53 @@
const AttachmentInput: FC<AttachmentInputProps> = ({
title,
accept,
setFiles,
files,
name,
isInvalid,
}) => {
return (
<div style={STYLES.attachmentInput} data-testid="attachment-input">
<span style={STYLES.title}>{title}</span>
<DropZone
accept={accept}
onNewFiles={onNewFiles}
multiple
name={name}
isInvalid={isInvalid}
>
<Button variant="outline-secondary" className="my-1">
<FontAwesomeIcon
icon={faPlus}
/>
{" "}
Adicionar arquivos
{" "}
</Button>
</DropZone>
{" "}
{files.length > 0 && (
<div data-testid="attachment-files-names">
<div className="ml-1" style={STYLES.toBeSentLabel}>{"Arquivos a enviar: "}</div>
{files.map((file) => (
<Badge
variant="secondary"
key={file.name}
className="mr-1 px-3"
style={STYLES.badge}
>
<div style={STYLES.badgeText}>{file.name}</div>
<FontAwesomeIcon
icon={faTimes}
className="ml-2"
data-testid="attachment-files-remove"
onClick={() => onFileRemoved(file)}
/>
</Badge>
))}
</div>
)}
</div>
);
};

@ -0,0 +1,48 @@
const AttachmentInput: FC<AttachmentInputProps> = ({
title,
accept,
setFiles,
files,
name,
isInvalid,
}) => {
return (
<div style={STYLES.attachmentInput} data-testid="attachment-input">
<span style={STYLES.title}>{title}</span>
<DropZone
accept={accept}
onNewFiles={onNewFiles}
multiple
name={name}
isInvalid={isInvalid}
>
<Button variant="outline-secondary" className="my-1">
<FontAwesomeIcon icon={faPlus} /> Adicionar arquivos{" "}
</Button>
</DropZone>{" "}
{files.length > 0 && (
<div data-testid="attachment-files-names">
<div className="ml-1" style={STYLES.toBeSentLabel}>
{"Arquivos a enviar: "}
</div>
{files.map((file) => (
<Badge
variant="secondary"
key={file.name}
className="mr-1 px-3"
style={STYLES.badge}
>
<div style={STYLES.badgeText}>{file.name}</div>
<FontAwesomeIcon
icon={faTimes}
className="ml-2"
data-testid="attachment-files-remove"
onClick={() => onFileRemoved(file)}
/>
</Badge>
))}
</div>
)}
</div>
);
};

@ -703,7 +703,7 @@ impl MatchedPos {
pos: &[SingleLineSpan],
is_close: bool,
) -> Vec<Self> {
let kind = match ck {
match ck {
ReplacedComment(this, opposite) => {
let this_content = match this {
List { .. } => unreachable!(),
@ -716,13 +716,13 @@ impl MatchedPos {
} => (content, position),
};
return split_comment_words(
split_comment_words(
this_content,
// TODO: handle the whole pos here.
pos[0],
opposite_content,
opposite_pos[0],
);
)
}
Unchanged(opposite) => {
let opposite_pos = match opposite {
@ -740,33 +740,60 @@ impl MatchedPos {
Atom { position, .. } => position.clone(),
};
MatchKind::UnchangedToken {
let opposite_pos_len = opposite_pos.len();
let kind = MatchKind::UnchangedToken {
highlight,
self_pos: pos.to_vec(),
opposite_pos,
};
// Create a MatchedPos for every line that `pos` covers.
let mut res = vec![];
for (i, line_pos) in pos.iter().enumerate() {
// Don't create a MatchedPos for empty positions
// at the start. We will want empty positions on
// multiline atoms elsewhere, as a multline string
// literal may include empty lines.
if i == 0 && line_pos.start_col == line_pos.end_col {
continue;
}
res.push(Self {
kind: kind.clone(),
pos: *line_pos,
});
// Ensure we have the same number of unchanged
// MatchedPos on the LHS and RHS. This allows us
// to consider unchanged MatchedPos values
// pairwise.
if res.len() == opposite_pos_len {
break;
}
}
res
}
Novel => MatchKind::Novel { highlight },
};
Novel => {
let kind = MatchKind::Novel { highlight };
// Create a MatchedPos for every line that `pos` covers.
let mut res = vec![];
for line_pos in pos {
// Don't create a MatchedPos for empty positions. This
// occurs when we have lists with empty open/close
// delimiter positions, such as the top-level list of syntax items.
if pos.len() == 1 && line_pos.start_col == line_pos.end_col {
continue;
}
// Create a MatchedPos for every line that `pos` covers.
// TODO: what about opposite pos?
let mut res = vec![];
for line_pos in pos {
// Don't create a MatchedPos for empty positions. This
// occurs when we have lists with empty open/close
// delimiter positions, such as the top-level list of syntax items.
if pos.len() == 1 && line_pos.start_col == line_pos.end_col {
break;
}
res.push(Self {
kind: kind.clone(),
pos: *line_pos,
});
}
res.push(Self {
kind: kind.clone(),
pos: *line_pos,
});
res
}
}
res
}
}