terminal: Treat paths with non-digit col/rows as paths nonetheless (#10691)

Piotr Osiewicz created

This relaxes path parsing to allow paths like ./foo.rs:food or
./food/foo_bar.rs:2:12:food as some tools may add a suffix without
regard for col/row end.

Fixes #10688 

Release Notes:

- Made path parsing in terminal (for directory links) more lenient with
regards to row/column fields.

Change summary

crates/util/src/paths.rs | 44 ++++++++++++++++++++++-------------------
1 file changed, 24 insertions(+), 20 deletions(-)

Detailed changes

crates/util/src/paths.rs 🔗

@@ -205,23 +205,27 @@ impl<P> PathLikeWithPosition<P> {
                                     column: None,
                                 })
                             } else {
-                                let maybe_col_str =
-                                    if maybe_col_str.ends_with(FILE_ROW_COLUMN_DELIMITER) {
-                                        &maybe_col_str[..maybe_col_str.len() - 1]
-                                    } else {
-                                        maybe_col_str
-                                    };
+                                let (maybe_col_str, _) =
+                                    maybe_col_str.split_once(':').unwrap_or((maybe_col_str, ""));
                                 match maybe_col_str.parse::<u32>() {
                                     Ok(col) => Ok(Self {
                                         path_like: parse_path_like_str(path_like_str)?,
                                         row: Some(row),
                                         column: Some(col),
                                     }),
-                                    Err(_) => fallback(s),
+                                    Err(_) => Ok(Self {
+                                        path_like: parse_path_like_str(path_like_str)?,
+                                        row: Some(row),
+                                        column: None,
+                                    }),
                                 }
                             }
                         }
-                        Err(_) => fallback(s),
+                        Err(_) => Ok(Self {
+                            path_like: parse_path_like_str(path_like_str)?,
+                            row: None,
+                            column: None,
+                        }),
                     }
                 }
             }
@@ -352,23 +356,23 @@ mod tests {
 
     #[test]
     fn path_with_position_parsing_negative() {
-        for input in [
-            "test_file.rs:a",
-            "test_file.rs:a:b",
-            "test_file.rs::",
-            "test_file.rs::1",
-            "test_file.rs:1::",
-            "test_file.rs::1:2",
-            "test_file.rs:1::2",
-            "test_file.rs:1:2:3",
+        for (input, row, column) in [
+            ("test_file.rs:a", None, None),
+            ("test_file.rs:a:b", None, None),
+            ("test_file.rs::", None, None),
+            ("test_file.rs::1", None, None),
+            ("test_file.rs:1::", Some(1), None),
+            ("test_file.rs::1:2", None, None),
+            ("test_file.rs:1::2", Some(1), None),
+            ("test_file.rs:1:2:3", Some(1), Some(2)),
         ] {
             let actual = parse_str(input);
             assert_eq!(
                 actual,
                 PathLikeWithPosition {
-                    path_like: input.to_string(),
-                    row: None,
-                    column: None,
+                    path_like: "test_file.rs".to_string(),
+                    row,
+                    column,
                 },
                 "For negative case input str '{input}', got a parse mismatch"
             );