diff --git a/crates/schema-store/src/schema/value_schema.rs b/crates/schema-store/src/schema/value_schema.rs index bacb4566..4649da11 100644 --- a/crates/schema-store/src/schema/value_schema.rs +++ b/crates/schema-store/src/schema/value_schema.rs @@ -361,21 +361,36 @@ impl FindSchemaCandidates for ValueSchema { match self { Self::Table(table) => { if accessors.is_empty() { - (vec![self.clone()], Vec::new()) + (vec![self.clone()], Vec::with_capacity(0)) } else { - table.find_schema_candidates(accessors, definitions) + table.find_schema_candidates(&accessors[1..], definitions) } } Self::Array(array) => { if accessors.is_empty() { - (vec![self.clone()], Vec::new()) + (vec![self.clone()], Vec::with_capacity(0)) } else { array.find_schema_candidates(accessors, definitions) } } - Self::OneOf(OneOfSchema { schemas, .. }) - | Self::AnyOf(AnyOfSchema { schemas, .. }) - | Self::AllOf(AllOfSchema { schemas, .. }) => { + Self::OneOf(OneOfSchema { + title, + description, + schemas, + .. + }) + | Self::AnyOf(AnyOfSchema { + title, + description, + schemas, + .. + }) + | Self::AllOf(AllOfSchema { + title, + description, + schemas, + .. + }) => { let mut candidates = Vec::new(); let mut errors = Vec::new(); @@ -384,15 +399,25 @@ impl FindSchemaCandidates for ValueSchema { let Ok(schema) = schema.resolve(definitions) else { continue; }; - let (schema_candidates, schema_errors) = + + let (mut schema_candidates, schema_errors) = schema.find_schema_candidates(accessors, definitions); + + for schema_candidate in &mut schema_candidates { + if title.is_some() || description.is_some() { + schema_candidate.set_title(title.clone()); + schema_candidate.set_description(description.clone()); + } + } + candidates.extend(schema_candidates); errors.extend(schema_errors); } } (candidates, errors) } - _ => (vec![self.clone()], Vec::new()), + ValueSchema::Null => (Vec::with_capacity(0), Vec::with_capacity(0)), + _ => (vec![self.clone()], Vec::with_capacity(0)), } } } diff --git a/crates/server/src/completion.rs b/crates/server/src/completion.rs index dab4d6f7..c80f8927 100644 --- a/crates/server/src/completion.rs +++ b/crates/server/src/completion.rs @@ -233,32 +233,28 @@ impl CompletionCandidate for T { definitions: &SchemaDefinitions, completion_hint: Option, ) -> Option { - match self.title().as_deref() { - Some(title) => Some(title.into()), - None => { - let mut candidates = ahash::AHashSet::new(); - { - if let Ok(mut schemas) = self.schemas().write() { - for schema in schemas.iter_mut() { - if let Ok(schema) = schema.resolve(definitions) { - if matches!(schema, ValueSchema::Null) { - continue; - } - if let Some(candidate) = - CompletionCandidate::title(schema, definitions, completion_hint) - { - candidates.insert(candidate.to_string()); - } - } + let mut candidates = ahash::AHashSet::new(); + { + if let Ok(mut schemas) = self.schemas().write() { + for schema in schemas.iter_mut() { + if let Ok(schema) = schema.resolve(definitions) { + if matches!(schema, ValueSchema::Null) { + continue; + } + if let Some(candidate) = + CompletionCandidate::title(schema, definitions, completion_hint) + { + candidates.insert(candidate.to_string()); } } } - if candidates.len() == 1 { - return candidates.into_iter().next(); - } - None } } + if candidates.len() == 1 { + return candidates.into_iter().next(); + } + + self.title().as_deref().map(|title| title.into()) } fn description( @@ -266,34 +262,31 @@ impl CompletionCandidate for T { definitions: &SchemaDefinitions, completion_hint: Option, ) -> Option { - match self.description().as_deref() { - Some(description) => Some(description.into()), - None => { - let mut candidates = ahash::AHashSet::new(); - { - if let Ok(mut schemas) = self.schemas().write() { - for schema in schemas.iter_mut() { - if let Ok(schema) = schema.resolve(definitions) { - if matches!(schema, ValueSchema::Null) { - continue; - } - if let Some(candidate) = CompletionCandidate::description( - schema, - definitions, - completion_hint, - ) { - candidates.insert(candidate.to_string()); - } - } + let mut candidates = ahash::AHashSet::new(); + { + if let Ok(mut schemas) = self.schemas().write() { + for schema in schemas.iter_mut() { + if let Ok(schema) = schema.resolve(definitions) { + if matches!(schema, ValueSchema::Null) { + continue; + } + if let Some(candidate) = + CompletionCandidate::description(schema, definitions, completion_hint) + { + candidates.insert(candidate.to_string()); } } } - if candidates.len() == 1 { - return candidates.into_iter().next(); - } - None } } + + if candidates.len() == 1 { + return candidates.into_iter().next(); + } + + self.description() + .as_deref() + .map(|description| description.into()) } } diff --git a/crates/server/src/completion/completion_content.rs b/crates/server/src/completion/completion_content.rs index 20074686..55d2f575 100644 --- a/crates/server/src/completion/completion_content.rs +++ b/crates/server/src/completion/completion_content.rs @@ -72,6 +72,25 @@ impl CompletionContent { preselect: None, } } + + pub fn new_property( + label: String, + detail: Option, + documentation: Option, + edit: Option, + schema_url: Option<&Url>, + ) -> Self { + Self { + label, + kind: Some(tower_lsp::lsp_types::CompletionItemKind::PROPERTY), + priority: CompletionPriority::Normal, + detail, + documentation, + edit, + schema_url: schema_url.cloned(), + preselect: None, + } + } } impl From for tower_lsp::lsp_types::CompletionItem { diff --git a/crates/server/src/completion/value/table.rs b/crates/server/src/completion/value/table.rs index 67ebab6f..ab2cdcb9 100644 --- a/crates/server/src/completion/value/table.rs +++ b/crates/server/src/completion/value/table.rs @@ -6,7 +6,7 @@ use crate::completion::{ use super::{find_all_if_completion_items, CompletionHint, FindCompletionContents}; use config::TomlVersion; use schema_store::{Accessor, FindSchemaCandidates, SchemaDefinitions, TableSchema, ValueSchema}; -use tower_lsp::lsp_types::{CompletionItemKind, Url}; +use tower_lsp::lsp_types::Url; impl FindCompletionContents for document_tree::Table { fn find_completion_contents( @@ -78,25 +78,21 @@ impl FindCompletionContents for document_tree::Table { continue; } } - - let completion_content = CompletionContent { - label: label.clone(), - kind: Some(CompletionItemKind::PROPERTY), - detail: schema_candidate + completions.push(CompletionContent::new_property( + label.clone(), + schema_candidate .detail(definitions, completion_hint), - documentation: schema_candidate.documentation( + schema_candidate.documentation( definitions, completion_hint, ), - edit: CompletionEdit::new_propery( + CompletionEdit::new_propery( &label, position, completion_hint, ), - schema_url: schema_url.cloned(), - ..Default::default() - }; - completions.push(completion_content); + schema_url, + )); } } } @@ -158,6 +154,7 @@ impl FindCompletionContents for document_tree::Table { for error in errors { tracing::error!("{}", error); } + for schema_candidate in schema_candidates { if let Some(CompletionHint::InTableHeader) = completion_hint { if count_header_table_or_array(value_schema, definitions) == 0 { @@ -182,21 +179,13 @@ impl FindCompletionContents for document_tree::Table { } } - let completion_content = CompletionContent { - label: label.clone(), - kind: Some(CompletionItemKind::PROPERTY), - detail: schema_candidate.detail(definitions, completion_hint), - documentation: schema_candidate - .documentation(definitions, completion_hint), - edit: CompletionEdit::new_propery( - &label, - position, - completion_hint, - ), - schema_url: schema_url.cloned(), - ..Default::default() - }; - completions.push(completion_content); + completions.push(CompletionContent::new_property( + label.clone(), + schema_candidate.detail(definitions, completion_hint), + schema_candidate.documentation(definitions, completion_hint), + CompletionEdit::new_propery(&label, position, completion_hint), + schema_url, + )); } } } @@ -272,16 +261,14 @@ impl FindCompletionContents for TableSchema { continue; } } - let completion_content = CompletionContent { - label: label.clone(), - kind: Some(CompletionItemKind::PROPERTY), - detail: schema_candidate.detail(definitions, completion_hint), - documentation: schema_candidate.documentation(definitions, completion_hint), - edit: CompletionEdit::new_propery(&label, position, completion_hint), - schema_url: schema_url.cloned(), - ..Default::default() - }; - completions.push(completion_content); + + completions.push(CompletionContent::new_property( + label.clone(), + schema_candidate.detail(definitions, completion_hint), + schema_candidate.documentation(definitions, completion_hint), + CompletionEdit::new_propery(&label, position, completion_hint), + schema_url, + )); } } }