Skip to content

Commit 663d809

Browse files
taylordotfishchrisbra
authored andcommitted
runtime(rust): Fix Rust indentation when string contains "if"
indent/rust.vim behaves incorrectly when a string literal contains the substring "if". For example, in this code: let x = " motif "; struct X { } indent/rust.vim thinks that the closing "}" should line up with "motif". This patch fixes the issue by checking whether the "if" is in a string literal or comment before considering it to be a match for a subsequent brace (and also by requiring it to start on a word boundary). Add an indent test to ensure this does not regress. closes: #19265 Signed-off-by: taylor.fish <[email protected]> Signed-off-by: Christian Brabandt <[email protected]>
1 parent 427fa3e commit 663d809

File tree

3 files changed

+35
-3
lines changed

3 files changed

+35
-3
lines changed

runtime/indent/rust.vim

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
" 2024 Jul 04 by Vim Project: use shiftwidth() instead of hard-coding shifted values #15138
66
" 2025 Dec 29 by Vim Project: clean up
77
" 2025 Dec 31 by Vim Project: correcly indent after nested array literal #19042
8+
" 2026 Jan 28 by Vim Project: fix indentation when a string literal contains 'if' #19265
89

910
" For bugs, patches and license go to https://github.com/rust-lang/rust.vim
1011
" Note: upstream seems umaintained: https://github.com/rust-lang/rust.vim/issues/502
@@ -139,9 +140,24 @@ function GetRustIndent(lnum)
139140
let l:standalone_close = line =~# '\V\^\s\*}\s\*\$'
140141
let l:standalone_where = line =~# '\V\^\s\*where\s\*\$'
141142
if l:standalone_open || l:standalone_close || l:standalone_where
142-
" ToDo: we can search for more items than 'fn' and 'if'.
143-
let [l:found_line, l:col, l:submatch] =
144-
\ searchpos('\<\(fn\)\|\(if\)\>', 'bnWp')
143+
let l:orig_line = line('.')
144+
let l:orig_col = col('.')
145+
let l:i = 0
146+
while 1
147+
" ToDo: we can search for more items than 'fn' and 'if'.
148+
let [l:found_line, l:col, l:submatch] =
149+
\ searchpos('\<\(fn\|if\)\>', 'bWp')
150+
if l:found_line ==# 0 || !s:is_string_comment(l:found_line, l:col)
151+
break
152+
endif
153+
let l:i += 1
154+
" Limit to 10 iterations as a failsafe against endless looping.
155+
if l:i >= 10
156+
let l:found_line = 0
157+
break
158+
endif
159+
endwhile
160+
call cursor(l:orig_line, l:orig_col)
145161
if l:found_line !=# 0
146162
" Now we count the number of '{' and '}' in between the match
147163
" locations and the current line (there is probably a better

runtime/indent/testdir/rust.in

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,11 @@ fn main() {
4040
// file goes out of scope, and the "hello.txt" file gets closed
4141
}
4242
// END_INDENT
43+
44+
// START_INDENT
45+
let x = "
46+
if fn motif
47+
";
48+
struct X {
49+
}
50+
// END_INDENT

runtime/indent/testdir/rust.ok

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,11 @@ fn main() {
4040
// file goes out of scope, and the "hello.txt" file gets closed
4141
}
4242
// END_INDENT
43+
44+
// START_INDENT
45+
let x = "
46+
if fn motif
47+
";
48+
struct X {
49+
}
50+
// END_INDENT

0 commit comments

Comments
 (0)