diff options
author | Norbert Preining <norbert@preining.info> | 2021-05-23 03:00:39 +0000 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2021-05-23 03:00:39 +0000 |
commit | f1261b349e875b842745b63258c3e338cb1fe3bf (patch) | |
tree | b5d402b3e80818cde2c079a42249f3dcb9732247 /support/texlab/tests | |
parent | 58aa1ac09b1d9e4769d0a0661cf12e2b2db41b14 (diff) |
CTAN sync 202105230300
Diffstat (limited to 'support/texlab/tests')
66 files changed, 5781 insertions, 3660 deletions
diff --git a/support/texlab/tests/integration/common.rs b/support/texlab/tests/integration/common.rs new file mode 100644 index 0000000000..5430bfd2be --- /dev/null +++ b/support/texlab/tests/integration/common.rs @@ -0,0 +1,318 @@ +use std::{ + fs, + sync::{ + atomic::{AtomicI32, Ordering}, + Mutex, + }, + thread::{self, JoinHandle}, +}; + +use anyhow::Result; +use lsp_server::{Connection, RequestId}; +use lsp_types::{notification::Notification, request::Request, *}; +use rustc_hash::FxHashMap; +use tempfile::{tempdir, TempDir}; +use texlab::Server; +use unindent::unindent; + +pub struct ServerTester { + pub directory: TempDir, + client: Connection, + handle: Option<JoinHandle<()>>, + request_id: AtomicI32, + pub diagnostics_by_uri: Mutex<FxHashMap<Url, Vec<Diagnostic>>>, +} + +impl ServerTester { + pub fn launch_new_instance() -> Result<Self> { + let directory = tempdir()?; + let (conn, client) = Connection::memory(); + let server = Server::with_connection(conn, directory.path().to_path_buf(), false)?; + let handle = thread::spawn(move || server.run().unwrap()); + Ok(Self { + directory, + client, + handle: Some(handle), + request_id: AtomicI32::new(0), + diagnostics_by_uri: Mutex::default(), + }) + } + + fn wait_for_response(&self, request_id: RequestId) -> Result<lsp_server::Response> { + loop { + match self.client.receiver.recv()? { + lsp_server::Message::Request(request) => { + match request.method.as_str() { + request::RegisterCapability::METHOD => { + self.client + .sender + .send(lsp_server::Response::new_ok(request.id, ()).into())?; + } + method => { + panic!("unknown request: {}", method); + } + }; + } + lsp_server::Message::Notification(notification) => { + match notification.method.as_str() { + notification::PublishDiagnostics::METHOD => { + let params = serde_json::from_value::<PublishDiagnosticsParams>( + notification.params, + )?; + let mut diagnostics_by_uri = self.diagnostics_by_uri.lock().unwrap(); + diagnostics_by_uri.insert(params.uri, params.diagnostics); + } + method => { + panic!("unknown notification: {}", method); + } + }; + } + lsp_server::Message::Response(response) => { + assert_eq!(response.id, request_id); + return Ok(response); + } + } + } + } + + #[allow(deprecated)] + pub fn initialize( + &self, + client_capabilities: ClientCapabilities, + client_info: Option<ClientInfo>, + ) -> anyhow::Result<()> { + let request_id = RequestId::from(self.request_id.fetch_add(1, Ordering::SeqCst)); + self.client.sender.send( + lsp_server::Request::new( + request_id.clone(), + request::Initialize::METHOD.to_string(), + InitializeParams { + process_id: None, + root_path: None, + root_uri: None, + initialization_options: None, + capabilities: client_capabilities, + trace: None, + workspace_folders: None, + client_info, + locale: None, + }, + ) + .into(), + )?; + self.wait_for_response(request_id)?; + + self.client.sender.send( + lsp_server::Notification::new(notification::Initialized::METHOD.to_string(), ()).into(), + )?; + + Ok(()) + } + + pub fn open(&self, name: &str, text: &str, language_id: &str, store: bool) -> Result<Url> { + let text = unindent(text).trim().to_string(); + let path = self.directory.path().join(name); + if store { + fs::create_dir_all(path.parent().unwrap())?; + fs::write(&path, &text)?; + } + + let uri = Url::from_file_path(path).unwrap(); + self.client.sender.send( + lsp_server::Notification::new( + notification::DidOpenTextDocument::METHOD.to_string(), + DidOpenTextDocumentParams { + text_document: TextDocumentItem::new( + uri.clone(), + language_id.to_string(), + 0, + text, + ), + }, + ) + .into(), + )?; + Ok(uri) + } + + pub fn open_memory(&self, uri: Url, text: &str, language_id: &str) -> Result<()> { + let text = unindent(text).trim().to_string(); + let text_document = TextDocumentItem::new(uri, language_id.to_string(), 0, text); + self.client.sender.send( + lsp_server::Notification::new( + notification::DidOpenTextDocument::METHOD.to_string(), + DidOpenTextDocumentParams { text_document }, + ) + .into(), + )?; + Ok(()) + } + + // pub fn edit(&self, uri: Url, text: &str) -> Result<()> { + // let text = unindent(text).trim().to_string(); + // self.client.sender.send( + // lsp_server::Notification::new( + // notification::DidChangeTextDocument::METHOD.to_string(), + // DidChangeTextDocumentParams { + // text_document: VersionedTextDocumentIdentifier::new(uri, 0), + // content_changes: vec![TextDocumentContentChangeEvent { + // text, + // range: None, + // range_length: None, + // }], + // }, + // ) + // .into(), + // )?; + // Ok(()) + // } + + pub fn complete(&self, uri: Url, line: u32, character: u32) -> Result<CompletionList> { + let request_id = RequestId::from(self.request_id.fetch_add(1, Ordering::SeqCst)); + + self.client.sender.send( + lsp_server::Request::new( + request_id.clone(), + request::Completion::METHOD.to_string(), + CompletionParams { + text_document_position: TextDocumentPositionParams::new( + TextDocumentIdentifier::new(uri), + Position::new(line, character), + ), + work_done_progress_params: WorkDoneProgressParams::default(), + partial_result_params: PartialResultParams::default(), + context: None, + }, + ) + .into(), + )?; + + let response = self.wait_for_response(request_id)?; + let list = serde_json::from_value(response.result.expect("completion request failed"))?; + Ok(list) + } + + pub fn resolve_completion_item(&self, item: CompletionItem) -> Result<CompletionItem> { + let request_id = RequestId::from(self.request_id.fetch_add(1, Ordering::SeqCst)); + + self.client.sender.send( + lsp_server::Request::new( + request_id.clone(), + request::ResolveCompletionItem::METHOD.to_string(), + item, + ) + .into(), + )?; + + let response = self.wait_for_response(request_id)?; + let result = serde_json::from_value( + response + .result + .expect("resolve completion item request failed"), + )?; + Ok(result) + } + + pub fn hover(&self, uri: Url, line: u32, character: u32) -> Result<Option<Hover>> { + let request_id = RequestId::from(self.request_id.fetch_add(1, Ordering::SeqCst)); + + self.client.sender.send( + lsp_server::Request::new( + request_id.clone(), + request::HoverRequest::METHOD.to_string(), + HoverParams { + text_document_position_params: TextDocumentPositionParams::new( + TextDocumentIdentifier::new(uri), + Position::new(line, character), + ), + work_done_progress_params: WorkDoneProgressParams::default(), + }, + ) + .into(), + )?; + + let response = self.wait_for_response(request_id)?; + let hover = serde_json::from_value(response.result.expect("hover request failed"))?; + Ok(hover) + } + + pub fn find_document_symbols(&self, uri: Url) -> Result<DocumentSymbolResponse> { + let request_id = RequestId::from(self.request_id.fetch_add(1, Ordering::SeqCst)); + + self.client.sender.send( + lsp_server::Request::new( + request_id.clone(), + request::DocumentSymbolRequest::METHOD.to_string(), + DocumentSymbolParams { + text_document: TextDocumentIdentifier::new(uri), + work_done_progress_params: WorkDoneProgressParams::default(), + partial_result_params: PartialResultParams::default(), + }, + ) + .into(), + )?; + + let response = self.wait_for_response(request_id)?; + let symbols = + serde_json::from_value(response.result.expect("document symbol request failed"))?; + Ok(symbols) + } + + pub fn find_workspace_symbols(&self, query: &str) -> Result<Vec<SymbolInformation>> { + let request_id = RequestId::from(self.request_id.fetch_add(1, Ordering::SeqCst)); + + self.client.sender.send( + lsp_server::Request::new( + request_id.clone(), + request::WorkspaceSymbol::METHOD.to_string(), + WorkspaceSymbolParams { + partial_result_params: PartialResultParams::default(), + work_done_progress_params: WorkDoneProgressParams::default(), + query: query.to_string(), + }, + ) + .into(), + )?; + + let response = self.wait_for_response(request_id)?; + let symbols = + serde_json::from_value(response.result.expect("workspace symbol request failed"))?; + Ok(symbols) + } + + // pub fn change_configuration(&self, options: Options) -> Result<()> { + // self.client.sender.send( + // lsp_server::Notification::new( + // notification::DidChangeConfiguration::METHOD.to_string(), + // DidChangeConfigurationParams { + // settings: serde_json::to_value(options)?, + // }, + // ) + // .into(), + // )?; + // Ok(()) + // } +} + +impl Drop for ServerTester { + fn drop(&mut self) { + self.client + .sender + .send( + lsp_server::Request::new( + RequestId::from(self.request_id.fetch_add(1, Ordering::SeqCst)), + request::Shutdown::METHOD.to_string(), + (), + ) + .into(), + ) + .unwrap(); + + self.client + .sender + .send(lsp_server::Notification::new(notification::Exit::METHOD.to_string(), ()).into()) + .unwrap(); + + self.handle.take().unwrap().join().unwrap(); + } +} diff --git a/support/texlab/tests/integration/completion.rs b/support/texlab/tests/integration/completion.rs index 4b3b4ecd83..33af77f003 100644 --- a/support/texlab/tests/integration/completion.rs +++ b/support/texlab/tests/integration/completion.rs @@ -1,1227 +1,762 @@ -#[cfg(feature = "citation")] -use texlab::protocol::{MarkupContent, MarkupKind}; - -use indoc::indoc; -use itertools::Itertools; -use texlab::{ - protocol::{CompletionItem, CompletionTextEdit, Documentation, Range, RangeExt, TextEdit}, - test::{TestBed, TestBedBuilder, TestLspClient, PULL_CAPABILITIES}, -}; - -async fn run_item( - test_bed: &TestBed, - relative_path: &str, - line: u64, - character: u64, - label: &str, -) -> CompletionItem { - let item = test_bed - .completion(relative_path, line, character) - .await - .unwrap() - .into_iter() - .find(|item| item.label == label) - .unwrap(); - - test_bed.client.completion_resolve(item).await.unwrap() -} - -async fn run_list( - test_bed: &TestBed, - relative_path: &str, - line: u64, - character: u64, -) -> Vec<String> { - test_bed - .completion(relative_path, line, character) - .await - .unwrap() - .into_iter() - .map(|item| item.label) - .sorted() - .collect() -} - -fn verify_text_edit( - item: &CompletionItem, - start_line: u64, - start_character: u64, - end_line: u64, - end_character: u64, - text: &str, -) { - assert_eq!( - *item.text_edit.as_ref().unwrap(), - CompletionTextEdit::Edit(TextEdit::new( - Range::new_simple(start_line, start_character, end_line, end_character), - text.into() - )) - ); -} - -fn verify_detail(item: &CompletionItem, detail: &str) { - assert_eq!(item.detail.as_ref().unwrap(), detail); -} - -#[tokio::test] -async fn empty_latex_document() { - let mut test_bed = TestBedBuilder::new().file("main.tex", "").build().await; - test_bed.spawn(); - test_bed.initialize(PULL_CAPABILITIES.clone()).await; - test_bed.open("main.tex").await; - - let actual_items = test_bed.completion("main.tex", 0, 0).await.unwrap(); - - test_bed.shutdown().await; - - assert!(actual_items.is_empty()); -} - -#[tokio::test] -async fn empty_bibtex_document() { - let mut test_bed = TestBedBuilder::new().file("main.bib", "").build().await; - test_bed.spawn(); - test_bed.initialize(PULL_CAPABILITIES.clone()).await; - test_bed.open("main.bib").await; - - let actual_items = test_bed.completion("main.bib", 0, 0).await.unwrap(); - - test_bed.shutdown().await; - - assert!(actual_items.is_empty()); -} - -#[tokio::test] -async fn bibtex_comment() { - let mut test_bed = TestBedBuilder::new().file("main.bib", "foo").build().await; - test_bed.spawn(); - test_bed.initialize(PULL_CAPABILITIES.clone()).await; - test_bed.open("main.bib").await; - - let actual_items = test_bed.completion("main.bib", 0, 2).await.unwrap(); - - test_bed.shutdown().await; - - assert!(actual_items.is_empty()); -} - -#[tokio::test] -async fn bibtex_command_incomplete_entry() { - let mut test_bed = TestBedBuilder::new() - .file( +use anyhow::Result; +use lsp_types::{CompletionList, Url}; + +use crate::common::ServerTester; + +fn complete_and_resolve( + server: &ServerTester, + uri: Url, + line: u32, + character: u32, +) -> Result<CompletionList> { + let mut list = server.complete(uri, line, character)?; + let mut new_items = Vec::new(); + for item in list.items.into_iter().take(7) { + let mut new_item = server.resolve_completion_item(item)?; + new_item.data = None; + new_items.push(new_item); + } + list.items = new_items; + Ok(list) +} + +mod bibtex { + use insta::assert_json_snapshot; + use lsp_types::ClientCapabilities; + + use super::*; + + #[test] + fn test_empty_document() -> Result<()> { + let server = ServerTester::launch_new_instance()?; + server.initialize(ClientCapabilities::default(), None)?; + let uri = server.open("main.bib", "", "bibtex", false)?; + assert_json_snapshot!(complete_and_resolve(&server, uri, 0, 0)?); + Ok(()) + } + + #[test] + fn test_junk() -> Result<()> { + let server = ServerTester::launch_new_instance()?; + server.initialize(ClientCapabilities::default(), None)?; + let uri = server.open("main.bib", "foo", "bibtex", false)?; + assert_json_snapshot!(complete_and_resolve(&server, uri, 0, 0)?); + Ok(()) + } + + #[test] + fn test_command_incomplete_entry() -> Result<()> { + let server = ServerTester::launch_new_instance()?; + server.initialize(ClientCapabilities::default(), None)?; + let uri = server.open( "main.bib", - indoc!( - r#" - @article{foo, - author = {\LaT - } - "# - ), - ) - .build() - .await; - test_bed.spawn(); - test_bed.initialize(PULL_CAPABILITIES.clone()).await; - test_bed.open("main.bib").await; - - let actual_item = run_item(&test_bed, "main.bib", 1, 18, "LaTeX").await; - - test_bed.shutdown().await; - - verify_detail(&actual_item, "built-in"); - verify_text_edit(&actual_item, 1, 15, 1, 18, "LaTeX"); -} - -#[tokio::test] -async fn bibtex_command_complete_entry() { - let mut test_bed = TestBedBuilder::new() - .file( + r#" + @article{foo, + author = {\LaT + } + "#, + "bibtex", + false, + )?; + assert_json_snapshot!(complete_and_resolve(&server, uri, 1, 18)?); + Ok(()) + } + + #[test] + fn test_command_complete_entry() -> Result<()> { + let server = ServerTester::launch_new_instance()?; + server.initialize(ClientCapabilities::default(), None)?; + let uri = server.open( "main.bib", - indoc!( - r#" - @article{foo, - author = {\LaT} - } - "# - ), - ) - .build() - .await; - test_bed.spawn(); - test_bed.initialize(PULL_CAPABILITIES.clone()).await; - test_bed.open("main.bib").await; - - let actual_item = run_item(&test_bed, "main.bib", 1, 18, "LaTeX").await; - - test_bed.shutdown().await; - - verify_detail(&actual_item, "built-in"); - verify_text_edit(&actual_item, 1, 15, 1, 18, "LaTeX"); -} - -#[tokio::test] -async fn bibtex_type_empty() { - let mut test_bed = TestBedBuilder::new() - .file( + r#" + @article{foo, + author = {\LaT} + } + "#, + "bibtex", + false, + )?; + assert_json_snapshot!(complete_and_resolve(&server, uri, 1, 18)?); + Ok(()) + } + + #[test] + fn test_entry_type_empty_name() -> Result<()> { + let server = ServerTester::launch_new_instance()?; + server.initialize(ClientCapabilities::default(), None)?; + let uri = server.open( "main.bib", - indoc!( - r#" - @ - "# - ), - ) - .build() - .await; - test_bed.spawn(); - test_bed.initialize(PULL_CAPABILITIES.clone()).await; - test_bed.open("main.bib").await; - - let actual_item = run_item(&test_bed, "main.bib", 0, 1, "article").await; - - test_bed.shutdown().await; - - assert!(actual_item.documentation.is_some()); - verify_text_edit(&actual_item, 0, 1, 0, 1, "article"); -} - -#[tokio::test] -async fn bibtex_type_incomplete() { - let mut test_bed = TestBedBuilder::new() - .file( + r#" + @ + "#, + "bibtex", + false, + )?; + assert_json_snapshot!(complete_and_resolve(&server, uri, 0, 1)?); + Ok(()) + } + + #[test] + fn test_entry_type_empty_name_before() -> Result<()> { + let server = ServerTester::launch_new_instance()?; + server.initialize(ClientCapabilities::default(), None)?; + let uri = server.open( "main.bib", - indoc!( - r#" - @art - "# - ), - ) - .build() - .await; - test_bed.spawn(); - test_bed.initialize(PULL_CAPABILITIES.clone()).await; - test_bed.open("main.bib").await; - - let actual_item = run_item(&test_bed, "main.bib", 0, 1, "article").await; - - test_bed.shutdown().await; - - assert!(actual_item.documentation.is_some()); - verify_text_edit(&actual_item, 0, 1, 0, 4, "article"); -} - -#[tokio::test] -async fn bibtex_type_complete() { - let mut test_bed = TestBedBuilder::new() - .file( + r#" + @ + "#, + "bibtex", + false, + )?; + assert_json_snapshot!(complete_and_resolve(&server, uri, 0, 0)?); + Ok(()) + } + + #[test] + fn test_entry_type_incomplete() -> Result<()> { + let server = ServerTester::launch_new_instance()?; + server.initialize(ClientCapabilities::default(), None)?; + let uri = server.open( "main.bib", - indoc!( - r#" - @article - "# - ), - ) - .build() - .await; - test_bed.spawn(); - test_bed.initialize(PULL_CAPABILITIES.clone()).await; - test_bed.open("main.bib").await; - - let actual_item = run_item(&test_bed, "main.bib", 0, 1, "article").await; - - test_bed.shutdown().await; - - assert!(actual_item.documentation.is_some()); - verify_text_edit(&actual_item, 0, 1, 0, 8, "article"); -} - -#[tokio::test] -async fn bibtex_field_incomplete_entry() { - let mut test_bed = TestBedBuilder::new() - .file( + r#" + @art + "#, + "bibtex", + false, + )?; + assert_json_snapshot!(complete_and_resolve(&server, uri, 0, 1)?); + Ok(()) + } + + #[test] + fn test_entry_type_complete() -> Result<()> { + let server = ServerTester::launch_new_instance()?; + server.initialize(ClientCapabilities::default(), None)?; + let uri = server.open( "main.bib", - indoc!( - r#" - @article{foo, - titl - "# - ), - ) - .build() - .await; - test_bed.spawn(); - test_bed.initialize(PULL_CAPABILITIES.clone()).await; - test_bed.open("main.bib").await; - - let actual_item = run_item(&test_bed, "main.bib", 1, 6, "title").await; - - test_bed.shutdown().await; - - assert!(actual_item.documentation.is_some()); - verify_text_edit(&actual_item, 1, 4, 1, 8, "title"); -} - -#[tokio::test] -async fn bibtex_field_complete_entry() { - let mut test_bed = TestBedBuilder::new() - .file( + r#" + @article + "#, + "bibtex", + false, + )?; + assert_json_snapshot!(complete_and_resolve(&server, uri, 0, 1)?); + Ok(()) + } + + #[test] + fn test_field_incomplete_entry() -> Result<()> { + let server = ServerTester::launch_new_instance()?; + server.initialize(ClientCapabilities::default(), None)?; + let uri = server.open( "main.bib", - indoc!( - r#" - @article{foo, - title = {} - } - "# - ), - ) - .build() - .await; - test_bed.spawn(); - test_bed.initialize(PULL_CAPABILITIES.clone()).await; - test_bed.open("main.bib").await; - - let actual_item = run_item(&test_bed, "main.bib", 1, 6, "title").await; - - test_bed.shutdown().await; - - assert!(actual_item.documentation.is_some()); - verify_text_edit(&actual_item, 1, 4, 1, 9, "title"); -} - -#[tokio::test] -async fn latex_begin_command() { - let mut test_bed = TestBedBuilder::new().file("main.tex", r#"\"#).build().await; - test_bed.spawn(); - test_bed.initialize(PULL_CAPABILITIES.clone()).await; - test_bed.open("main.tex").await; - - let actual_item = run_item(&test_bed, "main.tex", 0, 1, "begin").await; - - test_bed.shutdown().await; - - verify_detail(&actual_item, "built-in"); -} - -#[cfg(feature = "citation")] -#[tokio::test] -async fn latex_citation_valid() { - let mut test_bed = TestBedBuilder::new() - .file( - "main.tex", - indoc!( - r#" - \documentclass{article} - \bibliography{main} - \begin{document} - \cite{ - \end{document} - "# - ), - ) - .file( + r#" + @article{foo, + titl + "#, + "bibtex", + false, + )?; + assert_json_snapshot!(complete_and_resolve(&server, uri, 1, 6)?); + Ok(()) + } + + #[test] + fn test_field_complete_entry() -> Result<()> { + let server = ServerTester::launch_new_instance()?; + server.initialize(ClientCapabilities::default(), None)?; + let uri = server.open( "main.bib", - indoc!( - r#" - @article{foo:2019, - author = {Foo Bar}, - title = {Baz Qux}, - year = {2019}, - } - - @article{bar:2005,} - "# - ), - ) - .build() - .await; - test_bed.spawn(); - test_bed.initialize(PULL_CAPABILITIES.clone()).await; - test_bed.open("main.tex").await; - test_bed.open("main.bib").await; - - let actual_item = run_item(&test_bed, "main.tex", 3, 6, "foo:2019").await; - - test_bed.shutdown().await; - - verify_text_edit(&actual_item, 3, 6, 3, 6, "foo:2019"); - assert_eq!( - actual_item.documentation.unwrap(), - Documentation::MarkupContent(MarkupContent { - kind: MarkupKind::Markdown, - value: "Bar, F. (2019). *Baz Qux*.".into() - }) - ); -} - -#[cfg(feature = "citation")] -#[tokio::test] -async fn latex_citation_invalid() { - let mut test_bed = TestBedBuilder::new() - .file( + r#" + @article{foo, + title = {} + } + "#, + "bibtex", + false, + )?; + assert_json_snapshot!(complete_and_resolve(&server, uri, 1, 6)?); + Ok(()) + } +} + +mod latex { + use insta::assert_json_snapshot; + use lsp_types::ClientCapabilities; + + use super::*; + + #[test] + fn test_empty_document() -> Result<()> { + let server = ServerTester::launch_new_instance()?; + server.initialize(ClientCapabilities::default(), None)?; + let uri = server.open("main.tex", "", "latex", false)?; + assert_json_snapshot!(complete_and_resolve(&server, uri, 0, 0)?); + Ok(()) + } + + #[test] + fn test_begin_command() -> Result<()> { + let server = ServerTester::launch_new_instance()?; + server.initialize(ClientCapabilities::default(), None)?; + let uri = server.open("main.tex", r#"\b"#, "latex", false)?; + assert_json_snapshot!(complete_and_resolve(&server, uri, 0, 1)?); + Ok(()) + } + + #[test] + fn test_citation() -> Result<()> { + let server = ServerTester::launch_new_instance()?; + server.initialize(ClientCapabilities::default(), None)?; + let tex_uri = server.open( "main.tex", - indoc!( - r#" - \documentclass{article} - \bibliography{main} - \begin{document} - \cite{ - \end{document} - "# - ), - ) - .file( + r#" + \documentclass{article} + \bibliography{main} + \begin{document} + \cite{ + \end{document} + "#, + "latex", + false, + )?; + server.open( "main.bib", - indoc!( - r#" - @article{foo:2019, - author = {Foo Bar}, - title = {Baz Qux}, - year = {2019}, - } - - @article{bar:2005,} - "# - ), - ) - .build() - .await; - test_bed.spawn(); - test_bed.initialize(PULL_CAPABILITIES.clone()).await; - test_bed.open("main.tex").await; - test_bed.open("main.bib").await; - - let actual_item = run_item(&test_bed, "main.tex", 3, 6, "bar:2005").await; - - test_bed.shutdown().await; - - verify_text_edit(&actual_item, 3, 6, 3, 6, "bar:2005"); - assert_eq!(actual_item.documentation, None); -} - -#[tokio::test] -async fn latex_color_name() { - let mut test_bed = TestBedBuilder::new() - .file( - "main.tex", - indoc!( - r#" - \color{re} - \definecolor{foo}{ - \definecolorset{R} - "# - ), - ) - .build() - .await; - test_bed.spawn(); - test_bed.initialize(PULL_CAPABILITIES.clone()).await; - test_bed.open("main.tex").await; - - let actual_item = run_item(&test_bed, "main.tex", 0, 9, "red").await; - - test_bed.shutdown().await; - - verify_text_edit(&actual_item, 0, 7, 0, 9, "red"); -} - -#[tokio::test] -async fn latex_color_model_define_color() { - let mut test_bed = TestBedBuilder::new() - .file( - "main.tex", - indoc!( - r#" - \color{re} - \definecolor{foo}{ - \definecolorset{R} - "# - ), - ) - .build() - .await; - test_bed.spawn(); - test_bed.initialize(PULL_CAPABILITIES.clone()).await; - test_bed.open("main.tex").await; - - let actual_item = run_item(&test_bed, "main.tex", 1, 18, "rgb").await; - - test_bed.shutdown().await; - - verify_text_edit(&actual_item, 1, 18, 1, 18, "rgb"); -} - -#[tokio::test] -async fn latex_model_define_color_set() { - let mut test_bed = TestBedBuilder::new() - .file( + r#" + @article{foo:2019, + author = {Foo Bar}, + title = {Baz Qux}, + year = {2019}, + } + + @article{bar:2005,} + "#, + "bibtex", + false, + )?; + assert_json_snapshot!(complete_and_resolve(&server, tex_uri, 3, 6)?); + Ok(()) + } + + #[test] + fn test_citation_after() -> Result<()> { + let server = ServerTester::launch_new_instance()?; + server.initialize(ClientCapabilities::default(), None)?; + let tex_uri = server.open( "main.tex", - indoc!( - r#" - \color{re} - \definecolor{foo}{ - \definecolorset{R} - "# - ), - ) - .build() - .await; - test_bed.spawn(); - test_bed.initialize(PULL_CAPABILITIES.clone()).await; - test_bed.open("main.tex").await; - - let actual_item = run_item(&test_bed, "main.tex", 2, 17, "RGB").await; - - test_bed.shutdown().await; - - verify_text_edit(&actual_item, 2, 16, 2, 17, "RGB"); -} - -#[tokio::test] -async fn latex_component_kernel_command() { - let mut test_bed = TestBedBuilder::new() - .file( - "main.tex", - indoc!( - r#" - \documentclass{book} - \usepackage{amsmath} - \chap - \varDel - \begin{theind} - \end{alig} - \begin{doc} - \vareps - "# - ), - ) - .build() - .await; - test_bed.spawn(); - test_bed.initialize(PULL_CAPABILITIES.clone()).await; - test_bed.open("main.tex").await; - - let actual_item = run_item(&test_bed, "main.tex", 0, 1, "documentclass").await; - - test_bed.shutdown().await; - - verify_detail(&actual_item, "built-in"); - verify_text_edit(&actual_item, 0, 1, 0, 14, "documentclass"); -} - -#[tokio::test] -async fn latex_component_kernel_command_glyph() { - let mut test_bed = TestBedBuilder::new() - .file( + r#" + \documentclass{article} + \bibliography{main} + \begin{document} + \cite{} + \end{document} + "#, + "latex", + false, + )?; + server.open( + "main.bib", + r#" + @article{foo:2019, + author = {Foo Bar}, + title = {Baz Qux}, + year = {2019}, + } + + @article{bar:2005,} + "#, + "bibtex", + false, + )?; + assert_json_snapshot!(complete_and_resolve(&server, tex_uri, 3, 7)?); + Ok(()) + } + + #[test] + fn test_citation_open_brace() -> Result<()> { + let server = ServerTester::launch_new_instance()?; + server.initialize(ClientCapabilities::default(), None)?; + let tex_uri = server.open( "main.tex", - indoc!( - r#" - \documentclass{book} - \usepackage{amsmath} - \chap - \varDel - \begin{theind} - \end{alig} - \begin{doc} - \vareps - "# - ), - ) - .build() - .await; - test_bed.spawn(); - test_bed.initialize(PULL_CAPABILITIES.clone()).await; - test_bed.open("main.tex").await; - - let actual_item = run_item(&test_bed, "main.tex", 7, 7, "varepsilon").await; - - test_bed.shutdown().await; - - verify_detail(&actual_item, "ε, built-in"); - verify_text_edit(&actual_item, 7, 1, 7, 7, "varepsilon"); -} - -#[tokio::test] -async fn latex_component_kernel_environment() { - let mut test_bed = TestBedBuilder::new() - .file( + r#" + \documentclass{article} + \bibliography{main} + \begin{document} + \cite{Foo + \end{document} + "#, + "latex", + false, + )?; + server.open( + "main.bib", + r#" + @article{FooBar, + author = {Foo Bar}, + title = {Baz Qux}, + year = {2019}, + } + "#, + "bibtex", + false, + )?; + assert_json_snapshot!(complete_and_resolve(&server, tex_uri, 3, 9)?); + Ok(()) + } + + #[test] + fn test_color_name() -> Result<()> { + let server = ServerTester::launch_new_instance()?; + server.initialize(ClientCapabilities::default(), None)?; + let uri = server.open( "main.tex", - indoc!( - r#" - \documentclass{book} - \usepackage{amsmath} - \chap - \varDel - \begin{theind} - \end{alig} - \begin{doc} - \vareps - "# - ), - ) - .build() - .await; - test_bed.spawn(); - test_bed.initialize(PULL_CAPABILITIES.clone()).await; - test_bed.open("main.tex").await; - - let actual_item = run_item(&test_bed, "main.tex", 6, 10, "document").await; - - test_bed.shutdown().await; - - verify_detail(&actual_item, "built-in"); - verify_text_edit(&actual_item, 6, 7, 6, 10, "document"); -} - -#[tokio::test] -async fn latex_component_class_command() { - let mut test_bed = TestBedBuilder::new() - .file( + r#" + \color{re} + \definecolor{foo}{ + \definecolorset{R} + "#, + "latex", + false, + )?; + assert_json_snapshot!(complete_and_resolve(&server, uri, 0, 9)?); + Ok(()) + } + + #[test] + fn test_color_model_define_color() -> Result<()> { + let server = ServerTester::launch_new_instance()?; + server.initialize(ClientCapabilities::default(), None)?; + let uri = server.open( "main.tex", - indoc!( - r#" - \documentclass{book} - \usepackage{amsmath} - \chap - \varDel - \begin{theind} - \end{alig} - \begin{doc} - \vareps - "# - ), - ) - .build() - .await; - test_bed.spawn(); - test_bed.initialize(PULL_CAPABILITIES.clone()).await; - test_bed.open("main.tex").await; - - let actual_item = run_item(&test_bed, "main.tex", 2, 5, "chapter").await; - - test_bed.shutdown().await; - - verify_detail(&actual_item, "book.cls"); - verify_text_edit(&actual_item, 2, 1, 2, 5, "chapter"); -} - -#[tokio::test] -async fn latex_component_class_environment() { - let mut test_bed = TestBedBuilder::new() - .file( + r#" + \color{re} + \definecolor{foo}{ + \definecolorset{R} + "#, + "latex", + false, + )?; + assert_json_snapshot!(complete_and_resolve(&server, uri, 1, 18)?); + Ok(()) + } + + #[test] + fn test_color_model_define_color_set() -> Result<()> { + let server = ServerTester::launch_new_instance()?; + server.initialize(ClientCapabilities::default(), None)?; + let uri = server.open( "main.tex", - indoc!( - r#" - \documentclass{book} - \usepackage{amsmath} - \chap - \varDel - \begin{theind} - \end{alig} - \begin{doc} - \vareps - "# - ), - ) - .build() - .await; - test_bed.spawn(); - test_bed.initialize(PULL_CAPABILITIES.clone()).await; - test_bed.open("main.tex").await; - - let actual_item = run_item(&test_bed, "main.tex", 4, 13, "theindex").await; - - test_bed.shutdown().await; - - verify_detail(&actual_item, "book.cls"); - verify_text_edit(&actual_item, 4, 7, 4, 13, "theindex"); -} - -#[tokio::test] -async fn latex_component_package_command() { - let mut test_bed = TestBedBuilder::new() - .file( + r#" + \color{re} + \definecolor{foo}{ + \definecolorset{R} + "#, + "latex", + false, + )?; + assert_json_snapshot!(complete_and_resolve(&server, uri, 2, 17)?); + Ok(()) + } + + #[test] + fn test_kernel_command() -> Result<()> { + let server = ServerTester::launch_new_instance()?; + server.initialize(ClientCapabilities::default(), None)?; + let uri = server.open( "main.tex", - indoc!( - r#" - \documentclass{book} - \usepackage{amsmath} - \chap - \varDel - \begin{theind} - \end{alig} - \begin{doc} - \vareps - "# - ), - ) - .build() - .await; - test_bed.spawn(); - test_bed.initialize(PULL_CAPABILITIES.clone()).await; - test_bed.open("main.tex").await; - - let actual_item = run_item(&test_bed, "main.tex", 3, 7, "varDelta").await; - - test_bed.shutdown().await; - - verify_detail(&actual_item, "amsmath.sty"); - verify_text_edit(&actual_item, 3, 1, 3, 7, "varDelta"); -} - -#[tokio::test] -async fn latex_component_package_environment() { - let mut test_bed = TestBedBuilder::new() - .file( + r#" + \documentclass{book} + \usepackage{amsmath} + \chap + \varDel + \begin{theind} + \end{alig} + \begin{doc} + \vareps + "#, + "latex", + false, + )?; + assert_json_snapshot!(complete_and_resolve(&server, uri, 0, 1)?); + Ok(()) + } + + #[test] + fn test_kernel_command_glyph() -> Result<()> { + let server = ServerTester::launch_new_instance()?; + server.initialize(ClientCapabilities::default(), None)?; + let uri = server.open( "main.tex", - indoc!( - r#" - \documentclass{book} - \usepackage{amsmath} - \chap - \varDel - \begin{theind} - \end{alig} - \begin{doc} - \vareps - "# - ), - ) - .build() - .await; - test_bed.spawn(); - test_bed.initialize(PULL_CAPABILITIES.clone()).await; - test_bed.open("main.tex").await; - - let actual_item = run_item(&test_bed, "main.tex", 5, 5, "align").await; - - test_bed.shutdown().await; - - verify_detail(&actual_item, "amsmath.sty"); - verify_text_edit(&actual_item, 5, 5, 5, 9, "align"); -} - -#[tokio::test] -async fn latex_import_class() { - let mut test_bed = TestBedBuilder::new() - .file( + r#" + \documentclass{book} + \usepackage{amsmath} + \chap + \varDel + \begin{theind} + \end{alig} + \begin{doc} + \vareps + "#, + "latex", + false, + )?; + assert_json_snapshot!(complete_and_resolve(&server, uri, 7, 7)?); + Ok(()) + } + + #[test] + fn test_kernel_command_environment() -> Result<()> { + let server = ServerTester::launch_new_instance()?; + server.initialize(ClientCapabilities::default(), None)?; + let uri = server.open( "main.tex", - indoc!( - r#" - \documentclass{book} - \usepackage{amsmath} - "# - ), - ) - .build() - .await; - test_bed.spawn(); - test_bed.initialize(PULL_CAPABILITIES.clone()).await; - test_bed.open("main.tex").await; - - let actual_item = run_item(&test_bed, "main.tex", 0, 19, "book").await; - - test_bed.shutdown().await; - - assert!(actual_item.documentation.is_some()); - verify_text_edit(&actual_item, 0, 15, 0, 19, "book"); -} - -#[tokio::test] -async fn latex_import_package() { - let mut test_bed = TestBedBuilder::new() - .file( + r#" + \documentclass{book} + \usepackage{amsmath} + \chap + \varDel + \begin{theind} + \end{alig} + \begin{doc} + \vareps + "#, + "latex", + false, + )?; + assert_json_snapshot!(complete_and_resolve(&server, uri, 6, 10)?); + Ok(()) + } + + #[test] + fn test_class_command() -> Result<()> { + let server = ServerTester::launch_new_instance()?; + server.initialize(ClientCapabilities::default(), None)?; + let uri = server.open( "main.tex", - indoc!( - r#" - \documentclass{book} - \usepackage{amsmath} - "# - ), - ) - .build() - .await; - test_bed.spawn(); - test_bed.initialize(PULL_CAPABILITIES.clone()).await; - test_bed.open("main.tex").await; - - let actual_item = run_item(&test_bed, "main.tex", 1, 15, "amsmath").await; - - test_bed.shutdown().await; - - assert!(actual_item.documentation.is_some()); - verify_text_edit(&actual_item, 1, 12, 1, 19, "amsmath"); -} - -#[tokio::test] -async fn latex_include_relative_root_no_extension() { - let mut test_bed = TestBedBuilder::new() - .file( + r#" + \documentclass{book} + \usepackage{amsmath} + \chap + \varDel + \begin{theind} + \end{alig} + \begin{doc} + \vareps + "#, + "latex", + false, + )?; + assert_json_snapshot!(complete_and_resolve(&server, uri, 2, 5)?); + Ok(()) + } + + #[test] + fn test_class_environment() -> Result<()> { + let server = ServerTester::launch_new_instance()?; + server.initialize(ClientCapabilities::default(), None)?; + let uri = server.open( "main.tex", - indoc!( - r#" - \documentclass{article} - \include{} - \input{} - \input{qux/} - \addbibresource{} - "# - ), - ) - .file("foo.bib", "") - .file("bar.tex", "") - .file("qux/baz.tex", "") - .build() - .await; - test_bed.spawn(); - test_bed.initialize(PULL_CAPABILITIES.clone()).await; - test_bed.open("main.tex").await; - - let actual_items = run_list(&test_bed, "main.tex", 1, 9).await; - - test_bed.shutdown().await; - - assert_eq!(actual_items, vec!["bar", "main", "qux"]); -} - -#[tokio::test] -async fn latex_include_relative_root_with_extension() { - let mut test_bed = TestBedBuilder::new() - .file( + r#" + \documentclass{book} + \usepackage{amsmath} + \chap + \varDel + \begin{theind} + \end{alig} + \begin{doc} + \vareps + "#, + "latex", + false, + )?; + assert_json_snapshot!(complete_and_resolve(&server, uri, 4, 13)?); + Ok(()) + } + + #[test] + fn test_package_command() -> Result<()> { + let server = ServerTester::launch_new_instance()?; + server.initialize(ClientCapabilities::default(), None)?; + let uri = server.open( "main.tex", - indoc!( - r#" - \documentclass{article} - \include{} - \input{} - \input{qux/} - \addbibresource{} - "# - ), - ) - .file("foo.bib", "") - .file("bar.tex", "") - .file("qux/baz.tex", "") - .build() - .await; - test_bed.spawn(); - test_bed.initialize(PULL_CAPABILITIES.clone()).await; - test_bed.open("main.tex").await; - - let actual_items = run_list(&test_bed, "main.tex", 2, 7).await; - - test_bed.shutdown().await; - - assert_eq!(actual_items, vec!["bar.tex", "main.tex", "qux"]); -} - -#[tokio::test] -async fn latex_include_relative_subdir() { - let mut test_bed = TestBedBuilder::new() - .file( + r#" + \documentclass{book} + \usepackage{amsmath} + \chap + \varDel + \begin{theind} + \end{alig} + \begin{doc} + \vareps + "#, + "latex", + false, + )?; + assert_json_snapshot!(complete_and_resolve(&server, uri, 3, 7)?); + Ok(()) + } + + #[test] + fn test_package_environment() -> Result<()> { + let server = ServerTester::launch_new_instance()?; + server.initialize(ClientCapabilities::default(), None)?; + let uri = server.open( "main.tex", - indoc!( - r#" - \documentclass{article} - \include{} - \input{} - \input{qux/} - \addbibresource{} - "# - ), - ) - .file("foo.bib", "") - .file("bar.tex", "") - .file("qux/baz.tex", "") - .build() - .await; - test_bed.spawn(); - test_bed.initialize(PULL_CAPABILITIES.clone()).await; - test_bed.open("main.tex").await; - - let actual_items = run_list(&test_bed, "main.tex", 3, 11).await; - - test_bed.shutdown().await; - - assert_eq!(actual_items, vec!["baz.tex"]); -} - -#[tokio::test] -async fn latex_include_relative_parent_dir() { - let mut test_bed = TestBedBuilder::new() - .file( + r#" + \documentclass{book} + \usepackage{amsmath} + \chap + \varDel + \begin{theind} + \end{alig} + \begin{doc} + \vareps + "#, + "latex", + false, + )?; + assert_json_snapshot!(complete_and_resolve(&server, uri, 5, 5)?); + Ok(()) + } + + #[test] + fn test_class_import() -> Result<()> { + let server = ServerTester::launch_new_instance()?; + server.initialize(ClientCapabilities::default(), None)?; + let uri = server.open( "main.tex", - indoc!( - r#" - \documentclass{article} - \include{} - \input{} - \input{qux/} - \addbibresource{} - "# - ), - ) - .file("foo.bib", "") - .file("bar.tex", "") - .file("qux/baz.tex", r#"\input{../}"#) - .build() - .await; - test_bed.spawn(); - test_bed.initialize(PULL_CAPABILITIES.clone()).await; - test_bed.open("qux/baz.tex").await; - - let actual_items = run_list(&test_bed, "qux/baz.tex", 0, 10).await; - - test_bed.shutdown().await; - - assert_eq!(actual_items, vec!["bar.tex", "main.tex", "qux"]); -} - -#[tokio::test] -async fn latex_include_relative_bibliography() { - let mut test_bed = TestBedBuilder::new() - .file( + r#" + \documentclass{book} + \usepackage{amsmath} + "#, + "latex", + false, + )?; + assert_json_snapshot!(complete_and_resolve(&server, uri, 0, 19)?); + Ok(()) + } + + #[test] + fn test_package_import() -> Result<()> { + let server = ServerTester::launch_new_instance()?; + server.initialize(ClientCapabilities::default(), None)?; + let uri = server.open( "main.tex", - indoc!( - r#" - \documentclass{article} - \include{} - \input{} - \input{qux/} - \addbibresource{} - "# - ), - ) - .file("foo.bib", "") - .file("bar.tex", "") - .file("qux/baz.tex", "") - .build() - .await; - test_bed.spawn(); - test_bed.initialize(PULL_CAPABILITIES.clone()).await; - test_bed.open("main.tex").await; - - let actual_items = run_list(&test_bed, "main.tex", 4, 16).await; - - test_bed.shutdown().await; - - assert_eq!(actual_items, vec!["foo.bib", "qux"]); -} - -#[tokio::test] -async fn latex_include_root_dir() { - let mut test_bed = TestBedBuilder::new() - .file("src/main.tex", r#"\input{}"#) - .root_dir(".") - .build() - .await; - test_bed.spawn(); - test_bed.initialize(PULL_CAPABILITIES.clone()).await; - test_bed.open("src/main.tex").await; - - let actual_items = run_list(&test_bed, "src/main.tex", 0, 7).await; - - test_bed.shutdown().await; - - assert_eq!(actual_items, vec!["src"]); -} - -#[tokio::test] -async fn latex_label() { - let mut test_bed = TestBedBuilder::new() - .file( + r#" + \documentclass{book} + \usepackage{amsmath} + "#, + "latex", + false, + )?; + assert_json_snapshot!(complete_and_resolve(&server, uri, 1, 15)?); + Ok(()) + } + + #[test] + fn test_label() -> Result<()> { + let server = ServerTester::launch_new_instance()?; + server.initialize(ClientCapabilities::default(), None)?; + + server.open( "foo.tex", - indoc!( - r#" - \documentclass{article} - % - \usepackage{amsmath} - \usepackage{caption} - \usepackage{amsthm} - \newtheorem{lemma}{Lemma} - % - \begin{document} - % - \section{Foo}% - \label{sec:foo} - % - \begin{equation}% - \label{eq:foo} - 1 + 1 = 2 - \end{equation} - % - \begin{equation}% - \label{eq:bar} - 1 + 1 = 2 - \end{equation} - % - \begin{figure}% - \LaTeX{} - \caption{Baz}% - \label{fig:baz} - \end{figure} - % - \begin{lemma}% - \label{thm:foo} - 1 + 1 = 2 - \end{lemma} - % - \include{bar} - % - \end{document} - "# - ), - ) - .file( - "foo.aux", - indoc!( - r#" - \relax - \@writefile{lof}{\contentsline {figure}{\numberline {1}{\ignorespaces Baz\relax }}{1}\protected@file@percent } - \providecommand*\caption@xref[2]{\@setref\relax\@undefined{#1}} - \newlabel{fig:baz}{{1}{1}} - \@writefile{toc}{\contentsline {section}{\numberline {1}Foo}{1}\protected@file@percent } - \newlabel{sec:foo}{{1}{1}} - \newlabel{eq:foo}{{1}{1}} - \newlabel{eq:bar}{{2}{1}} - \newlabel{thm:foo}{{1}{1}} - \@input{bar.aux} - "# - ), - ) - .file( - "bar.tex", - indoc!( - r#" - \section{Bar}% - \label{sec:bar} - % - Lorem ipsum dolor sit amet. - \ref{} - \eqref{} - "# - ), - ) - .file( - "bar.aux", - indoc!( - r#" - \relax - \@writefile{toc}{\contentsline {section}{\numberline {2}Bar}{2}\protected@file@percent } - \newlabel{sec:bar}{{2}{2}} - \@setckpt{bar}{ - \setcounter{page}{3} - \setcounter{equation}{2} - \setcounter{enumi}{0} - \setcounter{enumii}{0} - \setcounter{enumiii}{0} - \setcounter{enumiv}{0} - \setcounter{footnote}{0} - \setcounter{mpfootnote}{0} - \setcounter{part}{0} - \setcounter{section}{2} - \setcounter{subsection}{0} - \setcounter{subsubsection}{0} - \setcounter{paragraph}{0} - \setcounter{subparagraph}{0} - \setcounter{figure}{1} - \setcounter{table}{0} - \setcounter{parentequation}{0} - \setcounter{caption@flags}{0} - \setcounter{ContinuedFloat}{0} - \setcounter{lemma}{1} - } - "#), - ) - .build() - .await; - test_bed.spawn(); - test_bed.initialize(PULL_CAPABILITIES.clone()).await; - test_bed.open("foo.tex").await; - test_bed.open("foo.aux").await; - test_bed.open("bar.tex").await; - test_bed.open("bar.aux").await; - - let actual_items = test_bed.completion("bar.tex", 4, 5).await.unwrap(); - - test_bed.shutdown().await; - - assert_eq!(actual_items.len(), 6); - verify_text_edit(&actual_items[0], 4, 5, 4, 5, "sec:bar"); - verify_text_edit(&actual_items[1], 4, 5, 4, 5, "sec:foo"); - verify_text_edit(&actual_items[2], 4, 5, 4, 5, "eq:foo"); - verify_text_edit(&actual_items[3], 4, 5, 4, 5, "eq:bar"); - verify_text_edit(&actual_items[4], 4, 5, 4, 5, "fig:baz"); - verify_text_edit(&actual_items[5], 4, 5, 4, 5, "thm:foo"); - verify_detail(&actual_items[0], "Section 2 (Bar)"); - verify_detail(&actual_items[1], "Section 1 (Foo)"); - verify_detail(&actual_items[2], "Equation (1)"); - verify_detail(&actual_items[3], "Equation (2)"); - verify_detail(&actual_items[4], "Figure 1"); - verify_detail(&actual_items[5], "Lemma 1"); - assert_eq!( - *actual_items[4].documentation.as_ref().unwrap(), - Documentation::String("Baz".into()) - ); -} - -#[tokio::test] -async fn latex_preselect_environment() { - let mut test_bed = TestBedBuilder::new() - .file( - "main.tex", - indoc!( - r#" - \begin{document} - \end{ - "# - ), - ) - .build() - .await; - test_bed.spawn(); - test_bed.initialize(PULL_CAPABILITIES.clone()).await; - test_bed.open("main.tex").await; - - let actual_item = run_item(&test_bed, "main.tex", 1, 5, "document").await; - - test_bed.shutdown().await; - - assert!(actual_item.preselect.unwrap()); -} - -#[tokio::test] -async fn latex_theorem() { - let mut test_bed = TestBedBuilder::new() - .file( + r#" + \documentclass{article} + + \usepackage{amsmath} + \usepackage{caption} + \usepackage{amsthm} + \newtheorem{lemma}{Lemma} + + \begin{document} + + \section{Foo}% + \label{sec:foo} + + \begin{equation}% + \label{eq:foo} + 1 + 1 = 2 + \end{equation} + + \begin{equation}% + \label{eq:bar} + 1 + 1 = 2 + \end{equation} + + \begin{figure}% + \LaTeX{} + \caption{Baz}% + \label{fig:baz} + \end{figure} + + \begin{lemma}% + \label{thm:foo} + 1 + 1 = 2 + \end{lemma} + + \include{bar} + + \end{document} + "#, + "latex", + true, + )?; + server.open( + "foo.aux", + r#" + \relax + \@writefile{lof}{\contentsline {figure}{\numberline {1}{\ignorespaces Baz\relax }}{1}\protected@file@percent } + \providecommand*\caption@xref[2]{\@setref\relax\@undefined{#1}} + \newlabel{fig:baz}{{1}{1}} + \@writefile{toc}{\contentsline {section}{\numberline {1}Foo}{1}\protected@file@percent } + \newlabel{sec:foo}{{1}{1}} + \newlabel{eq:foo}{{1}{1}} + \newlabel{eq:bar}{{2}{1}} + \newlabel{thm:foo}{{1}{1}} + \@input{bar.aux} + "#, + "latex", + true, + )?; + let uri = server.open( + "bar.tex", + r#" + \section{Bar}% + \label{sec:bar} + + Lorem ipsum dolor sit amet. + \ref{} + \eqref{} + "#, + "latex", + true, + )?; + server.open( + "bar.aux", + r#" + \relax + \@writefile{toc}{\contentsline {section}{\numberline {2}Bar}{2}\protected@file@percent } + \newlabel{sec:bar}{{2}{2}} + \@setckpt{bar}{ + \setcounter{page}{3} + \setcounter{equation}{2} + \setcounter{enumi}{0} + \setcounter{enumii}{0} + \setcounter{enumiii}{0} + \setcounter{enumiv}{0} + \setcounter{footnote}{0} + \setcounter{mpfootnote}{0} + \setcounter{part}{0} + \setcounter{section}{2} + \setcounter{subsection}{0} + \setcounter{subsubsection}{0} + \setcounter{paragraph}{0} + \setcounter{subparagraph}{0} + \setcounter{figure}{1} + \setcounter{table}{0} + \setcounter{parentequation}{0} + \setcounter{caption@flags}{0} + \setcounter{ContinuedFloat}{0} + \setcounter{lemma}{1} + "#, + "latex", + true, + )?; + assert_json_snapshot!(complete_and_resolve(&server, uri, 4, 5)?); + Ok(()) + } + + #[test] + fn test_preselect_environment() -> Result<()> { + let server = ServerTester::launch_new_instance()?; + server.initialize(ClientCapabilities::default(), None)?; + let uri = server.open( "main.tex", - indoc!( - r#" - \documentclass{article} - \usepackage{amsthm} - \newtheorem{foo}{Foo} - \begin{f} - "# - ), - ) - .build() - .await; - test_bed.spawn(); - test_bed.initialize(PULL_CAPABILITIES.clone()).await; - test_bed.open("main.tex").await; - - let actual_item = run_item(&test_bed, "main.tex", 3, 7, "foo").await; - - test_bed.shutdown().await; - - verify_text_edit(&actual_item, 3, 7, 3, 8, "foo"); - verify_detail(&actual_item, "user-defined"); -} - -#[tokio::test] -async fn latex_pgf_library() { - let mut test_bed = TestBedBuilder::new() - .file( + r#" + \begin{document} + \end{ + "#, + "latex", + false, + )?; + assert_json_snapshot!(complete_and_resolve(&server, uri, 1, 5)?); + Ok(()) + } + + #[test] + fn test_theorem_environment() -> Result<()> { + let server = ServerTester::launch_new_instance()?; + server.initialize(ClientCapabilities::default(), None)?; + let uri = server.open( "main.tex", - indoc!( - r#" - \usepackage{tikz} - \usepgflibrary{} - \usetikzlibrary{} - "# - ), - ) - .build() - .await; - test_bed.spawn(); - test_bed.initialize(PULL_CAPABILITIES.clone()).await; - test_bed.open("main.tex").await; - - let actual_item = run_item(&test_bed, "main.tex", 1, 15, "arrows").await; - - test_bed.shutdown().await; - - verify_text_edit(&actual_item, 1, 15, 1, 15, "arrows"); -} - -#[tokio::test] -async fn latex_tikz_library() { - let mut test_bed = TestBedBuilder::new() - .file( + r#" + \documentclass{article} + \usepackage{amsthm} + \newtheorem{foo}{Foo} + \begin{f} + "#, + "latex", + false, + )?; + assert_json_snapshot!(complete_and_resolve(&server, uri, 3, 7)?); + Ok(()) + } + + #[test] + fn test_pgf_library() -> Result<()> { + let server = ServerTester::launch_new_instance()?; + server.initialize(ClientCapabilities::default(), None)?; + let uri = server.open( "main.tex", - indoc!( - r#" - \usepackage{tikz} - \usepgflibrary{} - \usetikzlibrary{} - "# - ), - ) - .build() - .await; - test_bed.spawn(); - test_bed.initialize(PULL_CAPABILITIES.clone()).await; - test_bed.open("main.tex").await; - - let actual_item = run_item(&test_bed, "main.tex", 2, 16, "arrows").await; - - test_bed.shutdown().await; - - verify_text_edit(&actual_item, 2, 16, 2, 16, "arrows"); -} - -#[tokio::test] -async fn latex_user_command() { - let mut test_bed = TestBedBuilder::new() - .file( + r#" + \usepackage{tikz} + \usepgflibrary{} + \usetikzlibrary{} + "#, + "latex", + false, + )?; + assert_json_snapshot!(complete_and_resolve(&server, uri, 1, 15)?); + Ok(()) + } + + #[test] + fn test_user_command() -> Result<()> { + let server = ServerTester::launch_new_instance()?; + server.initialize(ClientCapabilities::default(), None)?; + let uri = server.open( "main.tex", - indoc!( - r#" - \foo - \fo - \begin{foo} - \end{foo} - \begin{fo} - "# - ), - ) - .build() - .await; - test_bed.spawn(); - test_bed.initialize(PULL_CAPABILITIES.clone()).await; - test_bed.open("main.tex").await; - - let actual_item = run_item(&test_bed, "main.tex", 1, 3, "foo").await; - - test_bed.shutdown().await; - - verify_detail(&actual_item, "user-defined"); - verify_text_edit(&actual_item, 1, 1, 1, 3, "foo"); -} - -#[tokio::test] -async fn latex_user_environment() { - let mut test_bed = TestBedBuilder::new() - .file( + r#" + \foobar + \fooba + \begin{foo} + \end{foo} + \begin{fo} + "#, + "latex", + false, + )?; + assert_json_snapshot!(complete_and_resolve(&server, uri, 1, 3)?); + Ok(()) + } + + #[test] + fn test_user_environment() -> Result<()> { + let server = ServerTester::launch_new_instance()?; + server.initialize(ClientCapabilities::default(), None)?; + let uri = server.open( "main.tex", - indoc!( - r#" - \foo - \fo - \begin{foo} - \end{foo} - \begin{fo} - "# - ), - ) - .build() - .await; - test_bed.spawn(); - test_bed.initialize(PULL_CAPABILITIES.clone()).await; - test_bed.open("main.tex").await; - - let actual_item = run_item(&test_bed, "main.tex", 4, 7, "foo").await; - - test_bed.shutdown().await; - - verify_detail(&actual_item, "user-defined"); - verify_text_edit(&actual_item, 4, 7, 4, 9, "foo"); + r#" + \foobar + \fooba + \begin{foo} + \end{foo} + \begin{fo} + "#, + "latex", + false, + )?; + assert_json_snapshot!(complete_and_resolve(&server, uri, 4, 7)?); + Ok(()) + } } diff --git a/support/texlab/tests/integration/definition.rs b/support/texlab/tests/integration/definition.rs deleted file mode 100644 index 685b121377..0000000000 --- a/support/texlab/tests/integration/definition.rs +++ /dev/null @@ -1,482 +0,0 @@ -use indoc::indoc; -use texlab::{ - protocol::{LocationLink, Range, RangeExt}, - test::{TestBedBuilder, LOCATION_LINK_CAPABILITIES, PULL_CAPABILITIES}, -}; - -fn verify_origin_selection_range( - link: &LocationLink, - start_line: u64, - start_character: u64, - end_line: u64, - end_character: u64, -) { - assert_eq!( - link.origin_selection_range, - Some(Range::new_simple( - start_line, - start_character, - end_line, - end_character - )) - ); -} - -#[tokio::test] -async fn empty_latex_document() { - let mut test_bed = TestBedBuilder::new().file("main.tex", "").build().await; - test_bed.spawn(); - test_bed.initialize(PULL_CAPABILITIES.clone()).await; - test_bed.open("main.tex").await; - - let actual_locations = test_bed - .definition_location("main.tex", 0, 0) - .await - .unwrap(); - - test_bed.shutdown().await; - - assert!(actual_locations.is_empty()); -} - -#[tokio::test] -async fn empty_bibtex_document() { - let mut test_bed = TestBedBuilder::new().file("main.bib", "").build().await; - test_bed.spawn(); - test_bed.initialize(PULL_CAPABILITIES.clone()).await; - test_bed.open("main.bib").await; - - let actual_locations = test_bed - .definition_location("main.bib", 0, 0) - .await - .unwrap(); - - test_bed.shutdown().await; - - assert!(actual_locations.is_empty()); -} - -#[tokio::test] -async fn bibtex_string() { - let mut test_bed = TestBedBuilder::new() - .file( - "main.bib", - indoc!( - r#" - @string{foo = "Foo"} - % - @string{bar = "Bar"} - % - @article{baz, - author = bar - } - "# - ), - ) - .build() - .await; - test_bed.spawn(); - test_bed - .initialize(LOCATION_LINK_CAPABILITIES.clone()) - .await; - test_bed.open("main.bib").await; - - let mut actual_links = test_bed.definition_link("main.bib", 5, 14).await.unwrap(); - - test_bed.shutdown().await; - - assert_eq!(actual_links.len(), 1); - let link = actual_links.pop().unwrap(); - verify_origin_selection_range(&link, 5, 13, 5, 16); - assert_eq!(link.target_uri, test_bed.uri("main.bib").into()); - assert_eq!(link.target_range, Range::new_simple(2, 0, 2, 20)); - assert_eq!(link.target_selection_range, Range::new_simple(2, 8, 2, 11)); -} - -#[tokio::test] -async fn latex_citation_link() { - let mut test_bed = TestBedBuilder::new() - .file( - "foo.tex", - indoc!( - r#" - \bibliography{bar} - \cite{bar} - "# - ), - ) - .file( - "bar.bib", - indoc!( - r#" - @article{foo,} - % - @article{bar,} - "# - ), - ) - .file( - "baz.bib", - indoc!( - r#" - @article{foo,} - % - @article{bar,} - "# - ), - ) - .build() - .await; - test_bed.spawn(); - test_bed - .initialize(LOCATION_LINK_CAPABILITIES.clone()) - .await; - test_bed.open("foo.tex").await; - test_bed.open("bar.bib").await; - test_bed.open("baz.bib").await; - - let mut actual_links = test_bed.definition_link("foo.tex", 1, 7).await.unwrap(); - - test_bed.shutdown().await; - - assert_eq!(actual_links.len(), 1); - let link = actual_links.pop().unwrap(); - verify_origin_selection_range(&link, 1, 6, 1, 9); - assert_eq!(link.target_uri, test_bed.uri("bar.bib").into()); - assert_eq!(link.target_range, Range::new_simple(2, 0, 2, 14)); - assert_eq!(link.target_selection_range, Range::new_simple(2, 9, 2, 12)); -} - -#[tokio::test] -async fn latex_citation_location() { - let mut test_bed = TestBedBuilder::new() - .file( - "foo.tex", - indoc!( - r#" - \bibliography{bar} - \cite{bar} - "# - ), - ) - .file( - "bar.bib", - indoc!( - r#" - @article{foo,} - % - @article{bar,} - "# - ), - ) - .file( - "baz.bib", - indoc!( - r#" - @article{foo,} - % - @article{bar,} - "# - ), - ) - .build() - .await; - test_bed.spawn(); - test_bed.initialize(PULL_CAPABILITIES.clone()).await; - test_bed.open("foo.tex").await; - test_bed.open("bar.bib").await; - test_bed.open("baz.bib").await; - - let mut actual_locations = test_bed.definition_location("foo.tex", 1, 7).await.unwrap(); - - test_bed.shutdown().await; - - assert_eq!(actual_locations.len(), 1); - let location = actual_locations.pop().unwrap(); - assert_eq!(location.uri, test_bed.uri("bar.bib").into()); - assert_eq!(location.range, Range::new_simple(2, 9, 2, 12)); -} - -#[tokio::test] -async fn latex_command_link() { - let mut test_bed = TestBedBuilder::new() - .file( - "main.tex", - indoc!( - r#" - \newcommand{\foo}{Foo} - % - \foo - "# - ), - ) - .build() - .await; - test_bed.spawn(); - test_bed - .initialize(LOCATION_LINK_CAPABILITIES.clone()) - .await; - test_bed.open("main.tex").await; - - let mut actual_links = test_bed.definition_link("main.tex", 2, 2).await.unwrap(); - - test_bed.shutdown().await; - - assert_eq!(actual_links.len(), 1); - let link = actual_links.pop().unwrap(); - verify_origin_selection_range(&link, 2, 0, 2, 4); - assert_eq!(link.target_uri, test_bed.uri("main.tex").into()); - assert_eq!(link.target_range, Range::new_simple(0, 0, 0, 22)); - assert_eq!(link.target_selection_range, Range::new_simple(0, 0, 0, 22)); -} - -#[tokio::test] -async fn latex_math_operator_link() { - let mut test_bed = TestBedBuilder::new() - .file( - "main.tex", - indoc!( - r#" - \DeclareMathOperator{\foo}{foo} - % - \foo - "# - ), - ) - .build() - .await; - test_bed.spawn(); - test_bed - .initialize(LOCATION_LINK_CAPABILITIES.clone()) - .await; - test_bed.open("main.tex").await; - - let mut actual_links = test_bed.definition_link("main.tex", 2, 2).await.unwrap(); - - test_bed.shutdown().await; - - assert_eq!(actual_links.len(), 1); - let link = actual_links.pop().unwrap(); - verify_origin_selection_range(&link, 2, 0, 2, 4); - assert_eq!(link.target_uri, test_bed.uri("main.tex").into()); - assert_eq!(link.target_range, Range::new_simple(0, 0, 0, 31)); - assert_eq!(link.target_selection_range, Range::new_simple(0, 0, 0, 31)); -} - -#[tokio::test] -async fn latex_label_unknown_link() { - let mut test_bed = TestBedBuilder::new() - .file( - "main.tex", - indoc!( - r#" - \label{foo} - \ref{foo} - "# - ), - ) - .build() - .await; - test_bed.spawn(); - test_bed - .initialize(LOCATION_LINK_CAPABILITIES.clone()) - .await; - test_bed.open("main.tex").await; - - let mut actual_links = test_bed.definition_link("main.tex", 1, 7).await.unwrap(); - - test_bed.shutdown().await; - - assert_eq!(actual_links.len(), 1); - let link = actual_links.pop().unwrap(); - verify_origin_selection_range(&link, 1, 5, 1, 8); - assert_eq!(link.target_uri, test_bed.uri("main.tex").into()); - assert_eq!(link.target_range, Range::new_simple(0, 0, 0, 11)); - assert_eq!(link.target_selection_range, Range::new_simple(0, 0, 0, 11)); -} - -#[tokio::test] -async fn latex_label_equation_link() { - let mut test_bed = TestBedBuilder::new() - .file( - "main.tex", - indoc!( - r#" - \begin{equation}% - \label{eq:foo} - Foo - \end{equation} - % - \ref{eq:foo} - "# - ), - ) - .build() - .await; - test_bed.spawn(); - test_bed - .initialize(LOCATION_LINK_CAPABILITIES.clone()) - .await; - test_bed.open("main.tex").await; - - let mut actual_links = test_bed.definition_link("main.tex", 5, 8).await.unwrap(); - - test_bed.shutdown().await; - - assert_eq!(actual_links.len(), 1); - let link = actual_links.pop().unwrap(); - verify_origin_selection_range(&link, 5, 5, 5, 11); - assert_eq!(link.target_uri, test_bed.uri("main.tex").into()); - assert_eq!(link.target_range, Range::new_simple(0, 0, 3, 14)); - assert_eq!(link.target_selection_range, Range::new_simple(1, 0, 1, 14)); -} - -#[tokio::test] -async fn latex_label_float_link() { - let mut test_bed = TestBedBuilder::new() - .file( - "main.tex", - indoc!( - r#" - \begin{figure} - Foo - \caption{Bar} - \label{fig} - \end{figure} - % - \ref{fig} - "# - ), - ) - .build() - .await; - test_bed.spawn(); - test_bed - .initialize(LOCATION_LINK_CAPABILITIES.clone()) - .await; - test_bed.open("main.tex").await; - - let mut actual_links = test_bed.definition_link("main.tex", 6, 6).await.unwrap(); - - test_bed.shutdown().await; - - assert_eq!(actual_links.len(), 1); - let link = actual_links.pop().unwrap(); - verify_origin_selection_range(&link, 6, 5, 6, 8); - assert_eq!(link.target_uri, test_bed.uri("main.tex").into()); - assert_eq!(link.target_range, Range::new_simple(0, 0, 4, 12)); - assert_eq!(link.target_selection_range, Range::new_simple(3, 0, 3, 11)); -} - -#[tokio::test] -async fn latex_label_item_link() { - let mut test_bed = TestBedBuilder::new() - .file( - "main.tex", - indoc!( - r#" - \begin{enumerate} - \item Foo - \item\label{bar} Bar - \item Baz - \end{enumerate} - % - \ref{bar} - "# - ), - ) - .build() - .await; - test_bed.spawn(); - test_bed - .initialize(LOCATION_LINK_CAPABILITIES.clone()) - .await; - test_bed.open("main.tex").await; - - let mut actual_links = test_bed.definition_link("main.tex", 6, 6).await.unwrap(); - - test_bed.shutdown().await; - - assert_eq!(actual_links.len(), 1); - let link = actual_links.pop().unwrap(); - verify_origin_selection_range(&link, 6, 5, 6, 8); - assert_eq!(link.target_uri, test_bed.uri("main.tex").into()); - assert_eq!(link.target_range, Range::new_simple(0, 0, 4, 15)); - assert_eq!(link.target_selection_range, Range::new_simple(2, 9, 2, 20)); -} - -#[tokio::test] -async fn latex_label_section_link() { - let mut test_bed = TestBedBuilder::new() - .file( - "main.tex", - indoc!( - r#" - \section{Foo} - \label{sec:foo} - % - \section{Bar} - \label{sec:bar} - % - \ref{sec:foo} - "# - ), - ) - .build() - .await; - test_bed.spawn(); - test_bed - .initialize(LOCATION_LINK_CAPABILITIES.clone()) - .await; - test_bed.open("main.tex").await; - - let mut actual_links = test_bed.definition_link("main.tex", 6, 6).await.unwrap(); - - test_bed.shutdown().await; - - assert_eq!(actual_links.len(), 1); - let link = actual_links.pop().unwrap(); - verify_origin_selection_range(&link, 6, 5, 6, 12); - assert_eq!(link.target_uri, test_bed.uri("main.tex").into()); - assert_eq!(link.target_range, Range::new_simple(0, 0, 3, 0)); - assert_eq!(link.target_selection_range, Range::new_simple(1, 0, 1, 15)); -} - -#[tokio::test] -async fn latex_label_theorem_link() { - let mut test_bed = TestBedBuilder::new() - .file( - "main.tex", - indoc!( - r#" - \usepackage{amsthm} - \newtheorem{lemma}{Lemma} - % - \begin{lemma}% - \label{thm:foo} - Foo - \end{lemma} - % - \ref{thm:foo} - "# - ), - ) - .build() - .await; - test_bed.spawn(); - test_bed - .initialize(LOCATION_LINK_CAPABILITIES.clone()) - .await; - test_bed.open("main.tex").await; - - let mut actual_links = test_bed.definition_link("main.tex", 8, 7).await.unwrap(); - - test_bed.shutdown().await; - - assert_eq!(actual_links.len(), 1); - let link = actual_links.pop().unwrap(); - verify_origin_selection_range(&link, 8, 5, 8, 12); - assert_eq!(link.target_uri, test_bed.uri("main.tex").into()); - assert_eq!(link.target_range, Range::new_simple(3, 0, 6, 11)); - assert_eq!(link.target_selection_range, Range::new_simple(4, 0, 4, 15)); -} diff --git a/support/texlab/tests/integration/document_symbol.rs b/support/texlab/tests/integration/document_symbol.rs index afc3d54831..dbdbe64972 100644 --- a/support/texlab/tests/integration/document_symbol.rs +++ b/support/texlab/tests/integration/document_symbol.rs @@ -1,424 +1,438 @@ -use indoc::indoc; -use texlab::{ - protocol::{DocumentSymbol, Range, RangeExt}, - test::{TestBedBuilder, NESTED_SYMBOL_CAPABILITIES}, +use anyhow::Result; +use insta::assert_json_snapshot; +use lsp_types::{ + ClientCapabilities, DocumentSymbolClientCapabilities, TextDocumentClientCapabilities, Url, }; -fn verify_symbol( - symbol: &DocumentSymbol, - name: &str, - detail: Option<&str>, - selection_range: Range, - range: Range, -) { - assert_eq!(symbol.name, name); - assert_eq!(symbol.detail.as_ref().map(AsRef::as_ref), detail); - assert_eq!(symbol.selection_range, selection_range); - assert_eq!(symbol.range, range); +use crate::common::ServerTester; + +fn nested_symbol_capabilities() -> ClientCapabilities { + ClientCapabilities { + text_document: Some(TextDocumentClientCapabilities { + document_symbol: Some(DocumentSymbolClientCapabilities { + hierarchical_document_symbol_support: Some(true), + ..DocumentSymbolClientCapabilities::default() + }), + ..TextDocumentClientCapabilities::default() + }), + ..ClientCapabilities::default() + } } -#[tokio::test] -async fn enumerate() { - let mut test_bed = TestBedBuilder::new() - .file( - "main.tex", - indoc!( - r#" - \documentclass{article} - % - \begin{document} - % - \begin{enumerate} - \item\label{it:foo} Foo - \item\label{it:bar} Bar - \item[Baz] Baz - \item[Qux]\label{it:qux} Qux - \end{enumerate} - % - \end{document} - "# - ), - ) - .file( - "main.aux", - indoc!( - r#" - \relax - \newlabel{it:foo}{{1}{1}} - \newlabel{it:qux}{{2}{1}} - "# - ), - ) - .build() - .await; - - test_bed.spawn(); - test_bed - .initialize(NESTED_SYMBOL_CAPABILITIES.clone()) - .await; - test_bed.open("main.tex").await; - test_bed.open("main.aux").await; - - let mut actual_symbols = test_bed.document_symbol_nested("main.tex").await.unwrap(); - - test_bed.shutdown().await; - - assert_eq!(actual_symbols.len(), 1); - verify_symbol( - &actual_symbols[0], - "Enumerate", - None, - Range::new_simple(4, 0, 9, 15), - Range::new_simple(4, 0, 9, 15), - ); - - let children = actual_symbols[0].children.take().unwrap(); - assert_eq!(children.len(), 4); - verify_symbol( - &children[0], - "1", - Some("it:foo"), - Range::new_simple(5, 9, 5, 23), - Range::new_simple(5, 4, 6, 4), - ); - verify_symbol( - &children[1], - "Item", - Some("it:bar"), - Range::new_simple(6, 9, 6, 23), - Range::new_simple(6, 4, 7, 4), - ); - verify_symbol( - &children[2], - "Baz", - None, - Range::new_simple(7, 4, 7, 14), - Range::new_simple(7, 4, 8, 4), - ); - verify_symbol( - &children[3], - "Qux", - Some("it:qux"), - Range::new_simple(8, 14, 8, 28), - Range::new_simple(8, 4, 9, 0), - ); +#[test] +fn test_enumerate_nested() -> Result<()> { + let server = ServerTester::launch_new_instance()?; + server.initialize(nested_symbol_capabilities(), None)?; + let uri = Url::parse("http://www.example.com/main.tex")?; + server.open_memory( + uri.clone(), + r#" + \documentclass{article} + + \begin{document} + + \begin{enumerate} + \item\label{it:foo} Foo + \item\label{it:bar} Bar + \item[Baz] Baz + \item[Qux]\label{it:qux} Qux + \end{enumerate} + + \end{document} + "#, + "latex", + )?; + server.open_memory( + Url::parse("http://www.example.com/main.aux")?, + r#" + \relax + \newlabel{it:foo}{{1}{1}} + \newlabel{it:qux}{{2}{1}} + "#, + "latex", + )?; + assert_json_snapshot!(server.find_document_symbols(uri)?); + Ok(()) } -#[tokio::test] -async fn equation() { - let mut test_bed = TestBedBuilder::new() - .file( - "main.tex", - indoc!( - r#" - \documentclass{article} - % - \begin{document} - % - \begin{equation}\label{eq:foo} - Foo - \end{equation} - % - \begin{equation}\label{eq:bar} - Bar - \end{equation} - % - \begin{equation} - Baz - \end{equation} - % - \end{document} - "# - ), - ) - .file( - "main.aux", - indoc!( - r#" - \relax - \newlabel{eq:foo}{{1}{1}} - "# - ), - ) - .build() - .await; - - test_bed.spawn(); - test_bed - .initialize(NESTED_SYMBOL_CAPABILITIES.clone()) - .await; - test_bed.open("main.tex").await; - test_bed.open("main.aux").await; - - let actual_symbols = test_bed.document_symbol_nested("main.tex").await.unwrap(); - - test_bed.shutdown().await; - - assert_eq!(actual_symbols.len(), 3); - verify_symbol( - &actual_symbols[0], - "Equation (1)", - Some("eq:foo"), - Range::new_simple(4, 16, 4, 30), - Range::new_simple(4, 0, 6, 14), - ); - verify_symbol( - &actual_symbols[1], - "Equation", - Some("eq:bar"), - Range::new_simple(8, 16, 8, 30), - Range::new_simple(8, 0, 10, 14), - ); - verify_symbol( - &actual_symbols[2], - "Equation", - None, - Range::new_simple(12, 0, 14, 14), - Range::new_simple(12, 0, 14, 14), - ); +#[test] +fn test_enumerate_flat() -> Result<()> { + let server = ServerTester::launch_new_instance()?; + server.initialize(ClientCapabilities::default(), None)?; + let uri = Url::parse("http://www.example.com/main.tex")?; + server.open_memory( + uri.clone(), + r#" + \documentclass{article} + + \begin{document} + + \begin{enumerate} + \item\label{it:foo} Foo + \item\label{it:bar} Bar + \item[Baz] Baz + \item[Qux]\label{it:qux} Qux + \end{enumerate} + + \end{document} + "#, + "latex", + )?; + server.open_memory( + Url::parse("http://www.example.com/main.aux")?, + r#" + \relax + \newlabel{it:foo}{{1}{1}} + \newlabel{it:qux}{{2}{1}} + "#, + "latex", + )?; + assert_json_snapshot!(server.find_document_symbols(uri)?); + Ok(()) } -#[tokio::test] -async fn float() { - let mut test_bed = TestBedBuilder::new() - .file( - "main.tex", - indoc!( - r#" - \documentclass{article} - % - \begin{document} - % - \begin{figure} - Foo - \caption{Foo}\label{fig:foo} - \end{figure} - % - \begin{figure} - Bar - \caption{Bar}\label{fig:bar} - \end{figure} - % - \begin{figure} - Baz - \caption{Baz} - \end{figure} - % - \begin{figure} - Qux - \end{figure} - % - \end{document} - "# - ), - ) - .file( - "main.aux", - indoc!( - r#" - \relax - \@writefile{lof}{\contentsline {figure}{\numberline {1}{\ignorespaces Foo}}{1}\protected@file@percent } - \newlabel{fig:foo}{{1}{1}} - \@writefile{lof}{\contentsline {figure}{\numberline {2}{\ignorespaces Bar}}{1}\protected@file@percent } - \@writefile{lof}{\contentsline {figure}{\numberline {3}{\ignorespaces Baz}}{1}\protected@file@percent } - "# - ), - ) - .build() - .await; - - test_bed.spawn(); - test_bed - .initialize(NESTED_SYMBOL_CAPABILITIES.clone()) - .await; - test_bed.open("main.tex").await; - test_bed.open("main.aux").await; - - let actual_symbols = test_bed.document_symbol_nested("main.tex").await.unwrap(); - - test_bed.shutdown().await; - - assert_eq!(actual_symbols.len(), 3); - verify_symbol( - &actual_symbols[0], - "Figure 1: Foo", - Some("fig:foo"), - Range::new_simple(6, 17, 6, 32), - Range::new_simple(4, 0, 7, 12), - ); - verify_symbol( - &actual_symbols[1], - "Figure: Bar", - Some("fig:bar"), - Range::new_simple(11, 17, 11, 32), - Range::new_simple(9, 0, 12, 12), - ); - verify_symbol( - &actual_symbols[2], - "Figure: Baz", - None, - Range::new_simple(14, 0, 17, 12), - Range::new_simple(14, 0, 17, 12), - ); +#[test] +fn test_equation_nested() -> Result<()> { + let server = ServerTester::launch_new_instance()?; + server.initialize(nested_symbol_capabilities(), None)?; + let uri = Url::parse("http://www.example.com/main.tex")?; + server.open_memory( + uri.clone(), + r#" + \documentclass{article} + + \begin{document} + + \begin{equation}\label{eq:foo} + Foo + \end{equation} + + \begin{equation}\label{eq:bar} + Bar + \end{equation} + + \begin{equation} + Baz + \end{equation} + + \end{document} + "#, + "latex", + )?; + server.open_memory( + Url::parse("http://www.example.com/main.aux")?, + r#" + \relax + \newlabel{eq:foo}{{1}{1}} + "#, + "latex", + )?; + assert_json_snapshot!(server.find_document_symbols(uri)?); + Ok(()) } -#[tokio::test] -async fn section() { - let mut test_bed = TestBedBuilder::new() - .file( - "main.tex", - indoc!( - r#" - \documentclass{article} - % - \begin{document} - % - \section{Foo} - % - \section{Bar}\label{sec:bar} - % - \subsection{Baz}\label{sec:baz} - % - \end{document} - "# - ), - ) - .file( - "main.aux", - indoc!( - r#" - \relax - \@writefile{toc}{\contentsline {section}{\numberline {1}Foo}{1}\protected@file@percent } - \@writefile{toc}{\contentsline {section}{\numberline {2}Bar}{1}\protected@file@percent } - \newlabel{sec:bar}{{2}{1}} - "# - ), - ) - .build() - .await; - - test_bed.spawn(); - test_bed - .initialize(NESTED_SYMBOL_CAPABILITIES.clone()) - .await; - test_bed.open("main.tex").await; - test_bed.open("main.aux").await; - - let mut actual_symbols = test_bed.document_symbol_nested("main.tex").await.unwrap(); - - test_bed.shutdown().await; - - assert_eq!(actual_symbols.len(), 2); - verify_symbol( - &actual_symbols[0], - "Foo", - None, - Range::new_simple(4, 0, 4, 13), - Range::new_simple(4, 0, 6, 0), - ); - verify_symbol( - &actual_symbols[1], - "2 Bar", - Some("sec:bar"), - Range::new_simple(6, 0, 6, 13), - Range::new_simple(6, 0, 10, 0), - ); - - let children = actual_symbols[1].children.take().unwrap(); - assert_eq!(children.len(), 1); - verify_symbol( - &children[0], - "Baz", - Some("sec:baz"), - Range::new_simple(8, 0, 8, 16), - Range::new_simple(8, 0, 10, 0), - ); +#[test] +fn test_equation_flat() -> Result<()> { + let server = ServerTester::launch_new_instance()?; + server.initialize(ClientCapabilities::default(), None)?; + let uri = Url::parse("http://www.example.com/main.tex")?; + server.open_memory( + uri.clone(), + r#" + \documentclass{article} + + \begin{document} + + \begin{equation}\label{eq:foo} + Foo + \end{equation} + + \begin{equation}\label{eq:bar} + Bar + \end{equation} + + \begin{equation} + Baz + \end{equation} + + \end{document} + "#, + "latex", + )?; + server.open_memory( + Url::parse("http://www.example.com/main.aux")?, + r#" + \relax + \newlabel{eq:foo}{{1}{1}} + "#, + "latex", + )?; + assert_json_snapshot!(server.find_document_symbols(uri)?); + Ok(()) } -#[tokio::test] -async fn theorem() { - let mut test_bed = TestBedBuilder::new() - .file( - "main.tex", - indoc!( - r#" - \documentclass{article} - \usepackage{amsthm} - \newtheorem{lemma}{Lemma} - % - \begin{document} - % - \begin{lemma}[Foo]\label{thm:foo} - Foo - \end{lemma} - % - \begin{lemma}\label{thm:bar} - Bar - \end{lemma} - % - \begin{lemma}\label{thm:baz} - Baz - \end{lemma} - % - \begin{lemma}[Qux] - Qux - \end{lemma} - % - \end{document} - "# - ), - ) - .file( - "main.aux", - indoc!( - r#" - \relax - \newlabel{thm:foo}{{1}{1}} - \newlabel{thm:bar}{{2}{1}} - "# - ), - ) - .build() - .await; - - test_bed.spawn(); - test_bed - .initialize(NESTED_SYMBOL_CAPABILITIES.clone()) - .await; - test_bed.open("main.tex").await; - test_bed.open("main.aux").await; - - let actual_symbols = test_bed.document_symbol_nested("main.tex").await.unwrap(); - - test_bed.shutdown().await; - - assert_eq!(actual_symbols.len(), 4); - verify_symbol( - &actual_symbols[0], - "Lemma 1 (Foo)", - Some("thm:foo"), - Range::new_simple(6, 18, 6, 33), - Range::new_simple(6, 0, 8, 11), - ); - verify_symbol( - &actual_symbols[1], - "Lemma 2", - Some("thm:bar"), - Range::new_simple(10, 13, 10, 28), - Range::new_simple(10, 0, 12, 11), - ); - verify_symbol( - &actual_symbols[2], - "Lemma", - Some("thm:baz"), - Range::new_simple(14, 13, 14, 28), - Range::new_simple(14, 0, 16, 11), - ); - verify_symbol( - &actual_symbols[3], - "Lemma (Qux)", - None, - Range::new_simple(18, 0, 20, 11), - Range::new_simple(18, 0, 20, 11), - ); +#[test] +fn test_float_nested() -> Result<()> { + let server = ServerTester::launch_new_instance()?; + server.initialize(nested_symbol_capabilities(), None)?; + let uri = Url::parse("http://www.example.com/main.tex")?; + server.open_memory( + uri.clone(), + r#" + \documentclass{article} + + \begin{document} + + \begin{figure} + Foo + \caption{Foo}\label{fig:foo} + \end{figure} + + \begin{figure} + Bar + \caption{Bar}\label{fig:bar} + \end{figure} + + \begin{figure} + Baz + \caption{Baz} + \end{figure} + + \begin{figure} + Qux + \end{figure} + + \end{document} + "#, + "latex", + )?; + server.open_memory( + Url::parse("http://www.example.com/main.aux")?, + r#" + \relax + \@writefile{lof}{\contentsline {figure}{\numberline {1}{\ignorespaces Foo}}{1}\protected@file@percent } + \newlabel{fig:foo}{{1}{1}} + \@writefile{lof}{\contentsline {figure}{\numberline {2}{\ignorespaces Bar}}{1}\protected@file@percent } + \@writefile{lof}{\contentsline {figure}{\numberline {3}{\ignorespaces Baz}}{1}\protected@file@percent } + "#, + "latex", + )?; + assert_json_snapshot!(server.find_document_symbols(uri)?); + Ok(()) +} + +#[test] +fn test_float_flat() -> Result<()> { + let server = ServerTester::launch_new_instance()?; + server.initialize(ClientCapabilities::default(), None)?; + let uri = Url::parse("http://www.example.com/main.tex")?; + server.open_memory( + uri.clone(), + r#" + \documentclass{article} + + \begin{document} + + \begin{figure} + Foo + \caption{Foo}\label{fig:foo} + \end{figure} + + \begin{figure} + Bar + \caption{Bar}\label{fig:bar} + \end{figure} + + \begin{figure} + Baz + \caption{Baz} + \end{figure} + + \begin{figure} + Qux + \end{figure} + + \end{document} + "#, + "latex", + )?; + server.open_memory( + Url::parse("http://www.example.com/main.aux")?, + r#" + \relax + \@writefile{lof}{\contentsline {figure}{\numberline {1}{\ignorespaces Foo}}{1}\protected@file@percent } + \newlabel{fig:foo}{{1}{1}} + \@writefile{lof}{\contentsline {figure}{\numberline {2}{\ignorespaces Bar}}{1}\protected@file@percent } + \@writefile{lof}{\contentsline {figure}{\numberline {3}{\ignorespaces Baz}}{1}\protected@file@percent } + "#, + "latex", + )?; + assert_json_snapshot!(server.find_document_symbols(uri)?); + Ok(()) +} + +#[test] +fn test_section_nested() -> Result<()> { + let server = ServerTester::launch_new_instance()?; + server.initialize(nested_symbol_capabilities(), None)?; + let uri = Url::parse("http://www.example.com/main.tex")?; + server.open_memory( + uri.clone(), + r#" + \documentclass{article} + + \begin{document} + + \section{Foo} + + \section{Bar}\label{sec:bar} + + \subsection{Baz}\label{sec:baz} + + \end{document} + "#, + "latex", + )?; + server.open_memory( + Url::parse("http://www.example.com/main.aux")?, + r#" + \relax + \@writefile{toc}{\contentsline {section}{\numberline {1}Foo}{1}\protected@file@percent } + \@writefile{toc}{\contentsline {section}{\numberline {2}Bar}{1}\protected@file@percent } + \newlabel{sec:bar}{{2}{1}} + "#, + "latex", + )?; + assert_json_snapshot!(server.find_document_symbols(uri)?); + Ok(()) +} + +#[test] +fn test_section_flat() -> Result<()> { + let server = ServerTester::launch_new_instance()?; + server.initialize(ClientCapabilities::default(), None)?; + let uri = Url::parse("http://www.example.com/main.tex")?; + server.open_memory( + uri.clone(), + r#" + \documentclass{article} + + \begin{document} + + \section{Foo} + + \section{Bar}\label{sec:bar} + + \subsection{Baz}\label{sec:baz} + + \end{document} + "#, + "latex", + )?; + server.open_memory( + Url::parse("http://www.example.com/main.aux")?, + r#" + \relax + \@writefile{toc}{\contentsline {section}{\numberline {1}Foo}{1}\protected@file@percent } + \@writefile{toc}{\contentsline {section}{\numberline {2}Bar}{1}\protected@file@percent } + \newlabel{sec:bar}{{2}{1}} + "#, + "latex", + )?; + assert_json_snapshot!(server.find_document_symbols(uri)?); + Ok(()) +} + +#[test] +fn test_theorem_nested() -> Result<()> { + let server = ServerTester::launch_new_instance()?; + server.initialize(nested_symbol_capabilities(), None)?; + let uri = Url::parse("http://www.example.com/main.tex")?; + server.open_memory( + uri.clone(), + r#" + \documentclass{article} + \usepackage{amsthm} + \newtheorem{lemma}{Lemma} + + \begin{document} + + \begin{lemma}[Foo]\label{thm:foo} + Foo + \end{lemma} + + \begin{lemma}\label{thm:bar} + Bar + \end{lemma} + + \begin{lemma}\label{thm:baz} + Baz + \end{lemma} + + \begin{lemma}[Qux] + Qux + \end{lemma} + + \end{document} + "#, + "latex", + )?; + server.open_memory( + Url::parse("http://www.example.com/main.aux")?, + r#" + \relax + \newlabel{thm:foo}{{1}{1}} + \newlabel{thm:bar}{{2}{1}} + "#, + "latex", + )?; + assert_json_snapshot!(server.find_document_symbols(uri)?); + Ok(()) +} + +#[test] +fn test_theorem_flat() -> Result<()> { + let server = ServerTester::launch_new_instance()?; + server.initialize(ClientCapabilities::default(), None)?; + let uri = Url::parse("http://www.example.com/main.tex")?; + server.open_memory( + uri.clone(), + r#" + \documentclass{article} + \usepackage{amsthm} + \newtheorem{lemma}{Lemma} + + \begin{document} + + \begin{lemma}[Foo]\label{thm:foo} + Foo + \end{lemma} + + \begin{lemma}\label{thm:bar} + Bar + \end{lemma} + + \begin{lemma}\label{thm:baz} + Baz + \end{lemma} + + \begin{lemma}[Qux] + Qux + \end{lemma} + + \end{document} + "#, + "latex", + )?; + server.open_memory( + Url::parse("http://www.example.com/main.aux")?, + r#" + \relax + \newlabel{thm:foo}{{1}{1}} + \newlabel{thm:bar}{{2}{1}} + "#, + "latex", + )?; + assert_json_snapshot!(server.find_document_symbols(uri)?); + Ok(()) } diff --git a/support/texlab/tests/integration/folding.rs b/support/texlab/tests/integration/folding.rs deleted file mode 100644 index 3540e2c680..0000000000 --- a/support/texlab/tests/integration/folding.rs +++ /dev/null @@ -1,126 +0,0 @@ -use indoc::indoc; -use texlab::{ - protocol::{FoldingRange, FoldingRangeKind}, - test::{TestBedBuilder, PULL_CAPABILITIES}, -}; - -#[tokio::test] -async fn empty_latex_document() { - let mut test_bed = TestBedBuilder::new().file("main.tex", "").build().await; - test_bed.spawn(); - test_bed.initialize(PULL_CAPABILITIES.clone()).await; - test_bed.open("main.tex").await; - - let actual_foldings = test_bed.folding_range("main.tex").await.unwrap(); - - test_bed.shutdown().await; - - assert!(actual_foldings.is_empty()); -} - -#[tokio::test] -async fn empty_bibtex_document() { - let mut test_bed = TestBedBuilder::new().file("main.bib", "").build().await; - test_bed.spawn(); - test_bed.initialize(PULL_CAPABILITIES.clone()).await; - test_bed.open("main.bib").await; - - let actual_foldings = test_bed.folding_range("main.bib").await.unwrap(); - - test_bed.shutdown().await; - - assert!(actual_foldings.is_empty()); -} - -#[tokio::test] -async fn latex_sections_with_env() { - let mut test_bed = TestBedBuilder::new() - .file( - "main.tex", - indoc!( - r#" - \begin{document} - \section{Foo} - Foo - \section{Bar} - Bar - \end{document} - "# - ), - ) - .build() - .await; - test_bed.spawn(); - test_bed.initialize(PULL_CAPABILITIES.clone()).await; - test_bed.open("main.tex").await; - - let actual_foldings = test_bed.folding_range("main.tex").await.unwrap(); - - test_bed.shutdown().await; - - let expected_foldings = vec![ - FoldingRange { - start_line: 0, - start_character: Some(16), - end_line: 5, - end_character: Some(0), - kind: Some(FoldingRangeKind::Region), - }, - FoldingRange { - start_line: 1, - start_character: Some(13), - end_line: 2, - end_character: Some(0), - kind: Some(FoldingRangeKind::Region), - }, - ]; - assert_eq!(actual_foldings, expected_foldings); -} - -#[tokio::test] -async fn bibtex_entry() { - let mut test_bed = TestBedBuilder::new() - .file( - "main.bib", - indoc!( - r#" - @article{foo, - author = {Foo Bar}, - title = {Baz Qux}, - } - "# - ), - ) - .build() - .await; - test_bed.spawn(); - test_bed.initialize(PULL_CAPABILITIES.clone()).await; - test_bed.open("main.bib").await; - - let actual_foldings = test_bed.folding_range("main.bib").await.unwrap(); - - test_bed.shutdown().await; - - let expected_foldings = vec![FoldingRange { - start_line: 0, - start_character: Some(0), - end_line: 3, - end_character: Some(1), - kind: Some(FoldingRangeKind::Region), - }]; - assert_eq!(actual_foldings, expected_foldings); -} - -#[tokio::test] -async fn unknown_file() { - let mut test_bed = TestBedBuilder::new().build().await; - - test_bed.spawn(); - test_bed.initialize(PULL_CAPABILITIES.clone()).await; - - let actual_foldings = test_bed.folding_range("main.tex").await; - - test_bed.shutdown().await; - - assert_eq!(actual_foldings, None); -} diff --git a/support/texlab/tests/integration/highlight.rs b/support/texlab/tests/integration/highlight.rs deleted file mode 100644 index ba77a7b8e3..0000000000 --- a/support/texlab/tests/integration/highlight.rs +++ /dev/null @@ -1,83 +0,0 @@ -use indoc::indoc; -use texlab::{ - protocol::{DocumentHighlight, DocumentHighlightKind, Range, RangeExt}, - test::{TestBedBuilder, PULL_CAPABILITIES}, -}; - -#[tokio::test] -async fn empty_latex_document() { - let mut test_bed = TestBedBuilder::new().file("main.tex", "").build().await; - test_bed.spawn(); - test_bed.initialize(PULL_CAPABILITIES.clone()).await; - test_bed.open("main.tex").await; - - let actual_highlights = test_bed.document_highlight("main.tex", 0, 0).await.unwrap(); - - test_bed.shutdown().await; - - assert!(actual_highlights.is_empty()); -} - -#[tokio::test] -async fn empty_bibtex_document() { - let mut test_bed = TestBedBuilder::new().file("main.bib", "").build().await; - test_bed.spawn(); - test_bed.initialize(PULL_CAPABILITIES.clone()).await; - test_bed.open("main.bib").await; - - let actual_highlights = test_bed.document_highlight("main.bib", 0, 0).await.unwrap(); - - test_bed.shutdown().await; - - assert!(actual_highlights.is_empty()); -} - -#[tokio::test] -async fn label() { - let mut test_bed = TestBedBuilder::new() - .file( - "main.tex", - indoc!( - r#" - \label{foo} - \ref{foo} - "# - ), - ) - .build() - .await; - test_bed.spawn(); - test_bed.initialize(PULL_CAPABILITIES.clone()).await; - test_bed.open("main.tex").await; - - let actual_highlights = test_bed.document_highlight("main.tex", 0, 7).await.unwrap(); - - let expected_highlights = vec![ - DocumentHighlight { - range: Range::new_simple(0, 7, 0, 10), - kind: Some(DocumentHighlightKind::Write), - }, - DocumentHighlight { - range: Range::new_simple(1, 5, 1, 8), - kind: Some(DocumentHighlightKind::Read), - }, - ]; - - test_bed.shutdown().await; - - assert_eq!(actual_highlights, expected_highlights); -} - -#[tokio::test] -async fn unknown_file() { - let mut test_bed = TestBedBuilder::new().build().await; - - test_bed.spawn(); - test_bed.initialize(PULL_CAPABILITIES.clone()).await; - - let actual_highlights = test_bed.document_highlight("main.tex", 0, 0).await; - - test_bed.shutdown().await; - - assert_eq!(actual_highlights, None); -} diff --git a/support/texlab/tests/integration/hover.rs b/support/texlab/tests/integration/hover.rs index 319ebcc5e9..70b14cccd0 100644 --- a/support/texlab/tests/integration/hover.rs +++ b/support/texlab/tests/integration/hover.rs @@ -1,86 +1,89 @@ -use indoc::indoc; -use texlab::{ - protocol::{HoverContents, MarkupContent, MarkupKind}, - test::{TestBedBuilder, PULL_CAPABILITIES}, -}; +use anyhow::Result; +use insta::assert_json_snapshot; +use lsp_types::ClientCapabilities; -#[tokio::test] -async fn label_theorem_child_file() { - let mut test_bed = TestBedBuilder::new() - .file( - "main.tex", - indoc!( - r#" - \documentclass{article} - \newtheorem{lemma}{Lemma} - \include{child} - \ref{thm:foo} - "# - ), - ) - .file( - "child.tex", - indoc!( - r#" - \begin{lemma}\label{thm:foo} - 1 + 1 = 2 - \end{lemma} - "# - ), - ) - .build() - .await; - test_bed.spawn(); - test_bed.initialize(PULL_CAPABILITIES.clone()).await; - test_bed.open("main.tex").await; +use crate::common::ServerTester; - let actual_hover = test_bed.hover("main.tex", 3, 8).await.unwrap().unwrap(); - assert_eq!( - actual_hover.contents, - HoverContents::Markup(MarkupContent { - kind: MarkupKind::PlainText, - value: "Lemma".into() - }) - ); +#[test] +fn test_empty_bibtex_document() -> Result<()> { + let server = ServerTester::launch_new_instance()?; + server.initialize(ClientCapabilities::default(), None)?; + let uri = server.open("main.bib", "", "bibtex", false)?; + assert_json_snapshot!(server.hover(uri, 0, 0)?); + Ok(()) } -#[tokio::test] -async fn label_theorem_child_file_number() { - let mut test_bed = TestBedBuilder::new() - .file( - "main.tex", - indoc!( - r#" - \documentclass{article} - \newtheorem{lemma}{Lemma} - \include{child} - \ref{thm:foo} - "# - ), - ) - .file( - "child.tex", - indoc!( - r#" - \begin{lemma}[Foo]\label{thm:foo} - 1 + 1 = 2 - \end{lemma} - "# - ), - ) - .file("child.aux", r#"\newlabel{thm:foo}{{1}{1}{Foo}{lemma.1}{}}"#) - .build() - .await; - test_bed.spawn(); - test_bed.initialize(PULL_CAPABILITIES.clone()).await; - test_bed.open("main.tex").await; +#[test] +fn test_empty_labtex_document() -> Result<()> { + let server = ServerTester::launch_new_instance()?; + server.initialize(ClientCapabilities::default(), None)?; + let uri = server.open("main.tex", "", "latex", false)?; + assert_json_snapshot!(server.hover(uri, 0, 0)?); + Ok(()) +} + +#[test] +fn test_label_theorem_child_file() -> Result<()> { + let server = ServerTester::launch_new_instance()?; + server.initialize(ClientCapabilities::default(), None)?; + let uri = server.open( + "main.tex", + r#" + \documentclass{article} + \newtheorem{lemma}{Lemma} + \include{child} + \ref{thm:foo} + "#, + "latex", + false, + )?; + server.open( + "child.tex", + r#" + \begin{lemma}\label{thm:foo} + 1 + 1 = 2 + \end{lemma} + "#, + "latex", + false, + )?; + + assert_json_snapshot!(server.hover(uri, 3, 8)?); + Ok(()) +} + +#[test] +fn test_label_theorem_child_file_mumber() -> Result<()> { + let server = ServerTester::launch_new_instance()?; + server.initialize(ClientCapabilities::default(), None)?; + let uri = server.open( + "main.tex", + r#" + \documentclass{article} + \newtheorem{lemma}{Lemma} + \include{child} + \ref{thm:foo} + "#, + "latex", + false, + )?; + server.open( + "child.tex", + r#" + \begin{lemma}[Foo]\label{thm:foo} + 1 + 1 = 2 + \end{lemma} + "#, + "latex", + false, + )?; + server.open( + "child.aux", + r#"\newlabel{thm:foo}{{1}{1}{Foo}{lemma.1}{}}"#, + "latex", + false, + )?; - let actual_hover = test_bed.hover("main.tex", 3, 8).await.unwrap().unwrap(); - assert_eq!( - actual_hover.contents, - HoverContents::Markup(MarkupContent { - kind: MarkupKind::PlainText, - value: "Lemma 1 (Foo)".into() - }) - ); + assert_json_snapshot!(server.hover(uri, 3, 8)?); + Ok(()) } diff --git a/support/texlab/tests/integration/issues.rs b/support/texlab/tests/integration/issues.rs index 59a1bfeacb..5d6caeb79d 100644 --- a/support/texlab/tests/integration/issues.rs +++ b/support/texlab/tests/integration/issues.rs @@ -1,350 +1,41 @@ -use indoc::indoc; -use texlab::{ - protocol::{HoverContents, Location, LocationLink, MarkupContent, MarkupKind, Range, RangeExt}, - test::{TestBedBuilder, LOCATION_LINK_CAPABILITIES, PULL_CAPABILITIES}, -}; - -#[tokio::test] -async fn issue_14() { - let mut test_bed = TestBedBuilder::new() - .file("main.tex", r#"\(\be\)"#) - .build() - .await; - test_bed.spawn(); - test_bed.initialize(PULL_CAPABILITIES.clone()).await; - test_bed.open("main.tex").await; - - let actual_items = test_bed.completion("main.tex", 0, 5).await.unwrap(); - - test_bed.shutdown().await; - assert!(actual_items.iter().any(|item| item.label == "beta")); -} - -#[tokio::test] -async fn issue_15_link() { - let mut test_bed = TestBedBuilder::new() - .file( - "main.tex", - indoc!( - r#" - \documentclass{article} - \begin{document} - \newcommand{\test}{test} - hello \test{} - \end{document} - "# - ), - ) - .build() - .await; - test_bed.spawn(); - test_bed - .initialize(LOCATION_LINK_CAPABILITIES.clone()) - .await; - test_bed.open("main.tex").await; - - let actual_links = test_bed.definition_link("main.tex", 3, 9).await.unwrap(); - - test_bed.shutdown().await; - let expected_links = vec![LocationLink { - origin_selection_range: Some(Range::new_simple(3, 6, 3, 13)), - target_range: Range::new_simple(2, 0, 2, 24), - target_selection_range: Range::new_simple(2, 0, 2, 24), - target_uri: test_bed.uri("main.tex").into(), - }]; - assert_eq!(actual_links, expected_links); -} - -#[tokio::test] -async fn issue_15_location() { - let mut test_bed = TestBedBuilder::new() - .file( - "main.tex", - indoc!( - r#" - \documentclass{article} - \begin{document} - \newcommand{\test}{test} - hello \test{} - \end{document} - "# - ), - ) - .build() - .await; - test_bed.spawn(); - test_bed.initialize(PULL_CAPABILITIES.clone()).await; - test_bed.open("main.tex").await; - - let actual_locations = test_bed - .definition_location("main.tex", 3, 9) - .await - .unwrap(); - - test_bed.shutdown().await; - let expected_locations = vec![Location { - range: Range::new_simple(2, 0, 2, 24), - uri: test_bed.uri("main.tex").into(), - }]; - assert_eq!(actual_locations, expected_locations); -} - -#[tokio::test] -async fn issue_17() { - let mut test_bed = TestBedBuilder::new() - .file("main.bib", r#"@ARTICLE{foo,}"#) - .build() - .await; - test_bed.spawn(); - test_bed.initialize(PULL_CAPABILITIES.clone()).await; - test_bed.open("main.bib").await; - - let actual_hover = test_bed.hover("main.bib", 0, 3).await.unwrap().unwrap(); - - test_bed.shutdown().await; - assert_eq!(actual_hover.range.unwrap(), Range::new_simple(0, 0, 0, 8)); -} - -#[tokio::test] -async fn issue_21() { - let mut test_bed = TestBedBuilder::new() - .file( - "main.tex", - indoc!( - r#" - \label{foo} - \cref{} - "# - ), - ) - .build() - .await; - test_bed.spawn(); - test_bed.initialize(PULL_CAPABILITIES.clone()).await; - test_bed.open("main.tex").await; - - let actual_items = test_bed.completion("main.tex", 1, 6).await.unwrap(); - - test_bed.shutdown().await; - assert!(actual_items.iter().any(|item| item.label == "foo")); -} - -#[tokio::test] -async fn issue_22_include() { - let mut test_bed = TestBedBuilder::new() - .file( - "main.tex", - indoc!( - r#" - \bibliography{bibfile} - \cite{} - "# - ), - ) - .file("bibfile.bib", r#"@article{foo,}"#) - .build() - .await; - - test_bed.spawn(); - test_bed.initialize(PULL_CAPABILITIES.clone()).await; - test_bed.open("main.tex").await; - - let actual_items = test_bed.completion("main.tex", 1, 6).await.unwrap(); - - test_bed.shutdown().await; - assert!(actual_items.iter().any(|item| item.label == "foo")); -} - -#[tokio::test] -async fn issue_22_definition() { - let mut test_bed = TestBedBuilder::new() - .file( - "main.tex", - indoc!( - r#" - \bibliography{bibfile} - \cite{A,B} - "# - ), - ) - .file( - "bibfile.bib", - indoc!( - r#" - @article{A,} - @article{B,} - "# - ), - ) - .build() - .await; - - test_bed.spawn(); - test_bed.initialize(PULL_CAPABILITIES.clone()).await; - test_bed.open("main.tex").await; - - let actual_locations = test_bed - .definition_location("main.tex", 1, 8) - .await - .unwrap(); - - test_bed.shutdown().await; - let expected_locations = vec![Location { - range: Range::new_simple(1, 9, 1, 10), - uri: test_bed.uri("bibfile.bib").into(), - }]; - assert_eq!(actual_locations, expected_locations); -} - -#[tokio::test] -async fn issue_23_completion() { - let mut test_bed = TestBedBuilder::new() - .file( - "main.tex", - indoc!( - r#" - \documentclass{article} - \begin{document} - \include{test1} - \include{test2} - \end{document} - "# - ), - ) - .file("test1.tex", r#"\section{Section 1}\label{sec:1}"#) - .file( - "test2.tex", - indoc!( - r#" - \section{Section 2}\label{sec:2} - % - This section continues from Section \ref{sec}"# - ), - ) - .build() - .await; - test_bed.spawn(); - test_bed.initialize(PULL_CAPABILITIES.clone()).await; - test_bed.open("test2.tex").await; - test_bed.detect_root("test2.tex").await; - - let actual_items = test_bed.completion("test2.tex", 2, 42).await.unwrap(); - - test_bed.shutdown().await; - assert_eq!(actual_items.len(), 2); -} - -#[tokio::test] -async fn issue_23_rename() { - let mut test_bed = TestBedBuilder::new() - .file( - "main.tex", - indoc!( - r#" - \documentclass{article} - \begin{document} - \include{test1} - \include{test2} - \end{document} - "# - ), - ) - .file("test1.tex", r#"\section{Section 1}\label{sec:1}"#) - .file( - "test2.tex", - indoc!( - r#" - \section{Section 2}\label{sec:2} - % - This section continues from Section \ref{sec:1}"# - ), - ) - .build() - .await; - test_bed.spawn(); - test_bed.initialize(PULL_CAPABILITIES.clone()).await; - test_bed.open("test1.tex").await; - test_bed.detect_root("test1.tex").await; - - let workspace_edit = test_bed - .rename("test1.tex", 0, 27, "foo") - .await - .unwrap() - .unwrap(); - - test_bed.shutdown().await; - let changes = workspace_edit.changes.unwrap(); - assert!(changes.contains_key(&test_bed.uri("test1.tex"))); - assert!(changes.contains_key(&test_bed.uri("test2.tex"))); -} - -#[tokio::test] -async fn issue_23_hover() { - let mut test_bed = TestBedBuilder::new() - .file( - "main.tex", - indoc!( - r#" - \documentclass{article} - \begin{document} - \include{test1} - \include{test2} - \end{document} - "# - ), - ) - .file("test1.tex", r#"\section{Section 1}\label{sec:1}"#) - .file( - "test2.tex", - indoc!( - r#" - \section{Section 2}\label{sec:2} - % - This section continues from Section \ref{sec:1}"# - ), - ) - .build() - .await; - test_bed.spawn(); - test_bed.initialize(PULL_CAPABILITIES.clone()).await; - test_bed.open("test2.tex").await; - test_bed.detect_root("test2.tex").await; - - let actual_hover = test_bed.hover("test2.tex", 2, 42).await.unwrap().unwrap(); - - test_bed.shutdown().await; - assert_eq!( - actual_hover.contents, - HoverContents::Markup(MarkupContent { - kind: MarkupKind::PlainText, - value: "Section (Section 1)".into() - }) - ); -} - -#[tokio::test] -async fn issue_26() { - let mut test_bed = TestBedBuilder::new() - .file( - "main.tex", - indoc!( - r#" - \section{Foo}\label{sec:foo} - \begin{equation}\label{eq:bar} - \end{equation} - \eqref{} - "# - ), - ) - .build() - .await; - test_bed.spawn(); - test_bed.initialize(PULL_CAPABILITIES.clone()).await; - test_bed.open("main.tex").await; - - let actual_items = test_bed.completion("main.tex", 3, 7).await.unwrap(); - - test_bed.shutdown().await; - assert!(actual_items.iter().any(|item| item.label == "eq:bar")); - assert!(actual_items.iter().all(|item| item.label != "sec:foo")); +use std::{fs, thread, time::Duration}; + +use anyhow::Result; +use lsp_types::ClientCapabilities; + +use crate::common::ServerTester; + +#[test] +#[cfg(feature = "completion")] +fn test_408_parent_expansion() -> Result<()> { + let server = ServerTester::launch_new_instance()?; + server.initialize(ClientCapabilities::default(), None)?; + let root = server.directory.path(); + + let level1 = root.join("level1"); + let level2 = level1.join("level2"); + let level3 = level2.join("level3"); + fs::create_dir_all(&level3)?; + fs::write(level3.join("d.tex"), "d")?; + fs::write( + level2.join("c.tex"), + r#"\documentclass{subfiles}\begin{document}\include{level3/d}\end{document}"#, + )?; + fs::write( + level1.join("b.tex"), + r#"\documentclass{article}\begin{document}\include{level2/c}\end{document}"#, + )?; + fs::write(root.join("a.tex"), "}")?; + + thread::sleep(Duration::from_millis(300)); + + let uri = server.open("level1/level2/level3/d.tex", "d", "latex", false)?; + server.complete(uri, 0, 0)?; + + let diagnostics_by_uri = server.diagnostics_by_uri.lock().unwrap(); + assert!(diagnostics_by_uri + .iter() + .all(|(uri, _)| !uri.as_str().ends_with("a.tex"))); + + Ok(()) } diff --git a/support/texlab/tests/integration/link.rs b/support/texlab/tests/integration/link.rs deleted file mode 100644 index 8db718bd26..0000000000 --- a/support/texlab/tests/integration/link.rs +++ /dev/null @@ -1,173 +0,0 @@ -use indoc::indoc; -use texlab::{ - protocol::{DocumentLink, Range, RangeExt}, - test::{TestBedBuilder, PULL_CAPABILITIES, PUSH_CAPABILITIES}, -}; - -#[tokio::test] -async fn empty_latex_document() { - let mut test_bed = TestBedBuilder::new().file("main.tex", "").build().await; - test_bed.spawn(); - test_bed.initialize(PULL_CAPABILITIES.clone()).await; - test_bed.open("main.tex").await; - - let actual_links = test_bed.document_link("main.tex").await.unwrap(); - - test_bed.shutdown().await; - - assert!(actual_links.is_empty()); -} - -#[tokio::test] -async fn default_settings() { - let mut test_bed = TestBedBuilder::new() - .file( - "main.tex", - indoc!( - r#" - \include{foo/bar} - \input{qux.tex} - "# - ), - ) - .file("foo/bar.tex", "") - .file("qux.tex", "") - .build() - .await; - - test_bed.spawn(); - test_bed.initialize(PULL_CAPABILITIES.clone()).await; - test_bed.open("main.tex").await; - - let actual_links = test_bed.document_link("main.tex").await.unwrap(); - - test_bed.shutdown().await; - - let expected_links = vec![ - DocumentLink { - range: Range::new_simple(0, 9, 0, 16), - target: test_bed.uri("foo/bar.tex").into(), - tooltip: None, - }, - DocumentLink { - range: Range::new_simple(1, 7, 1, 14), - target: test_bed.uri("qux.tex").into(), - tooltip: None, - }, - ]; - assert_eq!(actual_links, expected_links); -} - -#[tokio::test] -async fn root_directory() { - let mut test_bed = TestBedBuilder::new() - .file("src/main.tex", r#"\include{src/foo}"#) - .file("src/foo.tex", "") - .root_dir(".") - .build() - .await; - - test_bed.spawn(); - test_bed.initialize(PULL_CAPABILITIES.clone()).await; - test_bed.open("src/main.tex").await; - - let actual_links = test_bed.document_link("src/main.tex").await.unwrap(); - - test_bed.shutdown().await; - - let expected_links = vec![DocumentLink { - range: Range::new_simple(0, 9, 0, 16), - target: test_bed.uri("src/foo.tex").into(), - tooltip: None, - }]; - assert_eq!(actual_links, expected_links); -} - -#[tokio::test] -async fn parent_directory() { - let mut test_bed = TestBedBuilder::new() - .file("src/main.tex", r#"\addbibresource{../foo.bib}"#) - .file("foo.bib", "") - .build() - .await; - - test_bed.spawn(); - test_bed.initialize(PULL_CAPABILITIES.clone()).await; - test_bed.open("src/main.tex").await; - - let actual_links = test_bed.document_link("src/main.tex").await.unwrap(); - - test_bed.shutdown().await; - - let expected_links = vec![DocumentLink { - range: Range::new_simple(0, 16, 0, 26), - target: test_bed.uri("foo.bib").into(), - tooltip: None, - }]; - assert_eq!(actual_links, expected_links); -} - -#[tokio::test] -async fn unknown_file() { - let mut test_bed = TestBedBuilder::new().build().await; - - test_bed.spawn(); - test_bed.initialize(PULL_CAPABILITIES.clone()).await; - - let actual_links = test_bed.document_link("main.tex").await; - - test_bed.shutdown().await; - - assert_eq!(actual_links, None); -} - -#[tokio::test] -async fn edit_file() { - let mut test_bed = TestBedBuilder::new() - .file("main.tex", "") - .file("foo.tex", "") - .build() - .await; - - test_bed.spawn(); - test_bed.initialize(PULL_CAPABILITIES.clone()).await; - test_bed.open("main.tex").await; - test_bed.edit("main.tex", r#"\include{foo}"#).await; - - let actual_links = test_bed.document_link("main.tex").await.unwrap(); - - test_bed.shutdown().await; - - let expected_links = vec![DocumentLink { - range: Range::new_simple(0, 9, 0, 12), - target: test_bed.uri("foo.tex").into(), - tooltip: None, - }]; - assert_eq!(actual_links, expected_links); -} - -#[tokio::test] -async fn did_change_configuration() { - let mut test_bed = TestBedBuilder::new() - .file("src/main.tex", r#"\include{src/foo}"#) - .file("src/foo.tex", "") - .root_dir(".") - .build() - .await; - - test_bed.spawn(); - test_bed.initialize(PUSH_CAPABILITIES.clone()).await; - test_bed.open("src/main.tex").await; - test_bed.push_options().await; - - let actual_links = test_bed.document_link("src/main.tex").await.unwrap(); - - test_bed.shutdown().await; - - let expected_links = vec![DocumentLink { - range: Range::new_simple(0, 9, 0, 16), - target: test_bed.uri("src/foo.tex").into(), - tooltip: None, - }]; - assert_eq!(actual_links, expected_links); -} diff --git a/support/texlab/tests/integration/main.rs b/support/texlab/tests/integration/main.rs index 99c0b23a5c..ebccca7396 100644 --- a/support/texlab/tests/integration/main.rs +++ b/support/texlab/tests/integration/main.rs @@ -1,12 +1,7 @@ +mod common; +#[cfg(feature = "completion")] mod completion; -mod definition; mod document_symbol; -mod folding; -mod highlight; mod hover; mod issues; -mod link; -mod prepare_rename; -mod reference; -mod rename; mod workspace_symbol; diff --git a/support/texlab/tests/integration/prepare_rename.rs b/support/texlab/tests/integration/prepare_rename.rs deleted file mode 100644 index 0efaa712b2..0000000000 --- a/support/texlab/tests/integration/prepare_rename.rs +++ /dev/null @@ -1,151 +0,0 @@ -use texlab::{ - protocol::{Range, RangeExt}, - test::{TestBedBuilder, PULL_CAPABILITIES}, -}; - -#[tokio::test] -async fn empty_latex_document() { - let mut test_bed = TestBedBuilder::new().file("main.tex", "").build().await; - test_bed.spawn(); - test_bed.initialize(PULL_CAPABILITIES.clone()).await; - test_bed.open("main.tex").await; - - let actual_range = test_bed.prepare_rename("main.tex", 0, 0).await.unwrap(); - - test_bed.shutdown().await; - - assert_eq!(actual_range, None); -} - -#[tokio::test] -async fn empty_bibtex_document() { - let mut test_bed = TestBedBuilder::new().file("main.bib", "").build().await; - test_bed.spawn(); - test_bed.initialize(PULL_CAPABILITIES.clone()).await; - test_bed.open("main.bib").await; - - let actual_range = test_bed.prepare_rename("main.bib", 0, 0).await.unwrap(); - - test_bed.shutdown().await; - - assert_eq!(actual_range, None); -} - -#[tokio::test] -async fn bibtex_entry() { - let mut test_bed = TestBedBuilder::new() - .file("main.bib", r#"@article{foo,}"#) - .build() - .await; - test_bed.spawn(); - test_bed.initialize(PULL_CAPABILITIES.clone()).await; - test_bed.open("main.bib").await; - - let actual_range = test_bed - .prepare_rename("main.bib", 0, 10) - .await - .unwrap() - .unwrap(); - - test_bed.shutdown().await; - - assert_eq!(actual_range, Range::new_simple(0, 9, 0, 12)); -} - -#[tokio::test] -async fn latex_citation() { - let mut test_bed = TestBedBuilder::new() - .file("main.tex", r#"\cite{foo,bar}"#) - .build() - .await; - test_bed.spawn(); - test_bed.initialize(PULL_CAPABILITIES.clone()).await; - test_bed.open("main.tex").await; - - let actual_range = test_bed - .prepare_rename("main.tex", 0, 11) - .await - .unwrap() - .unwrap(); - - test_bed.shutdown().await; - - assert_eq!(actual_range, Range::new_simple(0, 10, 0, 13)); -} - -#[tokio::test] -async fn latex_command() { - let mut test_bed = TestBedBuilder::new() - .file("main.tex", r#"\foo"#) - .build() - .await; - test_bed.spawn(); - test_bed.initialize(PULL_CAPABILITIES.clone()).await; - test_bed.open("main.tex").await; - - let actual_range = test_bed - .prepare_rename("main.tex", 0, 1) - .await - .unwrap() - .unwrap(); - - test_bed.shutdown().await; - - assert_eq!(actual_range, Range::new_simple(0, 0, 0, 4)); -} - -#[tokio::test] -async fn latex_environment() { - let mut test_bed = TestBedBuilder::new() - .file("main.tex", r#"\begin{foo}\end{bar}"#) - .build() - .await; - test_bed.spawn(); - test_bed.initialize(PULL_CAPABILITIES.clone()).await; - test_bed.open("main.tex").await; - - let actual_range = test_bed - .prepare_rename("main.tex", 0, 7) - .await - .unwrap() - .unwrap(); - - test_bed.shutdown().await; - - assert_eq!(actual_range, Range::new_simple(0, 7, 0, 10)); -} - -#[tokio::test] -async fn latex_label() { - let mut test_bed = TestBedBuilder::new() - .file("main.tex", r#"\ref{foo,bar}"#) - .build() - .await; - test_bed.spawn(); - test_bed.initialize(PULL_CAPABILITIES.clone()).await; - test_bed.open("main.tex").await; - - let actual_range = test_bed - .prepare_rename("main.tex", 0, 9) - .await - .unwrap() - .unwrap(); - - test_bed.shutdown().await; - - assert_eq!(actual_range, Range::new_simple(0, 9, 0, 12)); -} - -#[tokio::test] -async fn unknown_file() { - let mut test_bed = TestBedBuilder::new().build().await; - - test_bed.spawn(); - test_bed.initialize(PULL_CAPABILITIES.clone()).await; - - let actual_range = test_bed.prepare_rename("main.tex", 0, 0).await; - - test_bed.shutdown().await; - - assert_eq!(actual_range, None); -} diff --git a/support/texlab/tests/integration/reference.rs b/support/texlab/tests/integration/reference.rs deleted file mode 100644 index 224f85fbfc..0000000000 --- a/support/texlab/tests/integration/reference.rs +++ /dev/null @@ -1,150 +0,0 @@ -use indoc::indoc; -use texlab::{ - protocol::{Location, Range, RangeExt}, - test::{TestBedBuilder, PULL_CAPABILITIES}, -}; - -#[tokio::test] -async fn empty_latex_document() { - let mut test_bed = TestBedBuilder::new().file("main.tex", "").build().await; - test_bed.spawn(); - test_bed.initialize(PULL_CAPABILITIES.clone()).await; - test_bed.open("main.tex").await; - - let actual_refs = test_bed.references("main.tex", 0, 0, false).await.unwrap(); - - test_bed.shutdown().await; - - assert!(actual_refs.is_empty()); -} - -#[tokio::test] -async fn empty_bibtex_document() { - let mut test_bed = TestBedBuilder::new().file("main.bib", "").build().await; - test_bed.spawn(); - test_bed.initialize(PULL_CAPABILITIES.clone()).await; - test_bed.open("main.bib").await; - - let actual_refs = test_bed.references("main.bib", 0, 0, false).await.unwrap(); - - test_bed.shutdown().await; - - assert!(actual_refs.is_empty()); -} - -#[tokio::test] -async fn bibtex_entry() { - let mut test_bed = TestBedBuilder::new() - .file("main.bib", r#"@article{foo,}"#) - .file( - "main.tex", - indoc!( - r#" - \addbibresource{main.bib} - \cite{foo} - "# - ), - ) - .build() - .await; - test_bed.spawn(); - test_bed.initialize(PULL_CAPABILITIES.clone()).await; - test_bed.open("main.bib").await; - test_bed.open("main.tex").await; - - let actual_refs = test_bed.references("main.tex", 1, 8, true).await.unwrap(); - - test_bed.shutdown().await; - - let expected_refs = vec![ - Location { - uri: test_bed.uri("main.tex").into(), - range: Range::new_simple(1, 6, 1, 9), - }, - Location { - uri: test_bed.uri("main.bib").into(), - range: Range::new_simple(0, 9, 0, 12), - }, - ]; - - assert_eq!(actual_refs, expected_refs); -} - -#[tokio::test] -async fn bibtex_string() { - let mut test_bed = TestBedBuilder::new() - .file( - "main.bib", - indoc!( - r#" - @string{foo = "foo"} - @article{bar, author = foo # foo} - "# - ), - ) - .build() - .await; - test_bed.spawn(); - test_bed.initialize(PULL_CAPABILITIES.clone()).await; - test_bed.open("main.bib").await; - - let actual_refs = test_bed.references("main.bib", 1, 31, false).await.unwrap(); - - test_bed.shutdown().await; - - let expected_refs = vec![ - Location { - uri: test_bed.uri("main.bib").into(), - range: Range::new_simple(1, 23, 1, 26), - }, - Location { - uri: test_bed.uri("main.bib").into(), - range: Range::new_simple(1, 29, 1, 32), - }, - ]; - - assert_eq!(actual_refs, expected_refs); -} - -#[tokio::test] -async fn latex_label() { - let mut test_bed = TestBedBuilder::new() - .file( - "main.tex", - indoc!( - r#" - \label{foo} - \ref{foo} - "# - ), - ) - .build() - .await; - test_bed.spawn(); - test_bed.initialize(PULL_CAPABILITIES.clone()).await; - test_bed.open("main.tex").await; - - let actual_refs = test_bed.references("main.tex", 0, 7, false).await.unwrap(); - - test_bed.shutdown().await; - - let expected_refs = vec![Location { - uri: test_bed.uri("main.tex").into(), - range: Range::new_simple(1, 5, 1, 8), - }]; - - assert_eq!(actual_refs, expected_refs); -} - -#[tokio::test] -async fn unknown_file() { - let mut test_bed = TestBedBuilder::new().build().await; - test_bed.spawn(); - test_bed.initialize(PULL_CAPABILITIES.clone()).await; - - let actual_refs = test_bed.references("main.tex", 0, 0, false).await; - - test_bed.shutdown().await; - - assert_eq!(actual_refs, None); -} diff --git a/support/texlab/tests/integration/rename.rs b/support/texlab/tests/integration/rename.rs deleted file mode 100644 index d8522f1ec6..0000000000 --- a/support/texlab/tests/integration/rename.rs +++ /dev/null @@ -1,236 +0,0 @@ -use indoc::indoc; -use std::collections::HashMap; -use texlab::{ - protocol::{Range, RangeExt, TextEdit, WorkspaceEdit}, - test::{TestBedBuilder, PULL_CAPABILITIES}, -}; - -#[tokio::test] -async fn empty_latex_document() { - let mut test_bed = TestBedBuilder::new().file("main.tex", "").build().await; - test_bed.spawn(); - test_bed.initialize(PULL_CAPABILITIES.clone()).await; - test_bed.open("main.tex").await; - - let actual_edit = test_bed.rename("main.tex", 0, 0, "").await.unwrap(); - - test_bed.shutdown().await; - - assert_eq!(actual_edit, None); -} - -#[tokio::test] -async fn empty_bibtex_document() { - let mut test_bed = TestBedBuilder::new().file("main.bib", "").build().await; - test_bed.spawn(); - test_bed.initialize(PULL_CAPABILITIES.clone()).await; - test_bed.open("main.bib").await; - - let actual_edit = test_bed.rename("main.bib", 0, 0, "").await.unwrap(); - - test_bed.shutdown().await; - - assert_eq!(actual_edit, None); -} - -#[tokio::test] -async fn bibtex_entry() { - let mut test_bed = TestBedBuilder::new() - .file( - "main.bib", - indoc!( - r#" - @article{foo,} - @article{bar,} - "# - ), - ) - .file( - "main.tex", - indoc!( - r#" - \addbibresource{main.bib} - \cite{foo,bar} - "# - ), - ) - .build() - .await; - test_bed.spawn(); - test_bed.initialize(PULL_CAPABILITIES.clone()).await; - test_bed.open("main.bib").await; - test_bed.open("main.tex").await; - - let actual_edit = test_bed - .rename("main.bib", 1, 10, "baz") - .await - .unwrap() - .unwrap(); - - test_bed.shutdown().await; - - let mut expected_changes = HashMap::new(); - expected_changes.insert( - test_bed.uri("main.bib").into(), - vec![TextEdit::new(Range::new_simple(1, 9, 1, 12), "baz".into())], - ); - expected_changes.insert( - test_bed.uri("main.tex").into(), - vec![TextEdit::new(Range::new_simple(1, 10, 1, 13), "baz".into())], - ); - - assert_eq!(actual_edit, WorkspaceEdit::new(expected_changes)); -} - -#[tokio::test] -async fn latex_command() { - let mut test_bed = TestBedBuilder::new() - .file( - "foo.tex", - indoc!( - r#" - \input{bar.tex} - \foo - "# - ), - ) - .file( - "bar.tex", - indoc!( - r#" - \foo - \bar - "# - ), - ) - .build() - .await; - test_bed.spawn(); - test_bed.initialize(PULL_CAPABILITIES.clone()).await; - test_bed.open("foo.tex").await; - test_bed.open("bar.tex").await; - - let actual_edit = test_bed - .rename("foo.tex", 1, 2, "baz") - .await - .unwrap() - .unwrap(); - - test_bed.shutdown().await; - - let mut expected_changes = HashMap::new(); - expected_changes.insert( - test_bed.uri("foo.tex").into(), - vec![TextEdit::new(Range::new_simple(1, 0, 1, 4), "\\baz".into())], - ); - expected_changes.insert( - test_bed.uri("bar.tex").into(), - vec![TextEdit::new(Range::new_simple(0, 0, 0, 4), "\\baz".into())], - ); - - assert_eq!(actual_edit, WorkspaceEdit::new(expected_changes)); -} - -#[tokio::test] -async fn latex_environment() { - let mut test_bed = TestBedBuilder::new() - .file( - "main.tex", - indoc!( - r#" - \begin{foo} - \begin{bar} - Baz - \end{bar} - \end{foo} - "# - ), - ) - .build() - .await; - test_bed.spawn(); - test_bed.initialize(PULL_CAPABILITIES.clone()).await; - test_bed.open("main.tex").await; - - let actual_edit = test_bed - .rename("main.tex", 3, 11, "baz") - .await - .unwrap() - .unwrap(); - - test_bed.shutdown().await; - - let mut expected_changes = HashMap::new(); - expected_changes.insert( - test_bed.uri("main.tex").into(), - vec![ - TextEdit::new(Range::new_simple(1, 11, 1, 14), "baz".into()), - TextEdit::new(Range::new_simple(3, 9, 3, 12), "baz".into()), - ], - ); - - assert_eq!(actual_edit, WorkspaceEdit::new(expected_changes)); -} - -#[tokio::test] -async fn latex_label() { - let mut test_bed = TestBedBuilder::new() - .file( - "foo.tex", - indoc!( - r#" - \input{bar.tex} - \ref{foo,bar} - "# - ), - ) - .file( - "bar.tex", - indoc!( - r#" - \label{foo} - \label{bar} - "# - ), - ) - .build() - .await; - test_bed.spawn(); - test_bed.initialize(PULL_CAPABILITIES.clone()).await; - test_bed.open("foo.tex").await; - test_bed.open("bar.tex").await; - - let actual_edit = test_bed - .rename("foo.tex", 1, 10, "baz") - .await - .unwrap() - .unwrap(); - - test_bed.shutdown().await; - - let mut expected_changes = HashMap::new(); - expected_changes.insert( - test_bed.uri("foo.tex").into(), - vec![TextEdit::new(Range::new_simple(1, 9, 1, 12), "baz".into())], - ); - expected_changes.insert( - test_bed.uri("bar.tex").into(), - vec![TextEdit::new(Range::new_simple(1, 7, 1, 10), "baz".into())], - ); - - assert_eq!(actual_edit, WorkspaceEdit::new(expected_changes)); -} - -#[tokio::test] -async fn unknown_file() { - let mut test_bed = TestBedBuilder::new().build().await; - - test_bed.spawn(); - test_bed.initialize(PULL_CAPABILITIES.clone()).await; - - let actual_edit = test_bed.rename("main.tex", 0, 0, "").await; - - test_bed.shutdown().await; - - assert_eq!(actual_edit, None); -} diff --git a/support/texlab/tests/integration/snapshots/integration__completion__bibtex__command_complete_entry.snap b/support/texlab/tests/integration/snapshots/integration__completion__bibtex__command_complete_entry.snap new file mode 100644 index 0000000000..acd3389f49 --- /dev/null +++ b/support/texlab/tests/integration/snapshots/integration__completion__bibtex__command_complete_entry.snap @@ -0,0 +1,150 @@ +--- +source: tests/integration/completion.rs +expression: "complete_and_resolve(&server, uri, 1, 18)?" + +--- +{ + "isIncomplete": true, + "items": [ + { + "label": "LaTeX", + "kind": 1, + "detail": "built-in", + "preselect": false, + "sortText": "00", + "textEdit": { + "range": { + "start": { + "line": 1, + "character": 15 + }, + "end": { + "line": 1, + "character": 18 + } + }, + "newText": "LaTeX" + } + }, + { + "label": "LaTeXe", + "kind": 1, + "detail": "built-in", + "preselect": false, + "sortText": "01", + "textEdit": { + "range": { + "start": { + "line": 1, + "character": 15 + }, + "end": { + "line": 1, + "character": 18 + } + }, + "newText": "LaTeXe" + } + }, + { + "label": "latexreleaseversion", + "kind": 1, + "detail": "built-in", + "preselect": false, + "sortText": "02", + "textEdit": { + "range": { + "start": { + "line": 1, + "character": 15 + }, + "end": { + "line": 1, + "character": 18 + } + }, + "newText": "latexreleaseversion" + } + }, + { + "label": "LastDeclaredEncoding", + "kind": 1, + "detail": "built-in", + "preselect": false, + "sortText": "03", + "textEdit": { + "range": { + "start": { + "line": 1, + "character": 15 + }, + "end": { + "line": 1, + "character": 18 + } + }, + "newText": "LastDeclaredEncoding" + } + }, + { + "label": "last", + "kind": 1, + "detail": "built-in", + "preselect": false, + "sortText": "04", + "textEdit": { + "range": { + "start": { + "line": 1, + "character": 15 + }, + "end": { + "line": 1, + "character": 18 + } + }, + "newText": "last" + } + }, + { + "label": "lastbox", + "kind": 1, + "detail": "built-in", + "preselect": false, + "sortText": "05", + "textEdit": { + "range": { + "start": { + "line": 1, + "character": 15 + }, + "end": { + "line": 1, + "character": 18 + } + }, + "newText": "lastbox" + } + }, + { + "label": "lastkern", + "kind": 1, + "detail": "built-in", + "preselect": false, + "sortText": "06", + "textEdit": { + "range": { + "start": { + "line": 1, + "character": 15 + }, + "end": { + "line": 1, + "character": 18 + } + }, + "newText": "lastkern" + } + } + ] +} diff --git a/support/texlab/tests/integration/snapshots/integration__completion__bibtex__command_incomplete_entry.snap b/support/texlab/tests/integration/snapshots/integration__completion__bibtex__command_incomplete_entry.snap new file mode 100644 index 0000000000..acd3389f49 --- /dev/null +++ b/support/texlab/tests/integration/snapshots/integration__completion__bibtex__command_incomplete_entry.snap @@ -0,0 +1,150 @@ +--- +source: tests/integration/completion.rs +expression: "complete_and_resolve(&server, uri, 1, 18)?" + +--- +{ + "isIncomplete": true, + "items": [ + { + "label": "LaTeX", + "kind": 1, + "detail": "built-in", + "preselect": false, + "sortText": "00", + "textEdit": { + "range": { + "start": { + "line": 1, + "character": 15 + }, + "end": { + "line": 1, + "character": 18 + } + }, + "newText": "LaTeX" + } + }, + { + "label": "LaTeXe", + "kind": 1, + "detail": "built-in", + "preselect": false, + "sortText": "01", + "textEdit": { + "range": { + "start": { + "line": 1, + "character": 15 + }, + "end": { + "line": 1, + "character": 18 + } + }, + "newText": "LaTeXe" + } + }, + { + "label": "latexreleaseversion", + "kind": 1, + "detail": "built-in", + "preselect": false, + "sortText": "02", + "textEdit": { + "range": { + "start": { + "line": 1, + "character": 15 + }, + "end": { + "line": 1, + "character": 18 + } + }, + "newText": "latexreleaseversion" + } + }, + { + "label": "LastDeclaredEncoding", + "kind": 1, + "detail": "built-in", + "preselect": false, + "sortText": "03", + "textEdit": { + "range": { + "start": { + "line": 1, + "character": 15 + }, + "end": { + "line": 1, + "character": 18 + } + }, + "newText": "LastDeclaredEncoding" + } + }, + { + "label": "last", + "kind": 1, + "detail": "built-in", + "preselect": false, + "sortText": "04", + "textEdit": { + "range": { + "start": { + "line": 1, + "character": 15 + }, + "end": { + "line": 1, + "character": 18 + } + }, + "newText": "last" + } + }, + { + "label": "lastbox", + "kind": 1, + "detail": "built-in", + "preselect": false, + "sortText": "05", + "textEdit": { + "range": { + "start": { + "line": 1, + "character": 15 + }, + "end": { + "line": 1, + "character": 18 + } + }, + "newText": "lastbox" + } + }, + { + "label": "lastkern", + "kind": 1, + "detail": "built-in", + "preselect": false, + "sortText": "06", + "textEdit": { + "range": { + "start": { + "line": 1, + "character": 15 + }, + "end": { + "line": 1, + "character": 18 + } + }, + "newText": "lastkern" + } + } + ] +} diff --git a/support/texlab/tests/integration/snapshots/integration__completion__bibtex__empty_document.snap b/support/texlab/tests/integration/snapshots/integration__completion__bibtex__empty_document.snap new file mode 100644 index 0000000000..7f8638455c --- /dev/null +++ b/support/texlab/tests/integration/snapshots/integration__completion__bibtex__empty_document.snap @@ -0,0 +1,9 @@ +--- +source: tests/integration/completion.rs +expression: "complete_and_resolve(&server, uri, 0, 0)?" + +--- +{ + "isIncomplete": false, + "items": [] +} diff --git a/support/texlab/tests/integration/snapshots/integration__completion__bibtex__entry_type_complete.snap b/support/texlab/tests/integration/snapshots/integration__completion__bibtex__entry_type_complete.snap new file mode 100644 index 0000000000..fdc29dacb4 --- /dev/null +++ b/support/texlab/tests/integration/snapshots/integration__completion__bibtex__entry_type_complete.snap @@ -0,0 +1,33 @@ +--- +source: tests/integration/completion.rs +expression: "complete_and_resolve(&server, uri, 0, 1)?" + +--- +{ + "isIncomplete": false, + "items": [ + { + "label": "article", + "kind": 1, + "documentation": { + "kind": "markdown", + "value": "An article in a journal, magazine, newspaper, or other periodical which forms a \n self-contained unit with its own title. The title of the periodical is given in the \n journaltitle field. If the issue has its own title in addition to the main title of \n the periodical, it goes in the issuetitle field. Note that editor and related \n fields refer to the journal while translator and related fields refer to the article.\n\nRequired fields: `author`, `title`, `journaltitle`, `year/date`" + }, + "preselect": false, + "sortText": "00", + "textEdit": { + "range": { + "start": { + "line": 0, + "character": 1 + }, + "end": { + "line": 0, + "character": 8 + } + }, + "newText": "article" + } + } + ] +} diff --git a/support/texlab/tests/integration/snapshots/integration__completion__bibtex__entry_type_empty_name.snap b/support/texlab/tests/integration/snapshots/integration__completion__bibtex__entry_type_empty_name.snap new file mode 100644 index 0000000000..ad571951ed --- /dev/null +++ b/support/texlab/tests/integration/snapshots/integration__completion__bibtex__entry_type_empty_name.snap @@ -0,0 +1,159 @@ +--- +source: tests/integration/completion.rs +expression: "complete_and_resolve(&server, uri, 0, 1)?" + +--- +{ + "isIncomplete": true, + "items": [ + { + "label": "preamble", + "kind": 1, + "preselect": false, + "sortText": "00", + "textEdit": { + "range": { + "start": { + "line": 0, + "character": 1 + }, + "end": { + "line": 0, + "character": 1 + } + }, + "newText": "preamble" + } + }, + { + "label": "string", + "kind": 1, + "preselect": false, + "sortText": "01", + "textEdit": { + "range": { + "start": { + "line": 0, + "character": 1 + }, + "end": { + "line": 0, + "character": 1 + } + }, + "newText": "string" + } + }, + { + "label": "comment", + "kind": 1, + "preselect": false, + "sortText": "02", + "textEdit": { + "range": { + "start": { + "line": 0, + "character": 1 + }, + "end": { + "line": 0, + "character": 1 + } + }, + "newText": "comment" + } + }, + { + "label": "article", + "kind": 1, + "documentation": { + "kind": "markdown", + "value": "An article in a journal, magazine, newspaper, or other periodical which forms a \n self-contained unit with its own title. The title of the periodical is given in the \n journaltitle field. If the issue has its own title in addition to the main title of \n the periodical, it goes in the issuetitle field. Note that editor and related \n fields refer to the journal while translator and related fields refer to the article.\n\nRequired fields: `author`, `title`, `journaltitle`, `year/date`" + }, + "preselect": false, + "sortText": "03", + "textEdit": { + "range": { + "start": { + "line": 0, + "character": 1 + }, + "end": { + "line": 0, + "character": 1 + } + }, + "newText": "article" + } + }, + { + "label": "book", + "kind": 1, + "documentation": { + "kind": "markdown", + "value": "A single-volume book with one or more authors where the authors share credit for\n the work as a whole. This entry type also covers the function of the `@inbook` type\n of traditional BibTeX.\n\nRequired fields: `author`, `title`, `year/date`" + }, + "preselect": false, + "sortText": "04", + "textEdit": { + "range": { + "start": { + "line": 0, + "character": 1 + }, + "end": { + "line": 0, + "character": 1 + } + }, + "newText": "book" + } + }, + { + "label": "mvbook", + "kind": 1, + "documentation": { + "kind": "markdown", + "value": "A multi-volume `@book`. For backwards compatibility, multi-volume books are also\n supported by the entry type `@book`. However, it is advisable to make use of the\n dedicated entry type `@mvbook`.\n\nRequired fields: `author`, `title`, `year/date`" + }, + "preselect": false, + "sortText": "05", + "textEdit": { + "range": { + "start": { + "line": 0, + "character": 1 + }, + "end": { + "line": 0, + "character": 1 + } + }, + "newText": "mvbook" + } + }, + { + "label": "inbook", + "kind": 1, + "documentation": { + "kind": "markdown", + "value": "A part of a book which forms a self-contained unit with its own title. Note that the\n profile of this entry type is different from standard BibTeX.\n\nRequired fields: `author`, `title`, `booktitle`, `year/date`" + }, + "preselect": false, + "sortText": "06", + "textEdit": { + "range": { + "start": { + "line": 0, + "character": 1 + }, + "end": { + "line": 0, + "character": 1 + } + }, + "newText": "inbook" + } + } + ] +} diff --git a/support/texlab/tests/integration/snapshots/integration__completion__bibtex__entry_type_empty_name_before.snap b/support/texlab/tests/integration/snapshots/integration__completion__bibtex__entry_type_empty_name_before.snap new file mode 100644 index 0000000000..7f8638455c --- /dev/null +++ b/support/texlab/tests/integration/snapshots/integration__completion__bibtex__entry_type_empty_name_before.snap @@ -0,0 +1,9 @@ +--- +source: tests/integration/completion.rs +expression: "complete_and_resolve(&server, uri, 0, 0)?" + +--- +{ + "isIncomplete": false, + "items": [] +} diff --git a/support/texlab/tests/integration/snapshots/integration__completion__bibtex__entry_type_incomplete.snap b/support/texlab/tests/integration/snapshots/integration__completion__bibtex__entry_type_incomplete.snap new file mode 100644 index 0000000000..2f3236bfc4 --- /dev/null +++ b/support/texlab/tests/integration/snapshots/integration__completion__bibtex__entry_type_incomplete.snap @@ -0,0 +1,79 @@ +--- +source: tests/integration/completion.rs +expression: "complete_and_resolve(&server, uri, 0, 1)?" + +--- +{ + "isIncomplete": false, + "items": [ + { + "label": "article", + "kind": 1, + "documentation": { + "kind": "markdown", + "value": "An article in a journal, magazine, newspaper, or other periodical which forms a \n self-contained unit with its own title. The title of the periodical is given in the \n journaltitle field. If the issue has its own title in addition to the main title of \n the periodical, it goes in the issuetitle field. Note that editor and related \n fields refer to the journal while translator and related fields refer to the article.\n\nRequired fields: `author`, `title`, `journaltitle`, `year/date`" + }, + "preselect": false, + "sortText": "00", + "textEdit": { + "range": { + "start": { + "line": 0, + "character": 1 + }, + "end": { + "line": 0, + "character": 4 + } + }, + "newText": "article" + } + }, + { + "label": "artwork", + "kind": 1, + "documentation": { + "kind": "markdown", + "value": "Works of the visual arts such as paintings, sculpture, and installations." + }, + "preselect": false, + "sortText": "01", + "textEdit": { + "range": { + "start": { + "line": 0, + "character": 1 + }, + "end": { + "line": 0, + "character": 4 + } + }, + "newText": "artwork" + } + }, + { + "label": "mastersthesis", + "kind": 1, + "documentation": { + "kind": "markdown", + "value": "Similar to `@thesis` except that the `type` field is optional and defaults to the\n localised term ‘Master’s thesis’. You may still use the `type` field to override that." + }, + "preselect": false, + "sortText": "02", + "textEdit": { + "range": { + "start": { + "line": 0, + "character": 1 + }, + "end": { + "line": 0, + "character": 4 + } + }, + "newText": "mastersthesis" + } + } + ] +} diff --git a/support/texlab/tests/integration/snapshots/integration__completion__bibtex__field_complete_entry.snap b/support/texlab/tests/integration/snapshots/integration__completion__bibtex__field_complete_entry.snap new file mode 100644 index 0000000000..8c6f330647 --- /dev/null +++ b/support/texlab/tests/integration/snapshots/integration__completion__bibtex__field_complete_entry.snap @@ -0,0 +1,171 @@ +--- +source: tests/integration/completion.rs +expression: "complete_and_resolve(&server, uri, 1, 6)?" + +--- +{ + "isIncomplete": false, + "items": [ + { + "label": "title", + "kind": 1, + "documentation": { + "kind": "markdown", + "value": "The title of the work." + }, + "preselect": false, + "sortText": "00", + "textEdit": { + "range": { + "start": { + "line": 1, + "character": 4 + }, + "end": { + "line": 1, + "character": 9 + } + }, + "newText": "title" + } + }, + { + "label": "titleaddon", + "kind": 1, + "documentation": { + "kind": "markdown", + "value": "An annex to the `title`, to be printed in a different font." + }, + "preselect": false, + "sortText": "01", + "textEdit": { + "range": { + "start": { + "line": 1, + "character": 4 + }, + "end": { + "line": 1, + "character": 9 + } + }, + "newText": "titleaddon" + } + }, + { + "label": "booksubtitle", + "kind": 1, + "documentation": { + "kind": "markdown", + "value": "The subtitle related to the `booktitle`. If the subtitle field refers to a work which is part of a larger publication, a possible subtitle of the main work is given in this field. See also `subtitle`." + }, + "preselect": false, + "sortText": "02", + "textEdit": { + "range": { + "start": { + "line": 1, + "character": 4 + }, + "end": { + "line": 1, + "character": 9 + } + }, + "newText": "booksubtitle" + } + }, + { + "label": "booktitle", + "kind": 1, + "documentation": { + "kind": "markdown", + "value": "If the `title` field indicates the title of a work which is part of a larger publication, the title of the main work is given in this field. See also `title`." + }, + "preselect": false, + "sortText": "03", + "textEdit": { + "range": { + "start": { + "line": 1, + "character": 4 + }, + "end": { + "line": 1, + "character": 9 + } + }, + "newText": "booktitle" + } + }, + { + "label": "booktitleaddon", + "kind": 1, + "documentation": { + "kind": "markdown", + "value": "An annex to the `booktitle`, to be printed in a different font." + }, + "preselect": false, + "sortText": "04", + "textEdit": { + "range": { + "start": { + "line": 1, + "character": 4 + }, + "end": { + "line": 1, + "character": 9 + } + }, + "newText": "booktitleaddon" + } + }, + { + "label": "eventtitle", + "kind": 1, + "documentation": { + "kind": "markdown", + "value": "The title of a conference, a symposium, or some other event in `@proceedings` and `@inproceedings` entries. Note that this field holds the plain title of the event. Things like \"Proceedings of the Fifth XYZ Conference\" go into the `titleaddon` or `booktitleaddon` field, respectively. See also `eventdate` and `venue`." + }, + "preselect": false, + "sortText": "05", + "textEdit": { + "range": { + "start": { + "line": 1, + "character": 4 + }, + "end": { + "line": 1, + "character": 9 + } + }, + "newText": "eventtitle" + } + }, + { + "label": "eventtitleaddon", + "kind": 1, + "documentation": { + "kind": "markdown", + "value": "An annex to the `eventtitle` field. Can be used for known event acronyms, for example." + }, + "preselect": false, + "sortText": "06", + "textEdit": { + "range": { + "start": { + "line": 1, + "character": 4 + }, + "end": { + "line": 1, + "character": 9 + } + }, + "newText": "eventtitleaddon" + } + } + ] +} diff --git a/support/texlab/tests/integration/snapshots/integration__completion__bibtex__field_incomplete_entry.snap b/support/texlab/tests/integration/snapshots/integration__completion__bibtex__field_incomplete_entry.snap new file mode 100644 index 0000000000..72e803cd36 --- /dev/null +++ b/support/texlab/tests/integration/snapshots/integration__completion__bibtex__field_incomplete_entry.snap @@ -0,0 +1,171 @@ +--- +source: tests/integration/completion.rs +expression: "complete_and_resolve(&server, uri, 1, 6)?" + +--- +{ + "isIncomplete": false, + "items": [ + { + "label": "title", + "kind": 1, + "documentation": { + "kind": "markdown", + "value": "The title of the work." + }, + "preselect": false, + "sortText": "00", + "textEdit": { + "range": { + "start": { + "line": 1, + "character": 4 + }, + "end": { + "line": 1, + "character": 8 + } + }, + "newText": "title" + } + }, + { + "label": "titleaddon", + "kind": 1, + "documentation": { + "kind": "markdown", + "value": "An annex to the `title`, to be printed in a different font." + }, + "preselect": false, + "sortText": "01", + "textEdit": { + "range": { + "start": { + "line": 1, + "character": 4 + }, + "end": { + "line": 1, + "character": 8 + } + }, + "newText": "titleaddon" + } + }, + { + "label": "booksubtitle", + "kind": 1, + "documentation": { + "kind": "markdown", + "value": "The subtitle related to the `booktitle`. If the subtitle field refers to a work which is part of a larger publication, a possible subtitle of the main work is given in this field. See also `subtitle`." + }, + "preselect": false, + "sortText": "02", + "textEdit": { + "range": { + "start": { + "line": 1, + "character": 4 + }, + "end": { + "line": 1, + "character": 8 + } + }, + "newText": "booksubtitle" + } + }, + { + "label": "booktitle", + "kind": 1, + "documentation": { + "kind": "markdown", + "value": "If the `title` field indicates the title of a work which is part of a larger publication, the title of the main work is given in this field. See also `title`." + }, + "preselect": false, + "sortText": "03", + "textEdit": { + "range": { + "start": { + "line": 1, + "character": 4 + }, + "end": { + "line": 1, + "character": 8 + } + }, + "newText": "booktitle" + } + }, + { + "label": "booktitleaddon", + "kind": 1, + "documentation": { + "kind": "markdown", + "value": "An annex to the `booktitle`, to be printed in a different font." + }, + "preselect": false, + "sortText": "04", + "textEdit": { + "range": { + "start": { + "line": 1, + "character": 4 + }, + "end": { + "line": 1, + "character": 8 + } + }, + "newText": "booktitleaddon" + } + }, + { + "label": "eventtitle", + "kind": 1, + "documentation": { + "kind": "markdown", + "value": "The title of a conference, a symposium, or some other event in `@proceedings` and `@inproceedings` entries. Note that this field holds the plain title of the event. Things like \"Proceedings of the Fifth XYZ Conference\" go into the `titleaddon` or `booktitleaddon` field, respectively. See also `eventdate` and `venue`." + }, + "preselect": false, + "sortText": "05", + "textEdit": { + "range": { + "start": { + "line": 1, + "character": 4 + }, + "end": { + "line": 1, + "character": 8 + } + }, + "newText": "eventtitle" + } + }, + { + "label": "eventtitleaddon", + "kind": 1, + "documentation": { + "kind": "markdown", + "value": "An annex to the `eventtitle` field. Can be used for known event acronyms, for example." + }, + "preselect": false, + "sortText": "06", + "textEdit": { + "range": { + "start": { + "line": 1, + "character": 4 + }, + "end": { + "line": 1, + "character": 8 + } + }, + "newText": "eventtitleaddon" + } + } + ] +} diff --git a/support/texlab/tests/integration/snapshots/integration__completion__bibtex__junk.snap b/support/texlab/tests/integration/snapshots/integration__completion__bibtex__junk.snap new file mode 100644 index 0000000000..7f8638455c --- /dev/null +++ b/support/texlab/tests/integration/snapshots/integration__completion__bibtex__junk.snap @@ -0,0 +1,9 @@ +--- +source: tests/integration/completion.rs +expression: "complete_and_resolve(&server, uri, 0, 0)?" + +--- +{ + "isIncomplete": false, + "items": [] +} diff --git a/support/texlab/tests/integration/snapshots/integration__completion__latex__begin_command.snap b/support/texlab/tests/integration/snapshots/integration__completion__latex__begin_command.snap new file mode 100644 index 0000000000..ab5ea7765b --- /dev/null +++ b/support/texlab/tests/integration/snapshots/integration__completion__latex__begin_command.snap @@ -0,0 +1,162 @@ +--- +source: tests/integration/completion.rs +expression: "complete_and_resolve(&server, uri, 0, 1)?" + +--- +{ + "isIncomplete": true, + "items": [ + { + "label": "begin", + "kind": 1, + "detail": "built-in", + "preselect": false, + "sortText": "00", + "textEdit": { + "range": { + "start": { + "line": 0, + "character": 1 + }, + "end": { + "line": 0, + "character": 2 + } + }, + "newText": "begin" + } + }, + { + "label": "b", + "kind": 1, + "detail": "built-in", + "documentation": { + "kind": "markdown", + "value": "![b](data:image/png;base64,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|width=48,height=48)" + }, + "preselect": false, + "sortText": "01", + "textEdit": { + "range": { + "start": { + "line": 0, + "character": 1 + }, + "end": { + "line": 0, + "character": 2 + } + }, + "newText": "b" + } + }, + { + "label": "backslash", + "kind": 1, + "detail": "\\, built-in", + "documentation": { + "kind": "markdown", + "value": "![backslash](data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABwAAAA6CAIAAAAsmq7oAAADD0lEQVR4nO2Y3Uv6UBzGv5stsyhCiUTRytJIDTMkRUEqhmnbVTf+o9sygqjAi4RIVqlJKWWl1FB6oyLt/C68K9tb5+YHncudw4fnczjbcxiBEALcg8RO/IN+ha6srKTT6ZeXF5xQSZJ2d3fPzs5wQjc2Nlqt1vb29m+O2lcoy7IWiyWTyTw+PmKDer3eUCgkiuLp6Sk26NDQEMMwT09PW1tb+ncAfRuFQsHhcEQiEUmSvs+qGT3O6dTUVDgcLhQKoijqC9oDOjAwwLLs29vb5ubm5+enHmrP/Ofn5y6XKxgMNhoNPPoA4HA4YrFYuVw+PDzUEbQ3tL+/n2GYTqcjCEK73dZM/Unh8vJydnbW5/PVajU8+gBgs9ni8XilUsnlclqD/gjt6+tjWZYgCI7jPj4+tFFlLG5ububn52dmZiqVCh59ABgfH19dXa3VatlsVlNQOajBYFhfX6coiuf59/d3DVR5kbu7u1AoNDExUSqV8OgDgMVioWn69vZ2f39ffVAFKEmSyWRycHCQ5/nX11e1VEWXZrMZjUZtNpsoinj0AWB0dHRtbe3+/n5nZwep+2wrQwmCSCQSIyMjgiCorG5Vlwmv1xsIBI6OjkqlEjbo8PBwMplUX92qoARB0DTdre6Hhwc8UADweDyLi4vHx8dqqlsttFvdz8/PmUxGubjUv3wnJyd2uz0cDitWt4arpMvlWlpaKhaL+XxefqUGqMlk6la3IAidTkduqXp9hFC5XJ6cnFxYWKjX63j0AcDpdEajUcXq1gY1Go3d6uY4Tq66NekjhKrVqtvtnpubu7q6wqMPAHa7PR6PV6vVg4ODn9ZohlIUxTCMQnVr1UcIXV9f+3y+6enpi4sLPPoAYLVal5eXZapbD9RgMDAMQ1EUx3G9q1uHPkKo0WgEg0Gn01ksFvHoA8DY2BhN0/V6fW9v7/usTihJkqlUymQy8Tzfo7j06SOEJEmKRCJWqzWXy+HRBwCz2ZxIJCRJ4nkeW1KEUDabNZvNfr8fW1IA8Pv9sVjMaDR+eU6gvx8z/wX0H6vA4+khaPAcAAAAAElFTkSuQmCC|width=48,height=48)" + }, + "preselect": false, + "sortText": "02", + "textEdit": { + "range": { + "start": { + "line": 0, + "character": 1 + }, + "end": { + "line": 0, + "character": 2 + } + }, + "newText": "backslash" + } + }, + { + "label": "badness", + "kind": 1, + "detail": "built-in", + "preselect": false, + "sortText": "03", + "textEdit": { + "range": { + "start": { + "line": 0, + "character": 1 + }, + "end": { + "line": 0, + "character": 2 + } + }, + "newText": "badness" + } + }, + { + "label": "bar", + "kind": 1, + "detail": " ̄, built-in", + "documentation": { + "kind": "markdown", + "value": "![bar](data:image/png;base64,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|width=48,height=48)" + }, + "preselect": false, + "sortText": "04", + "textEdit": { + "range": { + "start": { + "line": 0, + "character": 1 + }, + "end": { + "line": 0, + "character": 2 + } + }, + "newText": "bar" + } + }, + { + "label": "baselineskip", + "kind": 1, + "detail": "built-in", + "preselect": false, + "sortText": "05", + "textEdit": { + "range": { + "start": { + "line": 0, + "character": 1 + }, + "end": { + "line": 0, + "character": 2 + } + }, + "newText": "baselineskip" + } + }, + { + "label": "baselinestretch", + "kind": 1, + "detail": "built-in", + "preselect": false, + "sortText": "06", + "textEdit": { + "range": { + "start": { + "line": 0, + "character": 1 + }, + "end": { + "line": 0, + "character": 2 + } + }, + "newText": "baselinestretch" + } + } + ] +} diff --git a/support/texlab/tests/integration/snapshots/integration__completion__latex__citation.snap b/support/texlab/tests/integration/snapshots/integration__completion__latex__citation.snap new file mode 100644 index 0000000000..1ccf0206c8 --- /dev/null +++ b/support/texlab/tests/integration/snapshots/integration__completion__latex__citation.snap @@ -0,0 +1,54 @@ +--- +source: tests/integration/completion.rs +expression: "complete_and_resolve(&server, tex_uri, 3, 6)?" + +--- +{ + "isIncomplete": false, + "items": [ + { + "label": "foo:2019", + "kind": 1, + "documentation": { + "kind": "markdown", + "value": "Bar, F. (2019). *Baz Qux*." + }, + "preselect": false, + "sortText": "00 foo:2019 @articlefoo:2019 author Foo Bar title Baz Qux year 2019", + "filterText": "foo:2019 @articlefoo:2019 author Foo Bar title Baz Qux year 2019", + "textEdit": { + "range": { + "start": { + "line": 3, + "character": 6 + }, + "end": { + "line": 3, + "character": 6 + } + }, + "newText": "foo:2019" + } + }, + { + "label": "bar:2005", + "kind": 1, + "preselect": false, + "sortText": "01 bar:2005 @articlebar:2005", + "filterText": "bar:2005 @articlebar:2005", + "textEdit": { + "range": { + "start": { + "line": 3, + "character": 6 + }, + "end": { + "line": 3, + "character": 6 + } + }, + "newText": "bar:2005" + } + } + ] +} diff --git a/support/texlab/tests/integration/snapshots/integration__completion__latex__citation_after.snap b/support/texlab/tests/integration/snapshots/integration__completion__latex__citation_after.snap new file mode 100644 index 0000000000..156b28dc02 --- /dev/null +++ b/support/texlab/tests/integration/snapshots/integration__completion__latex__citation_after.snap @@ -0,0 +1,9 @@ +--- +source: tests/integration/completion.rs +expression: "complete_and_resolve(&server, tex_uri, 3, 7)?" + +--- +{ + "isIncomplete": false, + "items": [] +} diff --git a/support/texlab/tests/integration/snapshots/integration__completion__latex__citation_open_brace.snap b/support/texlab/tests/integration/snapshots/integration__completion__latex__citation_open_brace.snap new file mode 100644 index 0000000000..ba2a1c7ce3 --- /dev/null +++ b/support/texlab/tests/integration/snapshots/integration__completion__latex__citation_open_brace.snap @@ -0,0 +1,34 @@ +--- +source: tests/integration/completion.rs +expression: "complete_and_resolve(&server, tex_uri, 3, 9)?" + +--- +{ + "isIncomplete": false, + "items": [ + { + "label": "FooBar", + "kind": 1, + "documentation": { + "kind": "markdown", + "value": "Bar, F. (2019). *Baz Qux*." + }, + "preselect": false, + "sortText": "00 FooBar @articleFooBar author Foo Bar title Baz Qux year 2019", + "filterText": "FooBar @articleFooBar author Foo Bar title Baz Qux year 2019", + "textEdit": { + "range": { + "start": { + "line": 3, + "character": 6 + }, + "end": { + "line": 3, + "character": 9 + } + }, + "newText": "FooBar" + } + } + ] +} diff --git a/support/texlab/tests/integration/snapshots/integration__completion__latex__class_command.snap b/support/texlab/tests/integration/snapshots/integration__completion__latex__class_command.snap new file mode 100644 index 0000000000..ff214e764a --- /dev/null +++ b/support/texlab/tests/integration/snapshots/integration__completion__latex__class_command.snap @@ -0,0 +1,150 @@ +--- +source: tests/integration/completion.rs +expression: "complete_and_resolve(&server, uri, 2, 5)?" + +--- +{ + "isIncomplete": false, + "items": [ + { + "label": "chaptername", + "kind": 1, + "detail": "book.cls", + "preselect": false, + "sortText": "00", + "textEdit": { + "range": { + "start": { + "line": 2, + "character": 1 + }, + "end": { + "line": 2, + "character": 5 + } + }, + "newText": "chaptername" + } + }, + { + "label": "chaptermark", + "kind": 1, + "detail": "book.cls", + "preselect": false, + "sortText": "01", + "textEdit": { + "range": { + "start": { + "line": 2, + "character": 1 + }, + "end": { + "line": 2, + "character": 5 + } + }, + "newText": "chaptermark" + } + }, + { + "label": "chapter", + "kind": 1, + "detail": "book.cls", + "preselect": false, + "sortText": "02", + "textEdit": { + "range": { + "start": { + "line": 2, + "character": 1 + }, + "end": { + "line": 2, + "character": 5 + } + }, + "newText": "chapter" + } + }, + { + "label": "thechapter", + "kind": 1, + "detail": "book.cls", + "preselect": false, + "sortText": "03", + "textEdit": { + "range": { + "start": { + "line": 2, + "character": 1 + }, + "end": { + "line": 2, + "character": 5 + } + }, + "newText": "thechapter" + } + }, + { + "label": "scshape", + "kind": 1, + "detail": "built-in", + "preselect": false, + "sortText": "04", + "textEdit": { + "range": { + "start": { + "line": 2, + "character": 1 + }, + "end": { + "line": 2, + "character": 5 + } + }, + "newText": "scshape" + } + }, + { + "label": "fontchardp", + "kind": 1, + "detail": "amsmath.sty", + "preselect": false, + "sortText": "05", + "textEdit": { + "range": { + "start": { + "line": 2, + "character": 1 + }, + "end": { + "line": 2, + "character": 5 + } + }, + "newText": "fontchardp" + } + }, + { + "label": "XeTeXcharglyph", + "kind": 1, + "detail": "built-in", + "preselect": false, + "sortText": "06", + "textEdit": { + "range": { + "start": { + "line": 2, + "character": 1 + }, + "end": { + "line": 2, + "character": 5 + } + }, + "newText": "XeTeXcharglyph" + } + } + ] +} diff --git a/support/texlab/tests/integration/snapshots/integration__completion__latex__class_environment.snap b/support/texlab/tests/integration/snapshots/integration__completion__latex__class_environment.snap new file mode 100644 index 0000000000..c893498077 --- /dev/null +++ b/support/texlab/tests/integration/snapshots/integration__completion__latex__class_environment.snap @@ -0,0 +1,30 @@ +--- +source: tests/integration/completion.rs +expression: "complete_and_resolve(&server, uri, 4, 13)?" + +--- +{ + "isIncomplete": false, + "items": [ + { + "label": "theindex", + "kind": 1, + "detail": "book.cls", + "preselect": false, + "sortText": "00", + "textEdit": { + "range": { + "start": { + "line": 4, + "character": 7 + }, + "end": { + "line": 4, + "character": 13 + } + }, + "newText": "theindex" + } + } + ] +} diff --git a/support/texlab/tests/integration/snapshots/integration__completion__latex__class_import.snap b/support/texlab/tests/integration/snapshots/integration__completion__latex__class_import.snap new file mode 100644 index 0000000000..baf1218114 --- /dev/null +++ b/support/texlab/tests/integration/snapshots/integration__completion__latex__class_import.snap @@ -0,0 +1,171 @@ +--- +source: tests/integration/completion.rs +expression: "complete_and_resolve(&server, uri, 0, 19)?" + +--- +{ + "isIncomplete": false, + "items": [ + { + "label": "book", + "kind": 1, + "documentation": { + "kind": "plaintext", + "value": "LaTeX is a widely-used macro package for TeX, providing many basic document formating commands extended by a wide range of packages. It is a development of Leslie Lamport's LaTeX 2.09, and superseded the older system in June 1994. The basic distribution is catalogued separately, at latex-base; apart from a large set of contributed packages and third-party documentation (elsewhere on the archive), the distribution includes: - a bunch of required packages, which LaTeX authors are \"entitled to assume\" will be present on any system running LaTeX; and - a minimal set of documentation detailing differences from the 'old' version of LaTeX in the areas of user commands, font selection and control, class and package writing, font encodings, configuration options and modification of LaTeX. For downloading details, see the linked catalogue entries above." + }, + "preselect": false, + "sortText": "00", + "textEdit": { + "range": { + "start": { + "line": 0, + "character": 15 + }, + "end": { + "line": 0, + "character": 19 + } + }, + "newText": "book" + } + }, + { + "label": "bookcover", + "kind": 1, + "documentation": { + "kind": "plaintext", + "value": "This class helps typesetting book covers and dust jackets." + }, + "preselect": false, + "sortText": "01", + "textEdit": { + "range": { + "start": { + "line": 0, + "character": 15 + }, + "end": { + "line": 0, + "character": 19 + } + }, + "newText": "bookcover" + } + }, + { + "label": "bookest", + "kind": 1, + "documentation": { + "kind": "plaintext", + "value": "The class extends the standard book class, in the areas of colour scheme management, document layout, headings and footers, front page layout, and other minor items." + }, + "preselect": false, + "sortText": "02", + "textEdit": { + "range": { + "start": { + "line": 0, + "character": 15 + }, + "end": { + "line": 0, + "character": 19 + } + }, + "newText": "bookest" + } + }, + { + "label": "bbook", + "kind": 1, + "documentation": { + "kind": "plaintext", + "value": "The bundle provides class files for writing Bangla and Assamese with LaTeX, and Metafont sources for fonts." + }, + "preselect": false, + "sortText": "03", + "textEdit": { + "range": { + "start": { + "line": 0, + "character": 15 + }, + "end": { + "line": 0, + "character": 19 + } + }, + "newText": "bbook" + } + }, + { + "label": "basque-book", + "kind": 1, + "documentation": { + "kind": "plaintext", + "value": "The class is derived from the LaTeX book class. The extensions solve grammatical and numeration issues that occur when book-type documents are written in Basque. The class is useful for writing books, PhD and Master Theses, etc., in Basque." + }, + "preselect": false, + "sortText": "04", + "textEdit": { + "range": { + "start": { + "line": 0, + "character": 15 + }, + "end": { + "line": 0, + "character": 19 + } + }, + "newText": "basque-book" + } + }, + { + "label": "caesar_book", + "kind": 1, + "documentation": { + "kind": "plaintext", + "value": "The package allows typesetting of texts with notes, figures, citations, captions and tables in the margin. This is common (for example) in science text books." + }, + "preselect": false, + "sortText": "05", + "textEdit": { + "range": { + "start": { + "line": 0, + "character": 15 + }, + "end": { + "line": 0, + "character": 19 + } + }, + "newText": "caesar_book" + } + }, + { + "label": "tufte-book", + "kind": 1, + "documentation": { + "kind": "plaintext", + "value": "Provided are two classes inspired, respectively, by handouts and books created by Edward Tufte." + }, + "preselect": false, + "sortText": "06", + "textEdit": { + "range": { + "start": { + "line": 0, + "character": 15 + }, + "end": { + "line": 0, + "character": 19 + } + }, + "newText": "tufte-book" + } + } + ] +} diff --git a/support/texlab/tests/integration/snapshots/integration__completion__latex__color_model_define_color.snap b/support/texlab/tests/integration/snapshots/integration__completion__latex__color_model_define_color.snap new file mode 100644 index 0000000000..5385f5c646 --- /dev/null +++ b/support/texlab/tests/integration/snapshots/integration__completion__latex__color_model_define_color.snap @@ -0,0 +1,105 @@ +--- +source: tests/integration/completion.rs +expression: "complete_and_resolve(&server, uri, 1, 18)?" + +--- +{ + "isIncomplete": false, + "items": [ + { + "label": "gray", + "kind": 1, + "preselect": false, + "sortText": "00", + "textEdit": { + "range": { + "start": { + "line": 1, + "character": 18 + }, + "end": { + "line": 1, + "character": 18 + } + }, + "newText": "gray" + } + }, + { + "label": "rgb", + "kind": 1, + "preselect": false, + "sortText": "01", + "textEdit": { + "range": { + "start": { + "line": 1, + "character": 18 + }, + "end": { + "line": 1, + "character": 18 + } + }, + "newText": "rgb" + } + }, + { + "label": "RGB", + "kind": 1, + "preselect": false, + "sortText": "02", + "textEdit": { + "range": { + "start": { + "line": 1, + "character": 18 + }, + "end": { + "line": 1, + "character": 18 + } + }, + "newText": "RGB" + } + }, + { + "label": "HTML", + "kind": 1, + "preselect": false, + "sortText": "03", + "textEdit": { + "range": { + "start": { + "line": 1, + "character": 18 + }, + "end": { + "line": 1, + "character": 18 + } + }, + "newText": "HTML" + } + }, + { + "label": "cmyk", + "kind": 1, + "preselect": false, + "sortText": "04", + "textEdit": { + "range": { + "start": { + "line": 1, + "character": 18 + }, + "end": { + "line": 1, + "character": 18 + } + }, + "newText": "cmyk" + } + } + ] +} diff --git a/support/texlab/tests/integration/snapshots/integration__completion__latex__color_model_define_color_set.snap b/support/texlab/tests/integration/snapshots/integration__completion__latex__color_model_define_color_set.snap new file mode 100644 index 0000000000..7e6f4a1de6 --- /dev/null +++ b/support/texlab/tests/integration/snapshots/integration__completion__latex__color_model_define_color_set.snap @@ -0,0 +1,67 @@ +--- +source: tests/integration/completion.rs +expression: "complete_and_resolve(&server, uri, 2, 17)?" + +--- +{ + "isIncomplete": false, + "items": [ + { + "label": "RGB", + "kind": 1, + "preselect": false, + "sortText": "00", + "textEdit": { + "range": { + "start": { + "line": 2, + "character": 16 + }, + "end": { + "line": 2, + "character": 17 + } + }, + "newText": "RGB" + } + }, + { + "label": "rgb", + "kind": 1, + "preselect": false, + "sortText": "01", + "textEdit": { + "range": { + "start": { + "line": 2, + "character": 16 + }, + "end": { + "line": 2, + "character": 17 + } + }, + "newText": "rgb" + } + }, + { + "label": "gray", + "kind": 1, + "preselect": false, + "sortText": "02", + "textEdit": { + "range": { + "start": { + "line": 2, + "character": 16 + }, + "end": { + "line": 2, + "character": 17 + } + }, + "newText": "gray" + } + } + ] +} diff --git a/support/texlab/tests/integration/snapshots/integration__completion__latex__color_name.snap b/support/texlab/tests/integration/snapshots/integration__completion__latex__color_name.snap new file mode 100644 index 0000000000..b34b32f5ac --- /dev/null +++ b/support/texlab/tests/integration/snapshots/integration__completion__latex__color_name.snap @@ -0,0 +1,143 @@ +--- +source: tests/integration/completion.rs +expression: "complete_and_resolve(&server, uri, 0, 9)?" + +--- +{ + "isIncomplete": false, + "items": [ + { + "label": "red", + "kind": 1, + "preselect": false, + "sortText": "00", + "textEdit": { + "range": { + "start": { + "line": 0, + "character": 7 + }, + "end": { + "line": 0, + "character": 9 + } + }, + "newText": "red" + } + }, + { + "label": "RedOrange", + "kind": 1, + "preselect": false, + "sortText": "01", + "textEdit": { + "range": { + "start": { + "line": 0, + "character": 7 + }, + "end": { + "line": 0, + "character": 9 + } + }, + "newText": "RedOrange" + } + }, + { + "label": "Red", + "kind": 1, + "preselect": false, + "sortText": "02", + "textEdit": { + "range": { + "start": { + "line": 0, + "character": 7 + }, + "end": { + "line": 0, + "character": 9 + } + }, + "newText": "Red" + } + }, + { + "label": "RedViolet", + "kind": 1, + "preselect": false, + "sortText": "03", + "textEdit": { + "range": { + "start": { + "line": 0, + "character": 7 + }, + "end": { + "line": 0, + "character": 9 + } + }, + "newText": "RedViolet" + } + }, + { + "label": "OrangeRed", + "kind": 1, + "preselect": false, + "sortText": "04", + "textEdit": { + "range": { + "start": { + "line": 0, + "character": 7 + }, + "end": { + "line": 0, + "character": 9 + } + }, + "newText": "OrangeRed" + } + }, + { + "label": "VioletRed", + "kind": 1, + "preselect": false, + "sortText": "05", + "textEdit": { + "range": { + "start": { + "line": 0, + "character": 7 + }, + "end": { + "line": 0, + "character": 9 + } + }, + "newText": "VioletRed" + } + }, + { + "label": "BrickRed", + "kind": 1, + "preselect": false, + "sortText": "06", + "textEdit": { + "range": { + "start": { + "line": 0, + "character": 7 + }, + "end": { + "line": 0, + "character": 9 + } + }, + "newText": "BrickRed" + } + } + ] +} diff --git a/support/texlab/tests/integration/snapshots/integration__completion__latex__empty_document.snap b/support/texlab/tests/integration/snapshots/integration__completion__latex__empty_document.snap new file mode 100644 index 0000000000..7f8638455c --- /dev/null +++ b/support/texlab/tests/integration/snapshots/integration__completion__latex__empty_document.snap @@ -0,0 +1,9 @@ +--- +source: tests/integration/completion.rs +expression: "complete_and_resolve(&server, uri, 0, 0)?" + +--- +{ + "isIncomplete": false, + "items": [] +} diff --git a/support/texlab/tests/integration/snapshots/integration__completion__latex__kernel_command.snap b/support/texlab/tests/integration/snapshots/integration__completion__latex__kernel_command.snap new file mode 100644 index 0000000000..49f65f06ca --- /dev/null +++ b/support/texlab/tests/integration/snapshots/integration__completion__latex__kernel_command.snap @@ -0,0 +1,30 @@ +--- +source: tests/integration/completion.rs +expression: "complete_and_resolve(&server, uri, 0, 1)?" + +--- +{ + "isIncomplete": false, + "items": [ + { + "label": "documentclass", + "kind": 1, + "detail": "built-in", + "preselect": false, + "sortText": "00", + "textEdit": { + "range": { + "start": { + "line": 0, + "character": 1 + }, + "end": { + "line": 0, + "character": 14 + } + }, + "newText": "documentclass" + } + } + ] +} diff --git a/support/texlab/tests/integration/snapshots/integration__completion__latex__kernel_command_environment.snap b/support/texlab/tests/integration/snapshots/integration__completion__latex__kernel_command_environment.snap new file mode 100644 index 0000000000..8d01ea7b8d --- /dev/null +++ b/support/texlab/tests/integration/snapshots/integration__completion__latex__kernel_command_environment.snap @@ -0,0 +1,30 @@ +--- +source: tests/integration/completion.rs +expression: "complete_and_resolve(&server, uri, 6, 10)?" + +--- +{ + "isIncomplete": false, + "items": [ + { + "label": "document", + "kind": 1, + "detail": "built-in", + "preselect": false, + "sortText": "00", + "textEdit": { + "range": { + "start": { + "line": 6, + "character": 7 + }, + "end": { + "line": 6, + "character": 10 + } + }, + "newText": "document" + } + } + ] +} diff --git a/support/texlab/tests/integration/snapshots/integration__completion__latex__kernel_command_glyph.snap b/support/texlab/tests/integration/snapshots/integration__completion__latex__kernel_command_glyph.snap new file mode 100644 index 0000000000..293b190176 --- /dev/null +++ b/support/texlab/tests/integration/snapshots/integration__completion__latex__kernel_command_glyph.snap @@ -0,0 +1,34 @@ +--- +source: tests/integration/completion.rs +expression: "complete_and_resolve(&server, uri, 7, 7)?" + +--- +{ + "isIncomplete": false, + "items": [ + { + "label": "varepsilon", + "kind": 1, + "detail": "ε, built-in", + "documentation": { + "kind": "markdown", + "value": "![varepsilon](data:image/png;base64,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|width=48,height=48)" + }, + "preselect": false, + "sortText": "00", + "textEdit": { + "range": { + "start": { + "line": 7, + "character": 1 + }, + "end": { + "line": 7, + "character": 7 + } + }, + "newText": "varepsilon" + } + } + ] +} diff --git a/support/texlab/tests/integration/snapshots/integration__completion__latex__label.snap b/support/texlab/tests/integration/snapshots/integration__completion__latex__label.snap new file mode 100644 index 0000000000..efcaa02ce1 --- /dev/null +++ b/support/texlab/tests/integration/snapshots/integration__completion__latex__label.snap @@ -0,0 +1,137 @@ +--- +source: tests/integration/completion.rs +expression: "complete_and_resolve(&server, uri, 4, 5)?" + +--- +{ + "isIncomplete": false, + "items": [ + { + "label": "sec:bar", + "kind": 1, + "detail": "Section 2 (Bar)", + "preselect": false, + "sortText": "00 sec:bar Section 2 (Bar)", + "filterText": "sec:bar Section 2 (Bar)", + "textEdit": { + "range": { + "start": { + "line": 4, + "character": 5 + }, + "end": { + "line": 4, + "character": 5 + } + }, + "newText": "sec:bar" + } + }, + { + "label": "sec:foo", + "kind": 1, + "detail": "Section 1 (Foo)", + "preselect": false, + "sortText": "01 sec:foo Section 1 (Foo)", + "filterText": "sec:foo Section 1 (Foo)", + "textEdit": { + "range": { + "start": { + "line": 4, + "character": 5 + }, + "end": { + "line": 4, + "character": 5 + } + }, + "newText": "sec:foo" + } + }, + { + "label": "eq:foo", + "kind": 1, + "detail": "Equation (1)", + "preselect": false, + "sortText": "02 eq:foo Equation (1)", + "filterText": "eq:foo Equation (1)", + "textEdit": { + "range": { + "start": { + "line": 4, + "character": 5 + }, + "end": { + "line": 4, + "character": 5 + } + }, + "newText": "eq:foo" + } + }, + { + "label": "eq:bar", + "kind": 1, + "detail": "Equation (2)", + "preselect": false, + "sortText": "03 eq:bar Equation (2)", + "filterText": "eq:bar Equation (2)", + "textEdit": { + "range": { + "start": { + "line": 4, + "character": 5 + }, + "end": { + "line": 4, + "character": 5 + } + }, + "newText": "eq:bar" + } + }, + { + "label": "fig:baz", + "kind": 1, + "detail": "Figure 1", + "documentation": "Baz", + "preselect": false, + "sortText": "04 fig:baz Figure 1: Baz", + "filterText": "fig:baz Figure 1: Baz", + "textEdit": { + "range": { + "start": { + "line": 4, + "character": 5 + }, + "end": { + "line": 4, + "character": 5 + } + }, + "newText": "fig:baz" + } + }, + { + "label": "thm:foo", + "kind": 1, + "detail": "Lemma 1", + "preselect": false, + "sortText": "05 thm:foo Lemma 1", + "filterText": "thm:foo Lemma 1", + "textEdit": { + "range": { + "start": { + "line": 4, + "character": 5 + }, + "end": { + "line": 4, + "character": 5 + } + }, + "newText": "thm:foo" + } + } + ] +} diff --git a/support/texlab/tests/integration/snapshots/integration__completion__latex__package_command.snap b/support/texlab/tests/integration/snapshots/integration__completion__latex__package_command.snap new file mode 100644 index 0000000000..6a260fe387 --- /dev/null +++ b/support/texlab/tests/integration/snapshots/integration__completion__latex__package_command.snap @@ -0,0 +1,34 @@ +--- +source: tests/integration/completion.rs +expression: "complete_and_resolve(&server, uri, 3, 7)?" + +--- +{ + "isIncomplete": false, + "items": [ + { + "label": "varDelta", + "kind": 1, + "detail": "amsmath.sty", + "documentation": { + "kind": "markdown", + "value": "![varDelta](data:image/png;base64,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|width=48,height=48)" + }, + "preselect": false, + "sortText": "00", + "textEdit": { + "range": { + "start": { + "line": 3, + "character": 1 + }, + "end": { + "line": 3, + "character": 7 + } + }, + "newText": "varDelta" + } + } + ] +} diff --git a/support/texlab/tests/integration/snapshots/integration__completion__latex__package_environment.snap b/support/texlab/tests/integration/snapshots/integration__completion__latex__package_environment.snap new file mode 100644 index 0000000000..7dbe95a81b --- /dev/null +++ b/support/texlab/tests/integration/snapshots/integration__completion__latex__package_environment.snap @@ -0,0 +1,150 @@ +--- +source: tests/integration/completion.rs +expression: "complete_and_resolve(&server, uri, 5, 5)?" + +--- +{ + "isIncomplete": false, + "items": [ + { + "label": "alignedat", + "kind": 1, + "detail": "amsmath.sty", + "preselect": false, + "sortText": "00", + "textEdit": { + "range": { + "start": { + "line": 5, + "character": 5 + }, + "end": { + "line": 5, + "character": 9 + } + }, + "newText": "alignedat" + } + }, + { + "label": "aligned", + "kind": 1, + "detail": "amsmath.sty", + "preselect": false, + "sortText": "01", + "textEdit": { + "range": { + "start": { + "line": 5, + "character": 5 + }, + "end": { + "line": 5, + "character": 9 + } + }, + "newText": "aligned" + } + }, + { + "label": "alignat", + "kind": 1, + "detail": "amsmath.sty", + "preselect": false, + "sortText": "02", + "textEdit": { + "range": { + "start": { + "line": 5, + "character": 5 + }, + "end": { + "line": 5, + "character": 9 + } + }, + "newText": "alignat" + } + }, + { + "label": "align", + "kind": 1, + "detail": "amsmath.sty", + "preselect": false, + "sortText": "03", + "textEdit": { + "range": { + "start": { + "line": 5, + "character": 5 + }, + "end": { + "line": 5, + "character": 9 + } + }, + "newText": "align" + } + }, + { + "label": "align*", + "kind": 1, + "detail": "amsmath.sty", + "preselect": false, + "sortText": "04", + "textEdit": { + "range": { + "start": { + "line": 5, + "character": 5 + }, + "end": { + "line": 5, + "character": 9 + } + }, + "newText": "align*" + } + }, + { + "label": "alignat*", + "kind": 1, + "detail": "amsmath.sty", + "preselect": false, + "sortText": "05", + "textEdit": { + "range": { + "start": { + "line": 5, + "character": 5 + }, + "end": { + "line": 5, + "character": 9 + } + }, + "newText": "alignat*" + } + }, + { + "label": "flalign", + "kind": 1, + "detail": "amsmath.sty", + "preselect": false, + "sortText": "06", + "textEdit": { + "range": { + "start": { + "line": 5, + "character": 5 + }, + "end": { + "line": 5, + "character": 9 + } + }, + "newText": "flalign" + } + } + ] +} diff --git a/support/texlab/tests/integration/snapshots/integration__completion__latex__package_import.snap b/support/texlab/tests/integration/snapshots/integration__completion__latex__package_import.snap new file mode 100644 index 0000000000..992ea91692 --- /dev/null +++ b/support/texlab/tests/integration/snapshots/integration__completion__latex__package_import.snap @@ -0,0 +1,102 @@ +--- +source: tests/integration/completion.rs +expression: "complete_and_resolve(&server, uri, 1, 15)?" + +--- +{ + "isIncomplete": false, + "items": [ + { + "label": "amsmath", + "kind": 1, + "documentation": { + "kind": "plaintext", + "value": "The package provides the principal packages in the AMS-LaTeX distribution. It adapts for use in LaTeX most of the mathematical features found in AMS-TeX; it is highly recommended as an adjunct to serious mathematical typesetting in LaTeX. When amsmath is loaded, AMS-LaTeX packages amsbsy (for bold symbols), amsopn (for operator names) and amstext (for text embedded in mathematics) are also loaded. amsmath is part of the LaTeX required distribution; however, several contributed packages add still further to its appeal; examples are empheq, which provides functions for decorating and highlighting mathematics, and ntheorem, for specifying theorem (and similar) definitions." + }, + "preselect": false, + "sortText": "00", + "textEdit": { + "range": { + "start": { + "line": 1, + "character": 12 + }, + "end": { + "line": 1, + "character": 19 + } + }, + "newText": "amsmath" + } + }, + { + "label": "lwarp-amsmath", + "kind": 1, + "documentation": { + "kind": "plaintext", + "value": "This package converts LaTeX to HTML by using LaTeX to process the user's document and generate HTML tags. External utility programs are only used for the final conversion of text and images. Math may be represented by SVG files or MathJax. Hundreds of LaTeX packages are supported, and their load order is automatically verified. Documents may be produced by LaTeX, LuaLaTeX, XeLaTeX, and by several CJK engines, classes, and packages. A texlua script automates compilation, index, glossary, and batch image processing, and also supports latexmk. Configuration is semi-automatic at the first manual compile. Support files are self-generated. Print and HTML versions of each document may coexist. Assistance is provided for HTML import into EPUB conversion software and word processors. Requirements include the commonly-available Poppler utilities, and Perl. Detailed installation instructions are included for each of the major operating systems and TeX distributions. A quick-start tutorial is provided." + }, + "preselect": false, + "sortText": "01", + "textEdit": { + "range": { + "start": { + "line": 1, + "character": 12 + }, + "end": { + "line": 1, + "character": 19 + } + }, + "newText": "lwarp-amsmath" + } + }, + { + "label": "simurgh-amsmath", + "kind": 1, + "documentation": { + "kind": "plaintext", + "value": "The package provides an automatic and unified interface for Parsi typesetting in LaTeX, using the LuaTeX engine. The project to produce this system is dedicated to Ferdowsi The Great." + }, + "preselect": false, + "sortText": "02", + "textEdit": { + "range": { + "start": { + "line": 1, + "character": 12 + }, + "end": { + "line": 1, + "character": 19 + } + }, + "newText": "simurgh-amsmath" + } + }, + { + "label": "onlyamsmath", + "kind": 1, + "documentation": { + "kind": "plaintext", + "value": "This package inhibits the usage of plain TeX and (on demand) of standard LaTeX mathematics environments. This is useful for class writers who want to encourage their users to use the environments provided by the amsmath package." + }, + "preselect": false, + "sortText": "03", + "textEdit": { + "range": { + "start": { + "line": 1, + "character": 12 + }, + "end": { + "line": 1, + "character": 19 + } + }, + "newText": "onlyamsmath" + } + } + ] +} diff --git a/support/texlab/tests/integration/snapshots/integration__completion__latex__pgf_library.snap b/support/texlab/tests/integration/snapshots/integration__completion__latex__pgf_library.snap new file mode 100644 index 0000000000..da34563c8d --- /dev/null +++ b/support/texlab/tests/integration/snapshots/integration__completion__latex__pgf_library.snap @@ -0,0 +1,143 @@ +--- +source: tests/integration/completion.rs +expression: "complete_and_resolve(&server, uri, 1, 15)?" + +--- +{ + "isIncomplete": false, + "items": [ + { + "label": "arrows", + "kind": 1, + "preselect": false, + "sortText": "00", + "textEdit": { + "range": { + "start": { + "line": 1, + "character": 15 + }, + "end": { + "line": 1, + "character": 15 + } + }, + "newText": "arrows" + } + }, + { + "label": "arrows.meta", + "kind": 1, + "preselect": false, + "sortText": "01", + "textEdit": { + "range": { + "start": { + "line": 1, + "character": 15 + }, + "end": { + "line": 1, + "character": 15 + } + }, + "newText": "arrows.meta" + } + }, + { + "label": "arrows.spaced", + "kind": 1, + "preselect": false, + "sortText": "02", + "textEdit": { + "range": { + "start": { + "line": 1, + "character": 15 + }, + "end": { + "line": 1, + "character": 15 + } + }, + "newText": "arrows.spaced" + } + }, + { + "label": "curvilinear", + "kind": 1, + "preselect": false, + "sortText": "03", + "textEdit": { + "range": { + "start": { + "line": 1, + "character": 15 + }, + "end": { + "line": 1, + "character": 15 + } + }, + "newText": "curvilinear" + } + }, + { + "label": "datavisualization.barcharts", + "kind": 1, + "preselect": false, + "sortText": "04", + "textEdit": { + "range": { + "start": { + "line": 1, + "character": 15 + }, + "end": { + "line": 1, + "character": 15 + } + }, + "newText": "datavisualization.barcharts" + } + }, + { + "label": "datavisualization.formats.functions", + "kind": 1, + "preselect": false, + "sortText": "05", + "textEdit": { + "range": { + "start": { + "line": 1, + "character": 15 + }, + "end": { + "line": 1, + "character": 15 + } + }, + "newText": "datavisualization.formats.functions" + } + }, + { + "label": "datavisualization.polar", + "kind": 1, + "preselect": false, + "sortText": "06", + "textEdit": { + "range": { + "start": { + "line": 1, + "character": 15 + }, + "end": { + "line": 1, + "character": 15 + } + }, + "newText": "datavisualization.polar" + } + } + ] +} diff --git a/support/texlab/tests/integration/snapshots/integration__completion__latex__preselect_environment.snap b/support/texlab/tests/integration/snapshots/integration__completion__latex__preselect_environment.snap new file mode 100644 index 0000000000..791f045476 --- /dev/null +++ b/support/texlab/tests/integration/snapshots/integration__completion__latex__preselect_environment.snap @@ -0,0 +1,150 @@ +--- +source: tests/integration/completion.rs +expression: "complete_and_resolve(&server, uri, 1, 5)?" + +--- +{ + "isIncomplete": false, + "items": [ + { + "label": "document", + "kind": 1, + "detail": "built-in", + "preselect": true, + "sortText": "00", + "textEdit": { + "range": { + "start": { + "line": 1, + "character": 5 + }, + "end": { + "line": 1, + "character": 5 + } + }, + "newText": "document" + } + }, + { + "label": "abstract", + "kind": 1, + "detail": "built-in", + "preselect": false, + "sortText": "01", + "textEdit": { + "range": { + "start": { + "line": 1, + "character": 5 + }, + "end": { + "line": 1, + "character": 5 + } + }, + "newText": "abstract" + } + }, + { + "label": "array", + "kind": 1, + "detail": "built-in", + "preselect": false, + "sortText": "02", + "textEdit": { + "range": { + "start": { + "line": 1, + "character": 5 + }, + "end": { + "line": 1, + "character": 5 + } + }, + "newText": "array" + } + }, + { + "label": "center", + "kind": 1, + "detail": "built-in", + "preselect": false, + "sortText": "03", + "textEdit": { + "range": { + "start": { + "line": 1, + "character": 5 + }, + "end": { + "line": 1, + "character": 5 + } + }, + "newText": "center" + } + }, + { + "label": "csname", + "kind": 1, + "detail": "built-in", + "preselect": false, + "sortText": "04", + "textEdit": { + "range": { + "start": { + "line": 1, + "character": 5 + }, + "end": { + "line": 1, + "character": 5 + } + }, + "newText": "csname" + } + }, + { + "label": "description", + "kind": 1, + "detail": "built-in", + "preselect": false, + "sortText": "05", + "textEdit": { + "range": { + "start": { + "line": 1, + "character": 5 + }, + "end": { + "line": 1, + "character": 5 + } + }, + "newText": "description" + } + }, + { + "label": "displaymath", + "kind": 1, + "detail": "built-in", + "preselect": false, + "sortText": "06", + "textEdit": { + "range": { + "start": { + "line": 1, + "character": 5 + }, + "end": { + "line": 1, + "character": 5 + } + }, + "newText": "displaymath" + } + } + ] +} diff --git a/support/texlab/tests/integration/snapshots/integration__completion__latex__theorem_environment.snap b/support/texlab/tests/integration/snapshots/integration__completion__latex__theorem_environment.snap new file mode 100644 index 0000000000..cc0b336e9f --- /dev/null +++ b/support/texlab/tests/integration/snapshots/integration__completion__latex__theorem_environment.snap @@ -0,0 +1,130 @@ +--- +source: tests/integration/completion.rs +expression: "complete_and_resolve(&server, uri, 3, 7)?" + +--- +{ + "isIncomplete": false, + "items": [ + { + "label": "figure", + "kind": 1, + "detail": "built-in", + "preselect": false, + "sortText": "00", + "textEdit": { + "range": { + "start": { + "line": 3, + "character": 7 + }, + "end": { + "line": 3, + "character": 8 + } + }, + "newText": "figure" + } + }, + { + "label": "filecontents", + "kind": 1, + "detail": "built-in", + "preselect": false, + "sortText": "01", + "textEdit": { + "range": { + "start": { + "line": 3, + "character": 7 + }, + "end": { + "line": 3, + "character": 8 + } + }, + "newText": "filecontents" + } + }, + { + "label": "flushleft", + "kind": 1, + "detail": "built-in", + "preselect": false, + "sortText": "02", + "textEdit": { + "range": { + "start": { + "line": 3, + "character": 7 + }, + "end": { + "line": 3, + "character": 8 + } + }, + "newText": "flushleft" + } + }, + { + "label": "flushright", + "kind": 1, + "detail": "built-in", + "preselect": false, + "sortText": "03", + "textEdit": { + "range": { + "start": { + "line": 3, + "character": 7 + }, + "end": { + "line": 3, + "character": 8 + } + }, + "newText": "flushright" + } + }, + { + "label": "foo", + "kind": 1, + "detail": "user-defined", + "preselect": false, + "sortText": "04", + "textEdit": { + "range": { + "start": { + "line": 3, + "character": 7 + }, + "end": { + "line": 3, + "character": 8 + } + }, + "newText": "foo" + } + }, + { + "label": "proof", + "kind": 1, + "detail": "amsthm.sty", + "preselect": false, + "sortText": "05", + "textEdit": { + "range": { + "start": { + "line": 3, + "character": 7 + }, + "end": { + "line": 3, + "character": 8 + } + }, + "newText": "proof" + } + } + ] +} diff --git a/support/texlab/tests/integration/snapshots/integration__completion__latex__user_command.snap b/support/texlab/tests/integration/snapshots/integration__completion__latex__user_command.snap new file mode 100644 index 0000000000..f2f2eef4a5 --- /dev/null +++ b/support/texlab/tests/integration/snapshots/integration__completion__latex__user_command.snap @@ -0,0 +1,30 @@ +--- +source: tests/integration/completion.rs +expression: "complete_and_resolve(&server, uri, 1, 3)?" + +--- +{ + "isIncomplete": false, + "items": [ + { + "label": "foobar", + "kind": 1, + "detail": "user-defined", + "preselect": false, + "sortText": "00", + "textEdit": { + "range": { + "start": { + "line": 1, + "character": 1 + }, + "end": { + "line": 1, + "character": 6 + } + }, + "newText": "foobar" + } + } + ] +} diff --git a/support/texlab/tests/integration/snapshots/integration__completion__latex__user_environment.snap b/support/texlab/tests/integration/snapshots/integration__completion__latex__user_environment.snap new file mode 100644 index 0000000000..0f85b3fa56 --- /dev/null +++ b/support/texlab/tests/integration/snapshots/integration__completion__latex__user_environment.snap @@ -0,0 +1,50 @@ +--- +source: tests/integration/completion.rs +expression: "complete_and_resolve(&server, uri, 4, 7)?" + +--- +{ + "isIncomplete": false, + "items": [ + { + "label": "foo", + "kind": 1, + "detail": "user-defined", + "preselect": false, + "sortText": "00", + "textEdit": { + "range": { + "start": { + "line": 4, + "character": 7 + }, + "end": { + "line": 4, + "character": 9 + } + }, + "newText": "foo" + } + }, + { + "label": "filecontents", + "kind": 1, + "detail": "built-in", + "preselect": false, + "sortText": "01", + "textEdit": { + "range": { + "start": { + "line": 4, + "character": 7 + }, + "end": { + "line": 4, + "character": 9 + } + }, + "newText": "filecontents" + } + } + ] +} diff --git a/support/texlab/tests/integration/snapshots/integration__document_symbol__enumerate_flat.snap b/support/texlab/tests/integration/snapshots/integration__document_symbol__enumerate_flat.snap new file mode 100644 index 0000000000..1f042106a2 --- /dev/null +++ b/support/texlab/tests/integration/snapshots/integration__document_symbol__enumerate_flat.snap @@ -0,0 +1,97 @@ +--- +source: tests/integration/document_symbol.rs +expression: server.find_document_symbols(uri)? + +--- +[ + { + "name": "Enumerate", + "kind": 10, + "deprecated": false, + "location": { + "uri": "http://www.example.com/main.tex", + "range": { + "start": { + "line": 4, + "character": 0 + }, + "end": { + "line": 9, + "character": 15 + } + } + } + }, + { + "name": "1", + "kind": 22, + "deprecated": false, + "location": { + "uri": "http://www.example.com/main.tex", + "range": { + "start": { + "line": 5, + "character": 4 + }, + "end": { + "line": 5, + "character": 27 + } + } + } + }, + { + "name": "Item", + "kind": 22, + "deprecated": false, + "location": { + "uri": "http://www.example.com/main.tex", + "range": { + "start": { + "line": 6, + "character": 4 + }, + "end": { + "line": 6, + "character": 27 + } + } + } + }, + { + "name": "Baz", + "kind": 22, + "deprecated": false, + "location": { + "uri": "http://www.example.com/main.tex", + "range": { + "start": { + "line": 7, + "character": 4 + }, + "end": { + "line": 7, + "character": 18 + } + } + } + }, + { + "name": "2", + "kind": 22, + "deprecated": false, + "location": { + "uri": "http://www.example.com/main.tex", + "range": { + "start": { + "line": 8, + "character": 4 + }, + "end": { + "line": 8, + "character": 32 + } + } + } + } +] diff --git a/support/texlab/tests/integration/snapshots/integration__document_symbol__enumerate_nested.snap b/support/texlab/tests/integration/snapshots/integration__document_symbol__enumerate_nested.snap new file mode 100644 index 0000000000..2584b7ef50 --- /dev/null +++ b/support/texlab/tests/integration/snapshots/integration__document_symbol__enumerate_nested.snap @@ -0,0 +1,141 @@ +--- +source: tests/integration/document_symbol.rs +expression: server.find_document_symbols(uri)? + +--- +[ + { + "name": "Enumerate", + "kind": 10, + "deprecated": false, + "range": { + "start": { + "line": 4, + "character": 0 + }, + "end": { + "line": 9, + "character": 15 + } + }, + "selectionRange": { + "start": { + "line": 4, + "character": 0 + }, + "end": { + "line": 9, + "character": 15 + } + }, + "children": [ + { + "name": "1", + "detail": "it:foo", + "kind": 22, + "deprecated": false, + "range": { + "start": { + "line": 5, + "character": 4 + }, + "end": { + "line": 5, + "character": 27 + } + }, + "selectionRange": { + "start": { + "line": 5, + "character": 9 + }, + "end": { + "line": 5, + "character": 23 + } + }, + "children": [] + }, + { + "name": "Item", + "detail": "it:bar", + "kind": 22, + "deprecated": false, + "range": { + "start": { + "line": 6, + "character": 4 + }, + "end": { + "line": 6, + "character": 27 + } + }, + "selectionRange": { + "start": { + "line": 6, + "character": 9 + }, + "end": { + "line": 6, + "character": 23 + } + }, + "children": [] + }, + { + "name": "Baz", + "kind": 22, + "deprecated": false, + "range": { + "start": { + "line": 7, + "character": 4 + }, + "end": { + "line": 7, + "character": 18 + } + }, + "selectionRange": { + "start": { + "line": 7, + "character": 4 + }, + "end": { + "line": 7, + "character": 18 + } + }, + "children": [] + }, + { + "name": "2", + "detail": "it:qux", + "kind": 22, + "deprecated": false, + "range": { + "start": { + "line": 8, + "character": 4 + }, + "end": { + "line": 8, + "character": 32 + } + }, + "selectionRange": { + "start": { + "line": 8, + "character": 14 + }, + "end": { + "line": 8, + "character": 28 + } + }, + "children": [] + } + ] + } +] diff --git a/support/texlab/tests/integration/snapshots/integration__document_symbol__equation_flat.snap b/support/texlab/tests/integration/snapshots/integration__document_symbol__equation_flat.snap new file mode 100644 index 0000000000..1f4b3bfe4d --- /dev/null +++ b/support/texlab/tests/integration/snapshots/integration__document_symbol__equation_flat.snap @@ -0,0 +1,61 @@ +--- +source: tests/integration/document_symbol.rs +expression: server.find_document_symbols(uri)? + +--- +[ + { + "name": "Equation (1)", + "kind": 14, + "deprecated": false, + "location": { + "uri": "http://www.example.com/main.tex", + "range": { + "start": { + "line": 4, + "character": 0 + }, + "end": { + "line": 6, + "character": 14 + } + } + } + }, + { + "name": "Equation", + "kind": 14, + "deprecated": false, + "location": { + "uri": "http://www.example.com/main.tex", + "range": { + "start": { + "line": 8, + "character": 0 + }, + "end": { + "line": 10, + "character": 14 + } + } + } + }, + { + "name": "Equation", + "kind": 14, + "deprecated": false, + "location": { + "uri": "http://www.example.com/main.tex", + "range": { + "start": { + "line": 12, + "character": 0 + }, + "end": { + "line": 14, + "character": 14 + } + } + } + } +] diff --git a/support/texlab/tests/integration/snapshots/integration__document_symbol__equation_nested.snap b/support/texlab/tests/integration/snapshots/integration__document_symbol__equation_nested.snap new file mode 100644 index 0000000000..9ffb191b89 --- /dev/null +++ b/support/texlab/tests/integration/snapshots/integration__document_symbol__equation_nested.snap @@ -0,0 +1,87 @@ +--- +source: tests/integration/document_symbol.rs +expression: server.find_document_symbols(uri)? + +--- +[ + { + "name": "Equation (1)", + "detail": "eq:foo", + "kind": 14, + "deprecated": false, + "range": { + "start": { + "line": 4, + "character": 0 + }, + "end": { + "line": 6, + "character": 14 + } + }, + "selectionRange": { + "start": { + "line": 4, + "character": 16 + }, + "end": { + "line": 4, + "character": 30 + } + }, + "children": [] + }, + { + "name": "Equation", + "detail": "eq:bar", + "kind": 14, + "deprecated": false, + "range": { + "start": { + "line": 8, + "character": 0 + }, + "end": { + "line": 10, + "character": 14 + } + }, + "selectionRange": { + "start": { + "line": 8, + "character": 16 + }, + "end": { + "line": 8, + "character": 30 + } + }, + "children": [] + }, + { + "name": "Equation", + "kind": 14, + "deprecated": false, + "range": { + "start": { + "line": 12, + "character": 0 + }, + "end": { + "line": 14, + "character": 14 + } + }, + "selectionRange": { + "start": { + "line": 12, + "character": 0 + }, + "end": { + "line": 14, + "character": 14 + } + }, + "children": [] + } +] diff --git a/support/texlab/tests/integration/snapshots/integration__document_symbol__float_flat.snap b/support/texlab/tests/integration/snapshots/integration__document_symbol__float_flat.snap new file mode 100644 index 0000000000..c7465ddcc0 --- /dev/null +++ b/support/texlab/tests/integration/snapshots/integration__document_symbol__float_flat.snap @@ -0,0 +1,61 @@ +--- +source: tests/integration/document_symbol.rs +expression: server.find_document_symbols(uri)? + +--- +[ + { + "name": "Figure 1: Foo", + "kind": 6, + "deprecated": false, + "location": { + "uri": "http://www.example.com/main.tex", + "range": { + "start": { + "line": 4, + "character": 0 + }, + "end": { + "line": 7, + "character": 12 + } + } + } + }, + { + "name": "Figure: Bar", + "kind": 6, + "deprecated": false, + "location": { + "uri": "http://www.example.com/main.tex", + "range": { + "start": { + "line": 9, + "character": 0 + }, + "end": { + "line": 12, + "character": 12 + } + } + } + }, + { + "name": "Figure: Baz", + "kind": 6, + "deprecated": false, + "location": { + "uri": "http://www.example.com/main.tex", + "range": { + "start": { + "line": 14, + "character": 0 + }, + "end": { + "line": 17, + "character": 12 + } + } + } + } +] diff --git a/support/texlab/tests/integration/snapshots/integration__document_symbol__float_nested.snap b/support/texlab/tests/integration/snapshots/integration__document_symbol__float_nested.snap new file mode 100644 index 0000000000..886ffc560c --- /dev/null +++ b/support/texlab/tests/integration/snapshots/integration__document_symbol__float_nested.snap @@ -0,0 +1,87 @@ +--- +source: tests/integration/document_symbol.rs +expression: server.find_document_symbols(uri)? + +--- +[ + { + "name": "Figure 1: Foo", + "detail": "fig:foo", + "kind": 6, + "deprecated": false, + "range": { + "start": { + "line": 4, + "character": 0 + }, + "end": { + "line": 7, + "character": 12 + } + }, + "selectionRange": { + "start": { + "line": 6, + "character": 17 + }, + "end": { + "line": 6, + "character": 32 + } + }, + "children": [] + }, + { + "name": "Figure: Bar", + "detail": "fig:bar", + "kind": 6, + "deprecated": false, + "range": { + "start": { + "line": 9, + "character": 0 + }, + "end": { + "line": 12, + "character": 12 + } + }, + "selectionRange": { + "start": { + "line": 11, + "character": 17 + }, + "end": { + "line": 11, + "character": 32 + } + }, + "children": [] + }, + { + "name": "Figure: Baz", + "kind": 6, + "deprecated": false, + "range": { + "start": { + "line": 14, + "character": 0 + }, + "end": { + "line": 17, + "character": 12 + } + }, + "selectionRange": { + "start": { + "line": 14, + "character": 0 + }, + "end": { + "line": 17, + "character": 12 + } + }, + "children": [] + } +] diff --git a/support/texlab/tests/integration/snapshots/integration__document_symbol__section_flat.snap b/support/texlab/tests/integration/snapshots/integration__document_symbol__section_flat.snap new file mode 100644 index 0000000000..2f7ad319a7 --- /dev/null +++ b/support/texlab/tests/integration/snapshots/integration__document_symbol__section_flat.snap @@ -0,0 +1,61 @@ +--- +source: tests/integration/document_symbol.rs +expression: server.find_document_symbols(uri)? + +--- +[ + { + "name": "Foo", + "kind": 2, + "deprecated": false, + "location": { + "uri": "http://www.example.com/main.tex", + "range": { + "start": { + "line": 4, + "character": 0 + }, + "end": { + "line": 4, + "character": 13 + } + } + } + }, + { + "name": "2 Bar", + "kind": 2, + "deprecated": false, + "location": { + "uri": "http://www.example.com/main.tex", + "range": { + "start": { + "line": 6, + "character": 0 + }, + "end": { + "line": 8, + "character": 31 + } + } + } + }, + { + "name": "Baz", + "kind": 2, + "deprecated": false, + "location": { + "uri": "http://www.example.com/main.tex", + "range": { + "start": { + "line": 8, + "character": 0 + }, + "end": { + "line": 8, + "character": 31 + } + } + } + } +] diff --git a/support/texlab/tests/integration/snapshots/integration__document_symbol__section_nested.snap b/support/texlab/tests/integration/snapshots/integration__document_symbol__section_nested.snap new file mode 100644 index 0000000000..d5b5eb4b0c --- /dev/null +++ b/support/texlab/tests/integration/snapshots/integration__document_symbol__section_nested.snap @@ -0,0 +1,88 @@ +--- +source: tests/integration/document_symbol.rs +expression: server.find_document_symbols(uri)? + +--- +[ + { + "name": "Foo", + "kind": 2, + "deprecated": false, + "range": { + "start": { + "line": 4, + "character": 0 + }, + "end": { + "line": 4, + "character": 13 + } + }, + "selectionRange": { + "start": { + "line": 4, + "character": 0 + }, + "end": { + "line": 4, + "character": 13 + } + }, + "children": [] + }, + { + "name": "2 Bar", + "detail": "sec:bar", + "kind": 2, + "deprecated": false, + "range": { + "start": { + "line": 6, + "character": 0 + }, + "end": { + "line": 8, + "character": 31 + } + }, + "selectionRange": { + "start": { + "line": 6, + "character": 13 + }, + "end": { + "line": 6, + "character": 28 + } + }, + "children": [ + { + "name": "Baz", + "detail": "sec:baz", + "kind": 2, + "deprecated": false, + "range": { + "start": { + "line": 8, + "character": 0 + }, + "end": { + "line": 8, + "character": 31 + } + }, + "selectionRange": { + "start": { + "line": 8, + "character": 16 + }, + "end": { + "line": 8, + "character": 31 + } + }, + "children": [] + } + ] + } +] diff --git a/support/texlab/tests/integration/snapshots/integration__document_symbol__theorem_flat.snap b/support/texlab/tests/integration/snapshots/integration__document_symbol__theorem_flat.snap new file mode 100644 index 0000000000..8ce3824bea --- /dev/null +++ b/support/texlab/tests/integration/snapshots/integration__document_symbol__theorem_flat.snap @@ -0,0 +1,79 @@ +--- +source: tests/integration/document_symbol.rs +expression: server.find_document_symbols(uri)? + +--- +[ + { + "name": "Lemma 1 (Foo)", + "kind": 13, + "deprecated": false, + "location": { + "uri": "http://www.example.com/main.tex", + "range": { + "start": { + "line": 6, + "character": 0 + }, + "end": { + "line": 8, + "character": 11 + } + } + } + }, + { + "name": "Lemma 2", + "kind": 13, + "deprecated": false, + "location": { + "uri": "http://www.example.com/main.tex", + "range": { + "start": { + "line": 10, + "character": 0 + }, + "end": { + "line": 12, + "character": 11 + } + } + } + }, + { + "name": "Lemma", + "kind": 13, + "deprecated": false, + "location": { + "uri": "http://www.example.com/main.tex", + "range": { + "start": { + "line": 14, + "character": 0 + }, + "end": { + "line": 16, + "character": 11 + } + } + } + }, + { + "name": "Lemma (Qux)", + "kind": 13, + "deprecated": false, + "location": { + "uri": "http://www.example.com/main.tex", + "range": { + "start": { + "line": 18, + "character": 0 + }, + "end": { + "line": 20, + "character": 11 + } + } + } + } +] diff --git a/support/texlab/tests/integration/snapshots/integration__document_symbol__theorem_nested.snap b/support/texlab/tests/integration/snapshots/integration__document_symbol__theorem_nested.snap new file mode 100644 index 0000000000..052f62fec7 --- /dev/null +++ b/support/texlab/tests/integration/snapshots/integration__document_symbol__theorem_nested.snap @@ -0,0 +1,114 @@ +--- +source: tests/integration/document_symbol.rs +expression: server.find_document_symbols(uri)? + +--- +[ + { + "name": "Lemma 1 (Foo)", + "detail": "thm:foo", + "kind": 13, + "deprecated": false, + "range": { + "start": { + "line": 6, + "character": 0 + }, + "end": { + "line": 8, + "character": 11 + } + }, + "selectionRange": { + "start": { + "line": 6, + "character": 18 + }, + "end": { + "line": 6, + "character": 33 + } + }, + "children": [] + }, + { + "name": "Lemma 2", + "detail": "thm:bar", + "kind": 13, + "deprecated": false, + "range": { + "start": { + "line": 10, + "character": 0 + }, + "end": { + "line": 12, + "character": 11 + } + }, + "selectionRange": { + "start": { + "line": 10, + "character": 13 + }, + "end": { + "line": 10, + "character": 28 + } + }, + "children": [] + }, + { + "name": "Lemma", + "detail": "thm:baz", + "kind": 13, + "deprecated": false, + "range": { + "start": { + "line": 14, + "character": 0 + }, + "end": { + "line": 16, + "character": 11 + } + }, + "selectionRange": { + "start": { + "line": 14, + "character": 13 + }, + "end": { + "line": 14, + "character": 28 + } + }, + "children": [] + }, + { + "name": "Lemma (Qux)", + "kind": 13, + "deprecated": false, + "range": { + "start": { + "line": 18, + "character": 0 + }, + "end": { + "line": 20, + "character": 11 + } + }, + "selectionRange": { + "start": { + "line": 18, + "character": 0 + }, + "end": { + "line": 20, + "character": 11 + } + }, + "children": [] + } +] diff --git a/support/texlab/tests/integration/snapshots/integration__hover__empty_bibtex_document.snap b/support/texlab/tests/integration/snapshots/integration__hover__empty_bibtex_document.snap new file mode 100644 index 0000000000..e064602aa1 --- /dev/null +++ b/support/texlab/tests/integration/snapshots/integration__hover__empty_bibtex_document.snap @@ -0,0 +1,6 @@ +--- +source: tests/integration/hover.rs +expression: "server.hover(uri, 0, 0)?" + +--- +null diff --git a/support/texlab/tests/integration/snapshots/integration__hover__empty_labtex_document.snap b/support/texlab/tests/integration/snapshots/integration__hover__empty_labtex_document.snap new file mode 100644 index 0000000000..e064602aa1 --- /dev/null +++ b/support/texlab/tests/integration/snapshots/integration__hover__empty_labtex_document.snap @@ -0,0 +1,6 @@ +--- +source: tests/integration/hover.rs +expression: "server.hover(uri, 0, 0)?" + +--- +null diff --git a/support/texlab/tests/integration/snapshots/integration__hover__label_theorem_child_file.snap b/support/texlab/tests/integration/snapshots/integration__hover__label_theorem_child_file.snap new file mode 100644 index 0000000000..758c89cfac --- /dev/null +++ b/support/texlab/tests/integration/snapshots/integration__hover__label_theorem_child_file.snap @@ -0,0 +1,21 @@ +--- +source: tests/integration/hover.rs +expression: "server.hover(uri, 3, 8)?" + +--- +{ + "contents": { + "kind": "plaintext", + "value": "Lemma" + }, + "range": { + "start": { + "line": 3, + "character": 5 + }, + "end": { + "line": 3, + "character": 12 + } + } +} diff --git a/support/texlab/tests/integration/snapshots/integration__hover__label_theorem_child_file_mumber.snap b/support/texlab/tests/integration/snapshots/integration__hover__label_theorem_child_file_mumber.snap new file mode 100644 index 0000000000..43737f72a1 --- /dev/null +++ b/support/texlab/tests/integration/snapshots/integration__hover__label_theorem_child_file_mumber.snap @@ -0,0 +1,21 @@ +--- +source: tests/integration/hover.rs +expression: "server.hover(uri, 3, 8)?" + +--- +{ + "contents": { + "kind": "plaintext", + "value": "Lemma 1 (Foo)" + }, + "range": { + "start": { + "line": 3, + "character": 5 + }, + "end": { + "line": 3, + "character": 12 + } + } +} diff --git a/support/texlab/tests/integration/snapshots/integration__workspace_symbol__filter_bibtex.snap b/support/texlab/tests/integration/snapshots/integration__workspace_symbol__filter_bibtex.snap new file mode 100644 index 0000000000..bac8d65144 --- /dev/null +++ b/support/texlab/tests/integration/snapshots/integration__workspace_symbol__filter_bibtex.snap @@ -0,0 +1,43 @@ +--- +source: tests/integration/workspace_symbol.rs +expression: "run(\"bibtex\")?" + +--- +[ + { + "name": "foo", + "kind": 24, + "deprecated": false, + "location": { + "uri": "http://www.example.com/main.bib", + "range": { + "start": { + "line": 0, + "character": 0 + }, + "end": { + "line": 0, + "character": 14 + } + } + } + }, + { + "name": "bar", + "kind": 15, + "deprecated": false, + "location": { + "uri": "http://www.example.com/main.bib", + "range": { + "start": { + "line": 2, + "character": 0 + }, + "end": { + "line": 2, + "character": 20 + } + } + } + } +] diff --git a/support/texlab/tests/integration/snapshots/integration__workspace_symbol__filter_type_figure.snap b/support/texlab/tests/integration/snapshots/integration__workspace_symbol__filter_type_figure.snap new file mode 100644 index 0000000000..8842d02f7d --- /dev/null +++ b/support/texlab/tests/integration/snapshots/integration__workspace_symbol__filter_type_figure.snap @@ -0,0 +1,25 @@ +--- +source: tests/integration/workspace_symbol.rs +expression: "run(\"figure\")?" + +--- +[ + { + "name": "Figure 1: Bar", + "kind": 6, + "deprecated": false, + "location": { + "uri": "http://www.example.com/main.tex", + "range": { + "start": { + "line": 15, + "character": 0 + }, + "end": { + "line": 19, + "character": 12 + } + } + } + } +] diff --git a/support/texlab/tests/integration/snapshots/integration__workspace_symbol__filter_type_item.snap b/support/texlab/tests/integration/snapshots/integration__workspace_symbol__filter_type_item.snap new file mode 100644 index 0000000000..3434eaff9c --- /dev/null +++ b/support/texlab/tests/integration/snapshots/integration__workspace_symbol__filter_type_item.snap @@ -0,0 +1,61 @@ +--- +source: tests/integration/workspace_symbol.rs +expression: "run(\"item\")?" + +--- +[ + { + "name": "1", + "kind": 22, + "deprecated": false, + "location": { + "uri": "http://www.example.com/main.tex", + "range": { + "start": { + "line": 24, + "character": 4 + }, + "end": { + "line": 24, + "character": 28 + } + } + } + }, + { + "name": "2", + "kind": 22, + "deprecated": false, + "location": { + "uri": "http://www.example.com/main.tex", + "range": { + "start": { + "line": 25, + "character": 4 + }, + "end": { + "line": 25, + "character": 28 + } + } + } + }, + { + "name": "3", + "kind": 22, + "deprecated": false, + "location": { + "uri": "http://www.example.com/main.tex", + "range": { + "start": { + "line": 26, + "character": 4 + }, + "end": { + "line": 26, + "character": 28 + } + } + } + } +] diff --git a/support/texlab/tests/integration/snapshots/integration__workspace_symbol__filter_type_math.snap b/support/texlab/tests/integration/snapshots/integration__workspace_symbol__filter_type_math.snap new file mode 100644 index 0000000000..d2b7550efe --- /dev/null +++ b/support/texlab/tests/integration/snapshots/integration__workspace_symbol__filter_type_math.snap @@ -0,0 +1,43 @@ +--- +source: tests/integration/workspace_symbol.rs +expression: "run(\"math\")?" + +--- +[ + { + "name": "Equation (1)", + "kind": 14, + "deprecated": false, + "location": { + "uri": "http://www.example.com/main.tex", + "range": { + "start": { + "line": 9, + "character": 0 + }, + "end": { + "line": 11, + "character": 14 + } + } + } + }, + { + "name": "Lemma 1 (Qux)", + "kind": 13, + "deprecated": false, + "location": { + "uri": "http://www.example.com/main.tex", + "range": { + "start": { + "line": 33, + "character": 0 + }, + "end": { + "line": 35, + "character": 11 + } + } + } + } +] diff --git a/support/texlab/tests/integration/snapshots/integration__workspace_symbol__filter_type_section.snap b/support/texlab/tests/integration/snapshots/integration__workspace_symbol__filter_type_section.snap new file mode 100644 index 0000000000..e221d55dcb --- /dev/null +++ b/support/texlab/tests/integration/snapshots/integration__workspace_symbol__filter_type_section.snap @@ -0,0 +1,79 @@ +--- +source: tests/integration/workspace_symbol.rs +expression: "run(\"section\")?" + +--- +[ + { + "name": "1 Foo", + "kind": 2, + "deprecated": false, + "location": { + "uri": "http://www.example.com/main.tex", + "range": { + "start": { + "line": 7, + "character": 0 + }, + "end": { + "line": 11, + "character": 14 + } + } + } + }, + { + "name": "2 Bar", + "kind": 2, + "deprecated": false, + "location": { + "uri": "http://www.example.com/main.tex", + "range": { + "start": { + "line": 13, + "character": 0 + }, + "end": { + "line": 19, + "character": 12 + } + } + } + }, + { + "name": "3 Baz", + "kind": 2, + "deprecated": false, + "location": { + "uri": "http://www.example.com/main.tex", + "range": { + "start": { + "line": 21, + "character": 0 + }, + "end": { + "line": 27, + "character": 15 + } + } + } + }, + { + "name": "4 Qux", + "kind": 2, + "deprecated": false, + "location": { + "uri": "http://www.example.com/main.tex", + "range": { + "start": { + "line": 29, + "character": 0 + }, + "end": { + "line": 35, + "character": 11 + } + } + } + } +] diff --git a/support/texlab/tests/integration/workspace_symbol.rs b/support/texlab/tests/integration/workspace_symbol.rs index 5eb8e1ace7..54a0a8808d 100644 --- a/support/texlab/tests/integration/workspace_symbol.rs +++ b/support/texlab/tests/integration/workspace_symbol.rs @@ -1,228 +1,119 @@ -use indoc::indoc; -use texlab::{ - protocol::{Location, Range, RangeExt, SymbolInformation, WorkspaceSymbolParams}, - test::{TestBed, TestBedBuilder, TestLspClient, PULL_CAPABILITIES}, -}; - -pub fn verify_symbol_info( - symbol: &SymbolInformation, - test_bed: &TestBed, - relative_path: &str, - name: &str, - start_line: u64, - start_character: u64, - end_line: u64, - end_character: u64, -) { - assert_eq!(symbol.name, name); - let range = Range::new_simple(start_line, start_character, end_line, end_character); - assert_eq!( - symbol.location, - Location::new(test_bed.uri(relative_path).into(), range) - ); -} +use anyhow::Result; +use insta::assert_json_snapshot; +use lsp_types::{ClientCapabilities, SymbolInformation, Url}; + +use crate::common::ServerTester; + +fn run(query: &str) -> Result<Vec<SymbolInformation>> { + let server = ServerTester::launch_new_instance()?; + server.initialize(ClientCapabilities::default(), None)?; + let uri = Url::parse("http://www.example.com/main.tex")?; + server.open_memory( + uri.clone(), + r#" + \documentclass{article} + \usepackage{caption} + \usepackage{amsmath} + \usepackage{amsthm} + + \begin{document} + + \section{Foo}\label{sec:foo} + + \begin{equation}\label{eq:foo} + Foo + \end{equation} + + \section{Bar}\label{sec:bar} + + \begin{figure} + Bar + \caption{Bar} + \label{fig:bar} + \end{figure} + + \section{Baz}\label{sec:baz} + + \begin{enumerate} + \item\label{itm:foo} Foo + \item\label{itm:bar} Bar + \item\label{itm:baz} Baz + \end{enumerate} + + \section{Qux}\label{sec:qux} + + \newtheorem{lemma}{Lemma} + + \begin{lemma}[Qux]\label{thm:qux} + Qux + \end{lemma} + + \end{document} + "#, + "latex", + )?; + server.open_memory( + Url::parse("http://www.example.com/main.aux")?, + r#" + \relax + \@writefile{lof}{\contentsline {figure}{\numberline {1}{\ignorespaces Bar\relax }}{1}\protected@file@percent } + \providecommand*\caption@xref[2]{\@setref\relax\@undefined{#1}} + \newlabel{fig:bar}{{1}{1}} + \@writefile{toc}{\contentsline {section}{\numberline {1}Foo}{1}\protected@file@percent } + \newlabel{sec:foo}{{1}{1}} + \newlabel{eq:foo}{{1}{1}} + \@writefile{toc}{\contentsline {section}{\numberline {2}Bar}{1}\protected@file@percent } + \newlabel{sec:bar}{{2}{1}} + \@writefile{toc}{\contentsline {section}{\numberline {3}Baz}{1}\protected@file@percent } + \newlabel{sec:baz}{{3}{1}} + \newlabel{itm:foo}{{1}{1}} + \newlabel{itm:bar}{{2}{1}} + \newlabel{itm:baz}{{3}{1}} + \@writefile{toc}{\contentsline {section}{\numberline {4}Qux}{1}\protected@file@percent } + \newlabel{sec:qux}{{4}{1}} + \newlabel{thm:qux}{{1}{1}} + "#, + "latex", + )?; + server.open_memory( + Url::parse("http://www.example.com/main.bib")?, + r#" + @article{foo,} + + @string{bar = "bar"} + "#, + "bibtex", + )?; -async fn run(query: &str) -> (TestBed, Vec<SymbolInformation>) { - let mut test_bed = TestBedBuilder::new() - .file( - "foo.tex", - indoc!( - r#" - \documentclass{article} - \usepackage{caption} - \usepackage{amsmath} - \usepackage{amsthm} - % - \begin{document} - % - \section{Foo}\label{sec:foo} - % - \begin{equation}\label{eq:foo} - Foo - \end{equation} - % - \section{Bar}\label{sec:bar} - % - \begin{figure} - Bar - \caption{Bar} - \label{fig:bar} - \end{figure} - % - \section{Baz}\label{sec:baz} - % - \begin{enumerate} - \item\label{itm:foo} Foo - \item\label{itm:bar} Bar - \item\label{itm:baz} Baz - \end{enumerate} - % - \section{Qux}\label{sec:qux} - % - \newtheorem{lemma}{Lemma} - % - \begin{lemma}[Qux]\label{thm:qux} - Qux - \end{lemma} - % - \end{document} - "# - ), - ) - .file( - "foo.aux", - indoc!( - r#" - \relax - \@writefile{lof}{\contentsline {figure}{\numberline {1}{\ignorespaces Bar\relax }}{1}\protected@file@percent } - \providecommand*\caption@xref[2]{\@setref\relax\@undefined{#1}} - \newlabel{fig:bar}{{1}{1}} - \@writefile{toc}{\contentsline {section}{\numberline {1}Foo}{1}\protected@file@percent } - \newlabel{sec:foo}{{1}{1}} - \newlabel{eq:foo}{{1}{1}} - \@writefile{toc}{\contentsline {section}{\numberline {2}Bar}{1}\protected@file@percent } - \newlabel{sec:bar}{{2}{1}} - \@writefile{toc}{\contentsline {section}{\numberline {3}Baz}{1}\protected@file@percent } - \newlabel{sec:baz}{{3}{1}} - \newlabel{itm:foo}{{1}{1}} - \newlabel{itm:bar}{{2}{1}} - \newlabel{itm:baz}{{3}{1}} - \@writefile{toc}{\contentsline {section}{\numberline {4}Qux}{1}\protected@file@percent } - \newlabel{sec:qux}{{4}{1}} - \newlabel{thm:qux}{{1}{1}} - "# - ), - ) - .file( - "bar.bib", - indoc!( - r#" - @article{foo,} - % - @string{bar = "bar"} - "# - ), - ) - .build() - .await; - test_bed.spawn(); - test_bed.initialize(PULL_CAPABILITIES.clone()).await; - test_bed.open("foo.tex").await; - test_bed.open("foo.aux").await; - test_bed.open("bar.bib").await; - - let params = WorkspaceSymbolParams { - query: query.into(), - ..WorkspaceSymbolParams::default() - }; - let actual_symbols = test_bed.client.workspace_symbol(params).await.unwrap(); - - test_bed.shutdown().await; - - (test_bed, actual_symbols) + server.find_workspace_symbols(query) } -#[tokio::test] -async fn filter_type_section() { - let (test_bed, actual_symbols) = run("section").await; - assert_eq!(actual_symbols.len(), 4); - verify_symbol_info( - &actual_symbols[0], - &test_bed, - "foo.tex", - "1 Foo", - 7, - 0, - 13, - 0, - ); - verify_symbol_info( - &actual_symbols[1], - &test_bed, - "foo.tex", - "2 Bar", - 13, - 0, - 21, - 0, - ); - verify_symbol_info( - &actual_symbols[2], - &test_bed, - "foo.tex", - "3 Baz", - 21, - 0, - 29, - 0, - ); - verify_symbol_info( - &actual_symbols[3], - &test_bed, - "foo.tex", - "4 Qux", - 29, - 0, - 37, - 0, - ); +#[test] +fn test_filter_type_section() -> Result<()> { + assert_json_snapshot!(run("section")?); + Ok(()) } -#[tokio::test] -async fn filter_type_figure() { - let (test_bed, actual_symbols) = run("figure").await; - assert_eq!(actual_symbols.len(), 1); - verify_symbol_info( - &actual_symbols[0], - &test_bed, - "foo.tex", - "Figure 1: Bar", - 15, - 0, - 19, - 12, - ); +#[test] +fn test_filter_type_figure() -> Result<()> { + assert_json_snapshot!(run("figure")?); + Ok(()) } -#[tokio::test] -async fn filter_type_item() { - let (test_bed, actual_symbols) = run("item").await; - assert_eq!(actual_symbols.len(), 3); - verify_symbol_info(&actual_symbols[0], &test_bed, "foo.tex", "1", 24, 4, 25, 4); - verify_symbol_info(&actual_symbols[1], &test_bed, "foo.tex", "2", 25, 4, 26, 4); - verify_symbol_info(&actual_symbols[2], &test_bed, "foo.tex", "3", 26, 4, 27, 0); +#[test] +fn test_filter_type_item() -> Result<()> { + assert_json_snapshot!(run("item")?); + Ok(()) } -#[tokio::test] -async fn filter_type_math() { - let (test_bed, actual_symbols) = run("math").await; - assert_eq!(actual_symbols.len(), 2); - verify_symbol_info( - &actual_symbols[0], - &test_bed, - "foo.tex", - "Equation (1)", - 9, - 0, - 11, - 14, - ); - verify_symbol_info( - &actual_symbols[1], - &test_bed, - "foo.tex", - "Lemma 1 (Qux)", - 33, - 0, - 35, - 11, - ); +#[test] +fn test_filter_type_math() -> Result<()> { + assert_json_snapshot!(run("math")?); + Ok(()) } -#[tokio::test] -async fn filter_bibtex() { - let (test_bed, actual_symbols) = run("bibtex").await; - assert_eq!(actual_symbols.len(), 2); - verify_symbol_info(&actual_symbols[0], &test_bed, "bar.bib", "foo", 0, 0, 0, 14); - verify_symbol_info(&actual_symbols[1], &test_bed, "bar.bib", "bar", 2, 0, 2, 20); +#[test] +fn test_filter_bibtex() -> Result<()> { + assert_json_snapshot!(run("bibtex")?); + Ok(()) } |