Repair textDocument/foldingRange request

This commit is contained in:
Patrick Förster 2022-10-31 15:06:11 +01:00
parent 15978f0b9f
commit f0d39964b7
6 changed files with 81 additions and 50 deletions

1
.gitignore vendored
View file

@ -3,3 +3,4 @@ target/
/.idea /.idea
tarpaulin-report.html tarpaulin-report.html
crates/**/Cargo.lock crates/**/Cargo.lock
*.snap.new

View file

@ -1,6 +1,6 @@
use crate::{ use crate::{
db::analysis::TexAnalysis, db::analysis::TexAnalysis,
syntax::{latex, BuildLog}, syntax::{bibtex, latex, BuildLog},
Db, Db,
}; };
@ -9,6 +9,12 @@ pub struct TexDocumentData {
pub green: rowan::GreenNode, pub green: rowan::GreenNode,
} }
impl TexDocumentData {
pub fn root(self, db: &dyn Db) -> latex::SyntaxNode {
latex::SyntaxNode::new_root(self.green(db))
}
}
#[salsa::tracked] #[salsa::tracked]
impl TexDocumentData { impl TexDocumentData {
#[salsa::tracked] #[salsa::tracked]
@ -23,6 +29,12 @@ pub struct BibDocumentData {
pub green: rowan::GreenNode, pub green: rowan::GreenNode,
} }
impl BibDocumentData {
pub fn root(self, db: &dyn Db) -> bibtex::SyntaxNode {
bibtex::SyntaxNode::new_root(self.green(db))
}
}
#[salsa::interned] #[salsa::interned]
pub struct LogDocumentData { pub struct LogDocumentData {
pub log: BuildLog, pub log: BuildLog,

View file

@ -41,6 +41,13 @@ impl Workspace {
.copied() .copied()
} }
pub fn lookup_uri(self, db: &dyn Db, uri: &Url) -> Option<Document> {
self.documents(db)
.iter()
.find(|document| document.location(db).uri(db) == uri)
.copied()
}
pub fn lookup_path(self, db: &dyn Db, path: &Path) -> Option<Document> { pub fn lookup_path(self, db: &dyn Db, path: &Path) -> Option<Document> {
self.documents(db) self.documents(db)
.iter() .iter()

View file

@ -3,7 +3,7 @@ mod completion;
mod cursor; mod cursor;
mod definition; mod definition;
mod execute_command; mod execute_command;
mod folding; pub mod folding;
mod formatting; mod formatting;
mod forward_search; mod forward_search;
mod highlight; mod highlight;
@ -25,7 +25,6 @@ pub use self::{
completion::{complete, CompletionItemData, COMPLETION_LIMIT}, completion::{complete, CompletionItemData, COMPLETION_LIMIT},
definition::goto_definition, definition::goto_definition,
execute_command::execute_command, execute_command::execute_command,
folding::find_foldings,
formatting::format_source_code, formatting::format_source_code,
forward_search::{ForwardSearch, ForwardSearchResult, ForwardSearchStatus}, forward_search::{ForwardSearch, ForwardSearchResult, ForwardSearchStatus},
highlight::find_document_highlights, highlight::find_document_highlights,

View file

@ -1,49 +1,51 @@
use lsp_types::{FoldingRange, FoldingRangeKind, FoldingRangeParams, Range}; use lsp_types::{FoldingRange, FoldingRangeKind, Range, Url};
use rowan::ast::AstNode; use rowan::ast::AstNode;
use crate::{ use crate::{
db::{parse::DocumentData, workspace::Workspace},
syntax::{bibtex, latex}, syntax::{bibtex, latex},
DocumentData, LineIndexExt, Db, LineIndexExt,
}; };
use super::FeatureRequest; pub fn find_all(db: &dyn Db, uri: &Url) -> Option<Vec<FoldingRange>> {
let document = Workspace::get(db).lookup_uri(db, uri)?;
pub fn find_foldings(request: FeatureRequest<FoldingRangeParams>) -> Vec<FoldingRange> { let line_index = document.contents(db).line_index(db);
let mut foldings = Vec::new(); let foldings = match document.parse(db) {
let main_document = request.main_document(); DocumentData::Tex(data) => {
match main_document.data() { let mut results = Vec::new();
DocumentData::Latex(data) => { let root = data.root(db);
for node in latex::SyntaxNode::new_root(data.green.clone()).descendants() { for node in root.descendants() {
if let Some(folding) = latex::Environment::cast(node.clone()) if let Some(folding) = latex::Environment::cast(node.clone())
.map(|node| latex::small_range(&node)) .map(|node| latex::small_range(&node))
.or_else(|| { .or_else(|| {
latex::Section::cast(node.clone()).map(|node| latex::small_range(&node)) latex::Section::cast(node.clone()).map(|node| latex::small_range(&node))
}) })
.or_else(|| latex::EnumItem::cast(node).map(|node| latex::small_range(&node))) .or_else(|| latex::EnumItem::cast(node).map(|node| latex::small_range(&node)))
.map(|node| main_document.line_index().line_col_lsp_range(node)) .map(|node| line_index.line_col_lsp_range(node))
.map(create_range) .map(create_range)
{ {
foldings.push(folding); results.push(folding);
} }
} }
results
} }
DocumentData::Bibtex(data) => { DocumentData::Bib(data) => {
for node in bibtex::SyntaxNode::new_root(data.green.clone()).descendants() { let root = data.root(db);
if matches!( root.descendants()
node.kind(), .filter(|node| {
bibtex::PREAMBLE | bibtex::STRING | bibtex::ENTRY matches!(
) { node.kind(),
foldings.push(create_range( bibtex::PREAMBLE | bibtex::STRING | bibtex::ENTRY
main_document )
.line_index() })
.line_col_lsp_range(node.text_range()), .map(|node| create_range(line_index.line_col_lsp_range(node.text_range())))
)); .collect()
}
}
} }
DocumentData::BuildLog(_) => {} DocumentData::Log(_) => return None,
} };
foldings
Some(foldings)
} }
fn create_range(range: Range) -> FoldingRange { fn create_range(range: Range) -> FoldingRange {

View file

@ -10,7 +10,7 @@ use lsp_server::{Connection, Message, RequestId};
use lsp_types::{notification::*, request::*, *}; use lsp_types::{notification::*, request::*, *};
use rowan::{ast::AstNode, TextSize}; use rowan::{ast::AstNode, TextSize};
use rustc_hash::FxHashSet; use rustc_hash::FxHashSet;
use salsa::ParallelDatabase; use salsa::{DbWithJar, ParallelDatabase};
use serde::Serialize; use serde::Serialize;
use threadpool::ThreadPool; use threadpool::ThreadPool;
@ -19,7 +19,6 @@ use crate::{
client::LspClient, client::LspClient,
component_db::COMPONENT_DATABASE, component_db::COMPONENT_DATABASE,
db::{ db::{
self,
document::{Language, Owner}, document::{Language, Owner},
workspace::Workspace, workspace::Workspace,
Distro, Distro,
@ -31,7 +30,7 @@ use crate::{
features::{ features::{
building::{BuildParams, BuildResult, BuildStatus, TexCompiler}, building::{BuildParams, BuildResult, BuildStatus, TexCompiler},
execute_command, find_all_references, find_document_highlights, find_document_links, execute_command, find_all_references, find_document_highlights, find_document_links,
find_document_symbols, find_foldings, find_hover, find_inlay_hints, find_workspace_symbols, find_document_symbols, find_hover, find_inlay_hints, find_workspace_symbols, folding,
format_source_code, goto_definition, prepare_rename_all, rename_all, CompletionItemData, format_source_code, goto_definition, prepare_rename_all, rename_all, CompletionItemData,
FeatureRequest, ForwardSearch, ForwardSearchResult, ForwardSearchStatus, FeatureRequest, ForwardSearch, ForwardSearchResult, ForwardSearchStatus,
}, },
@ -52,7 +51,6 @@ enum InternalMessage {
struct ServerFork { struct ServerFork {
connection: Arc<Connection>, connection: Arc<Connection>,
internal_tx: Sender<InternalMessage>, internal_tx: Sender<InternalMessage>,
db: salsa::Snapshot<Database>,
workspace: crate::Workspace, workspace: crate::Workspace,
diagnostic_tx: debouncer::Sender<crate::Workspace>, diagnostic_tx: debouncer::Sender<crate::Workspace>,
diagnostic_manager: DiagnosticManager, diagnostic_manager: DiagnosticManager,
@ -107,6 +105,22 @@ impl Server {
} }
} }
fn run_async_query<R, Q>(&self, id: RequestId, query: Q)
where
R: Serialize + Default,
Q: FnOnce(&dyn Db) -> Option<R> + Send + 'static,
{
let snapshot = self.db.snapshot();
let client = self.client.clone();
self.pool.execute(move || {
let db = snapshot.as_jar_db();
let result = query(db).unwrap_or_default();
client
.send_response(lsp_server::Response::new_ok(id, result))
.unwrap();
});
}
fn spawn(&self, job: impl FnOnce(ServerFork) + Send + 'static) { fn spawn(&self, job: impl FnOnce(ServerFork) + Send + 'static) {
let fork = self.fork(); let fork = self.fork();
self.pool.execute(move || job(fork)); self.pool.execute(move || job(fork));
@ -116,7 +130,6 @@ impl Server {
ServerFork { ServerFork {
connection: self.connection.clone(), connection: self.connection.clone(),
internal_tx: self.internal_tx.clone(), internal_tx: self.internal_tx.clone(),
db: self.db.snapshot(),
workspace: self.workspace.clone(), workspace: self.workspace.clone(),
diagnostic_tx: self.diagnostic_tx.clone(), diagnostic_tx: self.diagnostic_tx.clone(),
diagnostic_manager: self.diagnostic_manager.clone(), diagnostic_manager: self.diagnostic_manager.clone(),
@ -362,12 +375,12 @@ impl Server {
Ok(()) Ok(())
} }
fn did_change(&mut self, mut params: DidChangeTextDocumentParams) -> Result<()> { fn did_change(&mut self, params: DidChangeTextDocumentParams) -> Result<()> {
normalize_uri(&mut params.text_document.uri); let mut uri = params.text_document.uri;
normalize_uri(&mut uri);
let workspace = Workspace::get(&self.db); let workspace = Workspace::get(&self.db);
let location = db::document::Location::new(&self.db, params.text_document.uri); let document = match workspace.lookup_uri(&self.db, &uri) {
let document = match workspace.lookup(&self.db, location) {
Some(document) => document, Some(document) => document,
None => return Ok(()), None => return Ok(()),
}; };
@ -430,8 +443,7 @@ impl Server {
let mut uri = params.text_document.uri; let mut uri = params.text_document.uri;
normalize_uri(&mut uri); normalize_uri(&mut uri);
let location = db::document::Location::new(&self.db, uri); if let Some(document) = Workspace::get(&self.db).lookup_uri(&self.db, &uri) {
if let Some(document) = Workspace::get(&self.db).lookup(&self.db, location) {
document document
.set_owner(&mut self.db) .set_owner(&mut self.db)
.with_durability(salsa::Durability::LOW) .with_durability(salsa::Durability::LOW)
@ -558,10 +570,10 @@ impl Server {
Ok(()) Ok(())
} }
fn folding_range(&self, id: RequestId, mut params: FoldingRangeParams) -> Result<()> { fn folding_range(&self, id: RequestId, params: FoldingRangeParams) -> Result<()> {
normalize_uri(&mut params.text_document.uri); let mut uri = params.text_document.uri;
let uri = Arc::new(params.text_document.uri.clone()); normalize_uri(&mut uri);
self.handle_feature_request(id, params, uri, find_foldings)?; self.run_async_query(id, move |db| folding::find_all(db.as_jar_db(), &uri));
Ok(()) Ok(())
} }
@ -583,8 +595,7 @@ impl Server {
); );
let workspace = Workspace::get(&self.db); let workspace = Workspace::get(&self.db);
let location = db::document::Location::new(&self.db, uri.as_ref().clone()); if let Some(document) = workspace.lookup_uri(&self.db, &uri) {
if let Some(document) = workspace.lookup(&self.db, location) {
let position = document let position = document
.contents(&self.db) .contents(&self.db)
.line_index(&self.db) .line_index(&self.db)
@ -759,8 +770,7 @@ impl Server {
callback: impl FnOnce(ForwardSearchStatus) + Send + 'static, callback: impl FnOnce(ForwardSearchStatus) + Send + 'static,
) -> Result<()> { ) -> Result<()> {
let workspace = Workspace::get(&self.db); let workspace = Workspace::get(&self.db);
let location = db::document::Location::new(&self.db, uri.clone()); let document = match workspace.lookup_uri(&self.db, &uri) {
let document = match workspace.lookup(&self.db, location) {
Some(document) => document, Some(document) => document,
None => { None => {
callback(ForwardSearchStatus::FAILURE); callback(ForwardSearchStatus::FAILURE);