diff --git a/crates/language/src/language.rs b/crates/language/src/language.rs index a2d02ecd96..bb83beeeea 100644 --- a/crates/language/src/language.rs +++ b/crates/language/src/language.rs @@ -345,6 +345,8 @@ pub struct LanguageConfig { #[serde(default)] pub block_comment: Option<(Arc, Arc)>, #[serde(default)] + pub scope_opt_in_language_servers: Vec, + #[serde(default)] pub overrides: HashMap, #[serde(default)] pub word_characters: HashSet, @@ -377,6 +379,8 @@ pub struct LanguageConfigOverride { pub disabled_bracket_ixs: Vec, #[serde(default)] pub word_characters: Override>, + #[serde(default)] + pub opt_into_language_servers: Vec, } #[derive(Clone, Deserialize, Debug)] @@ -415,6 +419,7 @@ impl Default for LanguageConfig { autoclose_before: Default::default(), line_comment: Default::default(), block_comment: Default::default(), + scope_opt_in_language_servers: Default::default(), overrides: Default::default(), collapsed_placeholder: Default::default(), word_characters: Default::default(), @@ -1352,13 +1357,23 @@ impl Language { Ok(self) } - pub fn with_override_query(mut self, source: &str) -> Result { + pub fn with_override_query(mut self, source: &str) -> anyhow::Result { let query = Query::new(self.grammar_mut().ts_language, source)?; let mut override_configs_by_id = HashMap::default(); for (ix, name) in query.capture_names().iter().enumerate() { if !name.starts_with('_') { let value = self.config.overrides.remove(name).unwrap_or_default(); + for server_name in &value.opt_into_language_servers { + if !self + .config + .scope_opt_in_language_servers + .contains(server_name) + { + util::debug_panic!("Server {server_name:?} has been opted-in by scope {name:?} but has not been marked as an opt-in server"); + } + } + override_configs_by_id.insert(ix as u32, (name.clone(), value)); } } @@ -1597,6 +1612,20 @@ impl LanguageScope { c.is_whitespace() || self.language.config.autoclose_before.contains(c) } + pub fn language_allowed(&self, name: &LanguageServerName) -> bool { + let config = &self.language.config; + let opt_in_servers = &config.scope_opt_in_language_servers; + if opt_in_servers.iter().any(|o| *o == *name.0) { + if let Some(over) = self.config_override() { + over.opt_into_language_servers.iter().any(|o| *o == *name.0) + } else { + false + } + } else { + true + } + } + fn config_override(&self) -> Option<&LanguageConfigOverride> { let id = self.override_id?; let grammar = self.language.grammar.as_ref()?; diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index c672a37cad..597deacd1a 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -4429,16 +4429,27 @@ impl Project { self.request_primary_lsp(buffer.clone(), GetHover { position }, cx) } - pub fn completions( + pub fn completions( &self, buffer: &ModelHandle, position: T, cx: &mut ModelContext, ) -> Task>> { + let snapshot = buffer.read(cx).snapshot(); + let offset = position.to_offset(&snapshot); let position = position.to_point_utf16(buffer.read(cx)); + + let scope = snapshot.language_scope_at(offset); + let server_ids: Vec<_> = self .language_servers_for_buffer(buffer.read(cx), cx) .filter(|(_, server)| server.capabilities().completion_provider.is_some()) + .filter(|(adapter, _)| { + scope + .as_ref() + .map(|scope| scope.language_allowed(&adapter.name)) + .unwrap_or(true) + }) .map(|(_, server)| server.server_id()) .collect(); diff --git a/crates/zed/src/languages/javascript/config.toml b/crates/zed/src/languages/javascript/config.toml index 7f6c6931e4..6f7ce49d3d 100644 --- a/crates/zed/src/languages/javascript/config.toml +++ b/crates/zed/src/languages/javascript/config.toml @@ -13,6 +13,7 @@ brackets = [ { start = "`", end = "`", close = true, newline = false, not_in = ["comment", "string"] }, { start = "/*", end = " */", close = true, newline = false, not_in = ["comment", "string"] }, ] +scope_opt_in_language_servers = ["tailwindcss-language-server"] [overrides.element] line_comment = { remove = true } @@ -20,3 +21,4 @@ block_comment = ["{/* ", " */}"] [overrides.string] word_characters = ["-"] +opt_into_language_servers = ["tailwindcss-language-server"] diff --git a/crates/zed/src/languages/tsx/config.toml b/crates/zed/src/languages/tsx/config.toml index 2f676f6710..3bdc638f73 100644 --- a/crates/zed/src/languages/tsx/config.toml +++ b/crates/zed/src/languages/tsx/config.toml @@ -12,6 +12,7 @@ brackets = [ { start = "`", end = "`", close = true, newline = false, not_in = ["string"] }, { start = "/*", end = " */", close = true, newline = false, not_in = ["string", "comment"] }, ] +scope_opt_in_language_servers = ["tailwindcss-language-server"] [overrides.element] line_comment = { remove = true } @@ -19,3 +20,4 @@ block_comment = ["{/* ", " */}"] [overrides.string] word_characters = ["-"] +opt_into_language_servers = ["tailwindcss-language-server"]