Handle empty match list and do safe vector selection instead of slicing (#50232) (cherry-pick to preview) (#50234)

zed-zippy[bot] and KyleBarton created

Cherry-pick of #50232 to preview

----
Handles a panic found in telemetry - when there are no template matches
or feature matches, the picker delegate will panic due to an indexing
exception. This solves by:
1. Returning early if there are no matches, and
2. Performing safe vector `get` operations instead of slicing, so we can
handle a not-found scenario.




https://github.com/user-attachments/assets/ac76164d-63aa-4e2b-8555-d8e4f4dd2524



Before you mark this PR as ready for review, make sure that you have:
- [x] Added a solid test coverage and/or screenshots from doing manual
testing
- [x] Done a self-review taking into account security and performance
aspects
- [x] Aligned any UI changes with the [UI

checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)

Release Notes:

- Fixed potential crash from initializing devcontainer.json

Co-authored-by: KyleBarton <kjb@initialcapacity.io>

Change summary

crates/dev_container/src/lib.rs | 30 +++++++++++++++++++++++-------
1 file changed, 23 insertions(+), 7 deletions(-)

Detailed changes

crates/dev_container/src/lib.rs 🔗

@@ -300,14 +300,20 @@ impl PickerDelegate for TemplatePickerDelegate {
     ) {
         let fun = &mut self.on_confirm;
 
+        if self.matching_indices.is_empty() {
+            return;
+        }
         self.stateful_modal
             .update(cx, |modal, cx| {
-                fun(
-                    self.candidate_templates[self.matching_indices[self.selected_index]].clone(),
-                    modal,
-                    window,
-                    cx,
-                );
+                let Some(confirmed_entry) = self
+                    .matching_indices
+                    .get(self.selected_index)
+                    .and_then(|ix| self.candidate_templates.get(*ix))
+                else {
+                    log::error!("Selected index not in range of known matches");
+                    return;
+                };
+                fun(confirmed_entry.clone(), modal, window, cx);
             })
             .ok();
     }
@@ -476,7 +482,17 @@ impl PickerDelegate for FeaturePickerDelegate {
                 })
                 .ok();
         } else {
-            let current = &mut self.candidate_features[self.matching_indices[self.selected_index]];
+            if self.matching_indices.is_empty() {
+                return;
+            }
+            let Some(current) = self
+                .matching_indices
+                .get(self.selected_index)
+                .and_then(|ix| self.candidate_features.get_mut(*ix))
+            else {
+                log::error!("Selected index not in range of matches");
+                return;
+            };
             current.toggle_state = match current.toggle_state {
                 ToggleState::Selected => {
                     self.template_entry