elixir: Fix `HEEx` name and add `EEx` defaults (#49812)

AltCode and Finn Evers created

- zed-extensions/elixir#61 renames `HEEX` to `HEEx`; to prevent any
disruptions from that change, this adds the correct name alongside a
settings migration
- zed-extensions/elixir#101 adds support for `EEx` templates; this sets
the default language server to be the same as that of `Elixir` and
`HEEx`

This also adds a few more extensions that should be recognized as `HEEx`
files

Release Notes:

- N/A

---------

Co-authored-by: Finn Evers <finn@zed.dev>

Change summary

assets/settings/default.json                            |  5 
crates/extensions_ui/src/extension_suggest.rs           |  2 
crates/languages/src/lib.rs                             |  2 
crates/languages/src/tailwind.rs                        |  7 -
crates/migrator/src/migrations.rs                       |  6 +
crates/migrator/src/migrations/m_2026_03_16/settings.rs | 50 ++++++++++
crates/migrator/src/migrator.rs                         |  8 +
crates/theme/src/icon_theme.rs                          |  2 
8 files changed, 73 insertions(+), 9 deletions(-)

Detailed changes

assets/settings/default.json 🔗

@@ -2029,6 +2029,9 @@
       "remove_trailing_whitespace_on_save": false,
       "ensure_final_newline_on_save": false,
     },
+    "EEx": {
+      "language_servers": ["elixir-ls", "!expert", "!next-ls", "!lexical", "..."],
+    },
     "Elixir": {
       "language_servers": ["elixir-ls", "!expert", "!next-ls", "!lexical", "..."],
     },
@@ -2055,7 +2058,7 @@
         "allowed": true,
       },
     },
-    "HEEX": {
+    "HEEx": {
       "language_servers": ["elixir-ls", "!expert", "!next-ls", "!lexical", "..."],
     },
     "HTML": {

crates/extensions_ui/src/extension_suggest.rs 🔗

@@ -22,7 +22,7 @@ const SUGGESTIONS_BY_EXTENSION_ID: &[(&str, &[&str])] = &[
     ("dart", &["dart"]),
     ("dockerfile", &["Dockerfile"]),
     ("elisp", &["el"]),
-    ("elixir", &["ex", "exs", "heex"]),
+    ("elixir", &["eex", "ex", "exs", "heex", "leex", "neex"]),
     ("elm", &["elm"]),
     ("erlang", &["erl", "hrl"]),
     ("fish", &["fish"]),

crates/languages/src/lib.rs 🔗

@@ -299,7 +299,7 @@ pub fn init(languages: Arc<LanguageRegistry>, fs: Arc<dyn Fs>, node: NodeRuntime
         "CSS",
         "ERB",
         "HTML+ERB",
-        "HEEX",
+        "HEEx",
         "HTML",
         "JavaScript",
         "TypeScript",

crates/languages/src/tailwind.rs 🔗

@@ -197,11 +197,8 @@ impl LspAdapter for TailwindLspAdapter {
                 "typescriptreact".to_string(),
             ),
             (LanguageName::new_static("Svelte"), "svelte".to_string()),
-            (
-                LanguageName::new_static("Elixir"),
-                "phoenix-heex".to_string(),
-            ),
-            (LanguageName::new_static("HEEX"), "phoenix-heex".to_string()),
+            (LanguageName::new_static("Elixir"), "elixir".to_string()),
+            (LanguageName::new_static("HEEx"), "heex".to_string()),
             (LanguageName::new_static("ERB"), "erb".to_string()),
             (LanguageName::new_static("HTML+ERB"), "erb".to_string()),
             (LanguageName::new_static("PHP"), "php".to_string()),

crates/migrator/src/migrations.rs 🔗

@@ -305,6 +305,12 @@ pub(crate) mod m_2026_02_25 {
     pub(crate) use settings::migrate_builtin_agent_servers_to_registry;
 }
 
+pub(crate) mod m_2026_03_16 {
+    mod settings;
+
+    pub(crate) use settings::SETTINGS_PATTERNS;
+}
+
 pub(crate) mod m_2026_03_23 {
     mod keymap;
 

crates/migrator/src/migrations/m_2026_03_16/settings.rs 🔗

@@ -0,0 +1,50 @@
+use std::ops::Range;
+use tree_sitter::{Query, QueryMatch};
+
+use crate::MigrationPatterns;
+use crate::patterns::SETTINGS_NESTED_KEY_VALUE_PATTERN;
+
+pub const SETTINGS_PATTERNS: MigrationPatterns =
+    &[(SETTINGS_NESTED_KEY_VALUE_PATTERN, rename_heex_settings)];
+
+fn rename_heex_settings(
+    contents: &str,
+    mat: &QueryMatch,
+    query: &Query,
+) -> Option<(Range<usize>, String)> {
+    if !is_heex_settings(contents, mat, query) {
+        return None;
+    }
+
+    let setting_name_ix = query.capture_index_for_name("setting_name")?;
+    let setting_name_range = mat
+        .nodes_for_capture_index(setting_name_ix)
+        .next()?
+        .byte_range();
+
+    Some((setting_name_range, "HEEx".to_string()))
+}
+
+fn is_heex_settings(contents: &str, mat: &QueryMatch, query: &Query) -> bool {
+    let parent_key_ix = match query.capture_index_for_name("parent_key") {
+        Some(ix) => ix,
+        None => return false,
+    };
+    let parent_range = match mat.nodes_for_capture_index(parent_key_ix).next() {
+        Some(node) => node.byte_range(),
+        None => return false,
+    };
+    if contents.get(parent_range) != Some("languages") {
+        return false;
+    }
+
+    let setting_name_ix = match query.capture_index_for_name("setting_name") {
+        Some(ix) => ix,
+        None => return false,
+    };
+    let setting_name_range = match mat.nodes_for_capture_index(setting_name_ix).next() {
+        Some(node) => node.byte_range(),
+        None => return false,
+    };
+    contents.get(setting_name_range) == Some("HEEX")
+}

crates/migrator/src/migrator.rs 🔗

@@ -243,6 +243,10 @@ pub fn migrate_settings(text: &str) -> Result<Option<String>> {
         MigrationType::Json(migrations::m_2026_02_03::migrate_experimental_sweep_mercury),
         MigrationType::Json(migrations::m_2026_02_04::migrate_tool_permission_defaults),
         MigrationType::Json(migrations::m_2026_02_25::migrate_builtin_agent_servers_to_registry),
+        MigrationType::TreeSitter(
+            migrations::m_2026_03_16::SETTINGS_PATTERNS,
+            &SETTINGS_QUERY_2026_03_16,
+        ),
     ];
     run_migrations(text, migrations)
 }
@@ -377,6 +381,10 @@ define_query!(
     SETTINGS_QUERY_2025_12_15,
     migrations::m_2025_12_15::SETTINGS_PATTERNS
 );
+define_query!(
+    SETTINGS_QUERY_2026_03_16,
+    migrations::m_2026_03_16::SETTINGS_PATTERNS
+);
 define_query!(
     KEYMAP_QUERY_2026_03_23,
     migrations::m_2026_03_23::KEYMAP_PATTERNS

crates/theme/src/icon_theme.rs 🔗

@@ -115,7 +115,7 @@ const FILE_SUFFIXES_BY_ICON_KEY: &[(&str, &[&str])] = &[
             "xlsx",
         ],
     ),
-    ("elixir", &["eex", "ex", "exs", "heex"]),
+    ("elixir", &["eex", "ex", "exs", "heex", "leex", "neex"]),
     ("elm", &["elm"]),
     (
         "erlang",