Add logic for managing language and theme extensions (#7467)

This PR adds the initial support for loading extensions in Zed.

### Extensions Directory

Extensions are loaded from the extensions directory.

The extensions directory has the following structure:

```
extensions/
  installed/
    extension-a/
      grammars/
      languages/
    extension-b/
      themes/
  manifest.json
```

The `manifest.json` file is used internally by Zed to keep track of
which extensions are installed. This file should be maintained
automatically, and shouldn't require any direct interaction with it.

Extensions can provide Tree-sitter grammars, languages, and themes.

Release Notes:

- N/A

---------

Co-authored-by: Marshall <marshall@zed.dev>
This commit is contained in:
Max Brunsfeld
2024-02-07 15:14:50 -05:00
committed by GitHub
co-authored by Marshall
parent 6b598a07d9
commit 6edeea7c8a
77 changed files with 1503 additions and 387 deletions
+13 -4
View File
@@ -1003,7 +1003,7 @@ pub mod tests {
use gpui::{div, font, observe, px, AppContext, Context, Element, Hsla};
use language::{
language_settings::{AllLanguageSettings, AllLanguageSettingsContent},
Buffer, Language, LanguageConfig, SelectionGoal,
Buffer, Language, LanguageConfig, LanguageMatcher, SelectionGoal,
};
use project::Project;
use rand::{prelude::*, Rng};
@@ -1453,7 +1453,10 @@ pub mod tests {
Language::new(
LanguageConfig {
name: "Test".into(),
path_suffixes: vec![".test".to_string()],
matcher: LanguageMatcher {
path_suffixes: vec![".test".to_string()],
..Default::default()
},
..Default::default()
},
Some(tree_sitter_rust::language()),
@@ -1540,7 +1543,10 @@ pub mod tests {
Language::new(
LanguageConfig {
name: "Test".into(),
path_suffixes: vec![".test".to_string()],
matcher: LanguageMatcher {
path_suffixes: vec![".test".to_string()],
..Default::default()
},
..Default::default()
},
Some(tree_sitter_rust::language()),
@@ -1608,7 +1614,10 @@ pub mod tests {
Language::new(
LanguageConfig {
name: "Test".into(),
path_suffixes: vec![".test".to_string()],
matcher: LanguageMatcher {
path_suffixes: vec![".test".to_string()],
..Default::default()
},
..Default::default()
},
Some(tree_sitter_rust::language()),
+30 -8
View File
@@ -15,7 +15,8 @@ use language::{
language_settings::{AllLanguageSettings, AllLanguageSettingsContent, LanguageSettingsContent},
BracketPairConfig,
Capability::ReadWrite,
FakeLspAdapter, LanguageConfig, LanguageConfigOverride, LanguageRegistry, Override, Point,
FakeLspAdapter, LanguageConfig, LanguageConfigOverride, LanguageMatcher, LanguageRegistry,
Override, Point,
};
use parking_lot::Mutex;
use project::project_settings::{LspSettings, ProjectSettings};
@@ -5077,7 +5078,10 @@ async fn test_document_format_during_save(cx: &mut gpui::TestAppContext) {
let mut language = Language::new(
LanguageConfig {
name: "Rust".into(),
path_suffixes: vec!["rs".to_string()],
matcher: LanguageMatcher {
path_suffixes: vec!["rs".to_string()],
..Default::default()
},
..Default::default()
},
Some(tree_sitter_rust::language()),
@@ -5196,7 +5200,10 @@ async fn test_range_format_during_save(cx: &mut gpui::TestAppContext) {
let mut language = Language::new(
LanguageConfig {
name: "Rust".into(),
path_suffixes: vec!["rs".to_string()],
matcher: LanguageMatcher {
path_suffixes: vec!["rs".to_string()],
..Default::default()
},
..Default::default()
},
Some(tree_sitter_rust::language()),
@@ -5318,7 +5325,10 @@ async fn test_document_format_manual_trigger(cx: &mut gpui::TestAppContext) {
let mut language = Language::new(
LanguageConfig {
name: "Rust".into(),
path_suffixes: vec!["rs".to_string()],
matcher: LanguageMatcher {
path_suffixes: vec!["rs".to_string()],
..Default::default()
},
// Enable Prettier formatting for the same buffer, and ensure
// LSP is called instead of Prettier.
prettier_parser_name: Some("test_parser".to_string()),
@@ -7747,7 +7757,10 @@ async fn test_on_type_formatting_not_triggered(cx: &mut gpui::TestAppContext) {
let mut language = Language::new(
LanguageConfig {
name: "Rust".into(),
path_suffixes: vec!["rs".to_string()],
matcher: LanguageMatcher {
path_suffixes: vec!["rs".to_string()],
..Default::default()
},
brackets: BracketPairConfig {
pairs: vec![BracketPair {
start: "{".to_string(),
@@ -7859,7 +7872,10 @@ async fn test_language_server_restart_due_to_settings_change(cx: &mut gpui::Test
let mut language = Language::new(
LanguageConfig {
name: Arc::clone(&language_name),
path_suffixes: vec!["rs".to_string()],
matcher: LanguageMatcher {
path_suffixes: vec!["rs".to_string()],
..Default::default()
},
..Default::default()
},
Some(tree_sitter_rust::language()),
@@ -8086,7 +8102,10 @@ async fn test_completions_in_languages_with_extra_word_characters(cx: &mut gpui:
let mut cx = EditorLspTestContext::new(
Language::new(
LanguageConfig {
path_suffixes: vec!["jsx".into()],
matcher: LanguageMatcher {
path_suffixes: vec!["jsx".into()],
..Default::default()
},
overrides: [(
"element".into(),
LanguageConfigOverride {
@@ -8187,7 +8206,10 @@ async fn test_document_format_with_prettier(cx: &mut gpui::TestAppContext) {
let mut language = Language::new(
LanguageConfig {
name: "Rust".into(),
path_suffixes: vec!["rs".to_string()],
matcher: LanguageMatcher {
path_suffixes: vec!["rs".to_string()],
..Default::default()
},
prettier_parser_name: Some("test_parser".to_string()),
..Default::default()
},
@@ -35,7 +35,7 @@ mod tests {
use super::*;
use crate::{editor_tests::init_test, test::editor_lsp_test_context::EditorLspTestContext};
use indoc::indoc;
use language::{BracketPair, BracketPairConfig, Language, LanguageConfig};
use language::{BracketPair, BracketPairConfig, Language, LanguageConfig, LanguageMatcher};
#[gpui::test]
async fn test_matching_bracket_highlights(cx: &mut gpui::TestAppContext) {
@@ -45,7 +45,10 @@ mod tests {
Language::new(
LanguageConfig {
name: "Rust".into(),
path_suffixes: vec!["rs".to_string()],
matcher: LanguageMatcher {
path_suffixes: vec!["rs".to_string()],
..Default::default()
},
brackets: BracketPairConfig {
pairs: vec![
BracketPair {
+25 -7
View File
@@ -1240,7 +1240,7 @@ pub mod tests {
use itertools::Itertools;
use language::{
language_settings::AllLanguageSettingsContent, Capability, FakeLspAdapter, Language,
LanguageConfig,
LanguageConfig, LanguageMatcher,
};
use lsp::FakeLanguageServer;
use parking_lot::Mutex;
@@ -1529,7 +1529,10 @@ pub mod tests {
let mut language = Language::new(
LanguageConfig {
name: name.into(),
path_suffixes: vec![path_suffix.to_string()],
matcher: LanguageMatcher {
path_suffixes: vec![path_suffix.to_string()],
..Default::default()
},
..Default::default()
},
Some(tree_sitter_rust::language()),
@@ -2209,7 +2212,10 @@ pub mod tests {
let mut language = Language::new(
LanguageConfig {
name: "Rust".into(),
path_suffixes: vec!["rs".to_string()],
matcher: LanguageMatcher {
path_suffixes: vec!["rs".to_string()],
..Default::default()
},
..Default::default()
},
Some(tree_sitter_rust::language()),
@@ -2500,7 +2506,10 @@ pub mod tests {
let mut language = Language::new(
LanguageConfig {
name: "Rust".into(),
path_suffixes: vec!["rs".to_string()],
matcher: LanguageMatcher {
path_suffixes: vec!["rs".to_string()],
..Default::default()
},
..Default::default()
},
Some(tree_sitter_rust::language()),
@@ -2848,7 +2857,10 @@ pub mod tests {
let mut language = Language::new(
LanguageConfig {
name: "Rust".into(),
path_suffixes: vec!["rs".to_string()],
matcher: LanguageMatcher {
path_suffixes: vec!["rs".to_string()],
..Default::default()
},
..Default::default()
},
Some(tree_sitter_rust::language()),
@@ -3079,7 +3091,10 @@ pub mod tests {
let mut language = Language::new(
LanguageConfig {
name: "Rust".into(),
path_suffixes: vec!["rs".to_string()],
matcher: LanguageMatcher {
path_suffixes: vec!["rs".to_string()],
..Default::default()
},
..Default::default()
},
Some(tree_sitter_rust::language()),
@@ -3319,7 +3334,10 @@ pub mod tests {
let mut language = Language::new(
LanguageConfig {
name: "Rust".into(),
path_suffixes: vec!["rs".to_string()],
matcher: LanguageMatcher {
path_suffixes: vec!["rs".to_string()],
..Default::default()
},
..Default::default()
},
Some(tree_sitter_rust::language()),
@@ -12,7 +12,9 @@ use collections::HashSet;
use futures::Future;
use gpui::{View, ViewContext, VisualTestContext};
use indoc::indoc;
use language::{point_to_lsp, FakeLspAdapter, Language, LanguageConfig, LanguageQueries};
use language::{
point_to_lsp, FakeLspAdapter, Language, LanguageConfig, LanguageMatcher, LanguageQueries,
};
use lsp::{notification, request};
use multi_buffer::ToPointUtf16;
use project::Project;
@@ -115,7 +117,10 @@ impl EditorLspTestContext {
let language = Language::new(
LanguageConfig {
name: "Rust".into(),
path_suffixes: vec!["rs".to_string()],
matcher: LanguageMatcher {
path_suffixes: vec!["rs".to_string()],
..Default::default()
},
..Default::default()
},
Some(tree_sitter_rust::language()),
@@ -160,7 +165,10 @@ impl EditorLspTestContext {
let language = Language::new(
LanguageConfig {
name: "Typescript".into(),
path_suffixes: vec!["ts".to_string()],
matcher: LanguageMatcher {
path_suffixes: vec!["ts".to_string()],
..Default::default()
},
brackets: language::BracketPairConfig {
pairs: vec![language::BracketPair {
start: "{".to_string(),