]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
runtime(rust): Fix Rust indentation when string contains "if"
authortaylor.fish <contact@taylor.fish>
Wed, 28 Jan 2026 22:04:21 +0000 (22:04 +0000)
committerChristian Brabandt <cb@256bit.org>
Wed, 28 Jan 2026 22:07:16 +0000 (22:07 +0000)
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 <contact@taylor.fish>
Signed-off-by: Christian Brabandt <cb@256bit.org>
runtime/indent/rust.vim
runtime/indent/testdir/rust.in
runtime/indent/testdir/rust.ok

index 30206be435d4b404ba01f787b8f91b2bf5429f63..f449a19de2b9fce4221874285fc0e9f4f69dba61 100644 (file)
@@ -5,6 +5,7 @@
 " 2024 Jul 04 by Vim Project: use shiftwidth() instead of hard-coding shifted values #15138
 " 2025 Dec 29 by Vim Project: clean up
 " 2025 Dec 31 by Vim Project: correcly indent after nested array literal #19042
+" 2026 Jan 28 by Vim Project: fix indentation when a string literal contains 'if' #19265
 
 " For bugs, patches and license go to https://github.com/rust-lang/rust.vim
 " Note: upstream seems umaintained: https://github.com/rust-lang/rust.vim/issues/502
@@ -139,9 +140,24 @@ function GetRustIndent(lnum)
     let l:standalone_close = line =~# '\V\^\s\*}\s\*\$'
     let l:standalone_where = line =~# '\V\^\s\*where\s\*\$'
     if l:standalone_open || l:standalone_close || l:standalone_where
-        " ToDo: we can search for more items than 'fn' and 'if'.
-        let [l:found_line, l:col, l:submatch] =
-                    \ searchpos('\<\(fn\)\|\(if\)\>', 'bnWp')
+        let l:orig_line = line('.')
+        let l:orig_col = col('.')
+        let l:i = 0
+        while 1
+            " ToDo: we can search for more items than 'fn' and 'if'.
+            let [l:found_line, l:col, l:submatch] =
+                        \ searchpos('\<\(fn\|if\)\>', 'bWp')
+            if l:found_line ==# 0 || !s:is_string_comment(l:found_line, l:col)
+                break
+            endif
+            let l:i += 1
+            " Limit to 10 iterations as a failsafe against endless looping.
+            if l:i >= 10
+                let l:found_line = 0
+                break
+            endif
+        endwhile
+        call cursor(l:orig_line, l:orig_col)
         if l:found_line !=# 0
             " Now we count the number of '{' and '}' in between the match
             " locations and the current line (there is probably a better
index 28a68924f69b030e441a7e837bc85fd1399d5091..9b1912b23e4074b7b1961fc7dd55e1bacd6e07a0 100644 (file)
@@ -40,3 +40,11 @@ fn main() {
     // file goes out of scope, and the "hello.txt" file gets closed
 }
 // END_INDENT
+
+// START_INDENT
+let x = "
+            if fn motif
+            ";
+            struct X {
+                        }
+// END_INDENT
index 04808e224f4d06826fec3742c069c8d0b8b9f641..73fff0620f03d825d498b69d4d0199adb18fd69a 100644 (file)
@@ -40,3 +40,11 @@ fn main() {
     // file goes out of scope, and the "hello.txt" file gets closed
 }
 // END_INDENT
+
+// START_INDENT
+let x = "
+            if fn motif
+            ";
+            struct X {
+}
+// END_INDENT