Improve snippet parse error context (#46277)

Oscar Vargas Torres created

Release Notes:

- N/A


Description:
E.g. Instead of saying:
2026-01-07T09:08:42-06:00 ERROR [crates/snippet_provider/src/lib.rs:46]
failed to parse snippet
  Caused by:
      expected an integer

Now the logs give more valuable information like:
2026-01-07T10:47:39-06:00 ERROR [crates/snippet_provider/src/lib.rs:48]
invalid snippet in /Users/oscarvarto/Library/Application
Support/Zed/extensions/installed/django-snippets/./snippets/python.json
(re_path)

Change summary

Cargo.lock                              |  1 +
crates/snippet_provider/Cargo.toml      |  1 +
crates/snippet_provider/src/lib.rs      | 10 +++++-----
crates/snippet_provider/src/registry.rs |  2 +-
4 files changed, 8 insertions(+), 6 deletions(-)

Detailed changes

Cargo.lock 🔗

@@ -15253,6 +15253,7 @@ dependencies = [
  "futures 0.3.31",
  "gpui",
  "indoc",
+ "log",
  "parking_lot",
  "paths",
  "schemars",

crates/snippet_provider/Cargo.toml 🔗

@@ -18,6 +18,7 @@ extension.workspace = true
 fs.workspace = true
 futures.workspace = true
 gpui.workspace = true
+log.workspace = true
 parking_lot.workspace = true
 paths.workspace = true
 serde.workspace = true

crates/snippet_provider/src/lib.rs 🔗

@@ -15,7 +15,6 @@ use fs::Fs;
 use futures::stream::StreamExt;
 use gpui::{App, AppContext as _, AsyncApp, Context, Entity, Task, WeakEntity};
 pub use registry::*;
-use util::ResultExt;
 
 pub fn init(cx: &mut App) {
     SnippetRegistry::init_global(cx);
@@ -32,7 +31,7 @@ fn file_stem_to_key(stem: &str) -> SnippetKind {
     }
 }
 
-fn file_to_snippets(file_contents: VsSnippetsFile) -> Vec<Arc<Snippet>> {
+fn file_to_snippets(file_contents: VsSnippetsFile, source: &Path) -> Vec<Arc<Snippet>> {
     let mut snippets = vec![];
     for (name, snippet) in file_contents.snippets {
         let snippet_name = name.clone();
@@ -43,9 +42,10 @@ fn file_to_snippets(file_contents: VsSnippetsFile) -> Vec<Arc<Snippet>> {
             .description
             .map(|description| description.to_string());
         let body = snippet.body.to_string();
-        if snippet::Snippet::parse(&body).log_err().is_none() {
+        if let Err(e) = snippet::Snippet::parse(&body) {
+            log::error!("Invalid snippet name '{name}' in {source:?}: {e:#}");
             continue;
-        };
+        }
         snippets.push(Arc::new(Snippet {
             body,
             prefix: prefixes,
@@ -105,7 +105,7 @@ async fn process_updates(
                 else {
                     return;
                 };
-                let snippets = file_to_snippets(as_json);
+                let snippets = file_to_snippets(as_json, entry_path.as_path());
                 *snippets_of_kind.entry(entry_path).or_default() = snippets;
             } else {
                 snippets_of_kind.remove(&entry_path);

crates/snippet_provider/src/registry.rs 🔗

@@ -42,7 +42,7 @@ impl SnippetRegistry {
         let kind = file_path
             .file_stem()
             .and_then(|stem| stem.to_str().and_then(file_stem_to_key));
-        let snippets = crate::file_to_snippets(snippets_in_file);
+        let snippets = crate::file_to_snippets(snippets_in_file, file_path);
         self.snippets.write().insert(kind, snippets);
 
         Ok(())