extension: Use `heck` instead of `convert_case` for snake_case check (#28608)

Marshall Bowers created

This PR updates the snake_case check for grammar names to use `heck`
instead of `convert_case`.

`heck` correctly handles values like `d2`.

Fixes https://github.com/zed-industries/zed/issues/28583.

Release Notes:

- Updated snake_case check for grammar names in extensions.

Change summary

Cargo.lock                                | 2 +-
Cargo.toml                                | 1 +
crates/extension/Cargo.toml               | 2 +-
crates/extension/src/extension_builder.rs | 4 ++--
4 files changed, 5 insertions(+), 4 deletions(-)

Detailed changes

Cargo.lock 🔗

@@ -4979,10 +4979,10 @@ dependencies = [
  "async-tar",
  "async-trait",
  "collections",
- "convert_case 0.8.0",
  "fs",
  "futures 0.3.31",
  "gpui",
+ "heck 0.5.0",
  "http_client",
  "language",
  "log",

Cargo.toml 🔗

@@ -443,6 +443,7 @@ futures-lite = "1.13"
 git2 = { version = "0.20.1", default-features = false }
 globset = "0.4"
 handlebars = "4.3"
+heck = "0.5"
 heed = { version = "0.21.0", features = ["read-txn-no-tls"] }
 hex = "0.4.3"
 html5ever = "0.27.0"

crates/extension/Cargo.toml 🔗

@@ -17,10 +17,10 @@ async-compression.workspace = true
 async-tar.workspace = true
 async-trait.workspace = true
 collections.workspace = true
-convert_case.workspace = true
 fs.workspace = true
 futures.workspace = true
 gpui.workspace = true
+heck.workspace = true
 http_client.workspace = true
 language.workspace = true
 log.workspace = true

crates/extension/src/extension_builder.rs 🔗

@@ -4,9 +4,9 @@ use crate::{
 use anyhow::{Context as _, Result, anyhow, bail};
 use async_compression::futures::bufread::GzipDecoder;
 use async_tar::Archive;
-use convert_case::{Case, Casing as _};
 use futures::AsyncReadExt;
 use futures::io::BufReader;
+use heck::ToSnakeCase;
 use http_client::{self, AsyncBody, HttpClient};
 use serde::Deserialize;
 use std::{
@@ -106,7 +106,7 @@ impl ExtensionBuilder {
         }
 
         for (grammar_name, grammar_metadata) in &extension_manifest.grammars {
-            let snake_cased_grammar_name = grammar_name.to_case(Case::Snake);
+            let snake_cased_grammar_name = grammar_name.to_snake_case();
             if grammar_name.as_ref() != snake_cased_grammar_name.as_str() {
                 bail!(
                     "grammar name '{grammar_name}' must be written in snake_case: {snake_cased_grammar_name}"