From e7acb31a549bdab9cb57a79981633f921f67fb1c Mon Sep 17 00:00:00 2001 From: Myriad-Dreamin <35292584+Myriad-Dreamin@users.noreply.github.com> Date: Tue, 9 Apr 2024 16:36:30 +0800 Subject: [PATCH] fix: set entry state on changing entry (#180) --- crates/tinymist/src/actor/typ_client.rs | 36 +++++---------- crates/tinymist/src/server/compiler.rs | 4 +- crates/tinymist/src/server/lsp.rs | 58 ++++++++++++++----------- crates/tinymist/src/state.rs | 8 ++-- 4 files changed, 49 insertions(+), 57 deletions(-) diff --git a/crates/tinymist/src/actor/typ_client.rs b/crates/tinymist/src/actor/typ_client.rs index 649e7869..9a1d7dd4 100644 --- a/crates/tinymist/src/actor/typ_client.rs +++ b/crates/tinymist/src/actor/typ_client.rs @@ -286,7 +286,7 @@ impl CompileDriver { pub struct CompileClientActor { pub diag_group: String, pub config: CompileConfig, - entry: Arc>, + entry: EntryState, inner: Deferred, render_tx: broadcast::Sender, } @@ -302,7 +302,7 @@ impl CompileClientActor { Self { diag_group, config, - entry: Arc::new(Mutex::new(entry)), + entry, inner, render_tx, } @@ -328,7 +328,7 @@ impl CompileClientActor { self.inner().steal_async(f).await } - pub fn settle(&self) { + pub fn settle(&mut self) { let _ = self.change_entry(None); info!("TypstActor({}): settle requested", self.diag_group); let res = self.inner().settle(); @@ -347,7 +347,7 @@ impl CompileClientActor { self.config = config; } - pub fn change_entry(&self, path: Option) -> Result<(), Error> { + pub fn change_entry(&mut self, path: Option) -> Result<(), Error> { if path .as_deref() .is_some_and(|p| !p.is_absolute() && !p.starts_with("/untitled")) @@ -357,15 +357,7 @@ impl CompileClientActor { let next_entry = self.config.determine_entry(path); - // todo: more robust rollback logic - let entry = self.entry.clone(); - let should_change = { - let prev_entry = entry.lock(); - let should_change = next_entry != *prev_entry; - should_change.then(|| prev_entry.clone()) - }; - - if let Some(prev) = should_change { + if next_entry != self.entry { let next = next_entry.clone(); info!( @@ -403,22 +395,18 @@ impl CompileClientActor { if res.is_err() { self.render_tx .send(RenderActorRequest::ChangeExportPath(PathVars { - entry: prev.clone(), + entry: self.entry.clone(), })) .unwrap(); - let mut entry = entry.lock(); - // todo: the rollback is actually not atomic - if *entry == next_entry { - *entry = prev; - } - return res; } - // todo: trigger recompile + // todo: better way to trigger recompile let files = FileChangeSet::new_inserts(vec![]); self.inner().add_memory_changes(MemoryEvent::Update(files)); + + self.entry = next_entry; } Ok(()) @@ -428,14 +416,12 @@ impl CompileClientActor { self.inner.wait().add_memory_changes(event); } - pub(crate) fn change_export_pdf(&self, config: ExportConfig) { - let entry = self.entry.lock().clone(); + pub(crate) fn change_export_pdf(&mut self, config: ExportConfig) { let _ = self .render_tx .send(RenderActorRequest::ChangeConfig(ExportConfig { substitute_pattern: config.substitute_pattern, - // root: self.root.get().cloned().flatten(), - entry, + entry: self.entry.clone(), mode: config.mode, })) .unwrap(); diff --git a/crates/tinymist/src/server/compiler.rs b/crates/tinymist/src/server/compiler.rs index bd323937..00da64eb 100644 --- a/crates/tinymist/src/server/compiler.rs +++ b/crates/tinymist/src/server/compiler.rs @@ -371,7 +371,7 @@ impl CompileServer { }; self.compiler - .as_ref() + .as_mut() .unwrap() .change_export_pdf(config.clone()); } @@ -457,7 +457,7 @@ impl CompileServer { } /// Focus main file to some path. - pub fn change_entry(&self, arguments: Vec) -> LspResult { + pub fn change_entry(&mut self, arguments: Vec) -> LspResult { let new_entry = parse_path_or_null(arguments.first())?; let update_result = self.do_change_entry(new_entry.clone()); diff --git a/crates/tinymist/src/server/lsp.rs b/crates/tinymist/src/server/lsp.rs index 2b35c2cb..33cdc0fc 100644 --- a/crates/tinymist/src/server/lsp.rs +++ b/crates/tinymist/src/server/lsp.rs @@ -658,25 +658,25 @@ impl TypstLanguageServer { } /// Export the current document as a PDF file. - pub fn export_pdf(&self, arguments: Vec) -> LspResult { + pub fn export_pdf(&mut self, arguments: Vec) -> LspResult { self.export(ExportKind::Pdf, arguments) } /// Export the current document as a Svg file. - pub fn export_svg(&self, arguments: Vec) -> LspResult { + pub fn export_svg(&mut self, arguments: Vec) -> LspResult { let opts = parse_opts(arguments.get(1))?; self.export(ExportKind::Svg { page: opts.page }, arguments) } /// Export the current document as a Png file. - pub fn export_png(&self, arguments: Vec) -> LspResult { + pub fn export_png(&mut self, arguments: Vec) -> LspResult { let opts = parse_opts(arguments.get(1))?; self.export(ExportKind::Png { page: opts.page }, arguments) } /// Export the current document as some format. The client is responsible /// for passing the correct absolute path of typst document. - pub fn export(&self, kind: ExportKind, arguments: Vec) -> LspResult { + pub fn export(&mut self, kind: ExportKind, arguments: Vec) -> LspResult { let path = parse_path(arguments.first())?.as_ref().to_owned(); let res = run_query!(self.OnExport(path, kind))?; @@ -687,7 +687,7 @@ impl TypstLanguageServer { /// Get the trace data of the document. pub fn get_document_trace( - &self, + &mut self, req_id: RequestId, arguments: Vec, ) -> LspResult> { @@ -744,7 +744,7 @@ impl TypstLanguageServer { } /// Get the metrics of the document. - pub fn get_document_metrics(&self, arguments: Vec) -> LspResult { + pub fn get_document_metrics(&mut self, arguments: Vec) -> LspResult { let path = parse_path(arguments.first())?.as_ref().to_owned(); let res = run_query!(self.DocumentMetrics(path))?; @@ -755,7 +755,7 @@ impl TypstLanguageServer { } /// Get the server info. - pub fn get_server_info(&self, _arguments: Vec) -> LspResult { + pub fn get_server_info(&mut self, _arguments: Vec) -> LspResult { let res = run_query!(self.ServerInfo())?; let res = serde_json::to_value(res) @@ -968,7 +968,7 @@ impl TypstLanguageServer { Ok(()) } - fn did_save(&self, params: DidSaveTextDocumentParams) -> LspResult<()> { + fn did_save(&mut self, params: DidSaveTextDocumentParams) -> LspResult<()> { let path = as_path(params.text_document); let _ = run_query!(self.OnSaveExport(path)); @@ -1056,7 +1056,7 @@ impl TypstLanguageServer { /// Standard Language Features impl TypstLanguageServer { fn goto_definition( - &self, + &mut self, params: GotoDefinitionParams, ) -> LspResult> { let (path, position) = as_path_pos(params.text_document_position_params); @@ -1064,31 +1064,34 @@ impl TypstLanguageServer { } fn goto_declaration( - &self, + &mut self, params: GotoDeclarationParams, ) -> LspResult> { let (path, position) = as_path_pos(params.text_document_position_params); run_query!(self.GotoDeclaration(path, position)) } - fn references(&self, params: ReferenceParams) -> LspResult>> { + fn references(&mut self, params: ReferenceParams) -> LspResult>> { let (path, position) = as_path_pos(params.text_document_position); run_query!(self.References(path, position)) } - fn hover(&self, params: HoverParams) -> LspResult> { + fn hover(&mut self, params: HoverParams) -> LspResult> { let (path, position) = as_path_pos(params.text_document_position_params); run_query!(self.Hover(path, position)) } - fn folding_range(&self, params: FoldingRangeParams) -> LspResult>> { + fn folding_range( + &mut self, + params: FoldingRangeParams, + ) -> LspResult>> { let path = as_path(params.text_document); let line_folding_only = self.const_config().doc_line_folding_only; run_query!(self.FoldingRange(path, line_folding_only)) } fn selection_range( - &self, + &mut self, params: SelectionRangeParams, ) -> LspResult>> { let path = as_path(params.text_document); @@ -1097,7 +1100,7 @@ impl TypstLanguageServer { } fn document_symbol( - &self, + &mut self, params: DocumentSymbolParams, ) -> LspResult> { let path = as_path(params.text_document); @@ -1105,7 +1108,7 @@ impl TypstLanguageServer { } fn semantic_tokens_full( - &self, + &mut self, params: SemanticTokensParams, ) -> LspResult> { let path = as_path(params.text_document); @@ -1113,7 +1116,7 @@ impl TypstLanguageServer { } fn semantic_tokens_full_delta( - &self, + &mut self, params: SemanticTokensDeltaParams, ) -> LspResult> { let path = as_path(params.text_document); @@ -1143,14 +1146,14 @@ impl TypstLanguageServer { .map_err(|e| internal_error(format!("could not format document: {e}"))) } - fn inlay_hint(&self, params: InlayHintParams) -> LspResult>> { + fn inlay_hint(&mut self, params: InlayHintParams) -> LspResult>> { let path = as_path(params.text_document); let range = params.range; run_query!(self.InlayHint(path, range)) } fn document_color( - &self, + &mut self, params: DocumentColorParams, ) -> LspResult>> { let path = as_path(params.text_document); @@ -1158,7 +1161,7 @@ impl TypstLanguageServer { } fn color_presentation( - &self, + &mut self, params: ColorPresentationParams, ) -> LspResult>> { let path = as_path(params.text_document); @@ -1167,12 +1170,12 @@ impl TypstLanguageServer { run_query!(self.ColorPresentation(path, color, range)) } - fn code_lens(&self, params: CodeLensParams) -> LspResult>> { + fn code_lens(&mut self, params: CodeLensParams) -> LspResult>> { let path = as_path(params.text_document); run_query!(self.CodeLens(path)) } - fn completion(&self, params: CompletionParams) -> LspResult> { + fn completion(&mut self, params: CompletionParams) -> LspResult> { let (path, position) = as_path_pos(params.text_document_position); let explicit = params .context @@ -1182,26 +1185,29 @@ impl TypstLanguageServer { run_query!(self.Completion(path, position, explicit)) } - fn signature_help(&self, params: SignatureHelpParams) -> LspResult> { + fn signature_help(&mut self, params: SignatureHelpParams) -> LspResult> { let (path, position) = as_path_pos(params.text_document_position_params); run_query!(self.SignatureHelp(path, position)) } - fn rename(&self, params: RenameParams) -> LspResult> { + fn rename(&mut self, params: RenameParams) -> LspResult> { let (path, position) = as_path_pos(params.text_document_position); let new_name = params.new_name; run_query!(self.Rename(path, position, new_name)) } fn prepare_rename( - &self, + &mut self, params: TextDocumentPositionParams, ) -> LspResult> { let (path, position) = as_path_pos(params); run_query!(self.PrepareRename(path, position)) } - fn symbol(&self, params: WorkspaceSymbolParams) -> LspResult>> { + fn symbol( + &mut self, + params: WorkspaceSymbolParams, + ) -> LspResult>> { let pattern = (!params.query.is_empty()).then_some(params.query); run_query!(self.Symbol(pattern)) } diff --git a/crates/tinymist/src/state.rs b/crates/tinymist/src/state.rs index b968dcc2..c125f58a 100644 --- a/crates/tinymist/src/state.rs +++ b/crates/tinymist/src/state.rs @@ -19,9 +19,9 @@ use crate::{actor::typ_client::CompileClientActor, compiler::CompileServer, Typs impl CompileServer { /// Focus main file to some path. - pub fn do_change_entry(&self, new_entry: Option) -> Result<(), Error> { + pub fn do_change_entry(&mut self, new_entry: Option) -> Result<(), Error> { self.compiler - .as_ref() + .as_mut() .unwrap() .change_entry(new_entry.clone())?; @@ -218,7 +218,7 @@ impl TypstLanguageServer { f(source) } - pub fn query(&self, query: CompilerQueryRequest) -> anyhow::Result { + pub fn query(&mut self, query: CompilerQueryRequest) -> anyhow::Result { use CompilerQueryRequest::*; match query { @@ -229,7 +229,7 @@ impl TypstLanguageServer { DocumentSymbol(req) => query_source!(self, DocumentSymbol, req), ColorPresentation(req) => Ok(CompilerQueryResponse::ColorPresentation(req.request())), _ => { - let client = &self.primary; + let client = &mut self.primary; if !self.pinning && !self.config.compile.has_default_entry_path { // todo: race condition, we need atomic primary query if let Some(path) = query.associated_path() {