diff --git a/crates/ark/src/lsp/config.rs b/crates/ark/src/lsp/config.rs index 79b8ee886..1a269be6c 100644 --- a/crates/ark/src/lsp/config.rs +++ b/crates/ark/src/lsp/config.rs @@ -62,6 +62,14 @@ pub static SETTINGS: &[Setting] = &[ .unwrap_or_else(|| SymbolsConfig::default().include_assignments_in_blocks) }, }, + Setting { + key: "positron.r.workspaceSymbols.includeCommentSections", + set: |cfg, v| { + cfg.workspace_symbols.include_comment_sections = v + .as_bool() + .unwrap_or_else(|| WorkspaceSymbolsConfig::default().include_comment_sections) + }, + }, ]; /// Configuration of the LSP @@ -69,6 +77,7 @@ pub static SETTINGS: &[Setting] = &[ pub(crate) struct LspConfig { pub(crate) diagnostics: DiagnosticsConfig, pub(crate) symbols: SymbolsConfig, + pub(crate) workspace_symbols: WorkspaceSymbolsConfig, pub(crate) document: DocumentConfig, } @@ -78,6 +87,12 @@ pub struct SymbolsConfig { pub include_assignments_in_blocks: bool, } +#[derive(Serialize, Deserialize, Clone, Debug)] +pub struct WorkspaceSymbolsConfig { + /// Whether to include sections like `# My section ---` in workspace symbols. + pub include_comment_sections: bool, +} + /// Configuration of a document. /// /// The naming follows where possible. @@ -141,6 +156,14 @@ impl Default for SymbolsConfig { } } +impl Default for WorkspaceSymbolsConfig { + fn default() -> Self { + Self { + include_comment_sections: false, + } + } +} + impl Default for IndentationConfig { fn default() -> Self { Self { diff --git a/crates/ark/src/lsp/handlers.rs b/crates/ark/src/lsp/handlers.rs index c111cfb82..cc468c5ec 100644 --- a/crates/ark/src/lsp/handlers.rs +++ b/crates/ark/src/lsp/handlers.rs @@ -124,8 +124,9 @@ pub(crate) async fn handle_initialized( #[tracing::instrument(level = "info", skip_all)] pub(crate) fn handle_symbol( params: WorkspaceSymbolParams, + state: &WorldState, ) -> anyhow::Result>> { - symbols::symbols(¶ms) + symbols::symbols(¶ms, state) .map(|res| Some(res)) .or_else(|err| { // Missing doc: Why are we not propagating errors to the frontend? diff --git a/crates/ark/src/lsp/indexer.rs b/crates/ark/src/lsp/indexer.rs index 34f018c7b..dc64e5a79 100644 --- a/crates/ark/src/lsp/indexer.rs +++ b/crates/ark/src/lsp/indexer.rs @@ -121,10 +121,17 @@ fn insert(path: &Path, entry: IndexEntry) -> anyhow::Result<()> { let index = index.entry(path.to_string()).or_default(); - // Retain the first occurrence in the index. In the future we'll track every occurrences and - // their scopes but for now we only track the first definition of an object (in a way, its + // We generally retain only the first occurrence in the index. In the + // future we'll track every occurrences and their scopes but for now we + // only track the first definition of an object (in a way, its // declaration). - if !index.contains_key(&entry.key) { + if let Some(existing_entry) = index.get(&entry.key) { + // Give priority to non-section entries. + if matches!(existing_entry.data, IndexEntryData::Section { .. }) { + index.insert(entry.key.clone(), entry); + } + // Else, ignore. + } else { index.insert(entry.key.clone(), entry); } diff --git a/crates/ark/src/lsp/main_loop.rs b/crates/ark/src/lsp/main_loop.rs index ac5588cea..0ee4be1a3 100644 --- a/crates/ark/src/lsp/main_loop.rs +++ b/crates/ark/src/lsp/main_loop.rs @@ -281,7 +281,7 @@ impl GlobalState { respond(tx, || state_handlers::initialize(params, &mut self.lsp_state, &mut self.world), LspResponse::Initialize)?; }, LspRequest::WorkspaceSymbol(params) => { - respond(tx, || handlers::handle_symbol(params), LspResponse::WorkspaceSymbol)?; + respond(tx, || handlers::handle_symbol(params, &self.world), LspResponse::WorkspaceSymbol)?; }, LspRequest::DocumentSymbol(params) => { respond(tx, || handlers::handle_document_symbol(params, &self.world), LspResponse::DocumentSymbol)?; diff --git a/crates/ark/src/lsp/symbols.rs b/crates/ark/src/lsp/symbols.rs index 4d3000d7d..ad70ff049 100644 --- a/crates/ark/src/lsp/symbols.rs +++ b/crates/ark/src/lsp/symbols.rs @@ -56,7 +56,10 @@ fn new_symbol_node( symbol } -pub fn symbols(params: &WorkspaceSymbolParams) -> anyhow::Result> { +pub(crate) fn symbols( + params: &WorkspaceSymbolParams, + state: &WorldState, +) -> anyhow::Result> { let query = ¶ms.query; let mut info: Vec = Vec::new(); @@ -81,18 +84,21 @@ pub fn symbols(params: &WorkspaceSymbolParams) -> anyhow::Result { - info.push(SymbolInformation { - name: title.to_string(), - kind: SymbolKind::STRING, - location: Location { - uri: Url::from_file_path(path).unwrap(), - range: entry.range, - }, - tags: None, - deprecated: None, - container_name: None, - }); + if state.config.workspace_symbols.include_comment_sections { + info.push(SymbolInformation { + name: title.to_string(), + kind: SymbolKind::STRING, + location: Location { + uri: Url::from_file_path(path).unwrap(), + range: entry.range, + }, + tags: None, + deprecated: None, + container_name: None, + }); + } }, + IndexEntryData::Variable { name } => { info.push(SymbolInformation { name: name.clone(),