Fix indent computation of a macro with braces.
The leading whitespace of a multine string was taken into account when computing the `min_prefix_space_width`, even if that line couldn't be trimmed. The consequence is it was always shifting the macro's content to the right.
This commit is contained in:
parent
81a4235c7f
commit
c3edf6d3a1
4 changed files with 354 additions and 15 deletions
|
|
@ -821,6 +821,10 @@ pub enum FullCodeCharKind {
|
||||||
InComment,
|
InComment,
|
||||||
/// Last character of a comment, '\n' for a line comment, '/' for a block comment.
|
/// Last character of a comment, '\n' for a line comment, '/' for a block comment.
|
||||||
EndComment,
|
EndComment,
|
||||||
|
/// Start of a mutlitine string
|
||||||
|
StartString,
|
||||||
|
/// End of a mutlitine string
|
||||||
|
EndString,
|
||||||
/// Inside a string.
|
/// Inside a string.
|
||||||
InString,
|
InString,
|
||||||
}
|
}
|
||||||
|
|
@ -836,7 +840,7 @@ impl FullCodeCharKind {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_string(self) -> bool {
|
pub fn is_string(self) -> bool {
|
||||||
self == FullCodeCharKind::InString
|
self == FullCodeCharKind::InString || self == FullCodeCharKind::StartString
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_codecharkind(self) -> CodeCharKind {
|
fn to_codecharkind(self) -> CodeCharKind {
|
||||||
|
|
@ -924,17 +928,14 @@ where
|
||||||
_ => CharClassesStatus::Normal, // Unreachable
|
_ => CharClassesStatus::Normal, // Unreachable
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
CharClassesStatus::LitString => match chr {
|
CharClassesStatus::LitString => {
|
||||||
|
char_kind = FullCodeCharKind::InString;
|
||||||
|
match chr {
|
||||||
'"' => CharClassesStatus::Normal,
|
'"' => CharClassesStatus::Normal,
|
||||||
'\\' => {
|
'\\' => CharClassesStatus::LitStringEscape,
|
||||||
char_kind = FullCodeCharKind::InString;
|
_ => CharClassesStatus::LitString,
|
||||||
CharClassesStatus::LitStringEscape
|
|
||||||
}
|
}
|
||||||
_ => {
|
|
||||||
char_kind = FullCodeCharKind::InString;
|
|
||||||
CharClassesStatus::LitString
|
|
||||||
}
|
}
|
||||||
},
|
|
||||||
CharClassesStatus::LitStringEscape => {
|
CharClassesStatus::LitStringEscape => {
|
||||||
char_kind = FullCodeCharKind::InString;
|
char_kind = FullCodeCharKind::InString;
|
||||||
CharClassesStatus::LitString
|
CharClassesStatus::LitString
|
||||||
|
|
@ -1052,9 +1053,22 @@ impl<'a> Iterator for LineClasses<'a> {
|
||||||
|
|
||||||
let mut line = String::new();
|
let mut line = String::new();
|
||||||
|
|
||||||
|
let start_class = match self.base.peek() {
|
||||||
|
Some((kind, _)) => *kind,
|
||||||
|
None => FullCodeCharKind::Normal,
|
||||||
|
};
|
||||||
|
|
||||||
while let Some((kind, c)) = self.base.next() {
|
while let Some((kind, c)) = self.base.next() {
|
||||||
self.kind = kind;
|
|
||||||
if c == '\n' {
|
if c == '\n' {
|
||||||
|
self.kind = match (start_class, kind) {
|
||||||
|
(FullCodeCharKind::Normal, FullCodeCharKind::InString) => {
|
||||||
|
FullCodeCharKind::StartString
|
||||||
|
}
|
||||||
|
(FullCodeCharKind::InString, FullCodeCharKind::Normal) => {
|
||||||
|
FullCodeCharKind::EndString
|
||||||
|
}
|
||||||
|
_ => kind,
|
||||||
|
};
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
line.push(c);
|
line.push(c);
|
||||||
|
|
@ -1227,7 +1241,10 @@ pub fn recover_comment_removed(
|
||||||
pub fn filter_normal_code(code: &str) -> String {
|
pub fn filter_normal_code(code: &str) -> String {
|
||||||
let mut buffer = String::with_capacity(code.len());
|
let mut buffer = String::with_capacity(code.len());
|
||||||
LineClasses::new(code).for_each(|(kind, line)| match kind {
|
LineClasses::new(code).for_each(|(kind, line)| match kind {
|
||||||
FullCodeCharKind::Normal | FullCodeCharKind::InString => {
|
FullCodeCharKind::Normal
|
||||||
|
| FullCodeCharKind::StartString
|
||||||
|
| FullCodeCharKind::InString
|
||||||
|
| FullCodeCharKind::EndString => {
|
||||||
buffer.push_str(&line);
|
buffer.push_str(&line);
|
||||||
buffer.push('\n');
|
buffer.push('\n');
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1118,6 +1118,7 @@ fn indent_macro_snippet(
|
||||||
} else {
|
} else {
|
||||||
Some(get_prefix_space_width(context, &line))
|
Some(get_prefix_space_width(context, &line))
|
||||||
};
|
};
|
||||||
|
|
||||||
let line = if veto_trim || (kind.is_string() && !line.ends_with('\\')) {
|
let line = if veto_trim || (kind.is_string() && !line.ends_with('\\')) {
|
||||||
veto_trim = kind.is_string() && !line.ends_with('\\');
|
veto_trim = kind.is_string() && !line.ends_with('\\');
|
||||||
trimmed = false;
|
trimmed = false;
|
||||||
|
|
@ -1126,7 +1127,12 @@ fn indent_macro_snippet(
|
||||||
line.trim().to_owned()
|
line.trim().to_owned()
|
||||||
};
|
};
|
||||||
trimmed_lines.push((trimmed, line, prefix_space_width));
|
trimmed_lines.push((trimmed, line, prefix_space_width));
|
||||||
prefix_space_width
|
|
||||||
|
// when computing the minimum, do not consider lines within a string
|
||||||
|
match kind {
|
||||||
|
FullCodeCharKind::InString | FullCodeCharKind::EndString => None,
|
||||||
|
_ => prefix_space_width,
|
||||||
|
}
|
||||||
}).min()?;
|
}).min()?;
|
||||||
|
|
||||||
Some(
|
Some(
|
||||||
|
|
@ -1139,7 +1145,7 @@ fn indent_macro_snippet(
|
||||||
let new_indent_width = indent.width() + original_indent_width
|
let new_indent_width = indent.width() + original_indent_width
|
||||||
.saturating_sub(min_prefix_space_width);
|
.saturating_sub(min_prefix_space_width);
|
||||||
let new_indent = Indent::from_width(context.config, new_indent_width);
|
let new_indent = Indent::from_width(context.config, new_indent_width);
|
||||||
format!("{}{}", new_indent.to_string(context.config), line.trim())
|
format!("{}{}", new_indent.to_string(context.config), line)
|
||||||
}
|
}
|
||||||
None => String::new(),
|
None => String::new(),
|
||||||
},
|
},
|
||||||
|
|
|
||||||
158
tests/source/issue-2973.rs
Normal file
158
tests/source/issue-2973.rs
Normal file
|
|
@ -0,0 +1,158 @@
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
summary_test! {
|
||||||
|
tokenize_recipe_interpolation_eol,
|
||||||
|
"foo: # some comment
|
||||||
|
{{hello}}
|
||||||
|
",
|
||||||
|
"foo: \
|
||||||
|
{{hello}} \
|
||||||
|
{{ahah}}",
|
||||||
|
"N:#$>^{N}$<.",
|
||||||
|
}
|
||||||
|
|
||||||
|
summary_test! {
|
||||||
|
tokenize_strings,
|
||||||
|
r#"a = "'a'" + '"b"' + "'c'" + '"d"'#echo hello"#,
|
||||||
|
r#"N="+'+"+'#."#,
|
||||||
|
}
|
||||||
|
|
||||||
|
summary_test! {
|
||||||
|
tokenize_recipe_interpolation_eol,
|
||||||
|
"foo: # some comment
|
||||||
|
{{hello}}
|
||||||
|
",
|
||||||
|
"N:#$>^{N}$<.",
|
||||||
|
}
|
||||||
|
|
||||||
|
summary_test! {
|
||||||
|
tokenize_recipe_interpolation_eof,
|
||||||
|
"foo: # more comments
|
||||||
|
{{hello}}
|
||||||
|
# another comment
|
||||||
|
",
|
||||||
|
"N:#$>^{N}$<#$.",
|
||||||
|
}
|
||||||
|
|
||||||
|
summary_test! {
|
||||||
|
tokenize_recipe_complex_interpolation_expression,
|
||||||
|
"foo: #lol\n {{a + b + \"z\" + blarg}}",
|
||||||
|
"N:#$>^{N+N+\"+N}<.",
|
||||||
|
}
|
||||||
|
|
||||||
|
summary_test! {
|
||||||
|
tokenize_recipe_multiple_interpolations,
|
||||||
|
"foo:,#ok\n {{a}}0{{b}}1{{c}}",
|
||||||
|
"N:,#$>^{N}_{N}_{N}<.",
|
||||||
|
}
|
||||||
|
|
||||||
|
summary_test! {
|
||||||
|
tokenize_junk,
|
||||||
|
"bob
|
||||||
|
|
||||||
|
hello blah blah blah : a b c #whatever
|
||||||
|
",
|
||||||
|
"N$$NNNN:NNN#$.",
|
||||||
|
}
|
||||||
|
|
||||||
|
summary_test! {
|
||||||
|
tokenize_empty_lines,
|
||||||
|
"
|
||||||
|
# this does something
|
||||||
|
hello:
|
||||||
|
asdf
|
||||||
|
bsdf
|
||||||
|
|
||||||
|
csdf
|
||||||
|
|
||||||
|
dsdf # whatever
|
||||||
|
|
||||||
|
# yolo
|
||||||
|
",
|
||||||
|
"$#$N:$>^_$^_$$^_$$^_$$<#$.",
|
||||||
|
}
|
||||||
|
|
||||||
|
summary_test! {
|
||||||
|
tokenize_comment_before_variable,
|
||||||
|
"
|
||||||
|
#
|
||||||
|
A='1'
|
||||||
|
echo:
|
||||||
|
echo {{A}}
|
||||||
|
",
|
||||||
|
"$#$N='$N:$>^_{N}$<.",
|
||||||
|
}
|
||||||
|
|
||||||
|
summary_test! {
|
||||||
|
tokenize_interpolation_backticks,
|
||||||
|
"hello:\n echo {{`echo hello` + `echo goodbye`}}",
|
||||||
|
"N:$>^_{`+`}<.",
|
||||||
|
}
|
||||||
|
|
||||||
|
summary_test! {
|
||||||
|
tokenize_assignment_backticks,
|
||||||
|
"a = `echo hello` + `echo goodbye`",
|
||||||
|
"N=`+`.",
|
||||||
|
}
|
||||||
|
|
||||||
|
summary_test! {
|
||||||
|
tokenize_multiple,
|
||||||
|
"
|
||||||
|
hello:
|
||||||
|
a
|
||||||
|
b
|
||||||
|
|
||||||
|
c
|
||||||
|
|
||||||
|
d
|
||||||
|
|
||||||
|
# hello
|
||||||
|
bob:
|
||||||
|
frank
|
||||||
|
",
|
||||||
|
|
||||||
|
"$N:$>^_$^_$$^_$$^_$$<#$N:$>^_$<.",
|
||||||
|
}
|
||||||
|
|
||||||
|
summary_test! {
|
||||||
|
tokenize_comment,
|
||||||
|
"a:=#",
|
||||||
|
"N:=#."
|
||||||
|
}
|
||||||
|
|
||||||
|
summary_test! {
|
||||||
|
tokenize_comment_with_bang,
|
||||||
|
"a:=#foo!",
|
||||||
|
"N:=#."
|
||||||
|
}
|
||||||
|
|
||||||
|
summary_test! {
|
||||||
|
tokenize_order,
|
||||||
|
r"
|
||||||
|
b: a
|
||||||
|
@mv a b
|
||||||
|
|
||||||
|
a:
|
||||||
|
@touch F
|
||||||
|
@touch a
|
||||||
|
|
||||||
|
d: c
|
||||||
|
@rm c
|
||||||
|
|
||||||
|
c: b
|
||||||
|
@mv b c",
|
||||||
|
"$N:N$>^_$$<N:$>^_$^_$$<N:N$>^_$$<N:N$>^_<.",
|
||||||
|
}
|
||||||
|
|
||||||
|
summary_test! {
|
||||||
|
tokenize_parens,
|
||||||
|
r"((())) )abc(+",
|
||||||
|
"((())))N(+.",
|
||||||
|
}
|
||||||
|
|
||||||
|
summary_test! {
|
||||||
|
crlf_newline,
|
||||||
|
"#\r\n#asdf\r\n",
|
||||||
|
"#$#$.",
|
||||||
|
}
|
||||||
|
}
|
||||||
158
tests/target/issue-2973.rs
Normal file
158
tests/target/issue-2973.rs
Normal file
|
|
@ -0,0 +1,158 @@
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
summary_test! {
|
||||||
|
tokenize_recipe_interpolation_eol,
|
||||||
|
"foo: # some comment
|
||||||
|
{{hello}}
|
||||||
|
",
|
||||||
|
"foo: \
|
||||||
|
{{hello}} \
|
||||||
|
{{ahah}}",
|
||||||
|
"N:#$>^{N}$<.",
|
||||||
|
}
|
||||||
|
|
||||||
|
summary_test! {
|
||||||
|
tokenize_strings,
|
||||||
|
r#"a = "'a'" + '"b"' + "'c'" + '"d"'#echo hello"#,
|
||||||
|
r#"N="+'+"+'#."#,
|
||||||
|
}
|
||||||
|
|
||||||
|
summary_test! {
|
||||||
|
tokenize_recipe_interpolation_eol,
|
||||||
|
"foo: # some comment
|
||||||
|
{{hello}}
|
||||||
|
",
|
||||||
|
"N:#$>^{N}$<.",
|
||||||
|
}
|
||||||
|
|
||||||
|
summary_test! {
|
||||||
|
tokenize_recipe_interpolation_eof,
|
||||||
|
"foo: # more comments
|
||||||
|
{{hello}}
|
||||||
|
# another comment
|
||||||
|
",
|
||||||
|
"N:#$>^{N}$<#$.",
|
||||||
|
}
|
||||||
|
|
||||||
|
summary_test! {
|
||||||
|
tokenize_recipe_complex_interpolation_expression,
|
||||||
|
"foo: #lol\n {{a + b + \"z\" + blarg}}",
|
||||||
|
"N:#$>^{N+N+\"+N}<.",
|
||||||
|
}
|
||||||
|
|
||||||
|
summary_test! {
|
||||||
|
tokenize_recipe_multiple_interpolations,
|
||||||
|
"foo:,#ok\n {{a}}0{{b}}1{{c}}",
|
||||||
|
"N:,#$>^{N}_{N}_{N}<.",
|
||||||
|
}
|
||||||
|
|
||||||
|
summary_test! {
|
||||||
|
tokenize_junk,
|
||||||
|
"bob
|
||||||
|
|
||||||
|
hello blah blah blah : a b c #whatever
|
||||||
|
",
|
||||||
|
"N$$NNNN:NNN#$.",
|
||||||
|
}
|
||||||
|
|
||||||
|
summary_test! {
|
||||||
|
tokenize_empty_lines,
|
||||||
|
"
|
||||||
|
# this does something
|
||||||
|
hello:
|
||||||
|
asdf
|
||||||
|
bsdf
|
||||||
|
|
||||||
|
csdf
|
||||||
|
|
||||||
|
dsdf # whatever
|
||||||
|
|
||||||
|
# yolo
|
||||||
|
",
|
||||||
|
"$#$N:$>^_$^_$$^_$$^_$$<#$.",
|
||||||
|
}
|
||||||
|
|
||||||
|
summary_test! {
|
||||||
|
tokenize_comment_before_variable,
|
||||||
|
"
|
||||||
|
#
|
||||||
|
A='1'
|
||||||
|
echo:
|
||||||
|
echo {{A}}
|
||||||
|
",
|
||||||
|
"$#$N='$N:$>^_{N}$<.",
|
||||||
|
}
|
||||||
|
|
||||||
|
summary_test! {
|
||||||
|
tokenize_interpolation_backticks,
|
||||||
|
"hello:\n echo {{`echo hello` + `echo goodbye`}}",
|
||||||
|
"N:$>^_{`+`}<.",
|
||||||
|
}
|
||||||
|
|
||||||
|
summary_test! {
|
||||||
|
tokenize_assignment_backticks,
|
||||||
|
"a = `echo hello` + `echo goodbye`",
|
||||||
|
"N=`+`.",
|
||||||
|
}
|
||||||
|
|
||||||
|
summary_test! {
|
||||||
|
tokenize_multiple,
|
||||||
|
"
|
||||||
|
hello:
|
||||||
|
a
|
||||||
|
b
|
||||||
|
|
||||||
|
c
|
||||||
|
|
||||||
|
d
|
||||||
|
|
||||||
|
# hello
|
||||||
|
bob:
|
||||||
|
frank
|
||||||
|
",
|
||||||
|
|
||||||
|
"$N:$>^_$^_$$^_$$^_$$<#$N:$>^_$<.",
|
||||||
|
}
|
||||||
|
|
||||||
|
summary_test! {
|
||||||
|
tokenize_comment,
|
||||||
|
"a:=#",
|
||||||
|
"N:=#."
|
||||||
|
}
|
||||||
|
|
||||||
|
summary_test! {
|
||||||
|
tokenize_comment_with_bang,
|
||||||
|
"a:=#foo!",
|
||||||
|
"N:=#."
|
||||||
|
}
|
||||||
|
|
||||||
|
summary_test! {
|
||||||
|
tokenize_order,
|
||||||
|
r"
|
||||||
|
b: a
|
||||||
|
@mv a b
|
||||||
|
|
||||||
|
a:
|
||||||
|
@touch F
|
||||||
|
@touch a
|
||||||
|
|
||||||
|
d: c
|
||||||
|
@rm c
|
||||||
|
|
||||||
|
c: b
|
||||||
|
@mv b c",
|
||||||
|
"$N:N$>^_$$<N:$>^_$^_$$<N:N$>^_$$<N:N$>^_<.",
|
||||||
|
}
|
||||||
|
|
||||||
|
summary_test! {
|
||||||
|
tokenize_parens,
|
||||||
|
r"((())) )abc(+",
|
||||||
|
"((())))N(+.",
|
||||||
|
}
|
||||||
|
|
||||||
|
summary_test! {
|
||||||
|
crlf_newline,
|
||||||
|
"#\r\n#asdf\r\n",
|
||||||
|
"#$#$.",
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue