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 12:14:50 -08:00 committed by GitHub
parent 6b598a07d9
commit 6edeea7c8a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
77 changed files with 1503 additions and 387 deletions

View file

@ -19,7 +19,7 @@ use gpui::{TestAppContext, VisualContext, VisualTestContext};
use indoc::indoc;
use language::{
language_settings::{AllLanguageSettings, InlayHintSettings},
tree_sitter_rust, FakeLspAdapter, Language, LanguageConfig,
tree_sitter_rust, FakeLspAdapter, Language, LanguageConfig, LanguageMatcher,
};
use rpc::RECEIVE_TIMEOUT;
use serde_json::json;
@ -269,7 +269,10 @@ async fn test_collaborating_with_completion(cx_a: &mut TestAppContext, cx_b: &mu
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()),
@ -455,7 +458,10 @@ async fn test_collaborating_with_code_actions(
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()),
@ -668,7 +674,10 @@ async fn test_collaborating_with_renames(cx_a: &mut TestAppContext, cx_b: &mut T
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()),
@ -853,7 +862,10 @@ async fn test_language_server_statuses(cx_a: &mut TestAppContext, cx_b: &mut Tes
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()),
@ -1144,7 +1156,10 @@ async fn test_on_input_format_from_host_to_guest(
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()),
@ -1272,7 +1287,10 @@ async fn test_on_input_format_from_guest_to_host(
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()),
@ -1431,7 +1449,10 @@ async fn test_mutual_editor_inlay_hint_cache_update(
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()),
@ -1697,7 +1718,10 @@ async fn test_inlay_hint_refresh_is_forwarded(
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()),

View file

@ -14,7 +14,7 @@ use gpui::{
use language::{
language_settings::{AllLanguageSettings, Formatter},
tree_sitter_rust, Diagnostic, DiagnosticEntry, FakeLspAdapter, Language, LanguageConfig,
LineEnding, OffsetRangeExt, Point, Rope,
LanguageMatcher, LineEnding, OffsetRangeExt, Point, Rope,
};
use live_kit_client::MacOSDisplay;
use lsp::LanguageServerId;
@ -2246,7 +2246,10 @@ async fn test_propagate_saves_and_fs_changes(
let rust = Arc::new(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()),
@ -2254,7 +2257,10 @@ async fn test_propagate_saves_and_fs_changes(
let javascript = Arc::new(Language::new(
LanguageConfig {
name: "JavaScript".into(),
path_suffixes: vec!["js".to_string()],
matcher: LanguageMatcher {
path_suffixes: vec!["js".to_string()],
..Default::default()
},
..Default::default()
},
Some(tree_sitter_rust::language()),
@ -3783,7 +3789,10 @@ async fn test_collaborating_with_diagnostics(
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()),
@ -4061,7 +4070,10 @@ async fn test_collaborating_with_lsp_progress_updates_and_diagnostics_ordering(
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()),
@ -4290,7 +4302,10 @@ async fn test_formatting_buffer(
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()),
@ -4395,7 +4410,10 @@ async fn test_prettier_formatting_buffer(
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()
},
@ -4511,7 +4529,10 @@ async fn test_definition(
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()),
@ -4655,7 +4676,10 @@ async fn test_references(
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()),
@ -4852,7 +4876,10 @@ async fn test_document_highlights(
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()),
@ -4955,7 +4982,10 @@ async fn test_lsp_hover(
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()),
@ -5051,7 +5081,10 @@ async fn test_project_symbols(
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()),
@ -5160,7 +5193,10 @@ async fn test_open_buffer_while_getting_definition_pointing_to_it(
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()),

View file

@ -8,7 +8,9 @@ use editor::Bias;
use fs::{repository::GitFileStatus, FakeFs, Fs as _};
use futures::StreamExt;
use gpui::{BackgroundExecutor, Model, TestAppContext};
use language::{range_to_lsp, FakeLspAdapter, Language, LanguageConfig, PointUtf16};
use language::{
range_to_lsp, FakeLspAdapter, Language, LanguageConfig, LanguageMatcher, PointUtf16,
};
use lsp::FakeLanguageServer;
use pretty_assertions::assert_eq;
use project::{search::SearchQuery, Project, ProjectPath};
@ -1022,7 +1024,10 @@ impl RandomizedTest for ProjectCollaborationTest {
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()
},
None,