diff options
Diffstat (limited to 'support/texlab')
549 files changed, 13453 insertions, 11889 deletions
diff --git a/support/texlab/CHANGELOG.md b/support/texlab/CHANGELOG.md index 85f8d0bdb3..5b12294b3e 100644 --- a/support/texlab/CHANGELOG.md +++ b/support/texlab/CHANGELOG.md @@ -5,7 +5,73 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [4.2.0] - 03.07.2022 +## [5.0.0] - 2022-12-29 + +### Changed + +- _BREAKING_: `texlab.rootDirectory` is now used as the folder path from which the compiler is executed + relative to the main document. By default it is equal to `"."`. For more information, please visit the wiki. +- Improve performance of completion by a huge margin due to a faster filtering method used internally +- Do not discover project files beyond the provided workspace folders +- Try to guess the root directory by checking for files such as `.latexmkrc` or `Tectonic.toml` if `texlab.rootDirectory` is not set + +### Fixed + +- Update positions of reported build diagnostics when editing the affected line +- Do not treat links to files as bidirectional by default. This prevents issues where `texlab` ends up compiling the wrong file + in projects with shared files ([#806](https://github.com/latex-lsp/texlab/issues/806), [#757](https://github.com/latex-lsp/texlab/issues/757), [#679](https://github.com/latex-lsp/texlab/issues/679)) +- Fix coverage of directories which need to be watched for changes ([#502](https://github.com/latex-lsp/texlab/issues/502), [#491](https://github.com/latex-lsp/texlab/issues/491)) +- Resolve links of the `import` package correctly +- Use `filterText` of completion items when filtering internally ([#829](https://github.com/latex-lsp/texlab/issues/829)) + +## [4.3.2] - 2022-11-20 + +### Fixed + +- Do not try to run the TeX engine on package files and fail the build instead ([#801](https://github.com/latex-lsp/texlab/issues/801)) +- Handle URIs with URL-encoded drive letters on Windows ([#802](https://github.com/latex-lsp/texlab/issues/802)) +- Parse BibTeX entries with unbalanced quotes correctly ([#809](https://github.com/latex-lsp/texlab/issues/809)) +- Provide completion for more acronym commands ([#813](https://github.com/latex-lsp/texlab/issues/813)) +- Fix parsing acronym definitions ([#813](https://github.com/latex-lsp/texlab/issues/813)) + +## [4.3.1] - 2022-10-22 + +### Fixed + +- Do not crash with a stack overflow when trying to load packages with many internal dependencies ([#793](https://github.com/latex-lsp/texlab/issues/793)) +- Normalize drive letters of all document URIs +- Fix parsing commands that take file paths as arguments ([#789](https://github.com/latex-lsp/texlab/issues/789)) +- Use the correct working directory and command line arguments when calling `latexindent` ([#645](https://github.com/latex-lsp/texlab/issues/645)) +- Fix publishing to CTAN + +## [4.3.0] - 2022-09-25 + +### Added + +- Add inlay hints for `\label{...}` ([#753](https://github.com/latex-lsp/texlab/issues/753)) + +### Fixed + +- Improve accuracy of the error locations reported by the TeX engine ([#738](https://github.com/latex-lsp/texlab/issues/738)) +- Reduce number of false positive errors reported by `texlab` ([#745](https://github.com/latex-lsp/texlab/issues/745)) + +## [4.2.2] - 2022-08-28 + +### Fixed + +- Do not watch the same directory multiple times, which can result in a memory leak on Windows ([#737](https://github.com/latex-lsp/texlab/issues/679)) +- Fix detection of root document when sharing files between projects ([#679](https://github.com/latex-lsp/texlab/issues/679)) +- Fix text synchronization problem caused by file watcher ([#724](https://github.com/latex-lsp/texlab/issues/724)) + +## [4.2.1] - 2022-08-05 + +### Fixed + +- Deserialize server options with missing keys (or not keys at all) correctly ([#707](https://github.com/latex-lsp/texlab/issues/707)) +- Pass `chktexrc` files if they are not in the current directory ([#683](https://github.com/latex-lsp/texlab/issues/683)) +- Revert back to server-side file watching due to lack of client support ([#679](https://github.com/latex-lsp/texlab/issues/679)) + +## [4.2.0] - 2022-07-03 ### Added @@ -22,7 +88,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Parse incomplete server options correctly ([#651](https://github.com/latex-lsp/texlab/issues/651)) -## [4.1.0] - 12.06.2022 +## [4.1.0] - 2022-06-12 ### Added @@ -38,7 +104,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Allow brackets in included file paths ([#639](https://github.com/latex-lsp/texlab/issues/639)) - Allow commands in included file paths ([#641](https://github.com/latex-lsp/texlab/issues/641)) -## [4.0.0] - 25.05.2022 +## [4.0.0] - 2022-05-25 ### Added @@ -63,7 +129,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Allow optional arguments in environment definitions ([#570](https://github.com/latex-lsp/texlab/issues/570)) - Allow `=` in include paths ([#568](https://github.com/latex-lsp/texlab/issues/568)) -## [3.3.2] - 26.02.2022 +## [3.3.2] - 2022-02-26 ### Fixed @@ -78,7 +144,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Make directory path in `\import` optional ([#540](https://github.com/latex-lsp/texlab/issues/540)) - Do not spam workspace/configuration requests ([#533](https://github.com/latex-lsp/texlab/issues/533)) -## [3.3.1] - 10.11.2021 +## [3.3.1] - 2021-11-10 ### Fixed @@ -87,7 +153,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fix a bug that sometimes causes the `aux` file to pick up the diagnostics of the `tex` file ([#502](https://github.com/latex-lsp/texlab/issues/502)) - Fix a bug that sometimes prevents `log` files from being reanalyzed ([#502](https://github.com/latex-lsp/texlab/issues/502)) -## [3.3.0] - 10.10.2021 +## [3.3.0] - 2021-10-10 ### Added @@ -103,7 +169,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Prevent `texlab` from hanging because of unanswered configuration requests sent to Emacs ([#456](https://github.com/latex-lsp/texlab/issues/456)) - Re-analyze the workspace if the initial configuration has been received late -## [3.2.0] - 12.06.2021 +## [3.2.0] - 2021-06-12 ### Added @@ -122,7 +188,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fix conditional compilation of the `citation` feature. -## [3.1.0] - 03.06.2021 +## [3.1.0] - 2021-06-03 ### Added @@ -140,14 +206,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed -## [3.0.1] - 22.05.2021 +## [3.0.1] - 2021-05-22 ### Fixed - Sometimes the log parser does not pick up errors from the log file ([#426](https://github.com/latex-lsp/texlab/issues/426)) - Fix a bug involving characters that are not part of the ASCII charset ([#428](https://github.com/latex-lsp/texlab/issues/428)) -## [3.0.0] - 16.05.2021 +## [3.0.0] - 2021-05-16 ### Added @@ -180,13 +246,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Hopefully fixes the ChkTeX spamming issue ([#186](https://github.com/latex-lsp/texlab/issues/186)) - Reduce CPU-load when idle ([#400](https://github.com/latex-lsp/texlab/issues/400)) -## [2.2.2] - 10.01.2021 +## [2.2.2] - 2021-01-10 ### Fixed - Fix compilation on `arm64-apple-darwin` (Apple Silicon) ([#343](https://github.com/latex-lsp/texlab/issues/343)) -## [2.2.1] - 06.01.2021 +## [2.2.1] - 2021-01-06 ### Added @@ -201,7 +267,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fix compilation on `aarch64` and `armv7l` ([#289](https://github.com/latex-lsp/texlab/issues/289)) -## [2.2.0] - 27.05.2020 +## [2.2.0] - 2020-05-27 ### Added @@ -216,7 +282,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fix the ordering of completion items when using `lsp-mode` ([#227](https://github.com/latex-lsp/texlab/issues/227)) - Fix preview when using custom class files ([#228](https://github.com/latex-lsp/texlab/issues/228)) -## [2.1.0] - 10.05.2020 +## [2.1.0] - 2020-05-10 ### Added @@ -229,7 +295,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fix a parsing error that caused `texlab` to take 100% CPU usage in some cases ([#212](https://github.com/latex-lsp/texlab/issues/212)) - Prevent building the same file multiple times at once -## [2.0.0] - 20.04.2020 +## [2.0.0] - 2020-04-20 ### Added @@ -253,7 +319,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Improve performance of completion (when completing LaTeX commands) - Improve workspace detection algorithm -## [1.10.0] - 11.02.2020 +## [1.10.0] - 2020-02-11 ### Added @@ -266,7 +332,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Show all digits of chktex warning number ([#160](https://github.com/latex-lsp/texlab/issues/160)) -## [1.9.0] - 30.12.2019 +## [1.9.0] - 2019-12-30 ### Added @@ -282,7 +348,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Run LaTeX linter when opening a file if enabled - Handle `\hyphen` when rendering citations -## [1.8.0] - 01.12.2019 +## [1.8.0] - 2019-12-01 ### Added @@ -294,7 +360,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Change license to GPLv3 - Do not require Node.js when building the server (#[87](https://github.com/latex-lsp/texlab/issues/87)) -## [1.7.0] - 20.11.2019 +## [1.7.0] - 2019-11-20 ### Added @@ -315,7 +381,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ([#110](https://github.com/latex-lsp/texlab/issues/110)) - Fix potential crash in "Goto Definition" -## [1.6.0] - 29.09.2019 +## [1.6.0] - 2019-09-29 ### Added @@ -341,7 +407,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fix filter text of citations with braces inside a field - Handle invalid UTF-8 in log files -## [1.5.0] - 27.08.2019 +## [1.5.0] - 2019-08-27 ### Added @@ -357,7 +423,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Do not run ChkTeX on BibTeX files - Fix build freezes on Windows ([#63](https://github.com/latex-lsp/texlab/issues/63)) -## [1.4.1] - 22.08.2019 +## [1.4.1] - 2019-08-22 ### Added @@ -369,7 +435,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fix rendering of theorem labels - Handle Windows paths correctly -## [1.4.0] - 20.08.2019 +## [1.4.0] - 2019-08-20 ### Added @@ -383,7 +449,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Use LocationLink for "peek definition" when possible - Node.js is no longer a dependency -## [1.3.0] - 06.08.2019 +## [1.3.0] - 2019-08-06 ### Added @@ -398,7 +464,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Build cancellation has been reimplemented ([#47](https://github.com/latex-lsp/texlab/issues/47), [#63](https://github.com/latex-lsp/texlab/issues/63)) -## [1.2.0] - 23.07.2019 +## [1.2.0] - 2019-07-23 ### Added @@ -409,7 +475,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - The index mechanism has been removed. Packages are now indexed with a script beforehand. -## [1.1.0] - 13.07.2019 +## [1.1.0] - 2019-07-13 ### Added @@ -427,7 +493,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fix preselect for environments with missing braces -## [1.0.0] - 04.07.2019 +## [1.0.0] - 2019-07-04 ### Added @@ -464,14 +530,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Do not depend on the `workspace/configuration` request (#[22](https://github.com/latex-lsp/texlab/issues/22)) - Prevent completion from triggering too often -## [0.4.2] - 10.04.2019 +## [0.4.2] - 2019-04-10 ### Fixed - Fix completion inside `\( \)`. ([#14](https://github.com/latex-lsp/texlab/issues/14)) - Do not crash on invalid requests. -## [0.4.1] - 30.03.2019 +## [0.4.1] - 2019-03-30 ### Changed @@ -481,7 +547,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Improve MiKTeX support ([#8](https://github.com/latex-lsp/texlab-vscode/issues/8)) -## [0.4.0] - 09.03.2019 +## [0.4.0] - 2019-03-09 ### Added @@ -493,7 +559,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Improve completion for includes - Improve performance of completion -## [0.3.0] - 05.03.2019 +## [0.3.0] - 2019-03-05 ### Added @@ -510,7 +576,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fix crash when hovering over invalid BibTeX entries - Fix a bug where the completion does not get triggered correctly -## [0.2.0] - 01.03.2019 +## [0.2.0] - 2019-03-01 ### Added @@ -523,14 +589,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fix completion of file includes - Prevent server crash when opening a locked file -## [0.1.2] - 16.02.2019 +## [0.1.2] - 2019-02-16 ### Fixed - Do not display an error when PDF viewers return a non-zero exit code while performing forward search -## [0.1.1] - 15.02.2019 +## [0.1.1] - 2019-02-15 ### Changed @@ -540,6 +606,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fix rendering of completion symbols -## [0.1.0] - 15.02.2019 +## [0.1.0] - 2019-02-15 - Initial release diff --git a/support/texlab/Cargo.lock b/support/texlab/Cargo.lock index cd1348e8c7..7f205d9514 100644 --- a/support/texlab/Cargo.lock +++ b/support/texlab/Cargo.lock @@ -9,15 +9,32 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] +name = "ahash" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" +dependencies = [ + "getrandom", + "once_cell", + "version_check", +] + +[[package]] name = "aho-corasick" -version = "0.7.18" +version = "0.7.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" +checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" dependencies = [ "memchr", ] [[package]] +name = "anes" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" + +[[package]] name = "ansi_term" version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -28,9 +45,15 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.58" +version = "1.0.67" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7724808837b77f4b4de9d283820f9d98bcf496d5692934b857a2399d31ff22e6" + +[[package]] +name = "arc-swap" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb07d2053ccdbe10e2af2995a2f116c1330396493dc1269f6a91d0ae82e19704" +checksum = "983cd8b9d4b02a6dc6ffa557262eb5858a27a0038ffffe21a0f133eaa819a164" [[package]] name = "assert_unordered" @@ -47,7 +70,7 @@ version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" dependencies = [ - "hermit-abi", + "hermit-abi 0.1.19", "libc", "winapi", ] @@ -72,63 +95,39 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "block-buffer" -version = "0.7.3" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" +checksum = "69cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e" dependencies = [ - "block-padding", - "byte-tools", - "byteorder", "generic-array", ] [[package]] -name = "block-padding" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" -dependencies = [ - "byte-tools", -] - -[[package]] name = "bstr" version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223" dependencies = [ - "lazy_static", "memchr", - "regex-automata", - "serde", ] [[package]] name = "bumpalo" -version = "3.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37ccbd214614c6783386c1af30caf03192f17891059cecc394b4fb119e363de3" - -[[package]] -name = "byte-tools" -version = "0.3.1" +version = "3.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" +checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba" [[package]] -name = "byteorder" -version = "1.4.3" +name = "cast" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] -name = "cast" -version = "0.2.7" +name = "cc" +version = "1.0.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c24dab4283a142afa2fdca129b80ad2c6284e073930f964c3a1293c225ee39a" -dependencies = [ - "rustc_version", -] +checksum = "a20104e2335ce8a659d6dd92a51a767a0c062599c73b343fd152cb401e828c3d" [[package]] name = "cfg-if" @@ -138,44 +137,73 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.19" +version = "0.4.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" +checksum = "16b0a3d9ed01224b22057780a37bb8c5dbfe1be8ba48678e7bf57ec4b385411f" dependencies = [ "num-integer", "num-traits", ] [[package]] +name = "ciborium" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0c137568cc60b904a7724001b35ce2630fd00d5d84805fbb608ab89509d788f" +dependencies = [ + "ciborium-io", + "ciborium-ll", + "serde", +] + +[[package]] +name = "ciborium-io" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "346de753af073cc87b52b2083a506b38ac176a44cfb05497b622e27be899b369" + +[[package]] +name = "ciborium-ll" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "213030a2b5a4e0c0892b6652260cf6ccac84827b83a85a534e178e3906c4cf1b" +dependencies = [ + "ciborium-io", + "half", +] + +[[package]] name = "clap" -version = "2.34.0" +version = "3.2.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" +checksum = "71655c45cb9845d3270c9d6df84ebe72b4dad3c2ba3f7023ad47c144e4e473a5" dependencies = [ "bitflags", - "textwrap 0.11.0", - "unicode-width", + "clap_lex 0.2.4", + "indexmap", + "textwrap", ] [[package]] name = "clap" -version = "3.2.8" +version = "4.0.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "190814073e85d238f31ff738fcb0bf6910cedeb73376c87cd69291028966fd83" +checksum = "4d63b9e9c07271b9957ad22c173bae2a4d9a81127680962039296abcd2f8251d" dependencies = [ "bitflags", "clap_derive", - "clap_lex", - "indexmap", + "clap_lex 0.3.0", + "is-terminal", "once_cell", - "textwrap 0.15.0", + "strsim", + "termcolor", ] [[package]] name = "clap_derive" -version = "3.2.7" +version = "4.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "759bf187376e1afa7b85b959e6a664a3e7a95203415dba952ad19139e798f902" +checksum = "0177313f9f02afc995627906bbd8967e2be069f5261954222dac78290c2b9014" dependencies = [ "heck", "proc-macro-error", @@ -194,31 +222,43 @@ dependencies = [ ] [[package]] +name = "clap_lex" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d4198f73e42b4936b35b5bb248d81d2b595ecb170da0bac7655c54eedfa8da8" +dependencies = [ + "os_str_bytes", +] + +[[package]] name = "console" -version = "0.15.0" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a28b32d32ca44b70c3e4acd7db1babf555fa026e385fb95f18028f88848b3c31" +checksum = "c050367d967ced717c04b65d8c619d863ef9292ce0c5760028655a2fb298718c" dependencies = [ "encode_unicode", + "lazy_static", "libc", - "once_cell", "terminal_size", "winapi", ] [[package]] -name = "convert_case" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" - -[[package]] name = "countme" version = "3.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7704b5fdd17b18ae31c4c1da5a2e0305a2bf17b5249300a9ee9ed7b72114c636" [[package]] +name = "cpufeatures" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320" +dependencies = [ + "libc", +] + +[[package]] name = "crc32fast" version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -229,15 +269,16 @@ dependencies = [ [[package]] name = "criterion" -version = "0.3.5" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1604dafd25fba2fe2d5895a9da139f8dc9b319a5fe5354ca137cbbce4e178d10" +checksum = "e7c76e09c1aae2bc52b3d2f29e13c6572553b30c4aa1b8a49fd70de6412654cb" dependencies = [ + "anes", "atty", "cast", - "clap 2.34.0", + "ciborium", + "clap 3.2.23", "criterion-plot", - "csv", "itertools", "lazy_static", "num-traits", @@ -246,7 +287,6 @@ dependencies = [ "rayon", "regex", "serde", - "serde_cbor", "serde_derive", "serde_json", "tinytemplate", @@ -255,19 +295,33 @@ dependencies = [ [[package]] name = "criterion-plot" -version = "0.4.4" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d00996de9f2f7559f7f4dc286073197f83e92256a59ed395f9aac01fe717da57" +checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1" dependencies = [ "cast", "itertools", ] [[package]] +name = "crossbeam" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2801af0d36612ae591caa9568261fddce32ce6e08a7275ea334a06a4ad021a2c" +dependencies = [ + "cfg-if", + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-epoch", + "crossbeam-queue", + "crossbeam-utils", +] + +[[package]] name = "crossbeam-channel" -version = "0.5.5" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c02a4d71819009c192cf4872265391563fd6a84c81ff2c0f2a7026ca4c1d85c" +checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521" dependencies = [ "cfg-if", "crossbeam-utils", @@ -275,9 +329,9 @@ dependencies = [ [[package]] name = "crossbeam-deque" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e" +checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc" dependencies = [ "cfg-if", "crossbeam-epoch", @@ -286,88 +340,94 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.9.9" +version = "0.9.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07db9d94cbd326813772c968ccd25999e5f8ae22f4f8d1b11effa37ef6ce281d" +checksum = "01a9af1f4c2ef74bb8aa1f7e19706bc72d03598c8a570bb5de72243c7a9d9d5a" dependencies = [ "autocfg", "cfg-if", "crossbeam-utils", - "memoffset", - "once_cell", + "memoffset 0.7.1", "scopeguard", ] [[package]] -name = "crossbeam-utils" -version = "0.8.10" +name = "crossbeam-queue" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d82ee10ce34d7bc12c2122495e7593a9c41347ecdd64185af4ecf72cb1a7f83" +checksum = "d1cfb3ea8a53f37c40dea2c7bedcbd88bdfae54f5e2175d6ecaff1c988353add" dependencies = [ "cfg-if", - "once_cell", + "crossbeam-utils", ] [[package]] -name = "csv" -version = "1.1.6" +name = "crossbeam-utils" +version = "0.8.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22813a6dc45b335f9bade10bf7271dc477e81113e89eb251a0bc2a8a81c536e1" +checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f" dependencies = [ - "bstr", - "csv-core", - "itoa 0.4.8", - "ryu", - "serde", + "cfg-if", ] [[package]] -name = "csv-core" -version = "0.1.10" +name = "crypto-common" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b2466559f260f48ad25fe6317b3c8dac77b5bdb5763ac7d9d6103530663bc90" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ - "memchr", + "generic-array", + "typenum", ] [[package]] name = "dashmap" -version = "5.2.0" +version = "5.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c8858831f7781322e539ea39e72449c46b059638250c14344fec8d0aa6e539c" +checksum = "907076dfda823b0b36d2a1bb5f90c96660a5bbcd7729e10727f07858f22c4edc" dependencies = [ "cfg-if", - "num_cpus", - "parking_lot", + "hashbrown", + "lock_api", + "once_cell", + "parking_lot_core", ] [[package]] -name = "derive_more" -version = "0.99.17" +name = "digest" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" dependencies = [ - "convert_case", - "proc-macro2", - "quote", - "rustc_version", - "syn", + "block-buffer", + "crypto-common", ] [[package]] -name = "digest" -version = "0.8.1" +name = "dirs" +version = "4.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" +checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" dependencies = [ - "generic-array", + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" +dependencies = [ + "libc", + "redox_users", + "winapi", ] [[package]] name = "either" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f107b87b6afc2a64fd13cac55fe06d6c8859f12d4b14cbcdd2c67d0976781be" +checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" [[package]] name = "encode_unicode" @@ -394,16 +454,54 @@ dependencies = [ ] [[package]] -name = "fake-simd" +name = "env_logger" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0" +dependencies = [ + "humantime", + "is-terminal", + "log", + "regex", + "termcolor", +] + +[[package]] +name = "errno" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1" +dependencies = [ + "errno-dragonfly", + "libc", + "winapi", +] + +[[package]] +name = "errno-dragonfly" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" +checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "eyre" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c2b6b5a29c02cdc822728b7d7b8ae1bab3e3b05d44522770ddd49722eeac7eb" +dependencies = [ + "indenter", + "once_cell", +] [[package]] name = "fastrand" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf" +checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499" dependencies = [ "instant", ] @@ -418,22 +516,41 @@ dependencies = [ ] [[package]] -name = "fixedbitset" -version = "0.4.1" +name = "filetime" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "279fb028e20b3c4c320317955b77c5e0c9701f05a1d309905d6fc702cdc5053e" +checksum = "4e884668cd0c7480504233e951174ddc3b382f7c2666e3b7310b5c4e7b0c37f9" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "windows-sys", +] [[package]] name = "flate2" -version = "1.0.24" +version = "1.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f82b0f4c27ad9f8bfd1f3208d882da2b09c301bc1c828fd3a00d0216d2fbbff6" +checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841" dependencies = [ "crc32fast", "miniz_oxide", ] [[package]] +name = "flume" +version = "0.10.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1657b4441c3403d9f7b3409e47575237dac27b1b5726df654a6ecbf92f0f7577" +dependencies = [ + "futures-core", + "futures-sink", + "nanorand", + "pin-project", + "spin", +] + +[[package]] name = "fnv" version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -441,15 +558,35 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "form_urlencoded" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191" +checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8" dependencies = [ - "matches", "percent-encoding", ] [[package]] +name = "fsevent-sys" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76ee7a02da4d231650c7cea31349b889be2f45ddb3ef3032d2ec8185f6313fd2" +dependencies = [ + "libc", +] + +[[package]] +name = "futures-core" +version = "0.3.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04909a7a7e4633ae6c4a9ab280aeb86da1236243a77b694a49eacd659a4bd3ac" + +[[package]] +name = "futures-sink" +version = "0.3.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39c15cf1a4aa79df40f1bb462fb39676d0ad9e366c2a33b590d7c66f4f81fcf9" + +[[package]] name = "fuzzy-matcher" version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -460,22 +597,38 @@ dependencies = [ [[package]] name = "generic-array" -version = "0.12.4" +version = "0.14.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd" +checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" dependencies = [ "typenum", + "version_check", ] [[package]] name = "getrandom" -version = "0.2.7" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6" +checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" dependencies = [ "cfg-if", + "js-sys", "libc", "wasi", + "wasm-bindgen", +] + +[[package]] +name = "globset" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a1e17342619edbc21a964c2afbeb6c820c6a2560032872f397bb97ea127bd0a" +dependencies = [ + "aho-corasick", + "bstr", + "fnv", + "log", + "regex", ] [[package]] @@ -486,9 +639,21 @@ checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" [[package]] name = "hashbrown" -version = "0.12.1" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +dependencies = [ + "ahash", +] + +[[package]] +name = "hashlink" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db0d4cf898abf0081f964436dc980e96670a0f36863e4b83aaacdb65c9d7ccc3" +checksum = "69fe1fcf8b4278d860ad0548329f892a3631fb63f82574df68275f34cdbe0ffa" +dependencies = [ + "hashbrown", +] [[package]] name = "heck" @@ -506,58 +671,102 @@ dependencies = [ ] [[package]] +name = "hermit-abi" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" +dependencies = [ + "libc", +] + +[[package]] name = "human_name" -version = "1.0.3" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29d4c0030db95c2e6e68fc240def0fc5bcbecab549c1c856a9f14ec309ccb332" +checksum = "42af7ece82db04720531abb16506781d40a72c8e62ecb0762d39746d2173255e" dependencies = [ + "crossbeam-utils", "libc", "phf", + "phf_codegen", "serde", - "serde_derive", "serde_json", "smallstr", "smallvec", + "unicode-case-mapping", "unicode-normalization", "unicode-segmentation", "unidecode", ] [[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + +[[package]] name = "idna" -version = "0.2.3" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8" +checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" dependencies = [ - "matches", "unicode-bidi", "unicode-normalization", ] [[package]] +name = "indenter" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" + +[[package]] name = "indexmap" -version = "1.9.1" +version = "1.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e" +checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" dependencies = [ "autocfg", "hashbrown", ] [[package]] +name = "inotify" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8069d3ec154eb856955c1c0fbffefbf5f3c40a104ec912d4797314c1801abff" +dependencies = [ + "bitflags", + "inotify-sys", + "libc", +] + +[[package]] +name = "inotify-sys" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb" +dependencies = [ + "libc", +] + +[[package]] name = "insta" -version = "1.15.0" +version = "1.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4126dd76ebfe2561486a1bd6738a33d2029ffb068a99ac446b7f8c77b2e58dbc" +checksum = "e48b08a091dfe5b09a6a9688c468fdd5b4396e92ce09e2eb932f0884b02788a4" dependencies = [ "console", - "once_cell", + "globset", + "lazy_static", + "linked-hash-map", "pest", "pest_derive", "serde", - "serde_json", - "serde_yaml", "similar", + "walkdir", + "yaml-rust", ] [[package]] @@ -570,6 +779,28 @@ dependencies = [ ] [[package]] +name = "io-lifetimes" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46112a93252b123d31a119a8d1a1ac19deac4fac6e0e8b0df58f0d4e5870e63c" +dependencies = [ + "libc", + "windows-sys", +] + +[[package]] +name = "is-terminal" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "927609f78c2913a6f6ac3c27a4fe87f43e2a35367c0c4b0f8265e8f49a104330" +dependencies = [ + "hermit-abi 0.2.6", + "io-lifetimes", + "rustix", + "windows-sys", +] + +[[package]] name = "isocountry" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -581,24 +812,18 @@ dependencies = [ [[package]] name = "itertools" -version = "0.10.3" +version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" dependencies = [ "either", ] [[package]] name = "itoa" -version = "0.4.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" - -[[package]] -name = "itoa" -version = "1.0.2" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "112c678d4050afce233f4f2852bb2eb519230b3cf12f33585275537d7e41578d" +checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440" [[package]] name = "jod-thread" @@ -607,15 +832,41 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b23360e99b8717f20aaa4598f5a6541efbe30630039fbc7706cf954a87947ae" [[package]] +name = "joinery" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72167d68f5fce3b8655487b8038691a3c9984ee769590f93f2a631f4ad64e4f5" + +[[package]] name = "js-sys" -version = "0.3.58" +version = "0.3.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3fac17f7123a73ca62df411b1bf727ccc805daa070338fda671c86dac1bdc27" +checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47" dependencies = [ "wasm-bindgen", ] [[package]] +name = "kqueue" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c8fc60ba15bf51257aa9807a48a61013db043fcf3a78cb0d916e8e396dcad98" +dependencies = [ + "kqueue-sys", + "libc", +] + +[[package]] +name = "kqueue-sys" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8367585489f01bc55dd27404dcf56b95e6da061a256a666ab23be9ba96a2e587" +dependencies = [ + "bitflags", + "libc", +] + +[[package]] name = "lazy_static" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -623,9 +874,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.126" +version = "0.2.138" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" +checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8" [[package]] name = "linked-hash-map" @@ -634,10 +885,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" [[package]] +name = "linux-raw-sys" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4" + +[[package]] name = "lock_api" -version = "0.4.7" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327fa5b6a6940e4699ec49a9beae1ea4845c6bab9314e4f84ac68742139d8c53" +checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" dependencies = [ "autocfg", "scopeguard", @@ -689,9 +946,9 @@ dependencies = [ [[package]] name = "lsp-types" -version = "0.93.0" +version = "0.93.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70c74e2173b2b31f8655d33724b4b45ac13f439386f66290f539c22b144c2212" +checksum = "9be6e9c7e2d18f651974370d7aff703f9513e0df6e464fd795660edc77e6ca51" dependencies = [ "bitflags", "serde", @@ -701,18 +958,6 @@ dependencies = [ ] [[package]] -name = "maplit" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" - -[[package]] -name = "matches" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" - -[[package]] name = "memchr" version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -728,15 +973,63 @@ dependencies = [ ] [[package]] +name = "memoffset" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" +dependencies = [ + "autocfg", +] + +[[package]] name = "miniz_oxide" -version = "0.5.3" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f5c75688da582b8ffc1f1799e9db273f32133c49e048f614d22ec3256773ccc" +checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" dependencies = [ "adler", ] [[package]] +name = "mio" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5d732bc30207a6423068df043e3d02e0735b155ad7ce1a6f76fe2baa5b158de" +dependencies = [ + "libc", + "log", + "wasi", + "windows-sys", +] + +[[package]] +name = "nanorand" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a51313c5820b0b02bd422f4b44776fbf47961755c74ce64afc73bfad10226c3" +dependencies = [ + "getrandom", +] + +[[package]] +name = "notify" +version = "5.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed2c66da08abae1c024c01d635253e402341b4060a12e99b31c7594063bf490a" +dependencies = [ + "bitflags", + "crossbeam-channel", + "filetime", + "fsevent-sys", + "inotify", + "kqueue", + "libc", + "mio", + "walkdir", + "winapi", +] + +[[package]] name = "num-integer" version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -757,19 +1050,19 @@ dependencies = [ [[package]] name = "num_cpus" -version = "1.13.1" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" +checksum = "f6058e64324c71e02bc2b150e4f3bc8286db6c83092132ffa3f6b1eab0f9def5" dependencies = [ - "hermit-abi", + "hermit-abi 0.1.19", "libc", ] [[package]] name = "once_cell" -version = "1.12.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7709cef83f0c1f58f666e746a08b21e0085f7440fa6a29cc194d68aac97a4225" +checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860" [[package]] name = "oorandom" @@ -778,16 +1071,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" [[package]] -name = "opaque-debug" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" - -[[package]] name = "os_str_bytes" -version = "6.1.0" +version = "6.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21326818e99cfe6ce1e524c2a805c189a99b5ae555a35d19f9a284b427d86afa" +checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee" [[package]] name = "parking_lot" @@ -801,9 +1088,9 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.3" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09a279cbf25cb0757810394fbc1e359949b59e348145c643a939a525692e6929" +checksum = "7ff9f3fef3968a3ec5945535ed654cb38ff72d7495a25619e2247fb15a2ed9ba" dependencies = [ "cfg-if", "libc", @@ -814,24 +1101,25 @@ dependencies = [ [[package]] name = "percent-encoding" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" +checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" [[package]] name = "pest" -version = "2.1.3" +version = "2.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53" +checksum = "cc8bed3549e0f9b0a2a78bf7c0018237a2cdf085eecbbc048e52612438e4e9d0" dependencies = [ + "thiserror", "ucd-trie", ] [[package]] name = "pest_derive" -version = "2.1.0" +version = "2.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "833d1ae558dc601e9a60366421196a8d94bc0ac980476d0b67e1d0988d72b2d0" +checksum = "cdc078600d06ff90d4ed238f0119d84ab5d43dbaad278b0e33a8820293b32344" dependencies = [ "pest", "pest_generator", @@ -839,9 +1127,9 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.1.3" +version = "2.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99b8db626e31e5b81787b9783425769681b347011cc59471e33ea46d2ea0cf55" +checksum = "28a1af60b1c4148bb269006a750cff8e2ea36aff34d2d96cf7be0b14d1bed23c" dependencies = [ "pest", "pest_meta", @@ -852,74 +1140,78 @@ dependencies = [ [[package]] name = "pest_meta" -version = "2.1.3" +version = "2.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54be6e404f5317079812fc8f9f5279de376d8856929e21c184ecf6bbd692a11d" +checksum = "fec8605d59fc2ae0c6c1aefc0c7c7a9769732017c0ce07f7a9cfffa7b4404f20" dependencies = [ - "maplit", + "once_cell", "pest", - "sha-1", + "sha1", ] [[package]] -name = "petgraph" -version = "0.6.2" +name = "phf" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6d5014253a1331579ce62aa67443b4a658c5e7dd03d4bc6d302b94474888143" +checksum = "928c6535de93548188ef63bb7c4036bd415cd8f36ad25af44b9789b2ee72a48c" dependencies = [ - "fixedbitset", - "indexmap", + "phf_shared", ] [[package]] -name = "phf" -version = "0.10.1" +name = "phf_codegen" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259" +checksum = "a56ac890c5e3ca598bbdeaa99964edb5b0258a583a9eb6ef4e89fc85d9224770" dependencies = [ - "phf_macros", + "phf_generator", "phf_shared", - "proc-macro-hack", ] [[package]] name = "phf_generator" -version = "0.10.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6" +checksum = "b1181c94580fa345f50f19d738aaa39c0ed30a600d95cb2d3e23f94266f14fbf" dependencies = [ "phf_shared", "rand", ] [[package]] -name = "phf_macros" -version = "0.10.0" +name = "phf_shared" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58fdf3184dd560f160dd73922bea2d5cd6e8f064bf4b13110abd81b03697b4e0" +checksum = "e1fb5f6f826b772a8d4c0394209441e7d37cbbb967ae9c7e0e8134365c9ee676" dependencies = [ - "phf_generator", - "phf_shared", - "proc-macro-hack", - "proc-macro2", - "quote", - "syn", + "siphasher", ] [[package]] -name = "phf_shared" -version = "0.10.0" +name = "pin-project" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" +checksum = "ad29a609b6bcd67fee905812e544992d216af9d755757c05ed2d0e15a74c6ecc" dependencies = [ - "siphasher", + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55" +dependencies = [ + "proc-macro2", + "quote", + "syn", ] [[package]] name = "plotters" -version = "0.3.1" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a3fd9ec30b9749ce28cd91f255d569591cdf937fe280c312143e3c4bad6f2a" +checksum = "2538b639e642295546c50fcd545198c9d64ee2a38620a628724a3b266d5fbf97" dependencies = [ "num-traits", "plotters-backend", @@ -930,26 +1222,20 @@ dependencies = [ [[package]] name = "plotters-backend" -version = "0.3.2" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d88417318da0eaf0fdcdb51a0ee6c3bed624333bff8f946733049380be67ac1c" +checksum = "193228616381fecdc1224c62e96946dfbc73ff4384fba576e052ff8c1bea8142" [[package]] name = "plotters-svg" -version = "0.3.1" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "521fa9638fa597e1dc53e9412a4f9cefb01187ee1f7413076f9e6749e2885ba9" +checksum = "f9a81d2759aae1dae668f783c308bc5c8ebd191ff4184aaa1b37f65a6ae5a56f" dependencies = [ "plotters-backend", ] [[package]] -name = "ppv-lite86" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" - -[[package]] name = "proc-macro-error" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -974,25 +1260,19 @@ dependencies = [ ] [[package]] -name = "proc-macro-hack" -version = "0.5.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" - -[[package]] name = "proc-macro2" -version = "1.0.40" +version = "1.0.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd96a1e8ed2596c337f8eae5f24924ec83f5ad5ab21ea8e455d3566c69fbcaf7" +checksum = "e9d89e5dba24725ae5678020bf8f1357a9aa7ff10736b551adbcd3f8d17d766f" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.20" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bcdf212e9776fbcb2d23ab029360416bb1706b1aea2d1a5ba002727cbcab804" +checksum = "556d0f47a940e895261e77dc200d5eadfc6ef644c179c6f5edfc105e3a2292c8" dependencies = [ "proc-macro2", ] @@ -1003,47 +1283,30 @@ version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ - "libc", - "rand_chacha", - "rand_core", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", "rand_core", ] [[package]] name = "rand_core" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" -dependencies = [ - "getrandom", -] +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" [[package]] name = "rayon" -version = "1.5.3" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd99e5772ead8baa5215278c9b15bf92087709e9c1b2d1f97cdb5a183c933a7d" +checksum = "6db3a213adf02b3bcfd2d3846bb41cb22857d131789e01df434fb7e7bc0759b7" dependencies = [ - "autocfg", - "crossbeam-deque", "either", "rayon-core", ] [[package]] name = "rayon-core" -version = "1.9.3" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "258bcdb5ac6dad48491bb2992db6b7cf74878b0384908af124823d118c99683f" +checksum = "cac410af5d00ab6884528b4ab69d1e8e146e8d471201800fa1b4524126de6ad3" dependencies = [ "crossbeam-channel", "crossbeam-deque", @@ -1053,18 +1316,29 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.2.13" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62f25bc4c7e55e0b0b7a1d43fb893f4fa1361d0abe38b9ce4f323c2adfe6ef42" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" dependencies = [ "bitflags", ] [[package]] +name = "redox_users" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" +dependencies = [ + "getrandom", + "redox_syscall", + "thiserror", +] + +[[package]] name = "regex" -version = "1.5.6" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d83f127d94bdbcda4c8cc2e50f6f84f4b611f69c902699ca385a39c3a75f9ff1" +checksum = "e076559ef8e241f2ae3479e36f97bd5741c0330689e217ad51ce2c76808b868a" dependencies = [ "aho-corasick", "memchr", @@ -1072,16 +1346,10 @@ dependencies = [ ] [[package]] -name = "regex-automata" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" - -[[package]] name = "regex-syntax" -version = "0.6.26" +version = "0.6.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49b3de9ec5dc0a3417da371aab17d729997c15010e7fd24ff707773a33bddb64" +checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" [[package]] name = "remove_dir_all" @@ -1094,13 +1362,13 @@ dependencies = [ [[package]] name = "rowan" -version = "0.15.5" +version = "0.15.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce1f383129e417a6265b16ed78e6e9307748f0863b2ba75f78ff14717db5b017" +checksum = "5811547e7ba31e903fe48c8ceab10d40d70a101f3d15523c847cce91aa71f332" dependencies = [ "countme", "hashbrown", - "memoffset", + "memoffset 0.6.5", "rustc-hash", "text-size", ] @@ -1112,25 +1380,60 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] -name = "rustc_version" -version = "0.4.0" +name = "rustix" +version = "0.36.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +checksum = "a3807b5d10909833d3e9acd1eb5fb988f79376ff10fce42937de71a449c4c588" dependencies = [ - "semver", + "bitflags", + "errno", + "io-lifetimes", + "libc", + "linux-raw-sys", + "windows-sys", ] [[package]] name = "rustversion" -version = "1.0.7" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0a5f7c728f5d284929a1cccb5bc19884422bfe6ef4d6c409da2c41838983fcf" +checksum = "97477e48b4cf8603ad5f7aaf897467cf42ab4218a38ef76fb14c2d6773a6d6a8" [[package]] name = "ryu" -version = "1.0.10" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3f6f92acf49d1b98f7a81226834412ada05458b7364277387724a237f062695" +checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde" + +[[package]] +name = "salsa-2022" +version = "0.1.0" +source = "git+https://github.com/salsa-rs/salsa?rev=20c7834ff34fd00a41b59bec61f3d5c85ea3abd4#20c7834ff34fd00a41b59bec61f3d5c85ea3abd4" +dependencies = [ + "arc-swap", + "crossbeam", + "crossbeam-utils", + "dashmap", + "hashlink", + "indexmap", + "log", + "parking_lot", + "rustc-hash", + "salsa-2022-macros", + "smallvec", +] + +[[package]] +name = "salsa-2022-macros" +version = "0.1.0" +source = "git+https://github.com/salsa-rs/salsa?rev=20c7834ff34fd00a41b59bec61f3d5c85ea3abd4#20c7834ff34fd00a41b59bec61f3d5c85ea3abd4" +dependencies = [ + "eyre", + "heck", + "proc-macro2", + "quote", + "syn", +] [[package]] name = "same-file" @@ -1148,35 +1451,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] -name = "semver" -version = "1.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2333e6df6d6598f2b1974829f853c2b4c5f4a6e503c10af918081aa6f8564e1" - -[[package]] name = "serde" -version = "1.0.138" +version = "1.0.151" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1578c6245786b9d168c5447eeacfb96856573ca56c9d68fdcf394be134882a47" +checksum = "97fed41fc1a24994d044e6db6935e69511a1153b52c15eb42493b26fa87feba0" dependencies = [ "serde_derive", ] [[package]] -name = "serde_cbor" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bef2ebfde456fb76bbcf9f59315333decc4fda0b2b44b420243c11e0f5ec1f5" -dependencies = [ - "half", - "serde", -] - -[[package]] name = "serde_derive" -version = "1.0.138" +version = "1.0.151" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "023e9b1467aef8a10fb88f25611870ada9800ef7e22afce356bb0d2387b6f27c" +checksum = "255abe9a125a985c05190d687b320c12f9b1f0b99445e608c21ba0782c719ad8" dependencies = [ "proc-macro2", "quote", @@ -1185,16 +1472,25 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.82" +version = "1.0.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82c2c1fdcd807d1098552c5b9a36e425e42e9fbd7c6a37a8425f390f781f7fa7" +checksum = "8778cc0b528968fe72abec38b5db5a20a70d148116cd9325d2bc5f5180ca3faf" dependencies = [ - "itoa 1.0.2", + "itoa", "ryu", "serde", ] [[package]] +name = "serde_millis" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e2dc780ca5ee2c369d1d01d100270203c4ff923d2a4264812d723766434d00" +dependencies = [ + "serde", +] + +[[package]] name = "serde_regex" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1206,9 +1502,9 @@ dependencies = [ [[package]] name = "serde_repr" -version = "0.1.8" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2ad84e47328a31223de7fed7a4f5087f2d6ddfe586cf3ca25b7a165bc0a5aed" +checksum = "9a5ec9fa74a20ebbe5d9ac23dac1fc96ba0ecfe9f50f2843b52e537b10fbcb4e" dependencies = [ "proc-macro2", "quote", @@ -1216,34 +1512,21 @@ dependencies = [ ] [[package]] -name = "serde_yaml" -version = "0.8.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "707d15895415db6628332b737c838b88c598522e4dc70647e59b72312924aebc" -dependencies = [ - "indexmap", - "ryu", - "serde", - "yaml-rust", -] - -[[package]] -name = "sha-1" -version = "0.8.2" +name = "sha1" +version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df" +checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" dependencies = [ - "block-buffer", + "cfg-if", + "cpufeatures", "digest", - "fake-simd", - "opaque-debug", ] [[package]] name = "similar" -version = "2.1.0" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e24979f63a11545f5f2c60141afe249d4f19f84581ea2138065e400941d83d3" +checksum = "420acb44afdae038210c99e69aae24109f32f15500aa708e81d46c9f29d55fcf" [[package]] name = "siphasher" @@ -1253,18 +1536,18 @@ checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de" [[package]] name = "smallstr" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e922794d168678729ffc7e07182721a14219c65814e66e91b839a272fe5ae4f" +checksum = "63b1aefdf380735ff8ded0b15f31aab05daf1f70216c01c02a12926badd1df9d" dependencies = [ "smallvec", ] [[package]] name = "smallvec" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1" +checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" [[package]] name = "smol_str" @@ -1276,6 +1559,21 @@ dependencies = [ ] [[package]] +name = "spin" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f6002a767bff9e83f8eeecf883ecb8011875a21ae8da43bffb817a57e78cc09" +dependencies = [ + "lock_api", +] + +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] name = "strum" version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1286,9 +1584,9 @@ dependencies = [ [[package]] name = "strum_macros" -version = "0.24.2" +version = "0.24.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4faebde00e8ff94316c01800f9054fd2ba77d30d9e922541913051d1d978918b" +checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59" dependencies = [ "heck", "proc-macro2", @@ -1299,9 +1597,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.98" +version = "1.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c50aef8a904de4c23c788f104b7dddc7d6f79c647c7c8ce4cc8f73eb0ca773dd" +checksum = "09ee3a69cd2c7e06684677e5629b3878b253af05e4714964204279c6bc02cf0b" dependencies = [ "proc-macro2", "quote", @@ -1323,6 +1621,15 @@ dependencies = [ ] [[package]] +name = "termcolor" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" +dependencies = [ + "winapi-util", +] + +[[package]] name = "terminal_size" version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1334,21 +1641,22 @@ dependencies = [ [[package]] name = "texlab" -version = "4.2.0" +version = "5.0.0" dependencies = [ "anyhow", "assert_unordered", - "byteorder", "chrono", - "clap 3.2.8", + "clap 4.0.29", "criterion", "crossbeam-channel", "dashmap", - "derive_more", + "dirs", "encoding_rs", "encoding_rs_io", + "env_logger", "fern", "flate2", + "flume", "fuzzy-matcher", "human_name", "insta", @@ -1359,23 +1667,24 @@ dependencies = [ "logos", "lsp-server", "lsp-types", + "notify", "once_cell", - "petgraph", "regex", "rowan", "rustc-hash", + "salsa-2022", "serde", "serde_json", + "serde_millis", "serde_regex", "serde_repr", "smol_str", "strum", "tempfile", + "thiserror", "threadpool", "titlecase", "unicode-normalization", - "url", - "uuid", ] [[package]] @@ -1386,33 +1695,24 @@ checksum = "288cb548dbe72b652243ea797201f3d481a0609a967980fcc5b2315ea811560a" [[package]] name = "textwrap" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" -dependencies = [ - "unicode-width", -] - -[[package]] -name = "textwrap" -version = "0.15.0" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb" +checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" [[package]] name = "thiserror" -version = "1.0.31" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd829fe32373d27f76265620b5309d0340cb8550f523c1dda251d6298069069a" +checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.31" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0396bc89e626244658bef819e22d0cc459e795a5ebe878e6ec336d1674a8d79a" +checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f" dependencies = [ "proc-macro2", "quote", @@ -1464,25 +1764,26 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "titlecase" -version = "2.0.0" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea7a2f1a76e892e6c07c275e6e851400257304a6e34c0e4e32ebbd3871808802" +checksum = "38397a8cdb017cfeb48bf6c154d6de975ac69ffeed35980fde199d2ee0842042" dependencies = [ + "joinery", "lazy_static", "regex", ] [[package]] name = "typenum" -version = "1.15.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" +checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" [[package]] name = "ucd-trie" -version = "0.1.3" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c" +checksum = "9e79c4d996edb816c91e4308506774452e55e95c3c9de07b6729e17e15a5ef81" [[package]] name = "unicode-bidi" @@ -1491,31 +1792,31 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" [[package]] +name = "unicode-case-mapping" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "916a391c62ffbc5b6220fdafa353e93b530d21904d82ca1a2e29cdb5cfb4399f" + +[[package]] name = "unicode-ident" -version = "1.0.1" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bd2fe26506023ed7b5e1e315add59d6f584c621d037f9368fea9cfb988f368c" +checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" [[package]] name = "unicode-normalization" -version = "0.1.21" +version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "854cbdc4f7bc6ae19c820d44abdc3277ac3e1b2b93db20a636825d9322fb60e6" +checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" dependencies = [ "tinyvec", ] [[package]] name = "unicode-segmentation" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e8820f5d777f6224dc4be3632222971ac30164d4a258d595640799554ebfd99" - -[[package]] -name = "unicode-width" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" +checksum = "0fdbf052a0783de01e944a6ce7a8cb939e295b1e7be835a1112c3b9a7f047a5a" [[package]] name = "unidecode" @@ -1525,27 +1826,17 @@ checksum = "402bb19d8e03f1d1a7450e2bd613980869438e0666331be3e073089124aa1adc" [[package]] name = "url" -version = "2.2.2" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c" +checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643" dependencies = [ "form_urlencoded", "idna", - "matches", "percent-encoding", "serde", ] [[package]] -name = "uuid" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd6469f4314d5f1ffec476e05f17cc9a78bc7a27a6a857842170bdf8d6f98d2f" -dependencies = [ - "getrandom", -] - -[[package]] name = "version_check" version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1570,9 +1861,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.81" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c53b543413a17a202f4be280a7e5c62a1c69345f5de525ee64f8cfdbc954994" +checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -1580,13 +1871,13 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.81" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5491a68ab4500fa6b4d726bd67408630c3dbe9c4fe7bda16d5c82a1fd8c7340a" +checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142" dependencies = [ "bumpalo", - "lazy_static", "log", + "once_cell", "proc-macro2", "quote", "syn", @@ -1595,9 +1886,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.81" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c441e177922bc58f1e12c022624b6216378e5febc2f0533e41ba443d505b80aa" +checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1605,9 +1896,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.81" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d94ac45fcf608c1f45ef53e748d35660f168490c10b23704c7779ab8f5c3048" +checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" dependencies = [ "proc-macro2", "quote", @@ -1618,15 +1909,15 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.81" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a89911bd99e5f3659ec4acf9c4d93b0a90fe4a2a11f15328472058edc5261be" +checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" [[package]] name = "web-sys" -version = "0.3.58" +version = "0.3.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fed94beee57daf8dd7d51f2b15dc2bcde92d7a72304cdf662a4371008b71b90" +checksum = "bcda906d8be16e728fd5adc5b729afad4e444e106ab28cd1c7256e54fa61510f" dependencies = [ "js-sys", "wasm-bindgen", @@ -1665,46 +1956,60 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-sys" -version = "0.36.1" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" +checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" dependencies = [ + "windows_aarch64_gnullvm", "windows_aarch64_msvc", "windows_i686_gnu", "windows_i686_msvc", "windows_x86_64_gnu", + "windows_x86_64_gnullvm", "windows_x86_64_msvc", ] [[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e" + +[[package]] name = "windows_aarch64_msvc" -version = "0.36.1" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" +checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4" [[package]] name = "windows_i686_gnu" -version = "0.36.1" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" +checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7" [[package]] name = "windows_i686_msvc" -version = "0.36.1" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" +checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246" [[package]] name = "windows_x86_64_gnu" -version = "0.36.1" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" +checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028" [[package]] name = "windows_x86_64_msvc" -version = "0.36.1" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" +checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5" [[package]] name = "yaml-rust" diff --git a/support/texlab/Cargo.toml b/support/texlab/Cargo.toml index 803f280e39..62e487b394 100644 --- a/support/texlab/Cargo.toml +++ b/support/texlab/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "texlab" description = "LaTeX Language Server" -version = "4.2.0" +version = "5.0.0" license = "GPL-3.0" readme = "README.md" authors = [ @@ -9,7 +9,7 @@ authors = [ "Patrick Förster <patrick.foerster@outlook.de>", ] edition = "2021" -rust-version = "1.58.1" +rust-version = "1.60" homepage = "https://github.com/latex-lsp/texlab" repository = "https://github.com/latex-lsp/texlab" documentation = "https://github.com/latex-lsp/texlab" @@ -33,55 +33,54 @@ test = false [lib] doctest = false -[features] -default = ["completion"] -completion = ["fuzzy-matcher"] - [dependencies] -anyhow = "1.0.58" -byteorder = "1.4.3" -chrono = { version = "0.4.19", default-features = false, features = ["std"] } -clap = { version = "3.2.8", features = [ - "std", - "derive", -], default-features = false } -crossbeam-channel = "0.5.5" -dashmap = "~5.2.0" -derive_more = "0.99.17" +anyhow = "1.0.66" +chrono = { version = "0.4.23", default-features = false, features = ["std"] } +clap = { version = "4.0.29", features = ["derive"] } +crossbeam-channel = "0.5.6" +dashmap = "5.4.0" +dirs = "4.0.0" encoding_rs = "0.8.31" encoding_rs_io = "0.1.7" -fern = "0.6" -flate2 = "1.0.24" -fuzzy-matcher = { version = "0.3.7", optional = true } -human_name = { version = "1.0.3", default-features = false } +fern = "0.6.1" +flate2 = "1.0.25" +flume = "0.10.14" +fuzzy-matcher = { version = "0.3.7", features = ["compact"] } +human_name = { version = "2.0.1", default-features = false } isocountry = "0.3.2" -itertools = "0.10.1" +itertools = "0.10.5" log = "0.4.17" logos = "0.12.1" lsp-server = "0.6.0" -lsp-types = "0.93.0" -once_cell = "1.10.0" -petgraph = "0.6.2" -regex = "1.5.5" -rowan = "0.15.5" +lsp-types = { version = "0.93.2", features = ["proposed"] } +notify = "5.0.0" +once_cell = "1.16.0" +regex = "1.7.0" +rowan = "0.15.10" rustc-hash = "1.1.0" -serde = "1.0.137" -serde_json = "1.0.82" +serde = "1.0.151" +serde_json = "1.0.90" +serde_millis = "0.1.1" serde_regex = "1.1.0" -serde_repr = "0.1.8" +serde_repr = "0.1.10" smol_str = { version = "0.1.23", features = ["serde"] } -strum = { version = "0.24.0", features = ["derive"] } +strum = { version = "0.24.1", features = ["derive"] } tempfile = "3.3.0" +thiserror = "1.0.38" threadpool = "1.8.1" -titlecase = "2.0.0" -unicode-normalization = "0.1.20" -url = { version = "2.2.2", features = ["serde"] } -uuid = { version = "1.1.2", features = ["v4"] } +titlecase = "2.2.1" +unicode-normalization = "0.1.22" + +[dependencies.salsa] +git = "https://github.com/salsa-rs/salsa" +rev = "20c7834ff34fd00a41b59bec61f3d5c85ea3abd4" +package = "salsa-2022" [dev-dependencies] assert_unordered = "0.3.5" -criterion = { version = "0.3.5" } -insta = { version = "1.15.0", features = ["backtrace", "redactions"] } +criterion = { version = "0.4.0" } +env_logger = "0.10.0" +insta = { version = "1.23.0", features = ["glob", "redactions", "json"] } jod-thread = "0.1.2" [profile.release] diff --git a/support/texlab/README.md b/support/texlab/README.md index e43082f20f..6e96e40f75 100644 --- a/support/texlab/README.md +++ b/support/texlab/README.md @@ -1,6 +1,7 @@ [![CI](https://github.com/latex-lsp/texlab/workflows/CI/badge.svg)](https://github.com/latex-lsp/texlab/actions) [![Coverage](https://codecov.io/gh/latex-lsp/texlab/branch/master/graph/badge.svg)](https://codecov.io/gh/latex-lsp/texlab) -[![Rust](https://img.shields.io/badge/rustc-1.58.1%2B-blue)](https://blog.rust-lang.org/2022/01/20/Rust-1.58.1.html) +![Rust](https://img.shields.io/badge/rustc-1.60%2B-blue) +[![Wiki](https://img.shields.io/badge/docs-Wiki-success)](https://github.com/latex-lsp/texlab/wiki) [![GitHub release](https://img.shields.io/github/release/latex-lsp/texlab?label=github)](https://github.com/latex-lsp/texlab/releases) [![crates.io](https://img.shields.io/crates/v/texlab)](https://crates.io/crates/texlab) @@ -12,7 +13,7 @@ A cross-platform implementation of the [Language Server Protocol](https://micros providing rich cross-editing support for the [LaTeX](https://www.latex-project.org/) typesetting system. The server may be used with [any editor that implements the Language Server Protocol](https://microsoft.github.io/language-server-protocol/implementors/tools/). -![Demo](docs/demo.gif) +![Demo](images/demo.gif) ## Getting Started @@ -30,7 +31,7 @@ For a list of supported package managers, you can take a look at [Repology](http A [TeX distribution](https://www.latex-project.org/get/#tex-distributions) is _not_ strictly required to use the server but TexLab cannot compile your documents without one. TexLab supports compiling using [Tectonic](https://tectonic-typesetting.github.io/). -For an example configuration, please see [here](docs/tectonic.md). +For an example configuration, please see [here](https://github.com/latex-lsp/texlab/wiki/Tectonic). On Windows, you may need to install [Microsoft Visual C++ Redistributable for Visual Studio 2015](https://www.microsoft.com/en-US/download/details.aspx?id=48145). @@ -59,7 +60,9 @@ There is no need for magic comments like `%!TEX root` and TexLab should figure out the dependencies of a file on its own. Note that you may need to set the `texlab.rootDirectory` option for some multi-folder projects. -TexLab features a variety of [options](docs/options.md) which can be used to configure features like building or [forward search](docs/previewing.md). +TexLab features a variety of options which can be used to configure features like building or forward search. + +See the [Wiki](https://github.com/latex-lsp/texlab/wiki) for more information. ## Development @@ -75,8 +78,6 @@ cargo test in the project folder. -For a list of custom messages, please see [here](docs/custom_messages.md). - ## Contributing See [CONTRIBUTING.md](CONTRIBUTING.md) for details on our code of conduct, and the process for submitting pull requests to us. diff --git a/support/texlab/benches/bench_main.rs b/support/texlab/benches/bench_main.rs index 44364c5d5e..196afb1f43 100644 --- a/support/texlab/benches/bench_main.rs +++ b/support/texlab/benches/bench_main.rs @@ -1,39 +1,22 @@ -use std::sync::Arc; - use criterion::{black_box, criterion_group, criterion_main, Criterion}; -use lsp_types::{ - CompletionParams, Position, TextDocumentIdentifier, TextDocumentPositionParams, Url, +use lsp_types::{Position, Url}; +use texlab::{ + db::{Language, Owner, Workspace}, + parser::parse_latex, + Database, }; -use texlab::{features::FeatureRequest, syntax::latex, DocumentLanguage, Workspace}; fn criterion_benchmark(c: &mut Criterion) { c.bench_function("LaTeX/Parser", |b| { - b.iter(|| latex::parse(black_box(include_str!("../texlab.tex")))); + b.iter(|| parse_latex(black_box(include_str!("../texlab.tex")))); }); c.bench_function("LaTeX/Completion/Command", |b| { - let uri = Arc::new(Url::parse("http://example.com/texlab.tex").unwrap()); - let text = Arc::new(include_str!("../texlab.tex").to_string()); - let mut workspace = Workspace::default(); - workspace - .open(Arc::clone(&uri), text, DocumentLanguage::Latex) - .unwrap(); - - b.iter(|| { - texlab::features::complete(FeatureRequest { - params: CompletionParams { - context: None, - partial_result_params: Default::default(), - work_done_progress_params: Default::default(), - text_document_position: TextDocumentPositionParams::new( - TextDocumentIdentifier::new(uri.as_ref().clone()), - Position::new(0, 1), - ), - }, - workspace: workspace.clone(), - uri: Arc::clone(&uri), - }) - }); + let uri = Url::parse("http://example.com/texlab.tex").unwrap(); + let text = include_str!("../texlab.tex").to_string(); + let mut db = Database::default(); + Workspace::get(&db).open(&mut db, uri.clone(), text, Language::Tex, Owner::Client); + b.iter(|| texlab::features::completion::complete(&db, &uri, Position::new(0, 1))); }); } diff --git a/support/texlab/docs/custom_commands.md b/support/texlab/docs/custom_commands.md deleted file mode 100644 index 2b85787f35..0000000000 --- a/support/texlab/docs/custom_commands.md +++ /dev/null @@ -1,21 +0,0 @@ -# Custom Commands - -The server provides the following commands through the `workspace/executeCommand` request: - -## texlab.cleanAuxiliary - -Removes the auxiliary files produced by compiling the specified LaTeX document. -At the moment, this command simply calls `latexmk -c` with the currently configured output directory. - -Parameters: - -- `document`: `TextDocumentIdentifier` (_Required_) - -## texlab.cleanArtifacts - -Removes the auxiliary files and the artifacts produced by compiling the specified LaTeX document. -At the moment, this command simply calls `latexmk -C` with the currently configured output directory. - -Parameters: - -- `document`: `TextDocumentIdentifier` (_Required_) diff --git a/support/texlab/docs/custom_messages.md b/support/texlab/docs/custom_messages.md deleted file mode 100644 index 0142a76342..0000000000 --- a/support/texlab/docs/custom_messages.md +++ /dev/null @@ -1,102 +0,0 @@ -# Custom Messages - -We extend the [Language Server Protocol](https://microsoft.github.io/language-server-protocol/specification) -with custom messages to provide better LaTeX integration. -These messages are _optional_ and it is up to the client to support them. - -## Build Request - -The build request is sent from the client to the server to build a given LaTeX document. - -_Request_: - -- method: 'textDocument/build' -- params: `BuildTextDocumentParams` defined as follows: - -```typescript -interface BuildTextDocumentParams { - /** - * The text document to build. - */ - textDocument: TextDocumentIdentifier; -} -``` - -_Response_: - -- result: `BuildResult` defined as follows: - -```typescript -interface BuildResult { - /** - * The status of the build process. - */ - status: BuildStatus; -} - -enum BuildStatus { - /** - * The build process terminated without any errors. - */ - Success = 0, - - /** - * The build process terminated with errors. - */ - Error = 1, - - /** - * The build process failed to start or crashed. - */ - Failure = 2, - - /** - * The build process was cancelled. - */ - Cancelled = 3, -} -``` - -## Forward Search Request - -The forward search request is sent from the client to the server when the user requests a forward search via SyncTeX. - -_Request_: - -- method: 'textDocument/forwardSearch' -- params: [`TextDocumentPositionParams`](https://microsoft.github.io/language-server-protocol/specification#textdocumentpositionparams) - -_Response_: - -- result: `ForwardSearchResult` defined as follows: - -```typescript -interface ForwardSearchResult { - /** - * The status of the previewer process. - */ - status: ForwardSearchStatus; -} - -enum ForwardSearchStatus { - /** - * The previewer process executed the command without any errors. - */ - Success = 0, - - /** - * The previewer process executed the command with errors. - */ - Error = 1, - - /** - * The previewer process failed to start or crashed. - */ - Failure = 2, - - /** - * The previewer command is not configured. - */ - Unconfigured = 3, -} -``` diff --git a/support/texlab/docs/lsp_kinds.md b/support/texlab/docs/lsp_kinds.md deleted file mode 100644 index 8d6ad6efc7..0000000000 --- a/support/texlab/docs/lsp_kinds.md +++ /dev/null @@ -1,31 +0,0 @@ -The following table describes the mapping of LaTeX and BibTeX structures -to their `CompletionItemKind` and `SymbolKind`. - -| LaTeX / BibTeX structure | CompletionItemKind | SymbolKind | -| ------------------------- | -------------------- | -------------------- | -| Command | `Function` (3) | `Function` (12) | -| Command Argument | `Value` (12) | `Number` (16) | -| Snippet | `Snippet` (15) | | -| Environment | `Enum` (13) | `Enum` (10) | -| Section | `Module` (9) | `Module` (2) | -| Float | `Method` (2) | `Method` (6) | -| Theorem | `Variable` (6) | `Variable` (13) | -| Equation | `Constant` (21) | `Constant` (14) | -| Enumeration Item | `EnumMember` (20) | `EnumMember` (22) | -| Label | `Constructor` (4) | `Constructor` (9) | -| Folder | `Folder` (19) | `Namespace` (3) | -| File | `File` (17) | `File` (1) | -| PGF Library | `Property` (10) | `Property` (7) | -| TikZ Library | `Property` (10) | `Property` (7) | -| Color | `Color` (16) | | -| Color Model | `Color` (16) | | -| Package | `Class` (7) | `Class` (5) | -| Class | `Class` (7) | `Class` (5) | -| BibTeX Entry (Misc) | `Interface` (8) | `Interface` (11) | -| BibTeX Entry (Article) | `Event` (23) | `Event` (24) | -| BibTeX Entry (Book) | `Struct` (22) | `Struct` (23) | -| BibTeX Entry (Collection) | `TypeParameter` (25) | `TypeParameter` (26) | -| BibTeX Entry (Part) | `Operator` (24) | `Operator` (25) | -| BibTeX Entry (Thesis) | `Unit` (11) | `Object` (19) | -| BibTeX String | `Text` (1) | `String` (15) | -| BibTeX Field | `Field` (5) | `Field` (8) | diff --git a/support/texlab/docs/options.md b/support/texlab/docs/options.md deleted file mode 100644 index 9b3599cce1..0000000000 --- a/support/texlab/docs/options.md +++ /dev/null @@ -1,225 +0,0 @@ -# Configuration - -This document describes the configuration settings -that the server will query from the LSP client / extension. - ---- - -## texlab.rootDirectory - -Defines the directory from which the source files get compiled. -You may need to set this property for multi-folder projects -where TexLab fails to detect the root document. - -**Type:** `string | null` - -**Default value**: `null` - ---- - -## texlab.build.executable - -Defines the executable of the LaTeX build tool. - -**Type:** `string` - -**Default value:** `latexmk` - ---- - -## texlab.build.args - -Defines additional arguments that are passed to the configured LaTeX build tool. -Note that flags and their arguments need to be separate -elements in this array. -To pass the arguments `-foo bar` to a build tool, -`latex.build.args` needs to be `["-foo", "bar"]`. -The placeholder `%f` will be replaced by the server. - -**Placeholders:** - -- `%f`: The path of the TeX file to compile. - -**Type:** `string[]` - -**Default value:** `["-pdf", "-interaction=nonstopmode", "-synctex=1", "%f"]` - ---- - -## texlab.build.forwardSearchAfter - -Set this property to `true` if you want to execute a forward search after a build. - -**Type:** `boolean` - -**Default value:** `false` - ---- - -## texlab.build.onSave - -Set this property to `true` if you want to compile the project after saving a file. - -**Type:** `boolean` - -**Default value:** `false` - ---- - -## texlab.auxDirectory - -Defines the directory containing the build artifacts. -Note that you need to set the output directory in `latex.build.args` too, -if you want to change the build directory. -In this case, use the `-outdir` flag for `latexmk`. - -**Type:** `string` - -**Default value:** `.` (the same directory as the TeX file) - ---- - -## texlab.forwardSearch.executable - -Defines the executable of the PDF previewer. -The previewer needs to support [SyncTeX](http://www.tug.org/TUGboat/tb29-3/tb93laurens.pdf). - -**Type:** `string | null` - -**Default value:** `null` - ---- - -## texlab.forwardSearch.args - -Defines additional arguments that are passed to the configured previewer to perform the forward search. -The placeholders `%f, %p, %l` will be replaced by the server. - -**Placeholders:** - -- `%f`: The path of the current TeX file. -- `%p`: The path of the current PDF file. -- `%l`: The current line number. - -**Type:** `string[] | null` - -**Default value:** `null` - ---- - -## texlab.chktex.onOpenAndSave - -Lint using [chktex](https://www.nongnu.org/chktex/) after opening and saving a file. - -**Type:** `boolean` - -**Default value:** `false` - ---- - -## texlab.chktex.onEdit - -Lint using [chktex](https://www.nongnu.org/chktex/) after editing a file. - -**Type:** `boolean` - -**Default value:** `false` - ---- - -## texlab.diagnosticsDelay - -Delay in milliseconds before reporting diagnostics. - -**Type:** `integer` - -**Default value:** `300` - ---- - -## texlab.diagnostics.allowedPatterns - -A list of regular expressions used to filter the list of reported diagnostics. -If specified, only diagnostics that match _at least one_ of the specified patterns -are sent to the client. - -See also [`texlab.diagnostics.ignoredPatterns`](#texlabdiagnosticsignoredpatterns). - -_Hint_: -If both `allowedPatterns` and `ignoredPatterns` are set, -then allowed patterns are applied first. Afterwards, the results are filtered with the ignored patterns. - -**Type:** `RegExp[]` - -**Default value:** `[]` - ---- - -## texlab.diagnostics.ignoredPatterns - -A list of regular expressions used to filter the list of reported diagnostics. -If specified, only diagnostics that match _none_ of the specified patterns -are sent to the client. - -See also [`texlab.diagnostics.allowedPatterns`](#texlabdiagnosticsallowedpatterns). - -**Type:** `RegExp[]` - -**Default value:** `[]` - ---- - -## texlab.formatterLineLength - -Defines the maximum amount of characters per line (0 = disable) when formatting BibTeX files. - -**Type:** `integer` - -**Default value:** `80` - ---- - -## texlab.bibtexFormatter - -Defines the formatter to use for BibTeX formatting. -Possible values are either `texlab` or `latexindent`. - -**Type:** `string` - -**Default value:** `texlab` - ---- - -## texlab.latexFormatter - -Defines the formatter to use for LaTeX formatting. -Possible values are either `texlab` or `latexindent`. -Note that `texlab` is not implemented yet. - -**Type:** `string` - -**Default value:** `latexindent` - ---- - -## texlab.latexindent.local - -Defines the path of a file containing the `latexindent` configuration. -This corresponds to the `--local=file.yaml` flag of `latexindent`. -By default the configuration inside the project root directory is used. - -**Type:** `string` - -**Default value:** `null` - ---- - -## texlab.latexindent.modifyLineBreaks - -Modifies linebreaks before, during, and at the end of code blocks -when formatting with `latexindent`. -This corresponds to the `--modifylinebreaks` flag of `latexindent`. - -**Type:** `boolean` - -**Default value:** `false` diff --git a/support/texlab/docs/previewing.md b/support/texlab/docs/previewing.md deleted file mode 100644 index 3e97390429..0000000000 --- a/support/texlab/docs/previewing.md +++ /dev/null @@ -1,195 +0,0 @@ -# Previewing - -`texlab` supports compiling LaTeX using a custom request (`textDocument/build`) -and by building a document after saving if configured to do so. -To enable building on save, simply set `texlab.build.onSave` to true. -Previewing can be configured in a variety of ways: - -1. If you are using `latexmk`, you can create a `.latexmkrc` file and call your viewer accordingly. - Afterwards, you can add the `-pv` flag to your `texlab.build.args`. - -2. If you want the PDF viewer to stay synchronized with the cursor position in your editor, - you can instruct `texlab` to execute a forward search after every build (`texlab.build.forwardSearchAfter`). - To do so, you need to enable [SyncTeX](http://www.tug.org/TUGboat/tb29-3/tb93laurens.pdf) - and update the `texlab.forwardSearch` configuration. - If you want to use this feature, we do _not_ recommend the `-pvc` flag - because `texlab` does not get notified by `latexmk` when a document gets built. - Instead, you can use `texlab.build.onSave`. - -In the following sections, we will give forward search configurations for several popular viewers. -If your viewer is not listed here, you can send us a pull request or create an issue. - -The inverse search configuration depends on the editor. -In this section, we will give instructions for [Visual Studio Code](https://code.visualstudio.com/). -However, these settings can easily be adapted to other editors. -Some plugins can help with setting up inverse search: - -- `Neovim`: [`f3fora/nvim-texlabconfig`](https://github.com/f3fora/nvim-texlabconfig) -- `Emacs`: [`ROCKTAKEY/lsp-latex`](https://github.com/ROCKTAKEY/lsp-latex#inverse-search) - ---- - -## SumatraPDF - -We highly recommend [SumatraPDF](https://www.sumatrapdfreader.org) on Windows -because Adobe Reader locks the opened PDF file and will therefore prevent further builds. - -### Forward Search - -Add the following lines to your editor config: - -```json -{ - "texlab.forwardSearch.executable": "C:/Users/{User}/AppData/Local/SumatraPDF/SumatraPDF.exe", - "texlab.forwardSearch.args": [ - "-reuse-instance", - "%p", - "-forward-search", - "%f", - "%l" - ] -} -``` - -### Inverse Search - -Add the following line to your SumatraPDF settings file (Menu -> Settings -> Advanced Options): - -```ini -InverseSearchCmdLine = "C:\Users\{User}\AppData\Local\Programs\Microsoft VS Code\Code.exe" -g "%f":%l -``` - -> **Note**: Please make sure to replace `{User}` with your Windows username. - -You can execute the search by pressing `Alt+DoubleClick` in the PDF document. - ---- - -## Evince - -The SyncTeX feature of [Evince](https://wiki.gnome.org/Apps/Evince) requires communication via D-Bus. -In order to use it from the command line, install the [evince-synctex](https://github.com/latex-lsp/evince-synctex) script. - -### Forward Search - -Add the following lines to your editor config: - -```json -{ - "texlab.forwardSearch.executable": "evince-synctex", - "texlab.forwardSearch.args": ["-f", "%l", "%p", "\"code -g %f:%l\""] -} -``` - -### Inverse Search - -The inverse search feature is already configured if you use `evince-synctex`. -You can execute the search by pressing `Ctrl+Click` in the PDF document. - ---- - -## Okular - -### Forward Search - -Add the following lines to your editor config: - -```json -{ - "texlab.forwardSearch.executable": "okular", - "texlab.forwardSearch.args": ["--editor-cmd": "code -g \"%%f\":%%l", "--unique", "file:%p#src:%l%f"] -} -``` - -### Inverse Search - -Change the editor of Okular (Settings -> Configure Okular... -> Editor) to "Custom Text Editor" and set the following command: - -```bash -code -g "%f":%l -``` - -You can execute the search by pressing `Shift+Click` in the PDF document. - ---- - -## Zathura - -### Forward Search - -Add the following lines to your editor config: - -```json -{ - "texlab.forwardSearch.executable": "zathura", - "texlab.forwardSearch.args": ["--synctex-forward", "%l:1:%f", "%p"] -} -``` - -### Inverse Search - -Add the following lines to your `~/.config/zathura/zathurarc` file: - -```bash -set synctex true -set synctex-editor-command "code -g %{input}:%{line}" -``` - -You can execute the search by pressing `Ctrl+Click` in the PDF document. - ---- - -## qpdfview - -### Forward Search - -Add the following lines to your editor config: - -```json -{ - "texlab.forwardSearch.executable": "qpdfview", - "texlab.forwardSearch.args": ["--unique", "%p#src:%f:%l:1"] -} -``` - -### Inverse Search - -Change the source editor setting (Edit -> Settings... -> Behavior -> Source editor) to: - -```bash -code -g "%1":%2 -``` - -and select a mouse button modifier (Edit -> Settings... -> Behavior -> Modifiers -> Mouse button modifiers -> Open in Source Editor) -of choice. -You can execute the search by pressing `Modifier+Click` in the PDF document. - ---- - -## Skim - -We recommend [Skim](https://skim-app.sourceforge.io/) on macOS since it is the only native viewer that supports SyncTeX. - -Additionally, enable the "Reload automatically" setting in the Skim preferences (Skim -> Preferences -> Sync -> Check for file changes). - -### Forward Search - -Add the following lines to your editor config: - -```json -{ - "texlab.forwardSearch.executable": "/Applications/Skim.app/Contents/SharedSupport/displayline", - "texlab.forwardSearch.args": ["%l", "%p", "%f"] -} -``` - -If you want Skim to stay in the background after -executing the forward search, you can add the `-g` option -to `texlab.forwardSearch.args`. - -### Inverse Search - -Select the Visual Studio Code preset in the Skim preferences (Skim -> Preferences -> Sync -> PDF-TeX Sync support). -You can execute the search by pressing `Shift+⌘+Click` in the PDF document. - ---- diff --git a/support/texlab/docs/tectonic.md b/support/texlab/docs/tectonic.md deleted file mode 100644 index b08e64b946..0000000000 --- a/support/texlab/docs/tectonic.md +++ /dev/null @@ -1,48 +0,0 @@ -# Usage with `tectonic` - -[`tectonic`](https://tectonic-typesetting.github.io/) is a modernized, alternative TeX engine. -Most features of `texlab` work out of the box when using `tectonic`. -To compile documents through `texlab`, you need to change the configuration. -See `tectonic --help` for more information about the flags. - ---- - -**Hint:** - -Please make sure to set `texlab.auxDirectory` if you change the build directory with the `--outdir` argument. - -Also, `--keep-intermediates` is recommended because they allow `texlab` -to find out the section numbers and show them in the completion. -Without the `--keep-logs` flag, `texlab` won't be able to report compilation warnings. - ---- - -## V2 CLI - -```json -{ - "texlab.build.executable": "tectonic", - "texlab.build.args": [ - "-X", - "compile", - "%f", - "--synctex", - "--keep-logs", - "--keep-intermediates" - ] -} -``` - -## V1 CLI - -```json -{ - "texlab.build.executable": "tectonic", - "texlab.build.args": [ - "%f", - "--synctex", - "--keep-logs", - "--keep-intermediates" - ] -} -``` diff --git a/support/texlab/docs/demo.gif b/support/texlab/images/demo.gif Binary files differindex 6bb0817a59..6bb0817a59 100644 --- a/support/texlab/docs/demo.gif +++ b/support/texlab/images/demo.gif diff --git a/support/texlab/rust-toolchain b/support/texlab/rust-toolchain deleted file mode 100644 index 870bbe4e50..0000000000 --- a/support/texlab/rust-toolchain +++ /dev/null @@ -1 +0,0 @@ -stable
\ No newline at end of file diff --git a/support/texlab/src/citation/driver.rs b/support/texlab/src/citation/driver.rs index 815474a107..ab3fe6d80f 100644 --- a/support/texlab/src/citation/driver.rs +++ b/support/texlab/src/citation/driver.rs @@ -1,7 +1,7 @@ use isocountry::CountryCode; use itertools::Itertools; +use lsp_types::Url; use titlecase::titlecase; -use url::Url; use crate::syntax::bibtex; diff --git a/support/texlab/src/citation/field/date.rs b/support/texlab/src/citation/field/date.rs index b67972e691..4eba9cdea4 100644 --- a/support/texlab/src/citation/field/date.rs +++ b/support/texlab/src/citation/field/date.rs @@ -42,7 +42,7 @@ impl Add for DateFieldData { | (Self::Other(_), date) | (date, Self::Other(_)) => date, (Self::Year(year), Self::Month(month)) | (Self::Month(month), Self::Year(year)) => { - let new_date = NaiveDate::from_ymd(year, month.number_from_month(), 1); + let new_date = NaiveDate::from_ymd_opt(year, month.number_from_month(), 1).unwrap(); Self::Date(new_date) } (Self::Year(year), Self::Date(date)) | (Self::Date(date), Self::Year(year)) => { diff --git a/support/texlab/src/citation/tests.rs b/support/texlab/src/citation/tests.rs index 16aefea11d..6caff1add0 100644 --- a/support/texlab/src/citation/tests.rs +++ b/support/texlab/src/citation/tests.rs @@ -1,10 +1,10 @@ use insta::assert_snapshot; use rowan::ast::AstNode; -use crate::syntax::bibtex; +use crate::{parser::parse_bibtex, syntax::bibtex}; fn render_entry(input: &str) -> String { - let green = bibtex::parse(input); + let green = parse_bibtex(input); let root = bibtex::Root::cast(bibtex::SyntaxNode::new_root(green)).unwrap(); let entry = root.entries().next().unwrap(); super::render(&entry).unwrap() diff --git a/support/texlab/src/client.rs b/support/texlab/src/client.rs index 72f2ac9eba..ab912653b0 100644 --- a/support/texlab/src/client.rs +++ b/support/texlab/src/client.rs @@ -1,53 +1,109 @@ -use std::sync::Mutex; +use std::sync::{ + atomic::{AtomicI32, Ordering}, + Arc, +}; -use anyhow::{anyhow, Result}; -use crossbeam_channel::{Receiver, Sender}; -use lsp_server::{Message, ResponseError}; +use anyhow::{bail, Result}; +use crossbeam_channel::Sender; +use dashmap::DashMap; +use lsp_server::{ErrorCode, Message, Request, RequestId, Response}; +use lsp_types::{notification::ShowMessage, MessageType, ShowMessageParams}; use serde::{de::DeserializeOwned, Serialize}; -use crate::req_queue::{OutgoingData, ReqQueue}; +use crate::Options; -pub fn send_notification<N>(lsp_sender: &Sender<Message>, params: N::Params) -> Result<()> -where - N: lsp_types::notification::Notification, - N::Params: Serialize, -{ - lsp_sender.send(lsp_server::Notification::new(N::METHOD.to_string(), params).into())?; - Ok(()) +#[derive(Debug)] +struct RawClient { + sender: Sender<Message>, + next_id: AtomicI32, + pending: DashMap<RequestId, Sender<Response>>, } -pub fn send_request<R>( - req_queue: &Mutex<ReqQueue>, - lsp_sender: &Sender<Message>, - params: R::Params, -) -> Result<R::Result> -where - R: lsp_types::request::Request, - R::Params: Serialize, - R::Result: DeserializeOwned, -{ - let receiver = register_outgoing_request::<R>(req_queue, lsp_sender, params)?; - let params = receiver.recv()?.map_err(|err| anyhow!(err.message))?; - let result = serde_json::from_value(params)?; - Ok(result) +#[derive(Debug, Clone)] +pub struct LspClient { + raw: Arc<RawClient>, } -fn register_outgoing_request<R>( - req_queue: &Mutex<ReqQueue>, - lsp_sender: &Sender<Message>, - params: R::Params, -) -> Result<Receiver<Result<serde_json::Value, ResponseError>>> -where - R: lsp_types::request::Request, - R::Params: Serialize, - R::Result: DeserializeOwned, -{ - let mut req_queue = req_queue.lock().unwrap(); - let (sender, receiver) = crossbeam_channel::bounded(1); - let method = R::METHOD.to_string(); - let data = OutgoingData { sender }; - let req = req_queue.outgoing.register(method, params, data); - drop(req_queue); - lsp_sender.send(req.into())?; - Ok(receiver) +impl LspClient { + pub fn new(sender: Sender<Message>) -> Self { + let raw = Arc::new(RawClient { + sender, + next_id: AtomicI32::new(1), + pending: DashMap::default(), + }); + + Self { raw } + } + + pub fn send_notification<N>(&self, params: N::Params) -> Result<()> + where + N: lsp_types::notification::Notification, + N::Params: Serialize, + { + self.raw + .sender + .send(lsp_server::Notification::new(N::METHOD.to_string(), params).into())?; + Ok(()) + } + + pub fn send_request<R>(&self, params: R::Params) -> Result<R::Result> + where + R: lsp_types::request::Request, + R::Params: Serialize, + R::Result: DeserializeOwned, + { + let id = RequestId::from(self.raw.next_id.fetch_add(1, Ordering::SeqCst)); + + let (tx, rx) = crossbeam_channel::bounded(1); + self.raw.pending.insert(id.clone(), tx); + + self.raw + .sender + .send(Request::new(id, R::METHOD.to_string(), params).into())?; + + let response = rx.recv()?; + let result = match response.error { + Some(error) => bail!(error.message), + None => response.result.unwrap_or_default(), + }; + + Ok(serde_json::from_value(result)?) + } + + pub fn send_response(&self, response: lsp_server::Response) -> Result<()> { + self.raw.sender.send(response.into())?; + Ok(()) + } + + pub fn send_error(&self, id: RequestId, code: ErrorCode, message: String) -> Result<()> { + self.send_response(lsp_server::Response::new_err(id, code as i32, message))?; + Ok(()) + } + + pub fn recv_response(&self, response: lsp_server::Response) -> Result<()> { + let (_, tx) = self + .raw + .pending + .remove(&response.id) + .expect("response with known request id received"); + + tx.send(response)?; + Ok(()) + } + + pub fn parse_options(&self, value: serde_json::Value) -> Result<Options> { + let options = match serde_json::from_value(value) { + Ok(new_options) => new_options, + Err(why) => { + let message = format!( + "The texlab configuration is invalid; using the default settings instead.\nDetails: {why}" + ); + let typ = MessageType::WARNING; + self.send_notification::<ShowMessage>(ShowMessageParams { message, typ })?; + None + } + }; + + Ok(options.unwrap_or_default()) + } } diff --git a/support/texlab/src/component_db.rs b/support/texlab/src/component_db.rs deleted file mode 100644 index 8dc547369f..0000000000 --- a/support/texlab/src/component_db.rs +++ /dev/null @@ -1,151 +0,0 @@ -use std::io::Read; - -use flate2::read::GzDecoder; -use itertools::Itertools; -use lsp_types::{MarkupContent, MarkupKind}; -use once_cell::sync::Lazy; -use serde::{Deserialize, Serialize}; -use smol_str::SmolStr; - -use crate::{syntax::latex::ExplicitLink, Workspace}; - -#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct ComponentDatabase { - pub components: Vec<Component>, - pub metadata: Vec<ComponentMetadata>, -} - -impl ComponentDatabase { - #[must_use] - pub fn find(&self, name: &str) -> Option<&Component> { - self.components.iter().find(|component| { - component - .file_names - .iter() - .any(|file_name| file_name == name) - }) - } - - #[must_use] - pub fn find_no_ext(&self, name: &str) -> Option<&Component> { - self.components.iter().find(|component| { - component - .file_names - .iter() - .any(|file_name| &file_name[0..file_name.len() - 4] == name) - }) - } - - #[must_use] - pub fn linked_components(&self, workspace: &Workspace) -> Vec<&Component> { - let mut start_components = vec![self.kernel()]; - for document in workspace.documents_by_uri.values() { - if let Some(data) = document.data.as_latex() { - data.extras - .explicit_links - .iter() - .filter_map(ExplicitLink::as_component_name) - .filter_map(|name| self.find(&name)) - .for_each(|component| start_components.push(component)); - } - } - - let mut all_components = Vec::new(); - for component in start_components { - all_components.push(component); - component - .references - .iter() - .filter_map(|file| self.find(file)) - .for_each(|component| all_components.push(component)); - } - - all_components - .into_iter() - .unique_by(|component| &component.file_names) - .collect() - } - - #[must_use] - pub fn contains(&self, short_name: &str) -> bool { - let sty = format!("{}.sty", short_name); - let cls = format!("{}.cls", short_name); - self.find(&sty).is_some() || self.find(&cls).is_some() - } - - #[must_use] - pub fn kernel(&self) -> &Component { - self.components - .iter() - .find(|component| component.file_names.is_empty()) - .unwrap() - } - - #[must_use] - pub fn exists(&self, file_name: &str) -> bool { - self.components - .iter() - .any(|component| component.file_names.iter().any(|f| f == file_name)) - } - - #[must_use] - pub fn documentation(&self, name: &str) -> Option<MarkupContent> { - let metadata = self - .metadata - .iter() - .find(|metadata| metadata.name == name)?; - - let desc = metadata.description.clone()?; - Some(MarkupContent { - kind: MarkupKind::PlainText, - value: desc, - }) - } -} - -#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct Component { - pub file_names: Vec<SmolStr>, - pub references: Vec<SmolStr>, - pub commands: Vec<ComponentCommand>, - pub environments: Vec<SmolStr>, -} - -#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct ComponentCommand { - pub name: SmolStr, - pub image: Option<String>, - pub glyph: Option<SmolStr>, - pub parameters: Vec<ComponentParameter>, -} - -#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct ComponentParameter(pub Vec<ComponentArgument>); - -#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct ComponentArgument { - pub name: SmolStr, - pub image: Option<String>, -} - -#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct ComponentMetadata { - pub name: String, - pub caption: Option<String>, - pub description: Option<String>, -} - -const JSON_GZ: &[u8] = include_bytes!("../data/components.json.gz"); - -pub static COMPONENT_DATABASE: Lazy<ComponentDatabase> = Lazy::new(|| { - let mut decoder = GzDecoder::new(JSON_GZ); - let mut buf = String::new(); - decoder.read_to_string(&mut buf).unwrap(); - serde_json::from_str(&buf).unwrap() -}); diff --git a/support/texlab/src/db.rs b/support/texlab/src/db.rs new file mode 100644 index 0000000000..64165b76c2 --- /dev/null +++ b/support/texlab/src/db.rs @@ -0,0 +1,14 @@ +pub mod analysis; +pub mod diagnostics; +mod discovery; +mod document; +pub mod parse; +mod workspace; + +pub use {discovery::*, document::*, workspace::*}; + +#[salsa::interned] +pub struct Word { + #[return_ref] + pub text: String, +} diff --git a/support/texlab/src/db/analysis.rs b/support/texlab/src/db/analysis.rs new file mode 100644 index 0000000000..35ee4be2a1 --- /dev/null +++ b/support/texlab/src/db/analysis.rs @@ -0,0 +1,199 @@ +pub mod label; + +use rowan::{ast::AstNode, TextRange}; + +use crate::{ + syntax::latex::{self, HasCurly}, + Db, +}; + +use super::Word; + +#[salsa::tracked] +pub struct TexLink { + pub kind: TexLinkKind, + pub path: Word, + pub range: TextRange, + pub base_dir: Option<Word>, +} + +impl TexLink { + fn of_include(db: &dyn Db, node: latex::SyntaxNode, results: &mut Vec<Self>) -> Option<()> { + let include = latex::Include::cast(node)?; + let kind = match include.syntax().kind() { + latex::LATEX_INCLUDE => TexLinkKind::Tex, + latex::BIBLATEX_INCLUDE | latex::BIBTEX_INCLUDE => TexLinkKind::Bib, + latex::PACKAGE_INCLUDE => TexLinkKind::Sty, + latex::CLASS_INCLUDE => TexLinkKind::Cls, + _ => return None, + }; + + for path in include.path_list()?.keys() { + results.push(Self::new( + db, + kind, + Word::new(db, path.to_string()), + latex::small_range(&path), + None, + )); + } + + Some(()) + } + + fn of_import(db: &dyn Db, node: latex::SyntaxNode, results: &mut Vec<Self>) -> Option<()> { + let import = latex::Import::cast(node)?; + + let mut base_dir = import.directory()?.key()?.to_string(); + if !base_dir.ends_with("/") { + base_dir.push('/'); + } + + let path = import.file()?.key()?; + results.push(Self::new( + db, + TexLinkKind::Tex, + Word::new(db, path.to_string()), + latex::small_range(&path), + Some(Word::new(db, base_dir)), + )); + + Some(()) + } +} + +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash)] +pub enum TexLinkKind { + Sty, + Cls, + Tex, + Bib, +} + +impl TexLinkKind { + pub fn extensions(self) -> &'static [&'static str] { + match self { + Self::Sty => &["sty"], + Self::Cls => &["cls"], + Self::Tex => &["tex"], + Self::Bib => &["bib"], + } + } +} + +#[salsa::tracked] +pub struct TheoremEnvironment { + pub name: Word, + pub description: Word, +} + +impl TheoremEnvironment { + fn of_definition(db: &dyn Db, node: latex::SyntaxNode, results: &mut Vec<Self>) -> Option<()> { + let theorem = latex::TheoremDefinition::cast(node)?; + let name = theorem.name()?.key()?.to_string(); + let description = theorem.description()?; + let description = description.content_text()?; + + results.push(Self::new( + db, + Word::new(db, name), + Word::new(db, description), + )); + + Some(()) + } +} + +#[salsa::tracked] +pub struct GraphicsPath { + #[return_ref] + pub path: String, +} + +impl GraphicsPath { + pub fn of_command(db: &dyn Db, node: latex::SyntaxNode, results: &mut Vec<Self>) -> Option<()> { + let definition = latex::GraphicsPath::cast(node)?; + for path in definition + .path_list() + .filter_map(|group| group.key()) + .map(|path| path.to_string()) + { + results.push(GraphicsPath::new(db, path)); + } + + Some(()) + } +} + +#[salsa::tracked] +pub struct TexAnalysis { + #[return_ref] + pub links: Vec<TexLink>, + + #[return_ref] + pub labels: Vec<label::Name>, + + #[return_ref] + pub label_numbers: Vec<label::Number>, + + #[return_ref] + pub theorem_environments: Vec<TheoremEnvironment>, + + #[return_ref] + pub graphics_paths: Vec<GraphicsPath>, + + #[return_ref] + pub command_name_ranges: Vec<TextRange>, + + #[return_ref] + pub environment_names: Vec<String>, +} + +impl TexAnalysis { + pub(super) fn analyze(db: &dyn Db, root: &latex::SyntaxNode) -> Self { + let mut links = Vec::new(); + let mut labels = Vec::new(); + let mut label_numbers = Vec::new(); + let mut theorem_environments = Vec::new(); + let mut graphics_paths = Vec::new(); + let mut command_name_ranges = Vec::new(); + let mut environment_names = Vec::new(); + + for node in root.descendants() { + TexLink::of_include(db, node.clone(), &mut links) + .or_else(|| TexLink::of_import(db, node.clone(), &mut links)) + .or_else(|| label::Name::of_definition(db, node.clone(), &mut labels)) + .or_else(|| label::Name::of_reference(db, node.clone(), &mut labels)) + .or_else(|| label::Name::of_reference_range(db, node.clone(), &mut labels)) + .or_else(|| label::Number::of_number(db, node.clone(), &mut label_numbers)) + .or_else(|| { + TheoremEnvironment::of_definition(db, node.clone(), &mut theorem_environments) + }) + .or_else(|| GraphicsPath::of_command(db, node.clone(), &mut graphics_paths)) + .or_else(|| { + let range = latex::GenericCommand::cast(node.clone())? + .name()? + .text_range(); + + command_name_ranges.push(range); + Some(()) + }) + .or_else(|| { + let begin = latex::Begin::cast(node.clone())?; + environment_names.push(begin.name()?.key()?.to_string()); + Some(()) + }); + } + + Self::new( + db, + links, + labels, + label_numbers, + theorem_environments, + graphics_paths, + command_name_ranges, + environment_names, + ) + } +} diff --git a/support/texlab/src/db/analysis/label.rs b/support/texlab/src/db/analysis/label.rs new file mode 100644 index 0000000000..77ee5268eb --- /dev/null +++ b/support/texlab/src/db/analysis/label.rs @@ -0,0 +1,122 @@ +use rowan::{ + ast::{AstNode, AstPtr}, + TextRange, +}; + +use crate::{db::Word, syntax::latex, Db}; + +#[salsa::tracked] +pub struct Number { + pub name: Word, + pub text: Word, +} + +impl Number { + pub(super) fn of_number( + db: &dyn Db, + node: latex::SyntaxNode, + results: &mut Vec<Self>, + ) -> Option<()> { + let number = latex::LabelNumber::cast(node)?; + let name = number.name()?.key()?.to_string(); + let text = number + .text()? + .syntax() + .descendants_with_tokens() + .filter_map(|element| element.into_node()) + .find(|node| node.kind() == latex::TEXT || node.kind() == latex::MIXED_GROUP)? + .text() + .to_string(); + + results.push(Self::new(db, Word::new(db, name), Word::new(db, text))); + + Some(()) + } +} + +#[derive(Debug, PartialEq, Eq, Clone, Hash)] +pub enum Origin { + Definition(AstPtr<latex::LabelDefinition>), + Reference(AstPtr<latex::LabelReference>), + ReferenceRange(AstPtr<latex::LabelReferenceRange>), +} + +impl Origin { + pub fn as_definition(&self) -> Option<&AstPtr<latex::LabelDefinition>> { + match self { + Self::Definition(ptr) => Some(ptr), + _ => None, + } + } +} + +#[salsa::tracked] +pub struct Name { + pub origin: Origin, + pub name: Word, + pub range: TextRange, +} + +impl Name { + pub(super) fn of_definition( + db: &dyn Db, + node: latex::SyntaxNode, + results: &mut Vec<Self>, + ) -> Option<()> { + let label = latex::LabelDefinition::cast(node)?; + let name = label.name()?.key()?; + results.push(Self::new( + db, + Origin::Definition(AstPtr::new(&label)), + Word::new(db, name.to_string()), + latex::small_range(&name), + )); + + Some(()) + } + + pub(super) fn of_reference( + db: &dyn Db, + node: latex::SyntaxNode, + results: &mut Vec<Self>, + ) -> Option<()> { + let label = latex::LabelReference::cast(node)?; + for name in label.name_list()?.keys() { + results.push(Self::new( + db, + Origin::Reference(AstPtr::new(&label)), + Word::new(db, name.to_string()), + latex::small_range(&name), + )); + } + + Some(()) + } + + pub(super) fn of_reference_range( + db: &dyn Db, + node: latex::SyntaxNode, + results: &mut Vec<Self>, + ) -> Option<()> { + let label = latex::LabelReferenceRange::cast(node)?; + if let Some(name) = label.from().and_then(|name| name.key()) { + results.push(Self::new( + db, + Origin::ReferenceRange(AstPtr::new(&label)), + Word::new(db, name.to_string()), + latex::small_range(&name), + )); + } + + if let Some(name) = label.to().and_then(|name| name.key()) { + results.push(Self::new( + db, + Origin::ReferenceRange(AstPtr::new(&label)), + Word::new(db, name.to_string()), + latex::small_range(&name), + )); + } + + Some(()) + } +} diff --git a/support/texlab/src/db/diagnostics.rs b/support/texlab/src/db/diagnostics.rs new file mode 100644 index 0000000000..9b6691b873 --- /dev/null +++ b/support/texlab/src/db/diagnostics.rs @@ -0,0 +1,187 @@ +pub mod bib; +pub mod log; +pub mod tex; + +use lsp_types::{DiagnosticSeverity, NumberOrString, Range}; +use rustc_hash::FxHashMap; + +use crate::{db::workspace::Workspace, Db}; + +use super::document::{Document, Language}; + +#[derive(Debug, PartialEq, Eq, Clone)] +pub struct Diagnostic { + pub severity: DiagnosticSeverity, + pub range: Range, + pub code: DiagnosticCode, + pub message: String, +} + +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Hash)] +pub enum DiagnosticCode { + Tex(TexCode), + Bib(BibCode), + Log(Document), + Chktex(String), +} + +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash)] +pub enum TexCode { + UnexpectedRCurly, + RCurlyInserted, + MismatchedEnvironment, +} + +impl From<TexCode> for String { + fn from(code: TexCode) -> Self { + match code { + TexCode::UnexpectedRCurly => "Unexpected \"}\"".to_string(), + TexCode::RCurlyInserted => "Missing \"}\" inserted".to_string(), + TexCode::MismatchedEnvironment => "Mismatched environment".to_string(), + } + } +} + +impl From<TexCode> for NumberOrString { + fn from(code: TexCode) -> Self { + match code { + TexCode::UnexpectedRCurly => NumberOrString::Number(1), + TexCode::RCurlyInserted => NumberOrString::Number(2), + TexCode::MismatchedEnvironment => NumberOrString::Number(3), + } + } +} + +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash)] +#[allow(clippy::enum_variant_names)] +pub enum BibCode { + ExpectingLCurly, + ExpectingKey, + ExpectingRCurly, + ExpectingEq, + ExpectingFieldValue, +} + +impl From<BibCode> for String { + fn from(code: BibCode) -> Self { + match code { + BibCode::ExpectingLCurly => "Expecting a curly bracket: \"{\"".to_string(), + BibCode::ExpectingKey => "Expecting a key".to_string(), + BibCode::ExpectingRCurly => "Expecting a curly bracket: \"}\"".to_string(), + BibCode::ExpectingEq => "Expecting an equality sign: \"=\"".to_string(), + BibCode::ExpectingFieldValue => "Expecting a field value".to_string(), + } + } +} + +impl From<BibCode> for NumberOrString { + fn from(code: BibCode) -> Self { + match code { + BibCode::ExpectingLCurly => NumberOrString::Number(4), + BibCode::ExpectingKey => NumberOrString::Number(5), + BibCode::ExpectingRCurly => NumberOrString::Number(6), + BibCode::ExpectingEq => NumberOrString::Number(7), + BibCode::ExpectingFieldValue => NumberOrString::Number(8), + } + } +} + +#[salsa::tracked(return_ref)] +pub fn collect(db: &dyn Db, workspace: Workspace) -> FxHashMap<Document, Vec<Diagnostic>> { + let mut results: FxHashMap<Document, Vec<Diagnostic>> = FxHashMap::default(); + + for document in workspace.documents(db).iter().copied() { + match document.language(db) { + Language::Tex => { + results.entry(document).or_default().extend( + tex::collect(db, document) + .iter() + .chain(document.linter(db).chktex(db)) + .cloned(), + ); + } + Language::Bib => { + results + .entry(document) + .or_default() + .extend(bib::collect(db, document).iter().cloned()); + } + Language::Log => { + log::collect(db, workspace, document) + .iter() + .for_each(|(document, diagnostics)| { + results + .entry(*document) + .or_default() + .extend(diagnostics.clone()); + }); + } + } + } + + results +} + +#[salsa::tracked] +pub fn collect_filtered( + db: &dyn Db, + workspace: Workspace, +) -> FxHashMap<Document, Vec<lsp_types::Diagnostic>> { + let all_diagnostics = collect(db, workspace); + let mut all_filtered: FxHashMap<Document, Vec<lsp_types::Diagnostic>> = FxHashMap::default(); + + let options = &workspace.options(db).diagnostics; + for document in workspace.documents(db) { + let mut filtered = Vec::new(); + if !matches!(document.language(db), Language::Tex | Language::Bib) { + continue; + } + + if let Some(diagnostics) = all_diagnostics.get(document) { + for diagnostic in diagnostics.iter() { + if !options.allowed_patterns.is_empty() + && !options + .allowed_patterns + .iter() + .any(|pattern| pattern.0.is_match(&diagnostic.message)) + { + continue; + } + + if options + .ignored_patterns + .iter() + .any(|pattern| pattern.0.is_match(&diagnostic.message)) + { + continue; + } + + let source = match diagnostic.code { + DiagnosticCode::Tex(_) | DiagnosticCode::Bib(_) => "texlab", + DiagnosticCode::Log(_) => "latex-build", + DiagnosticCode::Chktex(_) => "chktex", + }; + + let code = match diagnostic.code.clone() { + DiagnosticCode::Tex(code) => Some(code.into()), + DiagnosticCode::Bib(code) => Some(code.into()), + DiagnosticCode::Chktex(code) => Some(NumberOrString::String(code)), + DiagnosticCode::Log(_) => None, + }; + + filtered.push(lsp_types::Diagnostic { + range: diagnostic.range, + code, + severity: Some(diagnostic.severity), + message: diagnostic.message.clone(), + source: Some(source.to_string()), + ..Default::default() + }); + } + } + + all_filtered.insert(*document, filtered); + } + + all_filtered +} diff --git a/support/texlab/src/db/diagnostics/bib.rs b/support/texlab/src/db/diagnostics/bib.rs new file mode 100644 index 0000000000..6d0f66e960 --- /dev/null +++ b/support/texlab/src/db/diagnostics/bib.rs @@ -0,0 +1,112 @@ +use lsp_types::DiagnosticSeverity; +use rowan::{ast::AstNode, TextRange}; + +use crate::{ + db::document::Document, + syntax::bibtex::{self, HasDelims, HasEq, HasName, HasType, HasValue}, + util::line_index_ext::LineIndexExt, + Db, +}; + +use super::{BibCode, Diagnostic, DiagnosticCode}; + +#[salsa::tracked(return_ref)] +pub fn collect(db: &dyn Db, document: Document) -> Vec<Diagnostic> { + let mut results = Vec::new(); + let data = match document.parse(db).as_bib() { + Some(data) => data, + None => return results, + }; + + for node in data.root(db).descendants() { + analyze_entry(db, document, node.clone(), &mut results) + .or_else(|| analyze_field(db, document, node, &mut results)); + } + + results +} + +fn analyze_entry( + db: &dyn Db, + document: Document, + node: bibtex::SyntaxNode, + results: &mut Vec<Diagnostic>, +) -> Option<()> { + let line_index = document.contents(db).line_index(db); + + let entry = bibtex::Entry::cast(node)?; + if entry.left_delim_token().is_none() { + let code = BibCode::ExpectingLCurly; + results.push(Diagnostic { + severity: DiagnosticSeverity::ERROR, + range: line_index.line_col_lsp_range(entry.type_token()?.text_range()), + code: DiagnosticCode::Bib(code), + message: String::from(code), + }); + + return Some(()); + } + + if entry.name_token().is_none() { + let code = BibCode::ExpectingKey; + results.push(Diagnostic { + severity: DiagnosticSeverity::ERROR, + range: line_index.line_col_lsp_range(entry.left_delim_token()?.text_range()), + code: DiagnosticCode::Bib(code), + message: String::from(code), + }); + + return Some(()); + } + + if entry.right_delim_token().is_none() { + let code = BibCode::ExpectingRCurly; + results.push(Diagnostic { + severity: DiagnosticSeverity::ERROR, + range: line_index + .line_col_lsp_range(TextRange::empty(entry.syntax().text_range().end())), + code: DiagnosticCode::Bib(code), + message: String::from(code), + }); + + return Some(()); + } + + Some(()) +} + +fn analyze_field( + db: &dyn Db, + document: Document, + node: bibtex::SyntaxNode, + results: &mut Vec<Diagnostic>, +) -> Option<()> { + let line_index = document.contents(db).line_index(db); + + let field = bibtex::Field::cast(node)?; + if field.eq_token().is_none() { + let code = BibCode::ExpectingEq; + results.push(Diagnostic { + severity: DiagnosticSeverity::ERROR, + range: line_index.line_col_lsp_range(field.name_token()?.text_range()), + code: DiagnosticCode::Bib(code), + message: String::from(code), + }); + + return Some(()); + } + + if field.value().is_none() { + let code = BibCode::ExpectingFieldValue; + results.push(Diagnostic { + severity: DiagnosticSeverity::ERROR, + range: line_index.line_col_lsp_range(field.name_token()?.text_range()), + code: DiagnosticCode::Bib(code), + message: String::from(code), + }); + + return Some(()); + } + + Some(()) +} diff --git a/support/texlab/src/db/diagnostics/log.rs b/support/texlab/src/db/diagnostics/log.rs new file mode 100644 index 0000000000..436999259b --- /dev/null +++ b/support/texlab/src/db/diagnostics/log.rs @@ -0,0 +1,100 @@ +use lsp_types::{DiagnosticSeverity, Position, Range, Url}; +use rowan::{TextLen, TextRange, TextSize}; +use rustc_hash::FxHashMap; + +use crate::{ + db::{document::Document, workspace::Workspace}, + syntax::{BuildError, BuildErrorLevel}, + util::line_index_ext::LineIndexExt, + Db, +}; + +use super::{Diagnostic, DiagnosticCode}; + +#[salsa::tracked(return_ref)] +pub fn collect( + db: &dyn Db, + workspace: Workspace, + log_document: Document, +) -> FxHashMap<Document, Vec<Diagnostic>> { + let mut results = FxHashMap::default(); + + let log = match log_document.parse(db).as_log() { + Some(data) => data.log(db), + None => return results, + }; + + let root_document = match workspace.parents(db, log_document).iter().next().copied() { + Some(document) => document, + None => return results, + }; + + let base_path = match root_document + .location(db) + .path(db) + .as_deref() + .and_then(|path| path.parent()) + { + Some(path) => path, + None => return results, + }; + + for error in &log.errors { + let full_path = base_path.join(&error.relative_path); + let full_path_uri = if let Ok(uri) = Url::from_file_path(&full_path) { + uri + } else { + continue; + }; + + let severity = match error.level { + BuildErrorLevel::Error => DiagnosticSeverity::ERROR, + BuildErrorLevel::Warning => DiagnosticSeverity::WARNING, + }; + + let range = find_range_of_hint(db, workspace, &full_path_uri, error).unwrap_or_else(|| { + let line = error.line.unwrap_or(0); + Range::new(Position::new(line, 0), Position::new(line, 0)) + }); + + let diagnostic = Diagnostic { + severity, + range, + code: DiagnosticCode::Log(log_document), + message: error.message.clone(), + }; + + let tex_document = workspace + .lookup_uri(db, &full_path_uri) + .unwrap_or(root_document); + + results.entry(tex_document).or_default().push(diagnostic); + } + + results +} + +fn find_range_of_hint( + db: &dyn Db, + workspace: Workspace, + uri: &Url, + error: &BuildError, +) -> Option<Range> { + let document = workspace.lookup_uri(db, uri)?; + let text = document.contents(db).text(db); + let line = error.line? as usize; + let hint = error.hint.as_deref()?; + let line_index = document.contents(db).line_index(db); + + let line_start = line_index.newlines.get(line).copied()?; + let line_end = line_index + .newlines + .get(line + 1) + .copied() + .unwrap_or(text.text_len()); + + let line_text = &text[line_start.into()..line_end.into()]; + let hint_start = line_start + TextSize::try_from(line_text.find(hint)?).unwrap(); + let hint_end = hint_start + hint.text_len(); + Some(line_index.line_col_lsp_range(TextRange::new(hint_start, hint_end))) +} diff --git a/support/texlab/src/db/diagnostics/tex.rs b/support/texlab/src/db/diagnostics/tex.rs new file mode 100644 index 0000000000..50233f8bd6 --- /dev/null +++ b/support/texlab/src/db/diagnostics/tex.rs @@ -0,0 +1,125 @@ +use lsp_types::DiagnosticSeverity; +use rowan::{ast::AstNode, NodeOrToken, TextRange}; + +use crate::{db::document::Document, syntax::latex, util::line_index_ext::LineIndexExt, Db}; + +use super::{Diagnostic, DiagnosticCode, TexCode}; + +#[salsa::tracked(return_ref)] +pub fn collect(db: &dyn Db, document: Document) -> Vec<Diagnostic> { + let mut results = Vec::new(); + + if !document.location(db).uri(db).as_str().ends_with(".tex") { + return results; + } + + let data = match document.parse(db).as_tex() { + Some(data) => data, + None => return results, + }; + + for node in data.root(db).descendants() { + analyze_environment(db, document, node.clone(), &mut results) + .or_else(|| analyze_curly_group(db, document, node.clone(), &mut results)) + .or_else(|| analyze_curly_braces(document, db, node, &mut results)); + } + + results +} + +fn analyze_environment( + db: &dyn Db, + document: Document, + node: latex::SyntaxNode, + results: &mut Vec<Diagnostic>, +) -> Option<()> { + let environment = latex::Environment::cast(node)?; + let name1 = environment.begin()?.name()?.key()?; + let name2 = environment.end()?.name()?.key()?; + if name1 != name2 { + let code = TexCode::MismatchedEnvironment; + results.push(Diagnostic { + severity: DiagnosticSeverity::ERROR, + range: document + .contents(db) + .line_index(db) + .line_col_lsp_range(latex::small_range(&name1)), + code: DiagnosticCode::Tex(code), + message: String::from(code), + }); + } + + Some(()) +} + +fn analyze_curly_group( + db: &dyn Db, + document: Document, + node: latex::SyntaxNode, + results: &mut Vec<Diagnostic>, +) -> Option<()> { + if !matches!( + node.kind(), + latex::CURLY_GROUP + | latex::CURLY_GROUP_COMMAND + | latex::CURLY_GROUP_KEY_VALUE + | latex::CURLY_GROUP_WORD + | latex::CURLY_GROUP_WORD_LIST + ) { + return None; + } + + let is_inside_verbatim_environment = node + .ancestors() + .filter_map(latex::Environment::cast) + .filter_map(|env| env.begin()) + .filter_map(|begin| begin.name()) + .filter_map(|name| name.key()) + .any(|name| { + ["asy", "lstlisting", "minted", "verbatim"].contains(&name.to_string().as_str()) + }); + + if !is_inside_verbatim_environment + && !node + .children_with_tokens() + .filter_map(NodeOrToken::into_token) + .any(|token| token.kind() == latex::R_CURLY) + { + let code = TexCode::RCurlyInserted; + results.push(Diagnostic { + severity: DiagnosticSeverity::ERROR, + range: document + .contents(db) + .line_index(db) + .line_col_lsp_range(TextRange::empty(node.text_range().end())), + code: DiagnosticCode::Tex(code), + message: String::from(code), + }); + } + + Some(()) +} + +fn analyze_curly_braces( + document: Document, + db: &dyn Db, + node: rowan::SyntaxNode<latex::LatexLanguage>, + results: &mut Vec<Diagnostic>, +) -> Option<()> { + if node.kind() == latex::ERROR && node.first_token()?.text() == "}" { + let code = TexCode::UnexpectedRCurly; + results.push(Diagnostic { + severity: DiagnosticSeverity::ERROR, + range: document + .contents(db) + .line_index(db) + .line_col_lsp_range(node.text_range()), + code: DiagnosticCode::Tex(code), + message: String::from(code), + }); + + Some(()) + } else { + None + } +} diff --git a/support/texlab/src/db/discovery.rs b/support/texlab/src/db/discovery.rs new file mode 100644 index 0000000000..0e1ec314f7 --- /dev/null +++ b/support/texlab/src/db/discovery.rs @@ -0,0 +1,251 @@ +use std::path::Path; + +use itertools::Itertools; +use lsp_types::Url; +use rustc_hash::FxHashSet; + +use crate::{util::HOME_DIR, Db}; + +use super::{ + analysis::TexLink, + document::{Document, Language, Location, Owner}, + workspace::Workspace, +}; + +#[salsa::accumulator] +pub struct MissingDependencies(MissingDependency); + +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash)] +pub struct MissingDependency { + pub location: Location, +} + +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash)] +pub struct Dependency { + pub source: Document, + pub target: Document, + pub origin: Option<DependencyOrigin>, +} + +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash)] +pub struct DependencyOrigin { + pub link: TexLink, + pub old_base_dir: Location, + pub new_base_dir: Location, +} + +pub fn hidden_dependencies( + db: &dyn Db, + document: Document, + base_dir: Location, + dependencies: &mut Vec<Dependency>, +) { + dependencies.extend(hidden_dependency(db, document, base_dir, "log")); + dependencies.extend(hidden_dependency(db, document, base_dir, "aux")); +} + +#[salsa::tracked] +pub fn hidden_dependency( + db: &dyn Db, + source: Document, + base_dir: Location, + extension: &'static str, +) -> Option<Dependency> { + let workspace = Workspace::get(db); + + let stem = source.location(db).stem(db)?; + let name = format!("{stem}.{extension}"); + + let location = workspace.output_dir(db, base_dir).join(db, &name)?; + match workspace.lookup(db, location) { + Some(target) => Some(Dependency { + source, + target, + origin: None, + }), + None => { + MissingDependencies::push(db, MissingDependency { location }); + None + } + } +} + +pub fn source_dependencies<'db>( + db: &'db dyn Db, + source: Document, + base_dir: Location, +) -> impl Iterator<Item = Dependency> + 'db { + source + .parse(db) + .as_tex() + .into_iter() + .flat_map(|data| data.analyze(db).links(db)) + .filter_map(move |link| source_dependency(db, source, base_dir, *link)) +} + +#[salsa::tracked] +pub fn source_dependency( + db: &dyn Db, + source: Document, + base_dir: Location, + link: TexLink, +) -> Option<Dependency> { + let workspace = Workspace::get(db); + + let stem = link.path(db).text(db); + + let mut file_names = vec![stem.clone()]; + link.kind(db) + .extensions() + .iter() + .map(|ext| format!("{stem}.{ext}")) + .for_each(|name| file_names.push(name)); + + let file_name_db = workspace.file_name_db(db); + let distro_files = file_names + .iter() + .filter_map(|name| file_name_db.get(name)) + .filter(|path| { + HOME_DIR + .as_deref() + .map_or(false, |dir| path.starts_with(dir)) + }) + .flat_map(|path| Url::from_file_path(path)) + .map(|uri| Location::new(db, uri)); + + for location in file_names + .iter() + .filter_map(|file_name| base_dir.join(db, &file_name)) + .chain(distro_files) + { + match workspace.lookup(db, location) { + Some(target) => { + let origin = Some(DependencyOrigin { + link, + old_base_dir: base_dir, + new_base_dir: link + .base_dir(db) + .and_then(|path| base_dir.join(db, path.text(db))) + .unwrap_or(base_dir), + }); + + return Some(Dependency { + source, + target, + origin, + }); + } + None => { + MissingDependencies::push(db, MissingDependency { location }); + } + }; + } + + None +} + +#[derive(Debug, PartialEq, Eq, Clone, Hash)] +pub struct DependencyGraph { + pub start: Document, + pub edges: Vec<Dependency>, +} + +impl DependencyGraph { + pub fn preorder(&self) -> impl DoubleEndedIterator<Item = Document> + '_ { + std::iter::once(self.start) + .chain(self.edges.iter().map(|group| group.target)) + .unique() + } +} + +#[salsa::tracked] +pub fn dependency_graph(db: &dyn Db, start: Document) -> DependencyGraph { + let workspace = Workspace::get(db); + + let base_dir = workspace.working_dir(db, start.directory(db)); + let mut edges = Vec::new(); + let mut stack = vec![(start, base_dir)]; + let mut visited = FxHashSet::default(); + + while let Some((source, base_dir)) = stack.pop() { + for edge in source_dependencies(db, source, base_dir) { + edges.push(edge); + if visited.insert(edge.target) { + stack.push((edge.target, edge.origin.unwrap().new_base_dir)); + } + } + + hidden_dependencies(db, source, base_dir, &mut edges); + } + + DependencyGraph { start, edges } +} + +pub fn discover_dependencies(db: &mut dyn Db) { + let workspace = Workspace::get(db); + loop { + let mut changed = discover_parents(db, workspace); + + let paths: FxHashSet<_> = workspace + .documents(db) + .iter() + .flat_map(|&start| dependency_graph::accumulated::<MissingDependencies>(db, start)) + .filter_map(|link| link.location.path(db).as_deref()) + .filter(|path| path.is_file()) + .map(Path::to_path_buf) + .collect(); + + for path in paths { + if workspace.lookup_path(db, &path).is_none() { + let language = Language::from_path(&path).unwrap_or(Language::Tex); + changed |= workspace.load(db, &path, language, Owner::Server).is_some(); + } + } + + if !changed { + break; + } + } +} + +fn discover_parents(db: &mut dyn Db, workspace: Workspace) -> bool { + let mut changed = false; + + let dirs: FxHashSet<_> = workspace + .documents(db) + .iter() + .flat_map(|document| document.ancestor_dirs(db)) + .filter(|path| is_part_of_workspace(db, workspace, path)) + .map(Path::to_path_buf) + .collect(); + + for path in dirs + .iter() + .flat_map(std::fs::read_dir) + .flatten() + .flatten() + .filter(|entry| entry.file_type().map_or(false, |ty| ty.is_file())) + .map(|entry| entry.path()) + .filter(|path| Language::from_path(&path) == Some(Language::Tex)) + { + if workspace.lookup_path(db, &path).is_none() { + changed |= workspace + .load(db, &path, Language::Tex, Owner::Server) + .is_some(); + } + } + + changed +} + +fn is_part_of_workspace(db: &dyn Db, workspace: Workspace, path: &Path) -> bool { + let root_dirs = workspace.root_dirs(db); + if root_dirs.is_empty() { + return true; + } + + root_dirs + .iter() + .filter_map(|dir| dir.path(db).as_deref()) + .any(|dir| path.starts_with(dir)) +} diff --git a/support/texlab/src/db/document.rs b/support/texlab/src/db/document.rs new file mode 100644 index 0000000000..186bd06ab3 --- /dev/null +++ b/support/texlab/src/db/document.rs @@ -0,0 +1,193 @@ +use std::{ + ffi::OsStr, + path::{Path, PathBuf}, +}; + +use lsp_types::Url; +use rowan::{TextRange, TextSize}; + +use crate::{ + db::{ + diagnostics::Diagnostic, + parse::{BibDocumentData, LogDocumentData, TexDocumentData}, + }, + parser::{parse_bibtex, parse_build_log, parse_latex}, + util::line_index::LineIndex, + Db, +}; + +use super::{ + analysis::TexLinkKind, + parse::{self, DocumentData}, +}; + +#[salsa::interned] +pub struct Location { + #[return_ref] + pub uri: Url, +} + +#[salsa::tracked] +impl Location { + #[salsa::tracked(return_ref)] + pub fn path(self, db: &dyn Db) -> Option<PathBuf> { + let uri = self.uri(db); + if uri.scheme() == "file" { + uri.to_file_path().ok() + } else { + None + } + } + + pub fn stem<'db>(self, db: &'db dyn Db) -> Option<&'db str> { + let name = self.uri(db).path_segments()?.last()?; + let stem = name.rsplit_once('.').map_or(name, |(stem, _)| stem); + Some(stem) + } + + pub fn join(self, db: &dyn Db, path: &str) -> Option<Location> { + let uri = self.uri(db).join(path).ok()?; + Some(Location::new(db, uri)) + } + + pub fn into_dir(self, db: &dyn Db) -> Location { + if self.uri(db).path().ends_with("/") { + self.join(db, ".").unwrap() + } else { + self + } + } +} + +#[salsa::input] +pub struct Contents { + #[return_ref] + pub text: String, +} + +#[salsa::tracked] +impl Contents { + #[salsa::tracked(return_ref)] + pub fn line_index(self, db: &dyn Db) -> LineIndex { + LineIndex::new(self.text(db)) + } +} + +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash)] +pub enum Owner { + Client, + Server, +} + +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash)] +pub enum Language { + Tex, + Bib, + Log, +} + +impl Language { + pub fn from_path(path: &Path) -> Option<Self> { + path.extension() + .and_then(OsStr::to_str) + .and_then(Self::from_extension) + } + + pub fn from_extension(extension: &str) -> Option<Self> { + match extension.to_lowercase().as_str() { + "tex" | "sty" | "cls" | "def" | "lco" | "aux" | "rnw" => Some(Self::Tex), + "bib" | "bibtex" => Some(Self::Bib), + "log" => Some(Self::Log), + _ => None, + } + } + + pub fn from_id(id: &str) -> Option<Self> { + match id { + "tex" | "latex" => Some(Self::Tex), + "bib" | "bibtex" => Some(Self::Bib), + _ => None, + } + } +} + +#[salsa::input] +pub struct LinterData { + #[return_ref] + pub chktex: Vec<Diagnostic>, +} + +#[salsa::input] +pub struct Document { + pub location: Location, + pub contents: Contents, + pub language: Language, + pub owner: Owner, + pub cursor: TextSize, + pub linter: LinterData, +} + +impl Document { + pub fn edit(self, db: &mut dyn Db, range: TextRange, replace_with: &str) { + let mut text = self.contents(db).set_text(db).to(String::new()); + text.replace_range(std::ops::Range::<usize>::from(range), &replace_with); + self.contents(db).set_text(db).to(text); + self.set_cursor(db).to(range.start()); + } + + pub fn directory(self, db: &dyn Db) -> Location { + self.location(db).into_dir(db) + } + + pub fn ancestor_dirs<'db>(self, db: &'db dyn Db) -> impl Iterator<Item = &'db Path> + 'db { + self.location(db) + .path(db) + .as_deref() + .into_iter() + .flat_map(|path| path.ancestors()) + .skip(1) + } +} + +#[salsa::tracked] +impl Document { + #[salsa::tracked] + pub fn parse(self, db: &dyn Db) -> DocumentData { + let text = self.contents(db).text(db); + match self.language(db) { + Language::Tex => { + let data = TexDocumentData::new(db, parse_latex(text)); + parse::DocumentData::Tex(data) + } + Language::Bib => { + let data = BibDocumentData::new(db, parse_bibtex(text)); + DocumentData::Bib(data) + } + Language::Log => { + let data = LogDocumentData::new(db, parse_build_log(text)); + DocumentData::Log(data) + } + } + } + + #[salsa::tracked] + pub fn can_be_index(self, db: &dyn Db) -> bool { + self.parse(db).as_tex().map_or(false, |data| { + data.analyze(db) + .links(db) + .iter() + .filter(|link| link.kind(db) == TexLinkKind::Cls) + .any(|link| link.path(db).text(db) != "subfiles") + }) + } + + #[salsa::tracked] + pub fn can_be_built(self, db: &dyn Db) -> bool { + self.parse(db).as_tex().map_or(false, |data| { + data.analyze(db) + .links(db) + .iter() + .any(|link| link.kind(db) == TexLinkKind::Cls) + }) + } +} diff --git a/support/texlab/src/db/parse.rs b/support/texlab/src/db/parse.rs new file mode 100644 index 0000000000..d532c536a3 --- /dev/null +++ b/support/texlab/src/db/parse.rs @@ -0,0 +1,71 @@ +use crate::{ + db::analysis::TexAnalysis, + syntax::{bibtex, latex, BuildLog}, + Db, +}; + +#[salsa::interned] +pub struct TexDocumentData { + pub green: rowan::GreenNode, +} + +impl TexDocumentData { + pub fn root(self, db: &dyn Db) -> latex::SyntaxNode { + latex::SyntaxNode::new_root(self.green(db)) + } +} + +#[salsa::tracked] +impl TexDocumentData { + #[salsa::tracked] + pub fn analyze(self, db: &dyn Db) -> TexAnalysis { + let root = latex::SyntaxNode::new_root(self.green(db)); + TexAnalysis::analyze(db, &root) + } +} + +#[salsa::interned] +pub struct BibDocumentData { + pub green: rowan::GreenNode, +} + +impl BibDocumentData { + pub fn root(self, db: &dyn Db) -> bibtex::SyntaxNode { + bibtex::SyntaxNode::new_root(self.green(db)) + } +} + +#[salsa::interned] +pub struct LogDocumentData { + pub log: BuildLog, +} + +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash)] +pub enum DocumentData { + Tex(TexDocumentData), + Bib(BibDocumentData), + Log(LogDocumentData), +} + +impl DocumentData { + pub fn as_tex(self) -> Option<TexDocumentData> { + match self { + Self::Tex(data) => Some(data), + _ => None, + } + } + + pub fn as_bib(self) -> Option<BibDocumentData> { + match self { + Self::Bib(data) => Some(data), + _ => None, + } + } + + pub fn as_log(self) -> Option<LogDocumentData> { + match self { + Self::Log(data) => Some(data), + _ => None, + } + } +} diff --git a/support/texlab/src/db/workspace.rs b/support/texlab/src/db/workspace.rs new file mode 100644 index 0000000000..b8bdb27f1f --- /dev/null +++ b/support/texlab/src/db/workspace.rs @@ -0,0 +1,245 @@ +use std::{ + borrow::Cow, + path::{Path, PathBuf}, +}; + +use itertools::Itertools; +use lsp_types::{ClientCapabilities, ClientInfo, Url}; +use rowan::TextSize; +use rustc_hash::FxHashSet; + +use crate::{ + db::document::{Document, Location}, + distro::FileNameDB, + util::HOME_DIR, + Db, Options, +}; + +use super::{ + dependency_graph, + document::{Contents, Language, LinterData, Owner}, + Word, +}; + +#[salsa::input(singleton)] +pub struct Workspace { + #[return_ref] + pub documents: FxHashSet<Document>, + + #[return_ref] + pub options: Options, + + #[return_ref] + pub client_capabilities: ClientCapabilities, + + #[return_ref] + pub client_info: Option<ClientInfo>, + + #[return_ref] + pub root_dirs: Vec<Location>, + + #[return_ref] + pub file_name_db: FileNameDB, +} + +impl Workspace { + pub fn lookup(self, db: &dyn Db, location: Location) -> Option<Document> { + self.documents(db) + .iter() + .find(|document| document.location(db) == location) + .copied() + } + + pub fn lookup_uri(self, db: &dyn Db, uri: &Url) -> Option<Document> { + self.documents(db) + .iter() + .find(|document| document.location(db).uri(db) == uri) + .copied() + } + + pub fn lookup_path(self, db: &dyn Db, path: &Path) -> Option<Document> { + self.documents(db) + .iter() + .find(|document| document.location(db).path(db).as_deref() == Some(path)) + .copied() + } + + pub fn index_files<'db>(self, db: &'db dyn Db) -> impl Iterator<Item = Document> + 'db { + self.documents(db) + .iter() + .copied() + .filter(|&document| document.can_be_index(db)) + } + + pub fn open( + self, + db: &mut dyn Db, + uri: Url, + text: String, + language: Language, + owner: Owner, + ) -> Document { + let location = Location::new(db, uri); + let contents = Contents::new(db, text); + let cursor = TextSize::from(0); + match self.lookup(db, location) { + Some(document) => { + document.set_contents(db).to(contents); + document.set_language(db).to(language); + document.set_owner(db).to(owner); + document.set_cursor(db).to(cursor); + document + } + None => { + let document = Document::new( + db, + location, + contents, + language, + owner, + cursor, + LinterData::new(db, Vec::new()), + ); + + let mut documents = self.set_documents(db).to(FxHashSet::default()); + documents.insert(document); + self.set_documents(db).to(documents); + document + } + } + } + + pub fn load( + self, + db: &mut dyn Db, + path: &Path, + language: Language, + owner: Owner, + ) -> Option<Document> { + log::debug!("Loading document {} from disk...", path.display()); + + let uri = Url::from_file_path(path).ok()?; + let data = std::fs::read(path).ok()?; + let text = match String::from_utf8_lossy(&data) { + Cow::Borrowed(_) => unsafe { String::from_utf8_unchecked(data) }, + Cow::Owned(text) => text, + }; + + Some(self.open(db, uri, text, language, owner)) + } + + pub fn watch( + self, + db: &dyn Db, + watcher: &mut dyn notify::Watcher, + watched_dirs: &mut FxHashSet<PathBuf>, + ) { + let output_dirs = self + .documents(db) + .iter() + .map(|document| self.working_dir(db, document.directory(db))) + .map(|base_dir| self.output_dir(db, base_dir)) + .filter_map(|location| location.path(db).as_deref()); + + self.documents(db) + .iter() + .map(|document| document.location(db)) + .filter_map(|location| location.path(db).as_deref()) + .filter_map(|path| path.parent()) + .chain(output_dirs) + .filter(|path| watched_dirs.insert(path.to_path_buf())) + .for_each(|path| { + let _ = watcher.watch(path, notify::RecursiveMode::NonRecursive); + }); + } +} + +const SPECIAL_ENTRIES: &[&str] = &[ + ".git", + "Tectonic.toml", + ".latexmkrc", + "latexmkrc", + ".chktexrc", + "chktexrc", +]; + +#[salsa::tracked] +impl Workspace { + #[salsa::tracked] + pub fn working_dir(self, db: &dyn Db, base_dir: Location) -> Location { + let mut path = self + .options(db) + .root_directory + .as_deref() + .and_then(|path| path.to_str()) + .or_else(|| { + for dir in base_dir + .path(db) + .as_deref()? + .ancestors() + .skip(1) + .filter(|path| Some(*path) != HOME_DIR.as_deref()) + { + for name in SPECIAL_ENTRIES { + if dir.join(name).exists() { + return Some(dir.to_str()?); + } + } + } + + None + }) + .unwrap_or(".") + .to_string(); + + if !path.ends_with(".") { + path.push('/'); + } + + base_dir.join(db, &path).unwrap_or(base_dir) + } + + #[salsa::tracked] + pub fn output_dir(self, db: &dyn Db, base_dir: Location) -> Location { + let mut path = self + .options(db) + .aux_directory + .as_deref() + .and_then(|path| path.to_str()) + .unwrap_or(".") + .to_string(); + + if !path.ends_with("/") { + path.push('/'); + } + + base_dir.join(db, &path).unwrap_or(base_dir) + } + + #[salsa::tracked(return_ref)] + pub fn parents(self, db: &dyn Db, child: Document) -> Vec<Document> { + self.index_files(db) + .filter(|&parent| dependency_graph(db, parent).preorder().contains(&child)) + .collect() + } + + #[salsa::tracked(return_ref)] + pub fn related(self, db: &dyn Db, child: Document) -> FxHashSet<Document> { + self.index_files(db) + .chain(self.documents(db).iter().copied()) + .map(|start| dependency_graph(db, start).preorder().collect_vec()) + .filter(|project| project.contains(&child)) + .flatten() + .collect() + } + + #[salsa::tracked] + pub fn number_of_label(self, db: &dyn Db, child: Document, name: Word) -> Option<Word> { + self.related(db, child) + .iter() + .filter_map(|document| document.parse(db).as_tex()) + .flat_map(|data| data.analyze(db).label_numbers(db)) + .find(|number| number.name(db) == name) + .map(|number| number.text(db)) + } +} diff --git a/support/texlab/src/debouncer.rs b/support/texlab/src/debouncer.rs deleted file mode 100644 index b123dfc433..0000000000 --- a/support/texlab/src/debouncer.rs +++ /dev/null @@ -1,55 +0,0 @@ -use std::time::{Duration, Instant}; - -use anyhow::Result; - -pub struct Sender<T> { - tx: crossbeam_channel::Sender<(T, crossbeam_channel::Receiver<Instant>)>, -} - -impl<T> Clone for Sender<T> { - fn clone(&self) -> Self { - Self { - tx: self.tx.clone(), - } - } -} - -impl<T> Sender<T> -where - T: Send + Sync + 'static, -{ - pub fn send(&self, msg: T, delay: Duration) -> Result<()> { - self.tx.send((msg, crossbeam_channel::after(delay)))?; - Ok(()) - } -} - -pub struct Receiver<T> { - rx: crossbeam_channel::Receiver<(T, crossbeam_channel::Receiver<Instant>)>, -} - -impl<T> Clone for Receiver<T> { - fn clone(&self) -> Self { - Self { - rx: self.rx.clone(), - } - } -} - -impl<T> Receiver<T> { - pub fn recv(&self) -> Result<T> { - let (mut last_msg, delay) = self.rx.recv()?; - delay.recv()?; - while let Ok((msg, delay)) = self.rx.try_recv() { - delay.recv()?; - last_msg = msg; - } - - Ok(last_msg) - } -} - -pub fn unbounded<T>() -> (Sender<T>, Receiver<T>) { - let (tx, rx) = crossbeam_channel::unbounded(); - (Sender { tx }, Receiver { rx }) -} diff --git a/support/texlab/src/diagnostics.rs b/support/texlab/src/diagnostics.rs deleted file mode 100644 index bdd8faf106..0000000000 --- a/support/texlab/src/diagnostics.rs +++ /dev/null @@ -1,167 +0,0 @@ -mod bibtex; -mod build; -mod chktex; -mod latex; - -use std::sync::Arc; - -use dashmap::DashMap; -use lsp_types::{DiagnosticSeverity, NumberOrString, Range, Url}; -use regex::Regex; - -use crate::Workspace; - -use self::{ - bibtex::collect_bibtex_diagnostics, build::collect_build_diagnostics, - chktex::collect_chktex_diagnostics, latex::collect_latex_diagnostics, -}; - -#[derive(Debug, PartialEq, Eq, Clone)] -pub struct Diagnostic { - pub severity: DiagnosticSeverity, - pub range: Range, - pub code: DiagnosticCode, - pub message: String, -} - -#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Hash)] -pub enum DiagnosticCode { - Latex(LatexCode), - Bibtex(BibtexCode), - Chktex(String), - Build(Arc<Url>), -} - -#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash)] -pub enum LatexCode { - UnexpectedRCurly, - RCurlyInserted, - MismatchedEnvironment, -} - -impl From<LatexCode> for String { - fn from(code: LatexCode) -> Self { - match code { - LatexCode::UnexpectedRCurly => "Unexpected \"}\"".to_string(), - LatexCode::RCurlyInserted => "Missing \"}\" inserted".to_string(), - LatexCode::MismatchedEnvironment => "Mismatched environment".to_string(), - } - } -} - -impl From<LatexCode> for NumberOrString { - fn from(code: LatexCode) -> Self { - match code { - LatexCode::UnexpectedRCurly => NumberOrString::Number(1), - LatexCode::RCurlyInserted => NumberOrString::Number(2), - LatexCode::MismatchedEnvironment => NumberOrString::Number(3), - } - } -} - -#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash)] -#[allow(clippy::enum_variant_names)] -pub enum BibtexCode { - ExpectingLCurly, - ExpectingKey, - ExpectingRCurly, - ExpectingEq, - ExpectingFieldValue, -} - -impl From<BibtexCode> for String { - fn from(code: BibtexCode) -> Self { - match code { - BibtexCode::ExpectingLCurly => "Expecting a curly bracket: \"{\"".to_string(), - BibtexCode::ExpectingKey => "Expecting a key".to_string(), - BibtexCode::ExpectingRCurly => "Expecting a curly bracket: \"}\"".to_string(), - BibtexCode::ExpectingEq => "Expecting an equality sign: \"=\"".to_string(), - BibtexCode::ExpectingFieldValue => "Expecting a field value".to_string(), - } - } -} - -impl From<BibtexCode> for NumberOrString { - fn from(code: BibtexCode) -> Self { - match code { - BibtexCode::ExpectingLCurly => NumberOrString::Number(4), - BibtexCode::ExpectingKey => NumberOrString::Number(5), - BibtexCode::ExpectingRCurly => NumberOrString::Number(6), - BibtexCode::ExpectingEq => NumberOrString::Number(7), - BibtexCode::ExpectingFieldValue => NumberOrString::Number(8), - } - } -} - -#[derive(Default, Clone)] -pub struct DiagnosticManager { - all_diagnostics: Arc<DashMap<Arc<Url>, Vec<Diagnostic>>>, -} - -impl DiagnosticManager { - pub fn push_syntax(&self, workspace: &Workspace, uri: &Url) { - collect_bibtex_diagnostics(&self.all_diagnostics, workspace, uri) - .or_else(|| collect_latex_diagnostics(&self.all_diagnostics, workspace, uri)) - .or_else(|| collect_build_diagnostics(&self.all_diagnostics, workspace, uri)); - } - - pub fn push_chktex(&self, workspace: &Workspace, uri: &Url) { - collect_chktex_diagnostics(&self.all_diagnostics, workspace, uri); - } - - pub fn publish(&self, workspace: &Workspace, uri: &Url) -> Vec<lsp_types::Diagnostic> { - let options = &workspace.environment.options.diagnostics; - - let mut results = Vec::new(); - if let Some(diagnostics) = self.all_diagnostics.get(uri) { - for diagnostic in diagnostics.iter() { - if !options.allowed_patterns.is_empty() - && !options - .allowed_patterns - .iter() - .any(|pattern| pattern.0.is_match(&diagnostic.message)) - { - continue; - } - - if options - .ignored_patterns - .iter() - .any(|pattern| pattern.0.is_match(&diagnostic.message)) - { - continue; - } - - let source = match diagnostic.code { - DiagnosticCode::Latex(_) | DiagnosticCode::Bibtex(_) => "texlab", - DiagnosticCode::Chktex(_) => "chktex", - DiagnosticCode::Build(_) => "latex-build", - }; - - let code = match diagnostic.code.clone() { - DiagnosticCode::Latex(code) => Some(code.into()), - DiagnosticCode::Bibtex(code) => Some(code.into()), - DiagnosticCode::Chktex(code) => Some(NumberOrString::String(code)), - DiagnosticCode::Build(_) => None, - }; - - results.push(lsp_types::Diagnostic { - range: diagnostic.range, - code, - severity: Some(diagnostic.severity), - message: diagnostic.message.clone(), - source: Some(source.to_string()), - ..Default::default() - }); - } - } - - results - } -} - -#[derive(Debug, Default)] -pub struct DiagnosticFilter { - pub allowed_patterns: Vec<Regex>, - pub ignored_patterns: Vec<Regex>, -} diff --git a/support/texlab/src/diagnostics/bibtex.rs b/support/texlab/src/diagnostics/bibtex.rs deleted file mode 100644 index 42e215a794..0000000000 --- a/support/texlab/src/diagnostics/bibtex.rs +++ /dev/null @@ -1,139 +0,0 @@ -use std::sync::Arc; - -use dashmap::DashMap; -use lsp_types::{DiagnosticSeverity, Url}; -use rowan::{ast::AstNode, TextRange}; - -use crate::{ - syntax::bibtex::{self, HasDelims, HasEq, HasName, HasType, HasValue}, - Document, LineIndexExt, Workspace, -}; - -use super::{BibtexCode, Diagnostic, DiagnosticCode}; - -pub fn collect_bibtex_diagnostics( - all_diagnostics: &DashMap<Arc<Url>, Vec<Diagnostic>>, - workspace: &Workspace, - uri: &Url, -) -> Option<()> { - let document = workspace.documents_by_uri.get(uri)?; - let data = document.data.as_bibtex()?; - - all_diagnostics.alter(uri, |_, mut diagnostics| { - diagnostics.retain(|diag| !matches!(diag.code, DiagnosticCode::Bibtex(_))); - diagnostics - }); - - let root = bibtex::SyntaxNode::new_root(data.green.clone()); - for node in root.descendants() { - analyze_entry(all_diagnostics, document, node.clone()) - .or_else(|| analyze_field(all_diagnostics, document, node)); - } - - Some(()) -} - -fn analyze_entry( - all_diagnostics: &DashMap<Arc<Url>, Vec<Diagnostic>>, - document: &Document, - node: bibtex::SyntaxNode, -) -> Option<()> { - let entry = bibtex::Entry::cast(node)?; - if entry.left_delim_token().is_none() { - let code = BibtexCode::ExpectingLCurly; - all_diagnostics - .entry(Arc::clone(&document.uri)) - .or_default() - .push(Diagnostic { - severity: DiagnosticSeverity::ERROR, - range: document - .line_index - .line_col_lsp_range(entry.type_token()?.text_range()), - code: DiagnosticCode::Bibtex(code), - message: String::from(code), - }); - - return Some(()); - } - - if entry.name_token().is_none() { - let code = BibtexCode::ExpectingKey; - all_diagnostics - .entry(Arc::clone(&document.uri)) - .or_default() - .push(Diagnostic { - severity: DiagnosticSeverity::ERROR, - range: document - .line_index - .line_col_lsp_range(entry.left_delim_token()?.text_range()), - code: DiagnosticCode::Bibtex(code), - message: String::from(code), - }); - - return Some(()); - } - - if entry.right_delim_token().is_none() { - let code = BibtexCode::ExpectingRCurly; - all_diagnostics - .entry(Arc::clone(&document.uri)) - .or_default() - .push(Diagnostic { - severity: DiagnosticSeverity::ERROR, - range: document - .line_index - .line_col_lsp_range(TextRange::empty(entry.syntax().text_range().end())), - code: DiagnosticCode::Bibtex(code), - message: String::from(code), - }); - - return Some(()); - } - - Some(()) -} - -fn analyze_field( - all_diagnostics: &DashMap<Arc<Url>, Vec<Diagnostic>>, - document: &Document, - node: bibtex::SyntaxNode, -) -> Option<()> { - let field = bibtex::Field::cast(node)?; - if field.eq_token().is_none() { - let code = BibtexCode::ExpectingEq; - all_diagnostics - .entry(Arc::clone(&document.uri)) - .or_default() - .push(Diagnostic { - severity: DiagnosticSeverity::ERROR, - range: document - .line_index - .line_col_lsp_range(field.name_token()?.text_range()), - - code: DiagnosticCode::Bibtex(code), - message: String::from(code), - }); - - return Some(()); - } - - if field.value().is_none() { - let code = BibtexCode::ExpectingFieldValue; - all_diagnostics - .entry(Arc::clone(&document.uri)) - .or_default() - .push(Diagnostic { - severity: DiagnosticSeverity::ERROR, - range: document - .line_index - .line_col_lsp_range(field.name_token()?.text_range()), - - code: DiagnosticCode::Bibtex(code), - message: String::from(code), - }); - - return Some(()); - } - - Some(()) -} diff --git a/support/texlab/src/diagnostics/build.rs b/support/texlab/src/diagnostics/build.rs deleted file mode 100644 index 4b4ffcc8b4..0000000000 --- a/support/texlab/src/diagnostics/build.rs +++ /dev/null @@ -1,68 +0,0 @@ -use std::{path::PathBuf, sync::Arc}; - -use dashmap::DashMap; -use lsp_types::{DiagnosticSeverity, Position, Range, Url}; - -use crate::{syntax::build_log::BuildErrorLevel, Workspace}; - -use super::{Diagnostic, DiagnosticCode}; - -pub fn collect_build_diagnostics( - all_diagnostics: &DashMap<Arc<Url>, Vec<Diagnostic>>, - workspace: &Workspace, - build_log_uri: &Url, -) -> Option<()> { - let build_log_document = workspace.documents_by_uri.get(build_log_uri)?; - let build_log = build_log_document.data.as_build_log()?; - - all_diagnostics.alter_all(|_, mut diagnostics| { - diagnostics.retain( - |diag| !matches!(&diag.code, DiagnosticCode::Build(uri) if uri.as_ref() == build_log_uri), - ); - diagnostics - }); - - let root_document = workspace.documents_by_uri.values().find(|document| { - document.data.as_latex().map_or(false, |data| { - !document.uri.as_str().ends_with(".aux") - && data - .extras - .implicit_links - .log - .iter() - .any(|u| u.as_ref() == build_log_uri) - }) - })?; - - let base_path = PathBuf::from(root_document.uri.path()); - for error in &build_log.errors { - let position = Position::new(error.line.unwrap_or(0), 0); - let severity = match error.level { - BuildErrorLevel::Error => DiagnosticSeverity::ERROR, - BuildErrorLevel::Warning => DiagnosticSeverity::WARNING, - }; - let range = Range::new(position, position); - let diagnostic = Diagnostic { - severity, - range, - code: DiagnosticCode::Build(Arc::clone(&build_log_document.uri)), - message: error.message.clone(), - }; - - let full_path = base_path.join(&error.relative_path); - - let uri = if full_path.starts_with(&base_path) { - error - .relative_path - .to_str() - .and_then(|path| root_document.uri.join(path).map(Into::into).ok()) - .map_or_else(|| Arc::clone(&root_document.uri), Arc::new) - } else { - Arc::clone(&root_document.uri) - }; - - all_diagnostics.entry(uri).or_default().push(diagnostic); - } - - Some(()) -} diff --git a/support/texlab/src/diagnostics/chktex.rs b/support/texlab/src/diagnostics/chktex.rs deleted file mode 100644 index ad676bd70d..0000000000 --- a/support/texlab/src/diagnostics/chktex.rs +++ /dev/null @@ -1,103 +0,0 @@ -use std::{ - fs, io, - path::Path, - process::{Command, Stdio}, - sync::Arc, -}; - -use dashmap::DashMap; -use lsp_types::{DiagnosticSeverity, Range, Url}; -use once_cell::sync::Lazy; -use regex::Regex; -use tempfile::tempdir; - -use crate::{RangeExt, Workspace}; - -use super::{Diagnostic, DiagnosticCode}; - -pub fn collect_chktex_diagnostics( - all_diagnostics: &DashMap<Arc<Url>, Vec<Diagnostic>>, - workspace: &Workspace, - uri: &Url, -) -> Option<()> { - let document = workspace.documents_by_uri.get(uri)?; - document.data.as_latex()?; - - all_diagnostics.alter(uri, |_, mut diagnostics| { - diagnostics.retain(|diag| !matches!(diag.code, DiagnosticCode::Chktex(_))); - diagnostics - }); - - let current_dir = workspace - .environment - .options - .root_directory - .as_ref() - .cloned() - .or_else(|| { - if document.uri.scheme() == "file" { - document - .uri - .to_file_path() - .unwrap() - .parent() - .map(ToOwned::to_owned) - } else { - None - } - }) - .unwrap_or_else(|| ".".into()); - - all_diagnostics - .entry(Arc::clone(&document.uri)) - .or_default() - .extend(lint(&document.text, ¤t_dir).unwrap_or_default()); - - Some(()) -} - -static LINE_REGEX: Lazy<Regex> = - Lazy::new(|| Regex::new("(\\d+):(\\d+):(\\d+):(\\w+):(\\w+):(.*)").unwrap()); - -fn lint(text: &str, current_dir: &Path) -> io::Result<Vec<Diagnostic>> { - let directory = tempdir()?; - fs::write(directory.path().join("file.tex"), text)?; - drop(fs::copy( - current_dir.join("chktexrc"), - directory.path().join("chktexrc"), - )); - - let output = Command::new("chktex") - .args(&["-I0", "-f%l:%c:%d:%k:%n:%m\n", "file.tex"]) - .stdin(Stdio::null()) - .stdout(Stdio::piped()) - .stderr(Stdio::piped()) - .current_dir(directory.path()) - .output()?; - - let mut diagnostics = Vec::new(); - for line in String::from_utf8_lossy(&output.stdout).lines() { - let captures = LINE_REGEX.captures(line).unwrap(); - let line = captures[1].parse::<u32>().unwrap() - 1; - let character = captures[2].parse::<u32>().unwrap() - 1; - let digit = captures[3].parse::<u32>().unwrap(); - let kind = &captures[4]; - let code = &captures[5]; - let message = captures[6].into(); - let range = Range::new_simple(line, character, line, character + digit); - let severity = match kind { - "Message" => DiagnosticSeverity::INFORMATION, - "Warning" => DiagnosticSeverity::WARNING, - _ => DiagnosticSeverity::ERROR, - }; - - diagnostics.push(Diagnostic { - range, - severity, - code: DiagnosticCode::Chktex(code.into()), - message, - }); - } - - Ok(diagnostics) -} diff --git a/support/texlab/src/diagnostics/latex.rs b/support/texlab/src/diagnostics/latex.rs deleted file mode 100644 index a17aab3f77..0000000000 --- a/support/texlab/src/diagnostics/latex.rs +++ /dev/null @@ -1,126 +0,0 @@ -use std::sync::Arc; - -use dashmap::DashMap; -use lsp_types::{DiagnosticSeverity, Url}; -use rowan::{ast::AstNode, NodeOrToken, TextRange}; - -use crate::{syntax::latex, Document, LineIndexExt, Workspace}; - -use super::{Diagnostic, DiagnosticCode, LatexCode}; - -pub fn collect_latex_diagnostics( - all_diagnostics: &DashMap<Arc<Url>, Vec<Diagnostic>>, - workspace: &Workspace, - uri: &Url, -) -> Option<()> { - let document = workspace.documents_by_uri.get(uri)?; - if !document.uri.as_str().ends_with(".tex") { - return None; - } - - let data = document.data.as_latex()?; - - all_diagnostics.alter(uri, |_, mut diagnostics| { - diagnostics.retain(|diag| !matches!(diag.code, DiagnosticCode::Latex(_))); - diagnostics - }); - - for node in latex::SyntaxNode::new_root(data.green.clone()).descendants() { - analyze_environment(all_diagnostics, document, node.clone()) - .or_else(|| analyze_curly_group(all_diagnostics, document, &node)) - .or_else(|| { - if node.kind() == latex::ERROR && node.first_token()?.text() == "}" { - let code = LatexCode::UnexpectedRCurly; - all_diagnostics - .entry(Arc::clone(&document.uri)) - .or_default() - .push(Diagnostic { - severity: DiagnosticSeverity::ERROR, - range: document.line_index.line_col_lsp_range(node.text_range()), - code: DiagnosticCode::Latex(code), - message: String::from(code), - }); - - Some(()) - } else { - None - } - }); - } - - Some(()) -} - -fn analyze_environment( - all_diagnostics: &DashMap<Arc<Url>, Vec<Diagnostic>>, - document: &Document, - node: latex::SyntaxNode, -) -> Option<()> { - let environment = latex::Environment::cast(node)?; - let name1 = environment.begin()?.name()?.key()?; - let name2 = environment.end()?.name()?.key()?; - if name1 != name2 { - let code = LatexCode::MismatchedEnvironment; - all_diagnostics - .entry(Arc::clone(&document.uri)) - .or_default() - .push(Diagnostic { - severity: DiagnosticSeverity::ERROR, - range: document - .line_index - .line_col_lsp_range(latex::small_range(&name1)), - code: DiagnosticCode::Latex(code), - message: String::from(code), - }); - } - Some(()) -} - -fn analyze_curly_group( - all_diagnostics: &DashMap<Arc<Url>, Vec<Diagnostic>>, - document: &Document, - node: &latex::SyntaxNode, -) -> Option<()> { - if !matches!( - node.kind(), - latex::CURLY_GROUP - | latex::CURLY_GROUP_COMMAND - | latex::CURLY_GROUP_KEY_VALUE - | latex::CURLY_GROUP_WORD - | latex::CURLY_GROUP_WORD_LIST - ) { - return None; - } - - let is_inside_verbatim_environment = node - .ancestors() - .filter_map(latex::Environment::cast) - .filter_map(|env| env.begin()) - .filter_map(|begin| begin.name()) - .filter_map(|name| name.key()) - .any(|name| { - ["asy", "lstlisting", "minted", "verbatim"].contains(&name.to_string().as_str()) - }); - - if !is_inside_verbatim_environment - && !node - .children_with_tokens() - .filter_map(NodeOrToken::into_token) - .any(|token| token.kind() == latex::R_CURLY) - { - let code = LatexCode::RCurlyInserted; - all_diagnostics - .entry(Arc::clone(&document.uri)) - .or_default() - .push(Diagnostic { - severity: DiagnosticSeverity::ERROR, - range: document - .line_index - .line_col_lsp_range(TextRange::empty(node.text_range().end())), - code: DiagnosticCode::Latex(code), - message: String::from(code), - }); - } - - Some(()) -} diff --git a/support/texlab/src/distro.rs b/support/texlab/src/distro.rs index f869392366..759374da81 100644 --- a/support/texlab/src/distro.rs +++ b/support/texlab/src/distro.rs @@ -1,3 +1,4 @@ +mod file_name_db; mod kpsewhich; mod miktex; mod texlive; @@ -5,41 +6,40 @@ mod texlive; use std::process::{Command, Stdio}; use anyhow::Result; -use derive_more::Display; -use log::warn; -pub use kpsewhich::Resolver; +pub use file_name_db::FileNameDB; -#[derive(Debug, PartialEq, Eq, Clone, Copy, Display)] -pub enum DistributionKind { - #[display(fmt = "TeXLive")] +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub enum DistroKind { Texlive, - #[display(fmt = "MikTeX")] Miktex, - #[display(fmt = "Tectonic")] Tectonic, - #[display(fmt = "Unknown")] Unknown, } -#[derive(Debug, Clone)] -pub struct Distribution { - pub kind: DistributionKind, - pub resolver: Resolver, +impl Default for DistroKind { + fn default() -> Self { + Self::Unknown + } +} + +#[derive(Debug, Default)] +pub struct Distro { + pub kind: DistroKind, + pub file_name_db: FileNameDB, } -impl Distribution { - #[must_use] - pub fn detect() -> Self { +impl Distro { + pub fn detect() -> Result<Self> { let kind = match Command::new("latex").arg("--version").output() { Ok(output) => { let stdout = String::from_utf8_lossy(&output.stdout); if stdout.contains("TeX Live") { - DistributionKind::Texlive + DistroKind::Texlive } else if stdout.contains("MiKTeX") { - DistributionKind::Miktex + DistroKind::Miktex } else { - DistributionKind::Unknown + DistroKind::Unknown } } Err(_) => { @@ -50,26 +50,25 @@ impl Distribution { .status() .is_ok() { - DistributionKind::Tectonic + DistroKind::Tectonic } else { - DistributionKind::Unknown + DistroKind::Unknown } } }; - let resolver = match kind { - DistributionKind::Texlive => Self::load_resolver(texlive::load_resolver), - DistributionKind::Miktex => Self::load_resolver(miktex::load_resolver), - DistributionKind::Tectonic | DistributionKind::Unknown => Resolver::default(), + let file_name_db = match kind { + DistroKind::Texlive => { + let root_dirs = kpsewhich::root_directories()?; + FileNameDB::parse(&root_dirs, &mut texlive::read_database)? + } + DistroKind::Miktex => { + let root_dirs = kpsewhich::root_directories()?; + FileNameDB::parse(&root_dirs, &mut miktex::read_database)? + } + DistroKind::Tectonic | DistroKind::Unknown => FileNameDB::default(), }; - Self { kind, resolver } - } - fn load_resolver(loader: impl FnOnce() -> Result<Resolver>) -> Resolver { - match loader() { - Ok(resolver) => return resolver, - Err(why) => warn!("Failed to load resolver: {}", why), - }; - Resolver::default() + Ok(Self { kind, file_name_db }) } } diff --git a/support/texlab/src/distro/file_name_db.rs b/support/texlab/src/distro/file_name_db.rs new file mode 100644 index 0000000000..9234d0a3f9 --- /dev/null +++ b/support/texlab/src/distro/file_name_db.rs @@ -0,0 +1,80 @@ +use std::{ + borrow::Borrow, + path::{Path, PathBuf}, +}; + +use anyhow::Result; +use rustc_hash::FxHashSet; + +use crate::db::Language; + +#[derive(Debug)] +pub struct DistroFile(PathBuf); + +impl DistroFile { + pub fn path(&self) -> &Path { + &self.0 + } + + pub fn name(&self) -> &str { + self.0.file_name().unwrap().to_str().unwrap() + } +} + +impl PartialEq for DistroFile { + fn eq(&self, other: &Self) -> bool { + self.name() == other.name() + } +} + +impl Eq for DistroFile {} + +impl std::hash::Hash for DistroFile { + fn hash<H: std::hash::Hasher>(&self, state: &mut H) { + self.name().hash(state) + } +} + +impl Borrow<str> for DistroFile { + fn borrow(&self) -> &str { + self.name() + } +} + +#[derive(Debug, Default)] +pub struct FileNameDB { + files: FxHashSet<DistroFile>, +} + +impl FileNameDB { + pub fn get(&self, name: &str) -> Option<&Path> { + self.files.get(name).map(|file| file.path()) + } + + pub fn iter(&self) -> impl Iterator<Item = (&str, &Path)> + '_ { + self.files.iter().map(|file| (file.name(), file.path())) + } + + pub fn parse( + root_dirs: &[PathBuf], + reader: &mut dyn FnMut(&Path) -> Result<Vec<PathBuf>>, + ) -> Result<Self> { + let files = root_dirs + .iter() + .flat_map(|dir| reader(dir)) + .flatten() + .filter_map(|rel_path| { + Language::from_path(&rel_path)?; + rel_path.file_name()?.to_str()?; + let abs_path = root_dirs + .iter() + .rev() + .map(|dir| dir.join(&rel_path)) + .find_map(|path| std::fs::canonicalize(path).ok())?; + Some(DistroFile(abs_path)) + }) + .collect(); + + Ok(Self { files }) + } +} diff --git a/support/texlab/src/distro/kpsewhich.rs b/support/texlab/src/distro/kpsewhich.rs index b14e64bf56..0a6d1d35ad 100644 --- a/support/texlab/src/distro/kpsewhich.rs +++ b/support/texlab/src/distro/kpsewhich.rs @@ -1,56 +1,6 @@ -use std::{ - env, - ffi::OsStr, - fs, - path::{Path, PathBuf}, - process::Command, -}; +use std::{env, ffi::OsStr, path::PathBuf, process::Command}; use anyhow::Result; -use rustc_hash::FxHashMap; -use smol_str::SmolStr; - -use crate::DocumentLanguage; - -#[derive(Debug, PartialEq, Eq, Clone, Default)] -pub struct Resolver { - pub files_by_name: FxHashMap<SmolStr, PathBuf>, -} - -impl Resolver { - #[must_use] - pub fn new(files_by_name: FxHashMap<SmolStr, PathBuf>) -> Self { - Self { files_by_name } - } -} - -pub fn parse_database( - root_directories: &[PathBuf], - mut reader: impl FnMut(&Path) -> Result<Vec<PathBuf>>, -) -> Result<Resolver> { - let mut files_by_name = FxHashMap::default(); - for directory in root_directories { - for path in reader(directory)? { - if DocumentLanguage::by_path(&path).is_some() { - if let Some(path) = make_absolute(root_directories, &path) { - if let Some(name) = path.file_name().and_then(OsStr::to_str).map(Into::into) { - files_by_name.insert(name, path); - } - } - } - } - } - Ok(Resolver::new(files_by_name)) -} - -fn make_absolute(root_directories: &[PathBuf], relative_path: &Path) -> Option<PathBuf> { - for dir in root_directories.iter().rev() { - if let Ok(path) = fs::canonicalize(dir.join(&relative_path)) { - return Some(path); - } - } - None -} pub fn root_directories() -> Result<Vec<PathBuf>> { let texmf = run(&["-var-value", "TEXMF"])?; diff --git a/support/texlab/src/distro/miktex.rs b/support/texlab/src/distro/miktex.rs index c7a92d572e..fc778752db 100644 --- a/support/texlab/src/distro/miktex.rs +++ b/support/texlab/src/distro/miktex.rs @@ -1,20 +1,11 @@ use std::{ ffi::OsStr, fs, - io::{self, Cursor}, + io::{self, Cursor, Read}, path::{Path, PathBuf}, }; use anyhow::{Context, Result}; -use byteorder::{LittleEndian, ReadBytesExt}; - -use super::kpsewhich::{self, Resolver}; - -pub fn load_resolver() -> Result<Resolver> { - let root_directories = kpsewhich::root_directories()?; - let resolver = kpsewhich::parse_database(&root_directories, read_database)?; - Ok(resolver) -} const DATABASE_PATH: &str = "miktex/data/le"; const FNDB_SIGNATURE: u32 = 0x42_44_4e_46; @@ -23,7 +14,7 @@ const FNDB_TABLE_POINTER_OFFSET: u32 = 4 * FNDB_WORD_SIZE; const FNDB_TABLE_SIZE_OFFSET: u32 = 6 * FNDB_WORD_SIZE; const FNDB_ENTRY_SIZE: u32 = 4 * FNDB_WORD_SIZE; -fn read_database(directory: &Path) -> Result<Vec<PathBuf>> { +pub(super) fn read_database(directory: &Path) -> Result<Vec<PathBuf>> { let database_directory = directory.join(DATABASE_PATH); if !database_directory.exists() { return Ok(Vec::new()); @@ -36,27 +27,28 @@ fn read_database(directory: &Path) -> Result<Vec<PathBuf>> { database.extend(parse_database(&bytes).context("parsing kpsewhich database")?); } } + Ok(database) } fn parse_database(bytes: &[u8]) -> io::Result<Vec<PathBuf>> { let mut reader = Cursor::new(bytes); - if reader.read_u32::<LittleEndian>()? != FNDB_SIGNATURE { + if read_u32(&mut reader)? != FNDB_SIGNATURE { return Err(io::ErrorKind::InvalidData.into()); } reader.set_position(u64::from(FNDB_TABLE_POINTER_OFFSET)); - let table_address = reader.read_u32::<LittleEndian>()?; + let table_address = read_u32(&mut reader)?; reader.set_position(u64::from(FNDB_TABLE_SIZE_OFFSET)); - let table_size = reader.read_u32::<LittleEndian>()?; + let table_size = read_u32(&mut reader)?; let mut files = Vec::new(); for i in 0..table_size { let offset = table_address + i * FNDB_ENTRY_SIZE as u32; reader.set_position(u64::from(offset)); - let file_name_offset = reader.read_u32::<LittleEndian>()? as usize; - let directory_offset = reader.read_u32::<LittleEndian>()? as usize; + let file_name_offset = read_u32(&mut reader)? as usize; + let directory_offset = read_u32(&mut reader)? as usize; let file_name = read_string(bytes, file_name_offset)?; let directory = read_string(bytes, directory_offset)?; @@ -78,3 +70,9 @@ fn read_string(bytes: &[u8], offset: usize) -> io::Result<&str> { std::str::from_utf8(&bytes[offset..offset + length]) .map_err(|_| io::ErrorKind::InvalidData.into()) } + +fn read_u32(reader: &mut Cursor<&[u8]>) -> io::Result<u32> { + let mut buf = [0u8; std::mem::size_of::<u32>()]; + reader.read_exact(&mut buf)?; + Ok(u32::from_le_bytes(buf)) +} diff --git a/support/texlab/src/distro/texlive.rs b/support/texlab/src/distro/texlive.rs index 47159b2efc..8013033e6d 100644 --- a/support/texlab/src/distro/texlive.rs +++ b/support/texlab/src/distro/texlive.rs @@ -6,17 +6,9 @@ use std::{ use anyhow::Result; -use super::kpsewhich::{self, Resolver}; - -pub fn load_resolver() -> Result<Resolver> { - let root_directories = kpsewhich::root_directories()?; - let resolver = kpsewhich::parse_database(&root_directories, read_database)?; - Ok(resolver) -} - const DATABASE_PATH: &str = "ls-R"; -fn read_database(directory: &Path) -> Result<Vec<PathBuf>> { +pub(super) fn read_database(directory: &Path) -> Result<Vec<PathBuf>> { let file = directory.join(DATABASE_PATH); if !file.is_file() { return Ok(Vec::new()); diff --git a/support/texlab/src/document.rs b/support/texlab/src/document.rs deleted file mode 100644 index 60e295b2e4..0000000000 --- a/support/texlab/src/document.rs +++ /dev/null @@ -1,135 +0,0 @@ -use std::{fmt, sync::Arc}; - -use derive_more::From; -use lsp_types::Url; - -use crate::{ - line_index::LineIndex, - syntax::{ - bibtex, build_log, - latex::{self, LatexAnalyzerContext}, - }, - DocumentLanguage, Environment, -}; - -#[derive(Debug, Clone)] -pub struct LatexDocumentData { - pub green: rowan::GreenNode, - pub extras: Arc<latex::Extras>, -} - -#[derive(Debug, Clone)] -pub struct BibtexDocumentData { - pub green: rowan::GreenNode, -} - -#[derive(Debug, Clone, From)] -pub enum DocumentData { - Latex(Box<LatexDocumentData>), - Bibtex(BibtexDocumentData), - BuildLog(Arc<build_log::Parse>), -} - -impl DocumentData { - #[must_use] - pub fn language(&self) -> DocumentLanguage { - match self { - Self::Latex(_) => DocumentLanguage::Latex, - Self::Bibtex(_) => DocumentLanguage::Bibtex, - Self::BuildLog(_) => DocumentLanguage::BuildLog, - } - } - - #[must_use] - pub fn as_latex(&self) -> Option<&LatexDocumentData> { - if let Self::Latex(data) = self { - Some(data) - } else { - None - } - } - - #[must_use] - pub fn as_bibtex(&self) -> Option<&BibtexDocumentData> { - if let Self::Bibtex(data) = self { - Some(data) - } else { - None - } - } - - #[must_use] - pub fn as_build_log(&self) -> Option<&build_log::Parse> { - if let Self::BuildLog(v) = self { - Some(v) - } else { - None - } - } -} - -#[derive(Clone)] -pub struct Document { - pub uri: Arc<Url>, - pub text: Arc<String>, - pub line_index: Arc<LineIndex>, - pub data: DocumentData, -} - -impl fmt::Debug for Document { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", self.uri) - } -} - -impl Document { - #[must_use] - pub fn parse( - environment: &Environment, - uri: Arc<Url>, - text: Arc<String>, - language: DocumentLanguage, - ) -> Self { - let line_index = Arc::new(LineIndex::new(&text)); - let data = match language { - DocumentLanguage::Latex => { - let green = latex::parse(&text).green; - let root = latex::SyntaxNode::new_root(green.clone()); - - let base_uri = match &environment.options.root_directory { - Some(root_dir) => { - let root_dir = environment.current_directory.join(&root_dir); - Url::from_directory_path(root_dir) - .map_or_else(|()| Arc::clone(&uri), Arc::new) - } - None => Arc::clone(&uri), - }; - - let mut context = LatexAnalyzerContext { - environment, - extras: latex::Extras::default(), - document_uri: Arc::clone(&uri), - base_uri, - }; - latex::analyze(&mut context, &root); - let extras = Arc::new(context.extras); - DocumentData::Latex(Box::new(LatexDocumentData { green, extras })) - } - DocumentLanguage::Bibtex => { - let green = bibtex::parse(&text); - DocumentData::Bibtex(BibtexDocumentData { green }) - } - DocumentLanguage::BuildLog => { - let data = Arc::new(build_log::parse(&text)); - DocumentData::BuildLog(data) - } - }; - - Self { - uri, - text, - line_index, - data, - } - } -} diff --git a/support/texlab/src/environment.rs b/support/texlab/src/environment.rs deleted file mode 100644 index 54b6279f30..0000000000 --- a/support/texlab/src/environment.rs +++ /dev/null @@ -1,33 +0,0 @@ -use std::{path::PathBuf, sync::Arc}; - -use lsp_types::{ClientCapabilities, ClientInfo}; - -use crate::{distro::Resolver, Options}; - -#[derive(Debug, Clone)] -pub struct Environment { - pub current_directory: Arc<PathBuf>, - pub client_capabilities: Arc<ClientCapabilities>, - pub client_info: Option<Arc<ClientInfo>>, - pub options: Arc<Options>, - pub resolver: Arc<Resolver>, -} - -impl Environment { - #[must_use] - pub fn new(current_directory: Arc<PathBuf>) -> Self { - Self { - current_directory, - client_capabilities: Arc::new(ClientCapabilities::default()), - client_info: None, - options: Arc::new(Options::default()), - resolver: Arc::new(Resolver::default()), - } - } -} - -impl Default for Environment { - fn default() -> Self { - Self::new(Arc::new(std::env::temp_dir())) - } -} diff --git a/support/texlab/src/features.rs b/support/texlab/src/features.rs index 9576f266a9..0d82bcb4f4 100644 --- a/support/texlab/src/features.rs +++ b/support/texlab/src/features.rs @@ -1,52 +1,14 @@ -mod build; -#[cfg(feature = "completion")] -mod completion; -mod cursor; -mod definition; -mod execute_command; -mod folding; -mod formatting; -mod forward_search; -mod highlight; -mod hover; -mod link; -mod lsp_kinds; -mod reference; -mod rename; -mod symbol; - -use std::sync::Arc; - -use lsp_types::Url; - -use crate::{Document, Workspace}; - -#[cfg(feature = "completion")] -pub use self::completion::{complete, CompletionItemData, COMPLETION_LIMIT}; -pub use self::{ - build::{BuildEngine, BuildParams, BuildResult, BuildStatus}, - definition::goto_definition, - execute_command::execute_command, - folding::find_foldings, - formatting::format_source_code, - forward_search::{execute_forward_search, ForwardSearchResult, ForwardSearchStatus}, - highlight::find_document_highlights, - hover::find_hover, - link::find_document_links, - reference::find_all_references, - rename::{prepare_rename_all, rename_all}, - symbol::{find_document_symbols, find_workspace_symbols}, -}; - -#[derive(Clone)] -pub struct FeatureRequest<P> { - pub params: P, - pub workspace: Workspace, - pub uri: Arc<Url>, -} - -impl<P> FeatureRequest<P> { - pub fn main_document(&self) -> &Document { - &self.workspace.documents_by_uri[&self.uri] - } -} +pub mod build; +pub mod completion; +pub mod definition; +pub mod folding; +pub mod formatting; +pub mod forward_search; +pub mod highlight; +pub mod hover; +pub mod inlay_hint; +pub mod link; +pub mod reference; +pub mod rename; +pub mod symbol; +pub mod workspace_command; diff --git a/support/texlab/src/features/build.rs b/support/texlab/src/features/build.rs index d961052061..645f1e8e0e 100644 --- a/support/texlab/src/features/build.rs +++ b/support/texlab/src/features/build.rs @@ -1,28 +1,18 @@ +mod progress; + use std::{ io::{BufRead, BufReader, Read}, - path::Path, - process::{Command, Stdio}, - sync::{Arc, Mutex}, + path::{Path, PathBuf}, + process::Stdio, thread::{self, JoinHandle}, }; -use anyhow::Result; -use crossbeam_channel::{Receiver, Sender}; -use dashmap::DashMap; use encoding_rs_io::DecodeReaderBytesBuilder; -use lsp_types::{ - notification::{LogMessage, Progress}, - LogMessageParams, NumberOrString, Position, ProgressParams, ProgressParamsValue, - TextDocumentIdentifier, TextDocumentPositionParams, Url, WorkDoneProgress, - WorkDoneProgressBegin, WorkDoneProgressCreateParams, WorkDoneProgressEnd, -}; +use lsp_types::{notification::LogMessage, LogMessageParams, TextDocumentIdentifier, Url}; use serde::{Deserialize, Serialize}; use serde_repr::{Deserialize_repr, Serialize_repr}; -use uuid::Uuid; -use crate::{client, req_queue::ReqQueue, ClientCapabilitiesExt, DocumentLanguage}; - -use super::{forward_search, FeatureRequest}; +use crate::{client::LspClient, db::Workspace, util::capabilities::ClientCapabilitiesExt, Db}; #[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] @@ -30,6 +20,12 @@ pub struct BuildParams { pub text_document: TextDocumentIdentifier, } +#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct BuildResult { + pub status: BuildStatus, +} + #[derive(Debug, PartialEq, Eq, Clone, Copy, Serialize_repr, Deserialize_repr)] #[repr(i32)] pub enum BuildStatus { @@ -39,217 +35,132 @@ pub enum BuildStatus { CANCELLED = 3, } -#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct BuildResult { - pub status: BuildStatus, -} - -struct ProgressReporter<'a> { - supports_progress: bool, - req_queue: &'a Mutex<ReqQueue>, - lsp_sender: Sender<lsp_server::Message>, - token: &'a str, +#[derive(Debug)] +pub struct Command { + uri: Url, + progress: bool, + executable: String, + args: Vec<String>, + working_dir: PathBuf, + client: LspClient, } -impl<'a> ProgressReporter<'a> { - pub fn start(&self, uri: &Url) -> Result<()> { - if self.supports_progress { - client::send_request::<lsp_types::request::WorkDoneProgressCreate>( - self.req_queue, - &self.lsp_sender, - WorkDoneProgressCreateParams { - token: NumberOrString::String(self.token.to_string()), - }, - )?; - client::send_notification::<Progress>( - &self.lsp_sender, - ProgressParams { - token: NumberOrString::String(self.token.to_string()), - value: ProgressParamsValue::WorkDone(WorkDoneProgress::Begin( - WorkDoneProgressBegin { - title: "Building".to_string(), - message: Some(uri.as_str().to_string()), - cancellable: Some(false), - percentage: None, - }, - )), - }, - )?; +impl Command { + pub fn new(db: &dyn Db, uri: Url, client: LspClient) -> Option<Self> { + let workspace = Workspace::get(db); + let document = match workspace.lookup_uri(db, &uri) { + Some(child) => workspace + .parents(db, child) + .iter() + .next() + .copied() + .unwrap_or(child), + None => return None, }; - Ok(()) - } -} -impl<'a> Drop for ProgressReporter<'a> { - fn drop(&mut self) { - if self.supports_progress { - drop(client::send_notification::<Progress>( - &self.lsp_sender, - ProgressParams { - token: NumberOrString::String(self.token.to_string()), - value: ProgressParamsValue::WorkDone(WorkDoneProgress::End( - WorkDoneProgressEnd { message: None }, - )), - }, - )); + if document.location(db).path(db).is_none() { + log::warn!("Document {uri} cannot be compiled; skipping..."); + return None; } - } -} - -#[derive(Default)] -pub struct BuildEngine { - lock: Mutex<()>, - pub positions_by_uri: DashMap<Arc<Url>, Position>, -} - -impl BuildEngine { - pub fn build( - &self, - request: FeatureRequest<BuildParams>, - req_queue: &Mutex<ReqQueue>, - lsp_sender: &Sender<lsp_server::Message>, - ) -> Result<BuildResult> { - let lock = self.lock.lock().unwrap(); - - let document = request - .workspace - .documents_by_uri - .values() - .find(|document| { - if let Some(data) = document.data.as_latex() { - data.extras.has_document_environment - } else { - false - } - }) - .unwrap_or_else(|| request.main_document()); - - if document.data.language() != DocumentLanguage::Latex { - return Ok(BuildResult { - status: BuildStatus::SUCCESS, - }); - } - - if document.uri.scheme() != "file" { - return Ok(BuildResult { - status: BuildStatus::FAILURE, - }); - } - let path = document.uri.to_file_path().unwrap(); - - let supports_progress = request - .workspace - .environment - .client_capabilities - .has_work_done_progress_support(); - - let token = format!("texlab-build-{}", Uuid::new_v4()); - let progress_reporter = ProgressReporter { - supports_progress, - req_queue, - lsp_sender: lsp_sender.clone(), - token: &token, - }; - progress_reporter.start(&document.uri)?; - let options = &request.workspace.environment.options; - - let build_dir = options - .root_directory - .as_ref() - .map(AsRef::as_ref) - .or_else(|| path.parent()) - .unwrap(); - - let args: Vec<_> = options - .build + let options = &workspace.options(db).build; + let executable = options.executable.0.clone(); + let path = document.location(db).path(db).as_deref().unwrap(); + let args = options .args + .0 .iter() - .map(|arg| replace_placeholder(arg.clone(), &path)) + .map(|arg| replace_placeholder(arg, path)) .collect(); - let mut process = Command::new(&options.build.executable) - .args(args) - .stdin(Stdio::null()) - .stdout(Stdio::piped()) - .stderr(Stdio::piped()) - .current_dir(build_dir) - .spawn()?; - - let (exit_sender, exit_receiver) = crossbeam_channel::bounded(1); - let log_handle = capture_output(&mut process, lsp_sender, exit_receiver); - let success = process.wait().map(|status| status.success())?; - exit_sender.send(())?; - drop(exit_sender); + let working_dir = workspace + .working_dir(db, document.directory(db)) + .path(db) + .clone()?; + + Some(Self { + uri: document.location(db).uri(db).clone(), + progress: workspace + .client_capabilities(db) + .has_work_done_progress_support(), + executable, + args, + working_dir, + client, + }) + } - log_handle.join().unwrap(); - let status = if success { - BuildStatus::SUCCESS + pub fn run(self) -> BuildStatus { + let reporter = if self.progress { + let inner = progress::Reporter::new(&self.client); + inner.start(&self.uri).expect("report progress"); + Some(inner) } else { - BuildStatus::ERROR + None }; - drop(progress_reporter); - drop(lock); - - if options.build.forward_search_after { - let request = FeatureRequest { - params: TextDocumentPositionParams { - position: self - .positions_by_uri - .get(&request.main_document().uri) - .map(|guard| *guard) - .unwrap_or_default(), - text_document: TextDocumentIdentifier::new(request.uri.as_ref().clone()), - }, - uri: request.uri, - workspace: request.workspace, - }; - forward_search::execute_forward_search(request); - } - - Ok(BuildResult { status }) - } -} - -fn capture_output( - process: &mut std::process::Child, - lsp_sender: &Sender<lsp_server::Message>, - exit_receiver: Receiver<()>, -) -> JoinHandle<()> { - let (log_sender, log_receiver) = crossbeam_channel::unbounded(); - track_output(process.stdout.take().unwrap(), log_sender.clone()); - track_output(process.stderr.take().unwrap(), log_sender); - let lsp_sender = lsp_sender.clone(); - thread::spawn(move || loop { - crossbeam_channel::select! { - recv(&log_receiver) -> message => { - if let Ok(message) = message { - client::send_notification::<LogMessage>( - &lsp_sender, - LogMessageParams { - message, - typ: lsp_types::MessageType::LOG, - }, - ) - .unwrap(); - } - }, - recv(&exit_receiver) -> _ => break, + let mut process = match std::process::Command::new(&self.executable) + .args(self.args) + .stdin(Stdio::null()) + .stdout(Stdio::piped()) + .stderr(Stdio::piped()) + .current_dir(self.working_dir) + .spawn() + { + Ok(process) => process, + Err(_) => { + log::error!("Failed to spawn process: {:?}", self.executable); + return BuildStatus::FAILURE; + } }; - }) -} -fn replace_placeholder(arg: String, file: &Path) -> String { - if arg.starts_with('"') || arg.ends_with('"') { - arg - } else { - arg.replace("%f", &file.to_string_lossy()) + let (line_sender, line_receiver) = flume::unbounded(); + let (exit_sender, exit_receiver) = flume::unbounded(); + track_output(process.stderr.take().unwrap(), line_sender.clone()); + track_output(process.stdout.take().unwrap(), line_sender); + let client = self.client.clone(); + let handle = std::thread::spawn(move || { + let typ = lsp_types::MessageType::LOG; + + loop { + let done = flume::Selector::new() + .recv(&line_receiver, |line| match line { + Ok(message) => { + let params = LogMessageParams { message, typ }; + client.send_notification::<LogMessage>(params).unwrap(); + false + } + Err(_) => true, + }) + .recv(&exit_receiver, |_| true) + .wait(); + + if done { + break; + } + } + }); + + let status = process.wait().map_or(BuildStatus::FAILURE, |result| { + if result.success() { + BuildStatus::SUCCESS + } else { + BuildStatus::ERROR + } + }); + + let _ = exit_sender.send(()); + handle.join().unwrap(); + + drop(reporter); + status } } -fn track_output(output: impl Read + Send + 'static, sender: Sender<String>) -> JoinHandle<()> { +fn track_output( + output: impl Read + Send + 'static, + sender: flume::Sender<String>, +) -> JoinHandle<()> { let reader = BufReader::new( DecodeReaderBytesBuilder::new() .encoding(Some(encoding_rs::UTF_8)) @@ -264,3 +175,11 @@ fn track_output(output: impl Read + Send + 'static, sender: Sender<String>) -> J } }) } + +fn replace_placeholder(arg: &str, file: &Path) -> String { + if arg.starts_with('"') || arg.ends_with('"') { + arg.to_string() + } else { + arg.replace("%f", &file.to_string_lossy()) + } +} diff --git a/support/texlab/src/features/build/progress.rs b/support/texlab/src/features/build/progress.rs new file mode 100644 index 0000000000..6f235bebd6 --- /dev/null +++ b/support/texlab/src/features/build/progress.rs @@ -0,0 +1,54 @@ +use std::sync::atomic::{AtomicI32, Ordering}; + +use anyhow::Result; +use lsp_types::{ + notification::Progress, request::WorkDoneProgressCreate, NumberOrString, ProgressParams, + ProgressParamsValue, Url, WorkDoneProgress, WorkDoneProgressBegin, + WorkDoneProgressCreateParams, WorkDoneProgressEnd, +}; + +use crate::client::LspClient; + +static NEXT_TOKEN: AtomicI32 = AtomicI32::new(1); + +pub struct Reporter<'a> { + client: &'a LspClient, + token: i32, +} + +impl<'a> Reporter<'a> { + pub fn new(client: &'a LspClient) -> Self { + let token = NEXT_TOKEN.fetch_add(1, Ordering::SeqCst); + Self { client, token } + } + + pub fn start(&self, uri: &Url) -> Result<()> { + self.client + .send_request::<WorkDoneProgressCreate>(WorkDoneProgressCreateParams { + token: NumberOrString::Number(self.token), + })?; + + self.client.send_notification::<Progress>(ProgressParams { + token: NumberOrString::Number(self.token), + value: ProgressParamsValue::WorkDone(WorkDoneProgress::Begin(WorkDoneProgressBegin { + title: "Building".to_string(), + message: Some(uri.as_str().to_string()), + cancellable: Some(false), + percentage: None, + })), + })?; + + Ok(()) + } +} + +impl<'a> Drop for Reporter<'a> { + fn drop(&mut self) { + let _ = self.client.send_notification::<Progress>(ProgressParams { + token: NumberOrString::Number(self.token), + value: ProgressParamsValue::WorkDone(WorkDoneProgress::End(WorkDoneProgressEnd { + message: None, + })), + }); + } +} diff --git a/support/texlab/src/features/completion.rs b/support/texlab/src/features/completion.rs index 3009b437e7..949b5552e5 100644 --- a/support/texlab/src/features/completion.rs +++ b/support/texlab/src/features/completion.rs @@ -1,6 +1,7 @@ mod acronym_ref; mod argument; -mod begin_command; +mod begin_snippet; +pub mod builder; mod citation; mod color; mod color_model; @@ -14,584 +15,36 @@ mod include; mod label; mod theorem; mod tikz_library; -mod types; mod user_command; mod user_environment; -mod util; -use std::borrow::Cow; +use lsp_types::{CompletionList, Position, Url}; -use fuzzy_matcher::{skim::SkimMatcherV2, FuzzyMatcher}; -use itertools::Itertools; -use lsp_types::{ - CompletionItem, CompletionList, CompletionParams, CompletionTextEdit, Documentation, - InsertTextFormat, MarkupContent, MarkupKind, TextEdit, -}; -use rowan::{ast::AstNode, TextSize}; -use rustc_hash::FxHashSet; - -use crate::{ - syntax::{ - bibtex::{self}, - latex, - }, - LineIndexExt, -}; - -use self::{ - acronym_ref::complete_acronyms, - argument::complete_arguments, - begin_command::complete_begin_command, - citation::complete_citations, - color::complete_colors, - color_model::complete_color_models, - component_command::complete_component_commands, - component_environment::complete_component_environments, - entry_type::complete_entry_types, - field::complete_fields, - glossary_ref::complete_glossary_entries, - import::complete_imports, - include::complete_includes, - label::complete_labels, - theorem::complete_theorem_environments, - tikz_library::complete_tikz_libraries, - types::{InternalCompletionItem, InternalCompletionItemData}, - user_command::complete_user_commands, - user_environment::complete_user_environments, - util::{adjust_kind, component_detail, image_documentation}, -}; - -pub use self::types::CompletionItemData; - -use super::{ - cursor::{Cursor, CursorContext}, - lsp_kinds::Structure, - FeatureRequest, -}; +use crate::{features::completion::builder::CompletionBuilder, util::cursor::CursorContext, Db}; pub const COMPLETION_LIMIT: usize = 50; -#[must_use] -pub fn complete(request: FeatureRequest<CompletionParams>) -> Option<CompletionList> { - let mut items = Vec::new(); - let context = CursorContext::new(request); +pub fn complete(db: &dyn Db, uri: &Url, position: Position) -> Option<CompletionList> { + let context = CursorContext::new(db, uri, position, ())?; + let mut builder = CompletionBuilder::new(&context); log::debug!("[Completion] Cursor: {:?}", context.cursor); - complete_entry_types(&context, &mut items); - complete_fields(&context, &mut items); - complete_arguments(&context, &mut items); - complete_citations(&context, &mut items); - complete_imports(&context, &mut items); - complete_colors(&context, &mut items); - complete_color_models(&context, &mut items); - complete_acronyms(&context, &mut items); - complete_glossary_entries(&context, &mut items); - complete_includes(&context, &mut items); - complete_labels(&context, &mut items); - complete_tikz_libraries(&context, &mut items); - complete_component_environments(&context, &mut items); - complete_theorem_environments(&context, &mut items); - complete_user_environments(&context, &mut items); - complete_begin_command(&context, &mut items); - complete_component_commands(&context, &mut items); - complete_user_commands(&context, &mut items); - - let mut items = dedup(items); - preselect(&context, &mut items); - score(&context, &mut items); - - items.sort_by(|a, b| { - a.preselect - .cmp(&b.preselect) - .reverse() - .then_with(|| a.score.cmp(&b.score).reverse()) - .then_with(|| a.data.label().cmp(b.data.label())) - }); - - let items: Vec<_> = items - .into_iter() - .take(COMPLETION_LIMIT) - .filter(|item| item.score.is_some()) - .map(|item| convert_internal_items(&context, item)) - .enumerate() - .map(|(i, item)| append_sort_text(item, i)) - .collect(); - - let is_incomplete = if context - .request - .workspace - .environment - .client_info - .as_ref() - .as_ref() - .map_or(false, |info| info.name.as_str() == "Visual Studio Code") - { - true - } else { - items.len() >= COMPLETION_LIMIT - }; - - Some(CompletionList { - is_incomplete, - items, - }) -} - -fn dedup(items: Vec<InternalCompletionItem>) -> Vec<InternalCompletionItem> { - let mut labels = FxHashSet::default(); - let mut insert = vec![false; items.len()]; - for (i, item) in items.iter().enumerate() { - insert[i] = labels.insert(item.data.label()); - } - items - .into_iter() - .enumerate() - .filter(|(i, _)| insert[*i]) - .map(|(_, item)| item) - .collect() -} - -fn score(context: &CursorContext<CompletionParams>, items: &mut Vec<InternalCompletionItem>) { - let pattern: Cow<str> = match &context.cursor { - Cursor::Latex(token) if token.kind().is_command_name() => { - if token.text_range().start() + TextSize::from(1) == context.offset { - // Handle cases similar to this one correctly: - // $\|$ % (| is the cursor) - "\\".into() - } else { - token.text().trim_end().into() - } - } - Cursor::Latex(token) if token.kind() == latex::WORD => { - if let Some(key) = token.parent().and_then(latex::Key::cast) { - key.words() - .take_while(|word| word.text_range() != token.text_range()) - .chain(std::iter::once(token.clone())) - .filter(|word| word.text_range().start() < context.offset) - .join(" ") - .into() - } else { - token.text().into() - } - } - Cursor::Bibtex(token) - if matches!( - token.kind(), - bibtex::TYPE - | bibtex::NAME - | bibtex::WORD - | bibtex::COMMAND_NAME - | bibtex::ACCENT_NAME - ) => - { - token.text().into() - } - Cursor::Latex(_) | Cursor::Bibtex(_) | Cursor::Nothing => "".into(), - }; - - let file_pattern = pattern.split('/').last().unwrap(); - let matcher = SkimMatcherV2::default().ignore_case(); - for item in items { - item.score = match &item.data { - InternalCompletionItemData::EntryType { ty } => { - matcher.fuzzy_match(&ty.name, &pattern[1..]) - } - InternalCompletionItemData::Field { field } => { - matcher.fuzzy_match(&field.name, &pattern) - } - InternalCompletionItemData::Argument { name, .. } => { - matcher.fuzzy_match(name, &pattern) - } - InternalCompletionItemData::BeginCommand => matcher.fuzzy_match("begin", &pattern[1..]), - InternalCompletionItemData::Citation { key, .. } => matcher.fuzzy_match(key, &pattern), - InternalCompletionItemData::ComponentCommand { name, .. } => { - matcher.fuzzy_match(name, &pattern[1..]) - } - InternalCompletionItemData::ComponentEnvironment { name, .. } => { - matcher.fuzzy_match(name, &pattern) - } - InternalCompletionItemData::Class { name } => matcher.fuzzy_match(name, &pattern), - InternalCompletionItemData::Package { name } => matcher.fuzzy_match(name, &pattern), - InternalCompletionItemData::Color { name } => matcher.fuzzy_match(name, &pattern), - InternalCompletionItemData::ColorModel { name } => matcher.fuzzy_match(name, &pattern), - InternalCompletionItemData::Acronym { name } => matcher.fuzzy_match(name, &pattern), - InternalCompletionItemData::GlossaryEntry { name } => { - matcher.fuzzy_match(name, &pattern) - } - InternalCompletionItemData::File { name } => matcher.fuzzy_match(name, file_pattern), - InternalCompletionItemData::Directory { name } => { - matcher.fuzzy_match(name, file_pattern) - } - InternalCompletionItemData::Label { name, .. } => matcher.fuzzy_match(name, &pattern), - InternalCompletionItemData::UserCommand { name } => matcher.fuzzy_match(name, &pattern), - InternalCompletionItemData::UserEnvironment { name } => { - matcher.fuzzy_match(name, &pattern) - } - InternalCompletionItemData::PgfLibrary { name } => matcher.fuzzy_match(name, &pattern), - InternalCompletionItemData::TikzLibrary { name } => matcher.fuzzy_match(name, &pattern), - }; - } -} - -fn preselect( - context: &CursorContext<CompletionParams>, - items: &mut [InternalCompletionItem], -) -> Option<()> { - let name = context.cursor.as_latex()?; - let group = latex::CurlyGroupWord::cast(name.parent()?)?; - let end = latex::End::cast(group.syntax().parent()?)?; - let environment = latex::Environment::cast(end.syntax().parent()?)?; - let name = environment.begin()?.name()?.key()?.to_string(); - - for item in items { - if item.data.label() == name { - item.preselect = true; - } - } - Some(()) -} - -fn convert_internal_items( - context: &CursorContext<CompletionParams>, - item: InternalCompletionItem, -) -> CompletionItem { - let range = context - .request - .main_document() - .line_index - .line_col_lsp_range(item.range); - - let mut new_item = match item.data { - InternalCompletionItemData::EntryType { ty } => { - let text_edit = TextEdit::new(range, (&ty.name).into()); - let kind = Structure::Entry(ty.category).completion_kind(); - CompletionItem { - label: (&ty.name).into(), - kind: Some(adjust_kind(&context.request, kind)), - documentation: ty.documentation.as_ref().map(|doc| { - Documentation::MarkupContent(MarkupContent { - kind: MarkupKind::Markdown, - value: doc.into(), - }) - }), - text_edit: Some(CompletionTextEdit::Edit(text_edit)), - data: Some(serde_json::to_value(CompletionItemData::EntryType).unwrap()), - ..CompletionItem::default() - } - } - InternalCompletionItemData::Field { field } => { - let text_edit = TextEdit::new(range, (&field.name).into()); - CompletionItem { - label: (&field.name).into(), - kind: Some(adjust_kind( - &context.request, - Structure::Field.completion_kind(), - )), - documentation: Some(Documentation::MarkupContent(MarkupContent { - kind: MarkupKind::Markdown, - value: (&field.documentation).into(), - })), - text_edit: Some(CompletionTextEdit::Edit(text_edit)), - data: Some(serde_json::to_value(CompletionItemData::FieldName).unwrap()), - ..CompletionItem::default() - } - } - InternalCompletionItemData::Argument { name, image } => { - let text_edit = TextEdit::new(range, name.into()); - CompletionItem { - label: name.into(), - kind: Some(adjust_kind( - &context.request, - Structure::Argument.completion_kind(), - )), - data: Some(serde_json::to_value(CompletionItemData::Argument).unwrap()), - text_edit: Some(CompletionTextEdit::Edit(text_edit)), - documentation: image - .and_then(|image| image_documentation(&context.request, name, image)), - ..CompletionItem::default() - } - } - InternalCompletionItemData::BeginCommand => { - if context - .request - .workspace - .environment - .client_capabilities - .text_document - .as_ref() - .and_then(|cap| cap.completion.as_ref()) - .and_then(|cap| cap.completion_item.as_ref()) - .and_then(|cap| cap.snippet_support) - == Some(true) - { - let text_edit = TextEdit::new(range, "begin{$1}\n\t$0\n\\end{$1}".into()); - CompletionItem { - kind: Some(adjust_kind( - &context.request, - Structure::Snippet.completion_kind(), - )), - data: Some(serde_json::to_value(CompletionItemData::CommandSnippet).unwrap()), - text_edit: Some(CompletionTextEdit::Edit(text_edit)), - insert_text_format: Some(InsertTextFormat::SNIPPET), - ..CompletionItem::new_simple("begin".into(), component_detail(&[])) - } - } else { - let text_edit = TextEdit::new(range, "begin".to_string()); - CompletionItem { - kind: Some(adjust_kind( - &context.request, - Structure::Command.completion_kind(), - )), - data: Some(serde_json::to_value(CompletionItemData::Command).unwrap()), - text_edit: Some(CompletionTextEdit::Edit(text_edit)), - ..CompletionItem::new_simple("begin".to_string(), component_detail(&[])) - } - } - } - InternalCompletionItemData::Citation { uri, key, text, ty } => { - let text_edit = TextEdit::new(range, key.to_string()); - CompletionItem { - label: key.to_string(), - kind: Some(adjust_kind(&context.request, ty.completion_kind())), - filter_text: Some(text.clone()), - sort_text: Some(text), - data: Some( - serde_json::to_value(CompletionItemData::Citation { - uri: uri.as_ref().clone(), - key: key.into(), - }) - .unwrap(), - ), - text_edit: Some(CompletionTextEdit::Edit(text_edit)), - ..CompletionItem::default() - } - } - InternalCompletionItemData::ComponentCommand { - name, - image, - glyph, - file_names, - } => { - let detail = glyph.map_or_else( - || component_detail(file_names), - |glyph| format!("{}, {}", glyph, component_detail(file_names)), - ); - let documentation = - image.and_then(|img| image_documentation(&context.request, name, img)); - let text_edit = TextEdit::new(range, name.to_string()); - CompletionItem { - kind: Some(adjust_kind( - &context.request, - Structure::Command.completion_kind(), - )), - data: Some(serde_json::to_value(CompletionItemData::Command).unwrap()), - documentation, - text_edit: Some(CompletionTextEdit::Edit(text_edit)), - ..CompletionItem::new_simple(name.to_string(), detail) - } - } - InternalCompletionItemData::ComponentEnvironment { name, file_names } => { - let text_edit = TextEdit::new(range, name.to_string()); - CompletionItem { - kind: Some(adjust_kind( - &context.request, - Structure::Environment.completion_kind(), - )), - data: Some(serde_json::to_value(CompletionItemData::Environment).unwrap()), - text_edit: Some(CompletionTextEdit::Edit(text_edit)), - ..CompletionItem::new_simple(name.to_string(), component_detail(file_names)) - } - } - InternalCompletionItemData::Class { name } => { - let text_edit = TextEdit::new(range, name.to_string()); - CompletionItem { - label: name.into(), - kind: Some(adjust_kind( - &context.request, - Structure::Class.completion_kind(), - )), - data: Some(serde_json::to_value(CompletionItemData::Class).unwrap()), - text_edit: Some(CompletionTextEdit::Edit(text_edit)), - ..CompletionItem::default() - } - } - InternalCompletionItemData::Package { name } => { - let text_edit = TextEdit::new(range, name.to_string()); - CompletionItem { - label: name.into(), - kind: Some(adjust_kind( - &context.request, - Structure::Package.completion_kind(), - )), - data: Some(serde_json::to_value(CompletionItemData::Package).unwrap()), - text_edit: Some(CompletionTextEdit::Edit(text_edit)), - ..CompletionItem::default() - } - } - InternalCompletionItemData::Color { name } => { - let text_edit = TextEdit::new(range, name.into()); - CompletionItem { - label: name.into(), - kind: Some(adjust_kind( - &context.request, - Structure::Color.completion_kind(), - )), - data: Some(serde_json::to_value(CompletionItemData::Color).unwrap()), - text_edit: Some(CompletionTextEdit::Edit(text_edit)), - ..CompletionItem::default() - } - } - InternalCompletionItemData::ColorModel { name } => { - let text_edit = TextEdit::new(range, name.into()); - CompletionItem { - label: name.into(), - kind: Some(adjust_kind( - &context.request, - Structure::ColorModel.completion_kind(), - )), - data: Some(serde_json::to_value(CompletionItemData::ColorModel).unwrap()), - text_edit: Some(CompletionTextEdit::Edit(text_edit)), - ..CompletionItem::default() - } - } - InternalCompletionItemData::Acronym { name } => { - let text_edit = TextEdit::new(range, name.to_string()); - CompletionItem { - label: name, - kind: Some(adjust_kind( - &context.request, - Structure::GlossaryEntry.completion_kind(), - )), - data: Some(serde_json::to_value(CompletionItemData::Acronym).unwrap()), - text_edit: Some(CompletionTextEdit::Edit(text_edit)), - ..CompletionItem::default() - } - } - InternalCompletionItemData::GlossaryEntry { name } => { - let text_edit = TextEdit::new(range, name.to_string()); - CompletionItem { - label: name, - kind: Some(adjust_kind( - &context.request, - Structure::GlossaryEntry.completion_kind(), - )), - data: Some(serde_json::to_value(CompletionItemData::GlossaryEntry).unwrap()), - text_edit: Some(CompletionTextEdit::Edit(text_edit)), - ..CompletionItem::default() - } - } - InternalCompletionItemData::File { name } => { - let text_edit = TextEdit::new(range, name.to_string()); - CompletionItem { - label: name.into(), - kind: Some(adjust_kind( - &context.request, - Structure::File.completion_kind(), - )), - data: Some(serde_json::to_value(CompletionItemData::File).unwrap()), - text_edit: Some(CompletionTextEdit::Edit(text_edit)), - ..CompletionItem::default() - } - } - InternalCompletionItemData::Directory { name } => { - let text_edit = TextEdit::new(range, name.to_string()); - CompletionItem { - label: name.into(), - kind: Some(adjust_kind( - &context.request, - Structure::Folder.completion_kind(), - )), - data: Some(serde_json::to_value(CompletionItemData::Folder).unwrap()), - text_edit: Some(CompletionTextEdit::Edit(text_edit)), - ..CompletionItem::default() - } - } - InternalCompletionItemData::Label { - name, - kind, - header, - footer, - text, - } => { - let text_edit = TextEdit::new(range, name.to_string()); - CompletionItem { - label: name, - kind: Some(adjust_kind(&context.request, kind.completion_kind())), - detail: header, - documentation: footer.map(Documentation::String), - sort_text: Some(text.clone()), - filter_text: Some(text), - text_edit: Some(CompletionTextEdit::Edit(text_edit)), - data: Some(serde_json::to_value(CompletionItemData::Label).unwrap()), - ..CompletionItem::default() - } - } - InternalCompletionItemData::UserCommand { name } => { - let detail = "user-defined".into(); - let name = &name[1..]; - let text_edit = TextEdit::new(range, name.to_string()); - CompletionItem { - kind: Some(adjust_kind( - &context.request, - Structure::Command.completion_kind(), - )), - data: Some(serde_json::to_value(CompletionItemData::Command).unwrap()), - text_edit: Some(CompletionTextEdit::Edit(text_edit)), - ..CompletionItem::new_simple(name.into(), detail) - } - } - InternalCompletionItemData::UserEnvironment { name } => { - let detail = "user-defined".into(); - let text_edit = TextEdit::new(range, name.clone()); - CompletionItem { - kind: Some(adjust_kind( - &context.request, - Structure::Environment.completion_kind(), - )), - data: Some(serde_json::to_value(CompletionItemData::Environment).unwrap()), - text_edit: Some(CompletionTextEdit::Edit(text_edit)), - ..CompletionItem::new_simple(name, detail) - } - } - InternalCompletionItemData::PgfLibrary { name } => { - let text_edit = TextEdit::new(range, name.into()); - CompletionItem { - label: name.into(), - kind: Some(adjust_kind( - &context.request, - Structure::PgfLibrary.completion_kind(), - )), - data: Some(serde_json::to_value(CompletionItemData::PgfLibrary).unwrap()), - text_edit: Some(CompletionTextEdit::Edit(text_edit)), - ..CompletionItem::default() - } - } - InternalCompletionItemData::TikzLibrary { name } => { - let text_edit = TextEdit::new(range, name.into()); - CompletionItem { - label: name.into(), - kind: Some(adjust_kind( - &context.request, - Structure::TikzLibrary.completion_kind(), - )), - data: Some(serde_json::to_value(CompletionItemData::TikzLibrary).unwrap()), - text_edit: Some(CompletionTextEdit::Edit(text_edit)), - ..CompletionItem::default() - } - } - }; - new_item.preselect = Some(item.preselect); - new_item -} - -fn append_sort_text(mut item: CompletionItem, index: usize) -> CompletionItem { - let sort_prefix = format!("{:0>2}", index); - match &item.sort_text { - Some(sort_text) => { - item.sort_text = Some(format!("{} {}", sort_prefix, sort_text)); - } - None => { - item.sort_text = Some(sort_prefix); - } - }; - item + entry_type::complete(&context, &mut builder); + field::complete(&context, &mut builder); + argument::complete(&context, &mut builder); + citation::complete(&context, &mut builder); + import::complete(&context, &mut builder); + color::complete(&context, &mut builder); + color_model::complete(&context, &mut builder); + acronym_ref::complete(&context, &mut builder); + glossary_ref::complete(&context, &mut builder); + include::complete(&context, &mut builder); + label::complete(&context, &mut builder); + tikz_library::complete(&context, &mut builder); + component_environment::complete(&context, &mut builder); + theorem::complete(&context, &mut builder); + user_environment::complete(&context, &mut builder); + begin_snippet::complete(&context, &mut builder); + component_command::complete(&context, &mut builder); + user_command::complete(&context, &mut builder); + Some(builder.finish()) } diff --git a/support/texlab/src/features/completion/acronym_ref.rs b/support/texlab/src/features/completion/acronym_ref.rs index 84cbd8bc23..be7725fa2f 100644 --- a/support/texlab/src/features/completion/acronym_ref.rs +++ b/support/texlab/src/features/completion/acronym_ref.rs @@ -1,32 +1,29 @@ -use lsp_types::CompletionParams; use rowan::ast::AstNode; -use crate::{features::cursor::CursorContext, syntax::latex}; +use crate::{syntax::latex, util::cursor::CursorContext}; -use super::types::{InternalCompletionItem, InternalCompletionItemData}; +use super::builder::CompletionBuilder; -pub fn complete_acronyms<'a>( - context: &'a CursorContext<CompletionParams>, - items: &mut Vec<InternalCompletionItem<'a>>, +pub fn complete<'db>( + context: &'db CursorContext, + builder: &mut CompletionBuilder<'db>, ) -> Option<()> { let (_, range, group) = context.find_curly_group_word()?; latex::AcronymReference::cast(group.syntax().parent()?)?; - for document in context.request.workspace.documents_by_uri.values() { - if let Some(data) = document.data.as_latex() { - for name in latex::SyntaxNode::new_root(data.green.clone()) + for document in context.related() { + if let Some(data) = document.parse(context.db).as_tex() { + for name in data + .root(context.db) .descendants() .filter_map(latex::AcronymDefinition::cast) .filter_map(|node| node.name()) .filter_map(|name| name.key()) - .map(|name| name.to_string()) { - items.push(InternalCompletionItem::new( - range, - InternalCompletionItemData::Acronym { name }, - )); + builder.glossary_entry(range, name.to_string()); } } } + Some(()) } diff --git a/support/texlab/src/features/completion/argument.rs b/support/texlab/src/features/completion/argument.rs index 3ba28f9dea..10b377cb0e 100644 --- a/support/texlab/src/features/completion/argument.rs +++ b/support/texlab/src/features/completion/argument.rs @@ -1,15 +1,17 @@ -use lsp_types::CompletionParams; use rowan::{ast::AstNode, TextRange}; -use crate::{component_db::COMPONENT_DATABASE, features::cursor::CursorContext, syntax::latex}; +use crate::{ + syntax::latex, + util::{components::COMPONENT_DATABASE, cursor::CursorContext}, +}; -use super::types::{InternalCompletionItem, InternalCompletionItemData}; +use super::builder::CompletionBuilder; -pub fn complete_arguments<'a>( - context: &'a CursorContext<CompletionParams>, - items: &mut Vec<InternalCompletionItem<'a>>, +pub fn complete<'db>( + context: &'db CursorContext, + builder: &mut CompletionBuilder<'db>, ) -> Option<()> { - let token = context.cursor.as_latex()?; + let token = context.cursor.as_tex()?; let range = if token.kind() == latex::WORD { token.text_range() @@ -37,7 +39,7 @@ pub fn complete_arguments<'a>( let command_name = command.name()?; let command_name = &command_name.text()[1..]; - for component in COMPONENT_DATABASE.linked_components(&context.request.workspace) { + for component in COMPONENT_DATABASE.linked_components(context.db, context.document) { for component_command in component .commands .iter() @@ -50,14 +52,7 @@ pub fn complete_arguments<'a>( .filter(|(i, _)| *i == index) { for arg in ¶m.0 { - let item = InternalCompletionItem::new( - range, - InternalCompletionItemData::Argument { - name: &arg.name, - image: arg.image.as_deref(), - }, - ); - items.push(item); + builder.generic_argument(range, &arg.name, arg.image.as_deref()); } } } diff --git a/support/texlab/src/features/completion/begin_command.rs b/support/texlab/src/features/completion/begin_command.rs deleted file mode 100644 index 699b06c067..0000000000 --- a/support/texlab/src/features/completion/begin_command.rs +++ /dev/null @@ -1,18 +0,0 @@ -use lsp_types::CompletionParams; - -use crate::features::cursor::CursorContext; - -use super::types::{InternalCompletionItem, InternalCompletionItemData}; - -pub fn complete_begin_command( - context: &CursorContext<CompletionParams>, - items: &mut Vec<InternalCompletionItem>, -) -> Option<()> { - let range = context.cursor.command_range(context.offset)?; - - items.push(InternalCompletionItem::new( - range, - InternalCompletionItemData::BeginCommand, - )); - Some(()) -} diff --git a/support/texlab/src/features/completion/begin_snippet.rs b/support/texlab/src/features/completion/begin_snippet.rs new file mode 100644 index 0000000000..06be4faf13 --- /dev/null +++ b/support/texlab/src/features/completion/begin_snippet.rs @@ -0,0 +1,9 @@ +use crate::util::cursor::CursorContext; + +use super::builder::CompletionBuilder; + +pub fn complete(context: &CursorContext, builder: &mut CompletionBuilder) -> Option<()> { + let range = context.cursor.command_range(context.offset)?; + builder.begin_snippet(range); + Some(()) +} diff --git a/support/texlab/src/features/completion/builder.rs b/support/texlab/src/features/completion/builder.rs new file mode 100644 index 0000000000..f8ea4c5d15 --- /dev/null +++ b/support/texlab/src/features/completion/builder.rs @@ -0,0 +1,784 @@ +use fuzzy_matcher::{skim::SkimMatcherV2, FuzzyMatcher}; +use itertools::Itertools; +use lsp_types::{ + CompletionItem, CompletionItemKind, CompletionList, CompletionTextEdit, Documentation, + InsertTextFormat, MarkupContent, MarkupKind, TextEdit, Url, +}; +use once_cell::sync::Lazy; +use regex::Regex; +use rowan::{ast::AstNode, TextRange, TextSize}; +use serde::{Deserialize, Serialize}; +use smol_str::SmolStr; + +use crate::{ + db::{Document, Workspace}, + syntax::{ + bibtex::{self, HasName, HasType}, + latex, + }, + util::{ + capabilities::ClientCapabilitiesExt, + cursor::{Cursor, CursorContext}, + lang_data::{BibtexEntryTypeCategory, BibtexEntryTypeDoc, BibtexFieldDoc, LANGUAGE_DATA}, + line_index_ext::LineIndexExt, + lsp_enums::Structure, + }, +}; + +use super::COMPLETION_LIMIT; + +pub struct CompletionBuilder<'db> { + context: &'db CursorContext<'db>, + items: Vec<Item<'db>>, + matcher: SkimMatcherV2, + text_pattern: String, + file_pattern: String, + preselect: Option<String>, + snippets: bool, + markdown: bool, + item_kinds: &'db [CompletionItemKind], +} + +impl<'db> CompletionBuilder<'db> { + pub fn new(context: &'db CursorContext) -> Self { + let items = Vec::new(); + let matcher = SkimMatcherV2::default().ignore_case(); + let text_pattern = match &context.cursor { + Cursor::Tex(token) if token.kind().is_command_name() => { + if token.text_range().start() + TextSize::from(1) == context.offset { + // Handle cases similar to this one correctly: + // $\|$ % (| is the cursor) + String::from("\\") + } else { + token.text().trim_end().into() + } + } + Cursor::Tex(token) if token.kind() == latex::WORD => { + match token.parent().and_then(latex::Key::cast) { + Some(key) => key + .words() + .take_while(|word| word.text_range() != token.text_range()) + .chain(std::iter::once(token.clone())) + .filter(|word| word.text_range().start() < context.offset) + .join(" ") + .into(), + None => token.text().into(), + } + } + Cursor::Bib(token) + if matches!( + token.kind(), + bibtex::TYPE + | bibtex::NAME + | bibtex::WORD + | bibtex::COMMAND_NAME + | bibtex::ACCENT_NAME + ) => + { + token.text().into() + } + Cursor::Tex(_) | Cursor::Bib(_) | Cursor::Nothing => "".into(), + }; + + let file_pattern = text_pattern.split('/').last().unwrap().to_string(); + + let preselect = context + .cursor + .as_tex() + .and_then(|name| name.parent()) + .and_then(latex::CurlyGroupWord::cast) + .and_then(|group| group.syntax().parent()) + .and_then(|end| end.parent()) + .and_then(latex::Environment::cast) + .and_then(|env| env.begin()) + .and_then(|begin| begin.name()) + .and_then(|name| name.key()) + .map(|name| name.to_string()); + + let client_capabilities = context.workspace.client_capabilities(context.db); + let snippets = client_capabilities.has_snippet_support(); + let markdown = client_capabilities.has_completion_markdown_support(); + let item_kinds = client_capabilities + .text_document + .as_ref() + .and_then(|cap| cap.completion.as_ref()) + .and_then(|cap| cap.completion_item_kind.as_ref()) + .and_then(|cap| cap.value_set.as_deref()) + .unwrap_or_default(); + + Self { + context, + items, + matcher, + text_pattern, + file_pattern, + preselect, + snippets, + markdown, + item_kinds, + } + } + + pub fn glossary_entry(&mut self, range: TextRange, name: String) -> Option<()> { + let score = self.matcher.fuzzy_match(&name, &self.text_pattern)?; + self.items.push(Item { + range, + data: Data::GlossaryEntry { name }, + preselect: false, + score, + }); + + Some(()) + } + + pub fn generic_argument( + &mut self, + range: TextRange, + name: &'db str, + image: Option<&'db str>, + ) -> Option<()> { + let score = self.matcher.fuzzy_match(name, &self.text_pattern)?; + self.items.push(Item { + range, + data: Data::Argument { name, image }, + preselect: false, + score, + }); + + Some(()) + } + + pub fn begin_snippet(&mut self, range: TextRange) -> Option<()> { + let capabilities = Workspace::get(self.context.db).client_capabilities(self.context.db); + if capabilities.has_snippet_support() { + let score = self.matcher.fuzzy_match("begin", &self.text_pattern[1..])?; + self.items.push(Item { + range, + data: Data::BeginSnippet, + preselect: false, + score, + }); + } + + Some(()) + } + + pub fn citation( + &mut self, + range: TextRange, + document: Document, + entry: &bibtex::Entry, + ) -> Option<()> { + let key = entry.name_token()?.to_string(); + + let category = LANGUAGE_DATA + .find_entry_type(&entry.type_token()?.text()[1..]) + .map_or(BibtexEntryTypeCategory::Misc, |ty| ty.category); + + let code = entry.syntax().text().to_string(); + let filter_text = format!( + "{} {}", + key, + WHITESPACE_REGEX + .replace_all( + &code + .replace('{', " ") + .replace('}', " ") + .replace(',', " ") + .replace('=', " "), + " " + ) + .trim(), + ); + + let score = self.matcher.fuzzy_match(&filter_text, &self.text_pattern)?; + + let data = Data::Citation { + document, + key, + filter_text, + category, + }; + + self.items.push(Item { + range, + data, + preselect: false, + score, + }); + + Some(()) + } + + pub fn color_model(&mut self, range: TextRange, name: &'db str) -> Option<()> { + let score = self.matcher.fuzzy_match(name, &self.text_pattern)?; + self.items.push(Item { + range, + data: Data::ColorModel { name }, + preselect: false, + score, + }); + + Some(()) + } + + pub fn color(&mut self, range: TextRange, name: &'db str) -> Option<()> { + let score = self.matcher.fuzzy_match(name, &self.text_pattern)?; + self.items.push(Item { + range, + data: Data::Color { name }, + preselect: false, + score, + }); + + Some(()) + } + + pub fn component_command( + &mut self, + range: TextRange, + name: &'db str, + image: Option<&'db str>, + glyph: Option<&'db str>, + file_names: &'db [SmolStr], + ) -> Option<()> { + let score = self.matcher.fuzzy_match(name, &self.text_pattern[1..])?; + let data = Data::ComponentCommand { + name, + image, + glyph, + file_names, + }; + + self.items.push(Item { + range, + data, + preselect: false, + score, + }); + + Some(()) + } + + pub fn component_environment( + &mut self, + range: TextRange, + name: &'db str, + file_names: &'db [SmolStr], + ) -> Option<()> { + let score = self.matcher.fuzzy_match(name, &self.text_pattern)?; + self.items.push(Item { + range, + data: Data::ComponentEnvironment { name, file_names }, + preselect: Some(name) == self.preselect.as_deref(), + score, + }); + + Some(()) + } + + pub fn entry_type( + &mut self, + range: TextRange, + entry_type: &'db BibtexEntryTypeDoc, + ) -> Option<()> { + let score = self + .matcher + .fuzzy_match(&entry_type.name, &self.text_pattern[1..])?; + + self.items.push(Item { + range, + data: Data::EntryType { entry_type }, + preselect: false, + score, + }); + + Some(()) + } + + pub fn field(&mut self, range: TextRange, field: &'db BibtexFieldDoc) -> Option<()> { + let score = self.matcher.fuzzy_match(&field.name, &self.text_pattern)?; + self.items.push(Item { + range, + data: Data::Field { field }, + preselect: false, + score, + }); + + Some(()) + } + + pub fn class(&mut self, range: TextRange, name: &'db str) -> Option<()> { + let score = self.matcher.fuzzy_match(name, &self.text_pattern)?; + self.items.push(Item { + range, + data: Data::Class { name }, + preselect: false, + score, + }); + + Some(()) + } + + pub fn package(&mut self, range: TextRange, name: &'db str) -> Option<()> { + let score = self.matcher.fuzzy_match(name, &self.text_pattern)?; + self.items.push(Item { + range, + data: Data::Package { name }, + preselect: false, + score, + }); + + Some(()) + } + + pub fn file(&mut self, range: TextRange, name: String) -> Option<()> { + let score = self.matcher.fuzzy_match(&name, &self.file_pattern)?; + self.items.push(Item { + range, + data: Data::File { name }, + preselect: false, + score, + }); + + Some(()) + } + + pub fn directory(&mut self, range: TextRange, name: String) -> Option<()> { + let score = self.matcher.fuzzy_match(&name, &self.file_pattern)?; + self.items.push(Item { + range, + data: Data::Directory { name }, + preselect: false, + score, + }); + + Some(()) + } + + pub fn label( + &mut self, + range: TextRange, + name: &'db str, + kind: Structure, + header: Option<String>, + footer: Option<String>, + text: String, + ) -> Option<()> { + let score = self.matcher.fuzzy_match(&text, &self.text_pattern)?; + self.items.push(Item { + range, + data: Data::Label { + name, + kind, + header, + footer, + text, + }, + preselect: false, + score, + }); + + Some(()) + } + + pub fn tikz_library(&mut self, range: TextRange, name: &'db str) -> Option<()> { + let score = self.matcher.fuzzy_match(name, &self.text_pattern)?; + self.items.push(Item { + range, + data: Data::TikzLibrary { name }, + preselect: false, + score, + }); + + Some(()) + } + + pub fn user_command(&mut self, range: TextRange, name: &'db str) -> Option<()> { + let score = self.matcher.fuzzy_match(name, &self.text_pattern[1..])?; + self.items.push(Item { + range, + data: Data::UserCommand { name }, + preselect: false, + score, + }); + + Some(()) + } + + pub fn user_environment(&mut self, range: TextRange, name: &'db str) -> Option<()> { + let score = self.matcher.fuzzy_match(name, &self.text_pattern)?; + self.items.push(Item { + range, + data: Data::UserEnvironment { name }, + preselect: Some(name) == self.preselect.as_deref(), + score, + }); + + Some(()) + } + + pub fn finish(mut self) -> CompletionList { + let mut list = CompletionList::default(); + list.items = std::mem::take(&mut self.items) + .into_iter() + .sorted_by(|a, b| { + b.preselect + .cmp(&a.preselect) + .then_with(|| b.score.cmp(&a.score)) + .then_with(|| a.data.label().cmp(b.data.label())) + }) + .dedup_by(|a, b| a.data.label() == b.data.label()) + .take(COMPLETION_LIMIT) + .enumerate() + .map(|(i, item)| self.convert_item(item, i)) + .collect(); + + list.is_incomplete = if self + .context + .workspace + .client_info(self.context.db) + .as_ref() + .map_or(false, |client| client.name.as_str() == "Visual Studio Code") + { + true + } else { + list.items.len() >= COMPLETION_LIMIT + }; + + list + } + + fn convert_item(&self, item: Item, index: usize) -> CompletionItem { + let range = self.context.line_index.line_col_lsp_range(item.range); + let preselect = item.preselect; + let mut item = match item.data { + Data::EntryType { entry_type } => CompletionItem { + label: entry_type.name.clone(), + kind: Some(Structure::Entry(entry_type.category).completion_kind()), + documentation: entry_type.documentation.clone().map(|value| { + let kind = MarkupKind::Markdown; + Documentation::MarkupContent(MarkupContent { kind, value }) + }), + text_edit: Some(TextEdit::new(range, entry_type.name.clone()).into()), + ..CompletionItem::default() + }, + Data::Field { field } => CompletionItem { + label: field.name.clone(), + kind: Some(Structure::Field.completion_kind()), + documentation: Some(Documentation::MarkupContent(MarkupContent { + kind: MarkupKind::Markdown, + value: field.documentation.clone(), + })), + text_edit: Some(TextEdit::new(range, field.name.clone()).into()), + ..CompletionItem::default() + }, + Data::Argument { name, image } => { + let text_edit = TextEdit::new(range, String::from(name)); + CompletionItem { + label: name.into(), + kind: Some(Structure::Argument.completion_kind()), + text_edit: Some(CompletionTextEdit::Edit(text_edit)), + documentation: image.and_then(|base64| self.inline_image(name, base64)), + ..CompletionItem::default() + } + } + Data::BeginSnippet => { + if self.snippets { + CompletionItem { + kind: Some(Structure::Snippet.completion_kind()), + text_edit: Some( + TextEdit::new(range, "begin{$1}\n\t\n\\end{$1}".into()).into(), + ), + insert_text_format: Some(InsertTextFormat::SNIPPET), + ..CompletionItem::new_simple("begin".into(), self.component_detail(&[])) + } + } else { + CompletionItem { + kind: Some(Structure::Command.completion_kind()), + text_edit: Some(TextEdit::new(range, "begin".to_string()).into()), + ..CompletionItem::new_simple("begin".into(), self.component_detail(&[])) + } + } + } + Data::Citation { + document, + key, + filter_text, + category, + } => CompletionItem { + label: key.clone(), + kind: Some(Structure::Entry(category).completion_kind()), + filter_text: Some(filter_text.clone()), + sort_text: Some(filter_text), + data: Some( + serde_json::to_value(CompletionItemData::Citation { + uri: document + .location(self.context.db) + .uri(self.context.db) + .clone(), + key: key.clone(), + }) + .unwrap(), + ), + text_edit: Some(TextEdit::new(range, key).into()), + ..CompletionItem::default() + }, + Data::ComponentCommand { + name, + image, + glyph, + file_names, + } => CompletionItem { + label: name.into(), + detail: Some(glyph.map_or_else( + || self.component_detail(file_names), + |glyph| format!("{}, {}", glyph, self.component_detail(file_names)), + )), + kind: Some(Structure::Command.completion_kind()), + documentation: image.and_then(|base64| self.inline_image(name, base64)), + text_edit: Some(TextEdit::new(range, name.into()).into()), + ..CompletionItem::default() + }, + Data::ComponentEnvironment { name, file_names } => CompletionItem { + kind: Some(Structure::Environment.completion_kind()), + text_edit: Some(TextEdit::new(range, name.into()).into()), + ..CompletionItem::new_simple(name.into(), self.component_detail(file_names)) + }, + Data::Class { name } => CompletionItem { + label: name.into(), + kind: Some(Structure::Class.completion_kind()), + data: Some(serde_json::to_value(CompletionItemData::Package).unwrap()), + text_edit: Some(TextEdit::new(range, name.into()).into()), + ..CompletionItem::default() + }, + Data::Package { name } => CompletionItem { + label: name.into(), + kind: Some(Structure::Package.completion_kind()), + data: Some(serde_json::to_value(CompletionItemData::Class).unwrap()), + text_edit: Some(TextEdit::new(range, name.into()).into()), + ..CompletionItem::default() + }, + Data::Color { name } => CompletionItem { + label: name.into(), + kind: Some(Structure::Color.completion_kind()), + text_edit: Some(TextEdit::new(range, name.into()).into()), + ..CompletionItem::default() + }, + Data::ColorModel { name } => CompletionItem { + label: name.into(), + kind: Some(Structure::ColorModel.completion_kind()), + text_edit: Some(TextEdit::new(range, name.into()).into()), + ..CompletionItem::default() + }, + Data::GlossaryEntry { name } => CompletionItem { + label: name.clone(), + kind: Some(Structure::GlossaryEntry.completion_kind()), + text_edit: Some(TextEdit::new(range, name).into()), + ..CompletionItem::default() + }, + Data::File { name } => CompletionItem { + label: name.clone(), + kind: Some(Structure::File.completion_kind()), + text_edit: Some(TextEdit::new(range, name).into()), + ..CompletionItem::default() + }, + Data::Directory { name } => CompletionItem { + label: name.clone(), + kind: Some(Structure::Folder.completion_kind()), + text_edit: Some(TextEdit::new(range, name).into()), + ..CompletionItem::default() + }, + Data::Label { + name, + kind, + header, + footer, + text, + } => CompletionItem { + label: name.into(), + kind: Some(kind.completion_kind()), + detail: header, + documentation: footer.map(Documentation::String), + sort_text: Some(text.clone()), + filter_text: Some(text), + text_edit: Some(TextEdit::new(range, name.into()).into()), + ..CompletionItem::default() + }, + Data::UserCommand { name } => { + let detail = "user-defined".into(); + let name = &name[1..]; + CompletionItem { + kind: Some(Structure::Command.completion_kind()), + text_edit: Some(TextEdit::new(range, name.into()).into()), + ..CompletionItem::new_simple(name.into(), detail) + } + } + Data::UserEnvironment { name } => { + let detail = "user-defined".into(); + CompletionItem { + kind: Some(Structure::Environment.completion_kind()), + text_edit: Some(TextEdit::new(range, name.into()).into()), + ..CompletionItem::new_simple(name.into(), detail) + } + } + Data::TikzLibrary { name } => CompletionItem { + label: name.into(), + kind: Some(Structure::TikzLibrary.completion_kind()), + text_edit: Some(TextEdit::new(range, name.into()).into()), + ..CompletionItem::default() + }, + }; + + item.preselect = Some(preselect); + + if !self.item_kinds.contains(&item.kind.unwrap()) { + item.kind = Some(CompletionItemKind::TEXT); + } + + let sort_prefix = format!("{:0>2}", index); + match &item.sort_text { + Some(sort_text) => { + item.sort_text = Some(format!("{} {}", sort_prefix, sort_text)); + } + None => { + item.sort_text = Some(sort_prefix); + } + }; + + item + } + + fn inline_image(&self, name: &str, base64: &str) -> Option<Documentation> { + if self.markdown { + let kind = MarkupKind::Markdown; + let value = format!( + "![{}](data:image/png;base64,{}|width=48,height=48)", + name, base64 + ); + + Some(Documentation::MarkupContent(MarkupContent { kind, value })) + } else { + None + } + } + + fn component_detail(&self, file_names: &[SmolStr]) -> String { + if file_names.is_empty() { + "built-in".into() + } else { + file_names.join(", ") + } + } +} + +#[derive(Debug, Clone)] +struct Item<'db> { + range: TextRange, + data: Data<'db>, + preselect: bool, + score: i32, +} + +#[derive(Debug, Clone)] +enum Data<'db> { + EntryType { + entry_type: &'db BibtexEntryTypeDoc, + }, + Field { + field: &'db BibtexFieldDoc, + }, + Argument { + name: &'db str, + image: Option<&'db str>, + }, + BeginSnippet, + Citation { + document: Document, + key: String, + filter_text: String, + category: BibtexEntryTypeCategory, + }, + ComponentCommand { + name: &'db str, + image: Option<&'db str>, + glyph: Option<&'db str>, + file_names: &'db [SmolStr], + }, + ComponentEnvironment { + name: &'db str, + file_names: &'db [SmolStr], + }, + Class { + name: &'db str, + }, + Package { + name: &'db str, + }, + Color { + name: &'db str, + }, + ColorModel { + name: &'db str, + }, + GlossaryEntry { + name: String, + }, + File { + name: String, + }, + Directory { + name: String, + }, + Label { + name: &'db str, + kind: Structure, + header: Option<String>, + footer: Option<String>, + text: String, + }, + UserCommand { + name: &'db str, + }, + UserEnvironment { + name: &'db str, + }, + TikzLibrary { + name: &'db str, + }, +} + +impl<'db> Data<'db> { + pub fn label<'this: 'db>(&'this self) -> &'db str { + match self { + Self::EntryType { entry_type } => &entry_type.name, + Self::Field { field } => &field.name, + Self::Argument { name, .. } => name, + Self::BeginSnippet => "begin", + Self::Citation { key, .. } => key, + Self::ComponentCommand { name, .. } => name, + Self::ComponentEnvironment { name, .. } => name, + Self::Class { name } => name, + Self::Package { name } => name, + Self::Color { name } => name, + Self::ColorModel { name } => name, + Self::GlossaryEntry { name } => name, + Self::File { name } => name, + Self::Directory { name } => name, + Self::Label { name, .. } => name, + Self::UserCommand { name } => name, + Self::UserEnvironment { name } => name, + Self::TikzLibrary { name } => name, + } + } +} + +#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub(crate) enum CompletionItemData { + Package, + Class, + Citation { uri: Url, key: String }, +} + +static WHITESPACE_REGEX: Lazy<Regex> = Lazy::new(|| Regex::new("\\s+").unwrap()); diff --git a/support/texlab/src/features/completion/citation.rs b/support/texlab/src/features/completion/citation.rs index e6436689d7..68d72717a7 100644 --- a/support/texlab/src/features/completion/citation.rs +++ b/support/texlab/src/features/completion/citation.rs @@ -1,26 +1,17 @@ -use std::sync::Arc; - -use lsp_types::CompletionParams; -use once_cell::sync::Lazy; -use regex::Regex; use rowan::{ast::AstNode, TextRange}; use crate::{ - features::{cursor::CursorContext, lsp_kinds::Structure}, - syntax::{ - bibtex::{self, HasName, HasType}, - latex, - }, - BibtexEntryTypeCategory, Document, LANGUAGE_DATA, + syntax::{bibtex, latex}, + util::cursor::CursorContext, }; -use super::types::{InternalCompletionItem, InternalCompletionItemData}; +use super::builder::CompletionBuilder; -pub fn complete_citations<'a>( - context: &'a CursorContext<CompletionParams>, - items: &mut Vec<InternalCompletionItem<'a>>, +pub fn complete<'db>( + context: &'db CursorContext, + builder: &mut CompletionBuilder<'db>, ) -> Option<()> { - let token = context.cursor.as_latex()?; + let token = context.cursor.as_tex()?; let range = if token.kind() == latex::WORD { latex::Key::cast(token.parent()?) @@ -36,15 +27,14 @@ pub fn complete_citations<'a>( }; check_citation(context).or_else(|| check_acronym(context))?; - for document in context.request.workspace.documents_by_uri.values() { - if let Some(data) = document.data.as_bibtex() { - for entry in bibtex::SyntaxNode::new_root(data.green.clone()) + for document in context.related() { + if let Some(data) = document.parse(context.db).as_bib() { + for entry in data + .root(context.db) .children() .filter_map(bibtex::Entry::cast) { - if let Some(item) = make_item(document, &entry, range) { - items.push(item); - } + builder.citation(range, document, &entry); } } } @@ -52,14 +42,14 @@ pub fn complete_citations<'a>( Some(()) } -fn check_citation(context: &CursorContext<CompletionParams>) -> Option<()> { +fn check_citation(context: &CursorContext) -> Option<()> { let (_, _, group) = context.find_curly_group_word_list()?; latex::Citation::cast(group.syntax().parent()?)?; Some(()) } -fn check_acronym(context: &CursorContext<CompletionParams>) -> Option<()> { - let token = context.cursor.as_latex()?; +fn check_acronym(context: &CursorContext) -> Option<()> { + let token = context.cursor.as_tex()?; let pair = token .parent_ancestors() @@ -71,45 +61,3 @@ fn check_acronym(context: &CursorContext<CompletionParams>) -> Option<()> { latex::AcronymDeclaration::cast(pair.syntax().parent()?.parent()?.parent()?)?; Some(()) } - -fn make_item<'a>( - document: &'a Document, - entry: &bibtex::Entry, - range: TextRange, -) -> Option<InternalCompletionItem<'a>> { - let key = entry.name_token()?.to_string(); - let ty = LANGUAGE_DATA - .find_entry_type(&entry.type_token()?.text()[1..]) - .map_or_else( - || Structure::Entry(BibtexEntryTypeCategory::Misc), - |ty| Structure::Entry(ty.category), - ); - - let entry_code = entry.syntax().text().to_string(); - let text = format!( - "{} {}", - key, - WHITESPACE_REGEX - .replace_all( - &entry_code - .replace('{', " ") - .replace('}', " ") - .replace(',', " ") - .replace('=', " "), - " " - ) - .trim(), - ); - - Some(InternalCompletionItem::new( - range, - InternalCompletionItemData::Citation { - uri: Arc::clone(&document.uri), - key, - text, - ty, - }, - )) -} - -static WHITESPACE_REGEX: Lazy<Regex> = Lazy::new(|| Regex::new("\\s+").unwrap()); diff --git a/support/texlab/src/features/completion/color.rs b/support/texlab/src/features/completion/color.rs index a9a385c3c9..cce6517cb4 100644 --- a/support/texlab/src/features/completion/color.rs +++ b/support/texlab/src/features/completion/color.rs @@ -1,22 +1,21 @@ -use lsp_types::CompletionParams; use rowan::ast::AstNode; -use crate::{features::cursor::CursorContext, syntax::latex, LANGUAGE_DATA}; +use crate::{ + syntax::latex, + util::{cursor::CursorContext, lang_data::LANGUAGE_DATA}, +}; -use super::types::{InternalCompletionItem, InternalCompletionItemData}; +use super::builder::CompletionBuilder; -pub fn complete_colors<'a>( - context: &'a CursorContext<CompletionParams>, - items: &mut Vec<InternalCompletionItem<'a>>, +pub fn complete<'db>( + context: &'db CursorContext, + builder: &mut CompletionBuilder<'db>, ) -> Option<()> { let (_, range, group) = context.find_curly_group_word()?; latex::ColorReference::cast(group.syntax().parent()?)?; for name in &LANGUAGE_DATA.colors { - items.push(InternalCompletionItem::new( - range, - InternalCompletionItemData::Color { name }, - )); + builder.color(range, name); } Some(()) diff --git a/support/texlab/src/features/completion/color_model.rs b/support/texlab/src/features/completion/color_model.rs index cd582d0031..af700a96fb 100644 --- a/support/texlab/src/features/completion/color_model.rs +++ b/support/texlab/src/features/completion/color_model.rs @@ -1,29 +1,25 @@ -use lsp_types::CompletionParams; use rowan::{ast::AstNode, TextRange}; -use crate::{features::cursor::CursorContext, syntax::latex}; +use crate::{syntax::latex, util::cursor::CursorContext}; -use super::types::{InternalCompletionItem, InternalCompletionItemData}; +use super::builder::CompletionBuilder; const MODEL_NAMES: &[&str] = &["gray", "rgb", "RGB", "HTML", "cmyk"]; -pub fn complete_color_models<'a>( - context: &'a CursorContext<CompletionParams>, - items: &mut Vec<InternalCompletionItem<'a>>, +pub fn complete<'db>( + context: &'db CursorContext, + builder: &mut CompletionBuilder<'db>, ) -> Option<()> { let range = check_color_definition(context).or_else(|| check_color_definition_set(context))?; for name in MODEL_NAMES { - items.push(InternalCompletionItem::new( - range, - InternalCompletionItemData::ColorModel { name }, - )); + builder.color_model(range, name); } Some(()) } -fn check_color_definition(context: &CursorContext<CompletionParams>) -> Option<TextRange> { +fn check_color_definition(context: &CursorContext) -> Option<TextRange> { let (_, range, group) = context.find_curly_group_word()?; let definition = latex::ColorDefinition::cast(group.syntax().parent()?)?; @@ -33,7 +29,7 @@ fn check_color_definition(context: &CursorContext<CompletionParams>) -> Option<T Some(range) } -fn check_color_definition_set(context: &CursorContext<CompletionParams>) -> Option<TextRange> { +fn check_color_definition_set(context: &CursorContext) -> Option<TextRange> { let (_, range, group) = context.find_curly_group_word_list()?; let definition = latex::ColorSetDefinition::cast(group.syntax().parent()?)?; definition diff --git a/support/texlab/src/features/completion/component_command.rs b/support/texlab/src/features/completion/component_command.rs index 097b28633f..20cef73848 100644 --- a/support/texlab/src/features/completion/component_command.rs +++ b/support/texlab/src/features/completion/component_command.rs @@ -1,26 +1,22 @@ -use lsp_types::CompletionParams; +use crate::util::{components::COMPONENT_DATABASE, cursor::CursorContext}; -use crate::{component_db::COMPONENT_DATABASE, features::cursor::CursorContext}; +use super::builder::CompletionBuilder; -use super::types::{InternalCompletionItem, InternalCompletionItemData}; - -pub fn complete_component_commands<'a>( - context: &'a CursorContext<CompletionParams>, - items: &mut Vec<InternalCompletionItem<'a>>, +pub fn complete<'db>( + context: &'db CursorContext, + builder: &mut CompletionBuilder<'db>, ) -> Option<()> { let range = context.cursor.command_range(context.offset)?; - for component in COMPONENT_DATABASE.linked_components(&context.request.workspace) { + for component in COMPONENT_DATABASE.linked_components(context.db, context.document) { for command in &component.commands { - items.push(InternalCompletionItem::new( + builder.component_command( range, - InternalCompletionItemData::ComponentCommand { - name: &command.name, - image: command.image.as_deref(), - glyph: command.glyph.as_deref(), - file_names: &component.file_names, - }, - )); + &command.name, + command.image.as_deref(), + command.glyph.as_deref(), + &component.file_names, + ); } } diff --git a/support/texlab/src/features/completion/component_environment.rs b/support/texlab/src/features/completion/component_environment.rs index a9478694bb..e58e319a46 100644 --- a/support/texlab/src/features/completion/component_environment.rs +++ b/support/texlab/src/features/completion/component_environment.rs @@ -1,24 +1,16 @@ -use lsp_types::CompletionParams; +use crate::util::{components::COMPONENT_DATABASE, cursor::CursorContext}; -use crate::{component_db::COMPONENT_DATABASE, features::cursor::CursorContext}; +use super::builder::CompletionBuilder; -use super::types::{InternalCompletionItem, InternalCompletionItemData}; - -pub fn complete_component_environments<'a>( - context: &'a CursorContext<CompletionParams>, - items: &mut Vec<InternalCompletionItem<'a>>, +pub fn complete<'db>( + context: &'db CursorContext, + builder: &mut CompletionBuilder<'db>, ) -> Option<()> { let (_, range) = context.find_environment_name()?; - for component in COMPONENT_DATABASE.linked_components(&context.request.workspace) { + for component in COMPONENT_DATABASE.linked_components(context.db, context.document) { for name in &component.environments { - items.push(InternalCompletionItem::new( - range, - InternalCompletionItemData::ComponentEnvironment { - name, - file_names: &component.file_names, - }, - )); + builder.component_environment(range, name, &component.file_names); } } diff --git a/support/texlab/src/features/completion/entry_type.rs b/support/texlab/src/features/completion/entry_type.rs index 519737ed08..38bc0e3f3a 100644 --- a/support/texlab/src/features/completion/entry_type.rs +++ b/support/texlab/src/features/completion/entry_type.rs @@ -1,26 +1,26 @@ -use lsp_types::CompletionParams; use rowan::{TextRange, TextSize}; -use crate::{features::cursor::CursorContext, syntax::bibtex, LANGUAGE_DATA}; +use crate::{ + syntax::bibtex, + util::{cursor::CursorContext, lang_data::LANGUAGE_DATA}, +}; -use super::types::{InternalCompletionItem, InternalCompletionItemData}; +use super::builder::CompletionBuilder; -pub fn complete_entry_types<'a>( - context: &'a CursorContext<CompletionParams>, - items: &mut Vec<InternalCompletionItem<'a>>, +pub fn complete<'db>( + context: &'db CursorContext, + builder: &mut CompletionBuilder<'db>, ) -> Option<()> { let range = context .cursor - .as_bibtex() + .as_bib() .filter(|token| token.kind() == bibtex::TYPE) .map(bibtex::SyntaxToken::text_range) .filter(|range| range.start() != context.offset) .map(|range| TextRange::new(range.start() + TextSize::from(1), range.end()))?; - for ty in &LANGUAGE_DATA.entry_types { - let data = InternalCompletionItemData::EntryType { ty }; - let item = InternalCompletionItem::new(range, data); - items.push(item); + for entry_type in &LANGUAGE_DATA.entry_types { + builder.entry_type(range, entry_type); } Some(()) diff --git a/support/texlab/src/features/completion/field.rs b/support/texlab/src/features/completion/field.rs index 4f386ed1b1..ff6e54a562 100644 --- a/support/texlab/src/features/completion/field.rs +++ b/support/texlab/src/features/completion/field.rs @@ -1,19 +1,17 @@ -use lsp_types::CompletionParams; use rowan::{ast::AstNode, TextRange}; use crate::{ - features::cursor::CursorContext, syntax::bibtex::{self, HasName}, - LANGUAGE_DATA, + util::{cursor::CursorContext, lang_data::LANGUAGE_DATA}, }; -use super::types::{InternalCompletionItem, InternalCompletionItemData}; +use super::builder::CompletionBuilder; -pub fn complete_fields<'a>( - context: &'a CursorContext<CompletionParams>, - items: &mut Vec<InternalCompletionItem<'a>>, +pub fn complete<'db>( + context: &'db CursorContext, + builder: &mut CompletionBuilder<'db>, ) -> Option<()> { - let token = context.cursor.as_bibtex()?; + let token = context.cursor.as_bib()?; let range = if token.kind() == bibtex::NAME { token.text_range() @@ -31,9 +29,8 @@ pub fn complete_fields<'a>( } for field in &LANGUAGE_DATA.fields { - let data = InternalCompletionItemData::Field { field }; - let item = InternalCompletionItem::new(range, data); - items.push(item); + builder.field(range, field); } + Some(()) } diff --git a/support/texlab/src/features/completion/glossary_ref.rs b/support/texlab/src/features/completion/glossary_ref.rs index 6223079fdf..34d53bf24d 100644 --- a/support/texlab/src/features/completion/glossary_ref.rs +++ b/support/texlab/src/features/completion/glossary_ref.rs @@ -1,38 +1,31 @@ -use lsp_types::CompletionParams; use rowan::ast::AstNode; -use crate::{features::cursor::CursorContext, syntax::latex}; +use crate::{syntax::latex, util::cursor::CursorContext}; -use super::types::{InternalCompletionItem, InternalCompletionItemData}; +use super::builder::CompletionBuilder; -pub fn complete_glossary_entries<'a>( - context: &'a CursorContext<CompletionParams>, - items: &mut Vec<InternalCompletionItem<'a>>, +pub fn complete<'db>( + context: &'db CursorContext, + builder: &mut CompletionBuilder<'db>, ) -> Option<()> { let (_, range, group) = context.find_curly_group_word()?; latex::GlossaryEntryReference::cast(group.syntax().parent()?)?; - for document in context.request.workspace.documents_by_uri.values() { - if let Some(data) = document.data.as_latex() { - for node in latex::SyntaxNode::new_root(data.green.clone()).descendants() { + for document in context.related() { + if let Some(data) = document.parse(context.db).as_tex() { + for node in data.root(context.db).descendants() { if let Some(name) = latex::GlossaryEntryDefinition::cast(node.clone()) .and_then(|entry| entry.name()) .and_then(|name| name.key()) .map(|name| name.to_string()) { - items.push(InternalCompletionItem::new( - range, - InternalCompletionItemData::GlossaryEntry { name }, - )); + builder.glossary_entry(range, name); } else if let Some(name) = latex::AcronymDefinition::cast(node) .and_then(|entry| entry.name()) .and_then(|name| name.key()) .map(|name| name.to_string()) { - items.push(InternalCompletionItem::new( - range, - InternalCompletionItemData::Acronym { name }, - )); + builder.glossary_entry(range, name); } } } diff --git a/support/texlab/src/features/completion/import.rs b/support/texlab/src/features/completion/import.rs index 9cb35b68a7..bf6da78a43 100644 --- a/support/texlab/src/features/completion/import.rs +++ b/support/texlab/src/features/completion/import.rs @@ -1,31 +1,24 @@ -use lsp_types::CompletionParams; use rowan::ast::AstNode; use rustc_hash::FxHashSet; -use smol_str::SmolStr; -use crate::{component_db::COMPONENT_DATABASE, features::cursor::CursorContext, syntax::latex}; +use crate::{ + syntax::latex, + util::{components::COMPONENT_DATABASE, cursor::CursorContext}, +}; -use super::types::{InternalCompletionItem, InternalCompletionItemData}; +use super::builder::CompletionBuilder; -pub fn complete_imports<'a>( - context: &'a CursorContext<CompletionParams>, - items: &mut Vec<InternalCompletionItem<'a>>, +pub fn complete<'db>( + context: &'db CursorContext, + builder: &mut CompletionBuilder<'db>, ) -> Option<()> { let (_, range, group) = context.find_curly_group_word_list()?; - let (extension, mut factory): ( - &str, - Box<dyn FnMut(SmolStr) -> InternalCompletionItemData<'a>>, - ) = match group.syntax().parent()?.kind() { - latex::PACKAGE_INCLUDE => ( - "sty", - Box::new(|name| InternalCompletionItemData::Package { name }), - ), - latex::CLASS_INCLUDE => ( - "cls", - Box::new(|name| InternalCompletionItemData::Class { name }), - ), - _ => return None, + let kind = group.syntax().parent()?.kind(); + let extension = match kind { + latex::PACKAGE_INCLUDE => "sty", + latex::CLASS_INCLUDE => "cls", + _ => return Some(()), }; let mut file_names = FxHashSet::default(); @@ -35,21 +28,27 @@ pub fn complete_imports<'a>( .flat_map(|comp| comp.file_names.iter()) .filter(|file_name| file_name.ends_with(extension)) { - file_names.insert(file_name); + file_names.insert(file_name.as_str()); let stem = &file_name[0..file_name.len() - 4]; - let data = factory(stem.into()); - items.push(InternalCompletionItem::new(range, data)); + if kind == latex::PACKAGE_INCLUDE { + builder.package(range, stem); + } else { + builder.class(range, stem); + } } - let resolver = &context.request.workspace.environment.resolver; - for file_name in resolver - .files_by_name - .keys() + let file_name_db = context.workspace.file_name_db(context.db); + for file_name in file_name_db + .iter() + .map(|(file_name, _)| file_name) .filter(|file_name| file_name.ends_with(extension) && !file_names.contains(file_name)) { let stem = &file_name[0..file_name.len() - 4]; - let data = factory(stem.into()); - items.push(InternalCompletionItem::new(range, data)); + if kind == latex::PACKAGE_INCLUDE { + builder.package(range, stem); + } else { + builder.class(range, stem); + } } Some(()) diff --git a/support/texlab/src/features/completion/include.rs b/support/texlab/src/features/completion/include.rs index d851aca820..bde7544570 100644 --- a/support/texlab/src/features/completion/include.rs +++ b/support/texlab/src/features/completion/include.rs @@ -4,18 +4,22 @@ use std::{ path::{Path, PathBuf}, }; -use lsp_types::CompletionParams; use rowan::{ast::AstNode, TextRange, TextSize}; -use crate::{features::cursor::CursorContext, syntax::latex}; +use crate::{syntax::latex, util::cursor::CursorContext}; -use super::types::{InternalCompletionItem, InternalCompletionItemData}; +use super::builder::CompletionBuilder; -pub fn complete_includes<'a>( - context: &'a CursorContext<CompletionParams>, - items: &mut Vec<InternalCompletionItem<'a>>, +pub fn complete<'db>( + context: &'db CursorContext, + builder: &mut CompletionBuilder<'db>, ) -> Option<()> { - if context.request.main_document().uri.scheme() != "file" { + if context + .document + .location(context.db) + .path(context.db) + .is_none() + { return None; } @@ -51,10 +55,15 @@ pub fn complete_includes<'a>( let mut dirs = vec![current_dir(context, &path_text, None)]; if include.kind() == latex::GRAPHICS_INCLUDE { - for document in context.request.workspace.documents_by_uri.values() { - if let Some(data) = document.data.as_latex() { - for graphics_path in &data.extras.graphics_paths { - dirs.push(current_dir(context, &path_text, Some(graphics_path))); + for document in context.related() { + if let Some(data) = document.parse(context.db).as_tex() { + for path in data + .analyze(context.db) + .graphics_paths(context.db) + .iter() + .map(|node| node.path(context.db)) + { + dirs.push(current_dir(context, &path_text, Some(path))); } } } @@ -74,15 +83,12 @@ pub fn complete_includes<'a>( if !include_extension { remove_extension(&mut path); } + let name = path.file_name()?.to_str()?.into(); - let data = InternalCompletionItemData::File { name }; - let item = InternalCompletionItem::new(segment_range, data); - items.push(item); + builder.file(segment_range, name); } else if file_type.is_dir() { let name = path.file_name()?.to_str()?.into(); - let data = InternalCompletionItemData::Directory { name }; - let item = InternalCompletionItem::new(segment_range, data); - items.push(item); + builder.directory(segment_range, name); } } @@ -90,34 +96,24 @@ pub fn complete_includes<'a>( } fn current_dir( - context: &CursorContext<CompletionParams>, + context: &CursorContext, path_text: &str, graphics_path: Option<&str>, ) -> Option<PathBuf> { - let mut path = context - .request + let parent = context .workspace - .environment - .options - .root_directory - .as_ref() - .map_or_else( - || { - let mut path = context.request.main_document().uri.to_file_path().unwrap(); - path.pop(); - path - }, - |root_directory| { - context - .request - .workspace - .environment - .current_directory - .join(root_directory) - }, - ); - - path = PathBuf::from(path.to_str()?.replace('\\', "/")); + .parents(context.db, context.document) + .iter() + .next() + .map_or(context.document, Clone::clone); + + let path = context + .workspace + .working_dir(context.db, parent.directory(context.db)) + .path(context.db) + .as_deref()?; + + let mut path = PathBuf::from(path.to_str()?.replace('\\', "/")); if !path_text.is_empty() { if let Some(graphics_path) = graphics_path { path.push(graphics_path); diff --git a/support/texlab/src/features/completion/label.rs b/support/texlab/src/features/completion/label.rs index b662f98c8a..ae3e010b0e 100644 --- a/support/texlab/src/features/completion/label.rs +++ b/support/texlab/src/features/completion/label.rs @@ -1,83 +1,61 @@ -use lsp_types::CompletionParams; use rowan::{ast::AstNode, TextRange}; use crate::{ - features::{cursor::CursorContext, lsp_kinds::Structure}, - render_label, syntax::latex, - LabelledObject, + util::{self, cursor::CursorContext, label::LabeledObject, lsp_enums::Structure}, }; -use super::types::{InternalCompletionItem, InternalCompletionItemData}; +use super::builder::CompletionBuilder; -pub fn complete_labels<'a>( - context: &'a CursorContext<CompletionParams>, - items: &mut Vec<InternalCompletionItem<'a>>, +pub fn complete<'db>( + context: &'db CursorContext, + builder: &mut CompletionBuilder<'db>, ) -> Option<()> { let (range, is_math) = find_reference(context).or_else(|| find_reference_range(context))?; - for document in context.request.workspace.documents_by_uri.values() { - if let Some(data) = document.data.as_latex() { - for label in latex::SyntaxNode::new_root(data.green.clone()) - .descendants() - .filter_map(latex::LabelDefinition::cast) + let db = context.db; + for document in context.related() { + if let Some(data) = document.parse(db).as_tex() { + for label in data + .analyze(db) + .labels(db) + .iter() + .filter(|label| label.origin(db).as_definition().is_some()) { - if let Some(name) = label - .name() - .and_then(|name| name.key()) - .map(|name| name.to_string()) - { - match render_label(&context.request.workspace, &name, Some(label)) { - Some(rendered_label) => { - let kind = match &rendered_label.object { - LabelledObject::Section { .. } => Structure::Section, - LabelledObject::Float { .. } => Structure::Float, - LabelledObject::Theorem { .. } => Structure::Theorem, - LabelledObject::Equation => Structure::Equation, - LabelledObject::EnumItem => Structure::Item, - }; + match util::label::render(db, document, *label) { + Some(rendered_label) => { + let kind = match &rendered_label.object { + LabeledObject::Section { .. } => Structure::Section, + LabeledObject::Float { .. } => Structure::Float, + LabeledObject::Theorem { .. } => Structure::Theorem, + LabeledObject::Equation => Structure::Equation, + LabeledObject::EnumItem => Structure::Item, + }; - if is_math && kind != Structure::Equation { - continue; - } + if is_math && kind != Structure::Equation { + continue; + } - let header = rendered_label.detail(); - let footer = match &rendered_label.object { - LabelledObject::Float { caption, .. } => Some(caption.clone()), - _ => None, - }; + let header = rendered_label.detail(db); + let footer = match &rendered_label.object { + LabeledObject::Float { caption, .. } => Some(caption.clone()), + _ => None, + }; - let text = format!("{} {}", name, rendered_label.reference()); + let text = format!( + "{} {}", + label.name(db).text(db), + rendered_label.reference(db) + ); - let item = InternalCompletionItem::new( - range, - InternalCompletionItemData::Label { - name, - kind, - header, - footer, - text, - }, - ); - items.push(item); - } - None => { - let kind = Structure::Label; - let header = None; - let footer = None; - let text = name.to_string(); - let item = InternalCompletionItem::new( - range, - InternalCompletionItemData::Label { - name, - kind, - header, - footer, - text, - }, - ); - items.push(item); - } + builder.label(range, label.name(db).text(db), kind, header, footer, text); + } + None => { + let kind = Structure::Label; + let header = None; + let footer = None; + let text = label.name(db).text(db).clone(); + builder.label(range, label.name(db).text(db), kind, header, footer, text); } } } @@ -87,14 +65,14 @@ pub fn complete_labels<'a>( Some(()) } -fn find_reference(context: &CursorContext<CompletionParams>) -> Option<(TextRange, bool)> { +fn find_reference(context: &CursorContext) -> Option<(TextRange, bool)> { let (_, range, group) = context.find_curly_group_word_list()?; let reference = latex::LabelReference::cast(group.syntax().parent()?)?; let is_math = reference.command()?.text() == "\\eqref"; Some((range, is_math)) } -fn find_reference_range(context: &CursorContext<CompletionParams>) -> Option<(TextRange, bool)> { +fn find_reference_range(context: &CursorContext) -> Option<(TextRange, bool)> { let (_, range, group) = context.find_curly_group_word()?; latex::LabelReferenceRange::cast(group.syntax().parent()?)?; Some((range, false)) diff --git a/support/texlab/src/features/completion/theorem.rs b/support/texlab/src/features/completion/theorem.rs index 65b511f7ad..cd0dfe3a84 100644 --- a/support/texlab/src/features/completion/theorem.rs +++ b/support/texlab/src/features/completion/theorem.rs @@ -1,24 +1,18 @@ -use lsp_types::CompletionParams; +use crate::util::cursor::CursorContext; -use crate::features::cursor::CursorContext; +use super::builder::CompletionBuilder; -use super::types::{InternalCompletionItem, InternalCompletionItemData}; - -pub fn complete_theorem_environments<'a>( - context: &'a CursorContext<CompletionParams>, - items: &mut Vec<InternalCompletionItem<'a>>, +pub fn complete<'db>( + context: &'db CursorContext, + builder: &mut CompletionBuilder<'db>, ) -> Option<()> { let (_, range) = context.find_environment_name()?; - for document in context.request.workspace.documents_by_uri.values() { - if let Some(data) = document.data.as_latex() { - for environment in &data.extras.theorem_environments { - items.push(InternalCompletionItem::new( - range, - InternalCompletionItemData::UserEnvironment { - name: environment.name.clone(), - }, - )); + let db = context.db; + for document in context.related() { + if let Some(data) = document.parse(db).as_tex() { + for environment in data.analyze(db).theorem_environments(db) { + builder.user_environment(range, environment.name(db).text(db)); } } } diff --git a/support/texlab/src/features/completion/tikz_library.rs b/support/texlab/src/features/completion/tikz_library.rs index bf15695722..7ea26d50c2 100644 --- a/support/texlab/src/features/completion/tikz_library.rs +++ b/support/texlab/src/features/completion/tikz_library.rs @@ -1,13 +1,15 @@ -use lsp_types::CompletionParams; use rowan::ast::AstNode; -use crate::{features::cursor::CursorContext, syntax::latex, LANGUAGE_DATA}; +use crate::{ + syntax::latex, + util::{cursor::CursorContext, lang_data::LANGUAGE_DATA}, +}; -use super::types::{InternalCompletionItem, InternalCompletionItemData}; +use super::builder::CompletionBuilder; -pub fn complete_tikz_libraries<'a>( - context: &'a CursorContext<CompletionParams>, - items: &mut Vec<InternalCompletionItem<'a>>, +pub fn complete<'db>( + context: &'db CursorContext, + builder: &mut CompletionBuilder<'db>, ) -> Option<()> { let (_, range, group) = context.find_curly_group_word_list()?; @@ -15,17 +17,11 @@ pub fn complete_tikz_libraries<'a>( if import.command()?.text() == "\\usepgflibrary" { for name in &LANGUAGE_DATA.pgf_libraries { - items.push(InternalCompletionItem::new( - range, - InternalCompletionItemData::PgfLibrary { name }, - )); + builder.tikz_library(range, name); } } else { for name in &LANGUAGE_DATA.tikz_libraries { - items.push(InternalCompletionItem::new( - range, - InternalCompletionItemData::TikzLibrary { name }, - )); + builder.tikz_library(range, name); } } diff --git a/support/texlab/src/features/completion/types.rs b/support/texlab/src/features/completion/types.rs deleted file mode 100644 index 3655c6a074..0000000000 --- a/support/texlab/src/features/completion/types.rs +++ /dev/null @@ -1,151 +0,0 @@ -use std::sync::Arc; - -use lsp_types::Url; -use rowan::TextRange; -use serde::{Deserialize, Serialize}; -use smol_str::SmolStr; - -use crate::{features::lsp_kinds::Structure, BibtexEntryTypeDoc, BibtexFieldDoc}; - -#[derive(Debug, Clone)] -pub struct InternalCompletionItem<'a> { - pub range: TextRange, - pub data: InternalCompletionItemData<'a>, - pub preselect: bool, - pub score: Option<i64>, -} - -impl<'a> InternalCompletionItem<'a> { - pub fn new(range: TextRange, data: InternalCompletionItemData<'a>) -> Self { - Self { - range, - data, - preselect: false, - score: None, - } - } -} - -#[derive(Debug, Clone)] -pub enum InternalCompletionItemData<'a> { - EntryType { - ty: &'a BibtexEntryTypeDoc, - }, - Field { - field: &'a BibtexFieldDoc, - }, - Argument { - name: &'a str, - image: Option<&'a str>, - }, - BeginCommand, - Citation { - uri: Arc<Url>, - key: String, - text: String, - ty: Structure, - }, - ComponentCommand { - name: &'a SmolStr, - image: Option<&'a str>, - glyph: Option<&'a str>, - file_names: &'a [SmolStr], - }, - ComponentEnvironment { - name: &'a SmolStr, - file_names: &'a [SmolStr], - }, - Class { - name: SmolStr, - }, - Package { - name: SmolStr, - }, - Color { - name: &'a str, - }, - ColorModel { - name: &'a str, - }, - Acronym { - name: String, - }, - GlossaryEntry { - name: String, - }, - File { - name: SmolStr, - }, - Directory { - name: SmolStr, - }, - Label { - name: String, - kind: Structure, - header: Option<String>, - footer: Option<String>, - text: String, - }, - UserCommand { - name: SmolStr, - }, - UserEnvironment { - name: String, - }, - PgfLibrary { - name: &'a str, - }, - TikzLibrary { - name: &'a str, - }, -} - -impl<'a> InternalCompletionItemData<'a> { - pub fn label<'b: 'a>(&'b self) -> &'a str { - match self { - Self::EntryType { ty } => &ty.name, - Self::Field { field } => &field.name, - Self::Argument { name, .. } => name, - Self::BeginCommand => "begin", - Self::Citation { key, .. } => key, - Self::ComponentCommand { name, .. } => name, - Self::ComponentEnvironment { name, .. } => name, - Self::Class { name } => name, - Self::Package { name } => name, - Self::Color { name } => name, - Self::ColorModel { name } => name, - Self::Acronym { name } => name, - Self::GlossaryEntry { name } => name, - Self::File { name } => name, - Self::Directory { name } => name, - Self::Label { name, .. } => name, - Self::UserCommand { name } => name, - Self::UserEnvironment { name } => name, - Self::PgfLibrary { name } => name, - Self::TikzLibrary { name } => name, - } - } -} - -#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub enum CompletionItemData { - Command, - CommandSnippet, - Environment, - Label, - Folder, - File, - PgfLibrary, - TikzLibrary, - Color, - ColorModel, - Package, - Class, - EntryType, - FieldName, - Citation { uri: Url, key: SmolStr }, - Argument, - Acronym, - GlossaryEntry, -} diff --git a/support/texlab/src/features/completion/user_command.rs b/support/texlab/src/features/completion/user_command.rs index 8c4d593bee..99d9883ee9 100644 --- a/support/texlab/src/features/completion/user_command.rs +++ b/support/texlab/src/features/completion/user_command.rs @@ -1,29 +1,27 @@ -use lsp_types::CompletionParams; +use crate::util::cursor::CursorContext; -use crate::features::cursor::CursorContext; +use super::builder::CompletionBuilder; -use super::types::{InternalCompletionItem, InternalCompletionItemData}; - -pub fn complete_user_commands<'a>( - context: &'a CursorContext<CompletionParams>, - items: &mut Vec<InternalCompletionItem<'a>>, +pub fn complete<'db>( + context: &'db CursorContext, + builder: &mut CompletionBuilder<'db>, ) -> Option<()> { let range = context.cursor.command_range(context.offset)?; - let token = context.cursor.as_latex()?; + let token = context.cursor.as_tex()?; - for document in context.request.workspace.documents_by_uri.values() { - if let Some(data) = document.data.as_latex() { + let db = context.db; + for document in context.related() { + if let Some(data) = document.parse(db).as_tex() { + let text = document.contents(db).text(db); for name in data - .extras - .command_names + .analyze(db) + .command_name_ranges(db) .iter() - .filter(|name| name.as_str() != token.text()) - .cloned() + .copied() + .filter(|range| *range != token.text_range()) + .map(|range| &text[std::ops::Range::<usize>::from(range)]) { - items.push(InternalCompletionItem::new( - range, - InternalCompletionItemData::UserCommand { name }, - )); + builder.user_command(range, name); } } } diff --git a/support/texlab/src/features/completion/user_environment.rs b/support/texlab/src/features/completion/user_environment.rs index 91dd5a9ea2..cf6c2a7c78 100644 --- a/support/texlab/src/features/completion/user_environment.rs +++ b/support/texlab/src/features/completion/user_environment.rs @@ -1,28 +1,22 @@ -use lsp_types::CompletionParams; +use crate::util::cursor::CursorContext; -use crate::features::cursor::CursorContext; +use super::builder::CompletionBuilder; -use super::types::{InternalCompletionItem, InternalCompletionItemData}; - -pub fn complete_user_environments<'a>( - context: &'a CursorContext<CompletionParams>, - items: &mut Vec<InternalCompletionItem<'a>>, +pub fn complete<'db>( + context: &'db CursorContext, + builder: &mut CompletionBuilder<'db>, ) -> Option<()> { let (name, range) = context.find_environment_name()?; - for document in context.request.workspace.documents_by_uri.values() { - if let Some(data) = document.data.as_latex() { + for document in context.related() { + if let Some(data) = document.parse(context.db).as_tex() { for name in data - .extras - .environment_names + .analyze(context.db) + .environment_names(context.db) .iter() .filter(|n| n.as_str() != name) - .cloned() { - items.push(InternalCompletionItem::new( - range, - InternalCompletionItemData::UserEnvironment { name }, - )); + builder.user_environment(range, name); } } } diff --git a/support/texlab/src/features/completion/util.rs b/support/texlab/src/features/completion/util.rs deleted file mode 100644 index 05827bbf24..0000000000 --- a/support/texlab/src/features/completion/util.rs +++ /dev/null @@ -1,64 +0,0 @@ -use lsp_types::{CompletionItemKind, CompletionParams, Documentation, MarkupContent, MarkupKind}; -use smol_str::SmolStr; - -use crate::features::FeatureRequest; - -pub fn component_detail(file_names: &[SmolStr]) -> String { - if file_names.is_empty() { - "built-in".to_owned() - } else { - file_names.join(", ") - } -} - -pub fn image_documentation( - request: &FeatureRequest<CompletionParams>, - name: &str, - image: &str, -) -> Option<Documentation> { - if supports_images(request) { - Some(Documentation::MarkupContent(MarkupContent { - kind: MarkupKind::Markdown, - value: format!( - "![{}](data:image/png;base64,{}|width=48,height=48)", - name, image - ), - })) - } else { - None - } -} - -fn supports_images(request: &FeatureRequest<CompletionParams>) -> bool { - request - .workspace - .environment - .client_capabilities - .text_document - .as_ref() - .and_then(|cap| cap.completion.as_ref()) - .and_then(|cap| cap.completion_item.as_ref()) - .and_then(|cap| cap.documentation_format.as_ref()) - .map_or(true, |formats| formats.contains(&MarkupKind::Markdown)) -} - -pub fn adjust_kind( - request: &FeatureRequest<CompletionParams>, - kind: CompletionItemKind, -) -> CompletionItemKind { - if let Some(value_set) = request - .workspace - .environment - .client_capabilities - .text_document - .as_ref() - .and_then(|cap| cap.completion.as_ref()) - .and_then(|cap| cap.completion_item_kind.as_ref()) - .and_then(|cap| cap.value_set.as_ref()) - { - if value_set.contains(&kind) { - return kind; - } - } - CompletionItemKind::TEXT -} diff --git a/support/texlab/src/features/definition.rs b/support/texlab/src/features/definition.rs index 20da72a142..7c9e6d4841 100644 --- a/support/texlab/src/features/definition.rs +++ b/support/texlab/src/features/definition.rs @@ -4,48 +4,44 @@ mod entry; mod label; mod string; -use std::sync::Arc; - -use lsp_types::{GotoDefinitionParams, GotoDefinitionResponse, LocationLink, Url}; +use lsp_types::{GotoDefinitionResponse, LocationLink, Position, Url}; use rowan::TextRange; -use crate::LineIndexExt; - -use self::{ - command::goto_command_definition, document::goto_document_definition, - entry::goto_entry_definition, label::goto_label_definition, string::goto_string_definition, +use crate::{ + db::Document, + util::{cursor::CursorContext, line_index_ext::LineIndexExt}, + Db, }; -use super::{cursor::CursorContext, FeatureRequest}; - pub fn goto_definition( - request: FeatureRequest<GotoDefinitionParams>, + db: &dyn Db, + uri: &Url, + position: Position, ) -> Option<GotoDefinitionResponse> { - let context = CursorContext::new(request); + let context = CursorContext::new(db, uri, position, ())?; log::debug!("[Definition] Cursor: {:?}", context.cursor); - let origin_document = context.request.main_document(); - let links: Vec<_> = goto_command_definition(&context) - .or_else(|| goto_document_definition(&context)) - .or_else(|| goto_entry_definition(&context)) - .or_else(|| goto_label_definition(&context)) - .or_else(|| goto_string_definition(&context))? + let links: Vec<_> = command::goto_definition(&context) + .or_else(|| document::goto_definition(&context)) + .or_else(|| entry::goto_definition(&context)) + .or_else(|| label::goto_definition(&context)) + .or_else(|| string::goto_definition(&context))? .into_iter() .map(|result| { let origin_selection_range = Some( - origin_document - .line_index + context + .document + .contents(db) + .line_index(db) .line_col_lsp_range(result.origin_selection_range), ); - let target_document = &context.request.workspace.documents_by_uri[&result.target_uri]; - let target_uri = result.target_uri.as_ref().clone(); - let target_range = target_document - .line_index - .line_col_lsp_range(result.target_range); - let target_selection_range = target_document - .line_index - .line_col_lsp_range(result.target_selection_range); + let target_line_index = result.target.contents(db).line_index(db); + let target_uri = result.target.location(context.db).uri(context.db).clone(); + let target_range = target_line_index.line_col_lsp_range(result.target_range); + + let target_selection_range = + target_line_index.line_col_lsp_range(result.target_selection_range); LocationLink { origin_selection_range, @@ -62,7 +58,7 @@ pub fn goto_definition( #[derive(Debug, Clone)] struct DefinitionResult { origin_selection_range: TextRange, - target_uri: Arc<Url>, + target: Document, target_range: TextRange, target_selection_range: TextRange, } diff --git a/support/texlab/src/features/definition/command.rs b/support/texlab/src/features/definition/command.rs index 599c792dfd..cf9fe1b511 100644 --- a/support/texlab/src/features/definition/command.rs +++ b/support/texlab/src/features/definition/command.rs @@ -1,26 +1,20 @@ -use std::sync::Arc; - -use lsp_types::GotoDefinitionParams; use rowan::ast::AstNode; -use crate::{features::cursor::CursorContext, syntax::latex}; +use crate::{syntax::latex, util::cursor::CursorContext}; use super::DefinitionResult; -pub(super) fn goto_command_definition( - context: &CursorContext<GotoDefinitionParams>, -) -> Option<Vec<DefinitionResult>> { +pub(super) fn goto_definition(context: &CursorContext) -> Option<Vec<DefinitionResult>> { let name = context .cursor - .as_latex() + .as_tex() .filter(|token| token.kind().is_command_name())?; let origin_selection_range = name.text_range(); - for document in context.request.workspace.documents_by_uri.values() { - if let Some(data) = document.data.as_latex() { - let root = latex::SyntaxNode::new_root(data.green.clone()); - + for document in context.related() { + if let Some(data) = document.parse(context.db).as_tex() { + let root = data.root(context.db); if let Some(result) = root .descendants() .filter_map(latex::CommandDefinition::cast) @@ -32,7 +26,7 @@ pub(super) fn goto_command_definition( .find_map(|def| { Some(DefinitionResult { origin_selection_range, - target_uri: Arc::clone(&document.uri), + target: document, target_range: latex::small_range(&def), target_selection_range: def.name()?.command()?.text_range(), }) diff --git a/support/texlab/src/features/definition/document.rs b/support/texlab/src/features/definition/document.rs index 1c09bbc88d..58237f7521 100644 --- a/support/texlab/src/features/definition/document.rs +++ b/support/texlab/src/features/definition/document.rs @@ -1,40 +1,30 @@ -use std::sync::Arc; - -use lsp_types::GotoDefinitionParams; use rowan::TextRange; -use crate::features::cursor::CursorContext; +use crate::{db::dependency_graph, util::cursor::CursorContext}; use super::DefinitionResult; -pub(super) fn goto_document_definition( - context: &CursorContext<GotoDefinitionParams>, -) -> Option<Vec<DefinitionResult>> { - let data = context.request.main_document().data.as_latex()?; - - for include in data - .extras - .explicit_links +pub(super) fn goto_definition(context: &CursorContext) -> Option<Vec<DefinitionResult>> { + let db = context.db; + context + .workspace + .parents(db, context.document) .iter() - .filter(|link| link.stem_range.contains_inclusive(context.offset)) - { - for target in &include.targets { - if context - .request - .workspace - .documents_by_uri - .values() - .any(|document| document.uri.as_ref() == target.as_ref()) - { - return Some(vec![DefinitionResult { - origin_selection_range: include.stem_range, - target_uri: Arc::clone(target), + .copied() + .chain(std::iter::once(context.document)) + .flat_map(|parent| dependency_graph(db, parent).edges) + .filter(|edge| edge.source == context.document) + .find_map(|edge| { + let range = edge.origin?.link.range(db); + if range.contains_inclusive(context.offset) { + Some(vec![DefinitionResult { + origin_selection_range: range, + target: edge.target, target_range: TextRange::default(), target_selection_range: TextRange::default(), - }]); + }]) + } else { + None } - } - } - - None + }) } diff --git a/support/texlab/src/features/definition/entry.rs b/support/texlab/src/features/definition/entry.rs index 1dcd983af1..a945b18c41 100644 --- a/support/texlab/src/features/definition/entry.rs +++ b/support/texlab/src/features/definition/entry.rs @@ -1,24 +1,21 @@ -use std::sync::Arc; - -use lsp_types::GotoDefinitionParams; use rowan::ast::AstNode; use crate::{ - features::cursor::CursorContext, syntax::{ bibtex::{self, HasName}, latex, }, + util::cursor::CursorContext, }; use super::DefinitionResult; -pub(super) fn goto_entry_definition( - context: &CursorContext<GotoDefinitionParams>, -) -> Option<Vec<DefinitionResult>> { +pub(super) fn goto_definition(context: &CursorContext) -> Option<Vec<DefinitionResult>> { + let db = context.db; + let word = context .cursor - .as_latex() + .as_tex() .filter(|token| token.kind() == latex::WORD)?; let key = latex::Key::cast(word.parent()?)?; @@ -27,16 +24,13 @@ pub(super) fn goto_entry_definition( let origin_selection_range = latex::small_range(&key); - for document in context.request.workspace.documents_by_uri.values() { - if let Some(data) = document.data.as_bibtex() { - for entry in bibtex::SyntaxNode::new_root(data.green.clone()) - .children() - .filter_map(bibtex::Entry::cast) - { + for document in context.related() { + if let Some(data) = document.parse(db).as_bib() { + for entry in data.root(db).children().filter_map(bibtex::Entry::cast) { if let Some(key) = entry.name_token().filter(|k| k.text() == word.text()) { return Some(vec![DefinitionResult { origin_selection_range, - target_uri: Arc::clone(&document.uri), + target: document, target_selection_range: key.text_range(), target_range: entry.syntax().text_range(), }]); diff --git a/support/texlab/src/features/definition/label.rs b/support/texlab/src/features/definition/label.rs index 867e8a1076..a1cc4ed15b 100644 --- a/support/texlab/src/features/definition/label.rs +++ b/support/texlab/src/features/definition/label.rs @@ -1,31 +1,32 @@ -use std::sync::Arc; - -use lsp_types::GotoDefinitionParams; - -use crate::{features::cursor::CursorContext, find_label_definition, render_label, syntax::latex}; +use crate::{ + db::analysis::label, + util::{self, cursor::CursorContext}, +}; use super::DefinitionResult; -pub(super) fn goto_label_definition( - context: &CursorContext<GotoDefinitionParams>, -) -> Option<Vec<DefinitionResult>> { +pub(super) fn goto_definition(context: &CursorContext) -> Option<Vec<DefinitionResult>> { + let db = context.db; let (name_text, origin_selection_range) = context .find_label_name_key() .or_else(|| context.find_label_name_command())?; - for document in context.request.workspace.documents_by_uri.values() { - if let Some(data) = document.data.as_latex() { - let root = latex::SyntaxNode::new_root(data.green.clone()); - if let Some(definition) = find_label_definition(&root, &name_text) { - let target_selection_range = latex::small_range(&definition.name()?.key()?); - let target_range = - render_label(&context.request.workspace, &name_text, Some(definition)) - .map(|label| label.range) - .unwrap_or(target_selection_range); + for document in context.related() { + if let Some(data) = document.parse(db).as_tex() { + if let Some(label) = data + .analyze(db) + .labels(db) + .iter() + .filter(|label| matches!(label.origin(db), label::Origin::Definition(_))) + .find(|label| label.name(db).text(db) == name_text.as_str()) + { + let target_selection_range = label.range(db); + let target_range = util::label::render(db, document, *label) + .map_or(target_selection_range, |label| label.range); return Some(vec![DefinitionResult { origin_selection_range, - target_uri: Arc::clone(&document.uri), + target: document, target_range, target_selection_range, }]); diff --git a/support/texlab/src/features/definition/string.rs b/support/texlab/src/features/definition/string.rs index c774e24e1d..44ea1e9094 100644 --- a/support/texlab/src/features/definition/string.rs +++ b/support/texlab/src/features/definition/string.rs @@ -1,43 +1,34 @@ -use std::sync::Arc; - -use lsp_types::GotoDefinitionParams; use rowan::ast::AstNode; use crate::{ - features::cursor::CursorContext, syntax::bibtex::{self, HasName}, + util::cursor::CursorContext, }; use super::DefinitionResult; -pub(super) fn goto_string_definition( - context: &CursorContext<GotoDefinitionParams>, -) -> Option<Vec<DefinitionResult>> { - let main_document = context.request.main_document(); - - let data = main_document.data.as_bibtex()?; +pub(super) fn goto_definition(context: &CursorContext) -> Option<Vec<DefinitionResult>> { + let db = context.db; + let data = context.document.parse(db).as_bib()?; let key = context .cursor - .as_bibtex() + .as_bib() .filter(|token| token.kind() == bibtex::NAME)?; bibtex::Value::cast(key.parent()?)?; let origin_selection_range = key.text_range(); - for string in bibtex::SyntaxNode::new_root(data.green.clone()) + data.root(db) .children() .filter_map(bibtex::StringDef::cast) - { - if let Some(string_name) = string.name_token().filter(|k| k.text() == key.text()) { - return Some(vec![DefinitionResult { + .find_map(|string| { + let string_name = string.name_token().filter(|k| k.text() == key.text())?; + Some(vec![DefinitionResult { origin_selection_range, - target_uri: Arc::clone(&main_document.uri), + target: context.document, target_selection_range: string_name.text_range(), target_range: string.syntax().text_range(), - }]); - } - } - - None + }]) + }) } diff --git a/support/texlab/src/features/execute_command.rs b/support/texlab/src/features/execute_command.rs deleted file mode 100644 index b1b89d4f50..0000000000 --- a/support/texlab/src/features/execute_command.rs +++ /dev/null @@ -1,103 +0,0 @@ -use std::{path::PathBuf, process::Stdio, sync::Arc}; - -use anyhow::Result; -use lsp_types::{TextDocumentIdentifier, Url}; - -use crate::Workspace; - -pub fn execute_command( - workspace: &Workspace, - name: &str, - args: Vec<serde_json::Value>, -) -> Result<()> { - match name { - "texlab.cleanAuxiliary" => { - let params = args - .into_iter() - .next() - .ok_or_else(|| anyhow::anyhow!("texlab.cleanAuxiliary requires one argument"))?; - - clean_output_files(workspace, CleanOptions::Auxiliary, params)?; - } - "texlab.cleanArtifacts" => { - let params = args - .into_iter() - .next() - .ok_or_else(|| anyhow::anyhow!("texlab.cleanArtifacts requires one argument"))?; - - clean_output_files(workspace, CleanOptions::Artifacts, params)?; - } - _ => anyhow::bail!("Unknown command: {}", name), - } - - Ok(()) -} - -#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash)] -enum CleanOptions { - Auxiliary, - Artifacts, -} - -fn clean_output_files( - workspace: &Workspace, - options: CleanOptions, - params: serde_json::Value, -) -> Result<()> { - let params: TextDocumentIdentifier = serde_json::from_value(params)?; - - let uri = workspace - .find_parent(¶ms.uri) - .map(|document| document.uri) - .unwrap_or_else(|| Arc::new(params.uri)); - - if let Some(cx) = BuildContext::find(workspace, &uri) { - let flag = match options { - CleanOptions::Auxiliary => "-c", - CleanOptions::Artifacts => "-C", - }; - - std::process::Command::new("latexmk") - .arg(format!("-outdir={}", cx.output_dir.to_string_lossy())) - .arg(flag) - .arg(cx.input_file) - .stdin(Stdio::null()) - .stdout(Stdio::null()) - .stderr(Stdio::null()) - .status()?; - } - - Ok(()) -} - -struct BuildContext { - input_file: PathBuf, - output_dir: PathBuf, -} - -impl BuildContext { - pub fn find(workspace: &Workspace, uri: &Url) -> Option<Self> { - if uri.scheme() != "file" { - return None; - } - - let input_file = uri.to_file_path().ok()?; - let options = &workspace.environment.options; - let current_dir = &workspace.environment.current_directory; - let output_dir = match ( - options.root_directory.as_ref(), - options.aux_directory.as_ref(), - ) { - (_, Some(aux_dir)) => current_dir.join(aux_dir), - (Some(root_dir), None) => current_dir.join(root_dir), - (None, None) => input_file.parent()?.to_path_buf(), - }; - - log::info!("Output = {:#?}", output_dir); - - Some(Self { - input_file, - output_dir, - }) - } -} diff --git a/support/texlab/src/features/folding.rs b/support/texlab/src/features/folding.rs index 71fb0bee6f..ea26121f3f 100644 --- a/support/texlab/src/features/folding.rs +++ b/support/texlab/src/features/folding.rs @@ -1,49 +1,52 @@ -use lsp_types::{FoldingRange, FoldingRangeKind, FoldingRangeParams, Range}; +use lsp_types::{FoldingRange, FoldingRangeKind, Range, Url}; use rowan::ast::AstNode; use crate::{ + db::{parse::DocumentData, Workspace}, syntax::{bibtex, latex}, - DocumentData, LineIndexExt, + util::line_index_ext::LineIndexExt, + Db, }; -use super::FeatureRequest; - -pub fn find_foldings(request: FeatureRequest<FoldingRangeParams>) -> Vec<FoldingRange> { - let mut foldings = Vec::new(); - let main_document = request.main_document(); - match &main_document.data { - DocumentData::Latex(data) => { - for node in latex::SyntaxNode::new_root(data.green.clone()).descendants() { +pub fn find_all(db: &dyn Db, uri: &Url) -> Option<Vec<FoldingRange>> { + let document = Workspace::get(db).lookup_uri(db, uri)?; + let line_index = document.contents(db).line_index(db); + let foldings = match document.parse(db) { + DocumentData::Tex(data) => { + let mut results = Vec::new(); + let root = data.root(db); + for node in root.descendants() { if let Some(folding) = latex::Environment::cast(node.clone()) .map(|node| latex::small_range(&node)) .or_else(|| { latex::Section::cast(node.clone()).map(|node| latex::small_range(&node)) }) .or_else(|| latex::EnumItem::cast(node).map(|node| latex::small_range(&node))) - .map(|node| main_document.line_index.line_col_lsp_range(node)) + .map(|node| line_index.line_col_lsp_range(node)) .map(create_range) { - foldings.push(folding); + results.push(folding); } } + + results } - DocumentData::Bibtex(data) => { - for node in bibtex::SyntaxNode::new_root(data.green.clone()).descendants() { - if matches!( - node.kind(), - bibtex::PREAMBLE | bibtex::STRING | bibtex::ENTRY - ) { - foldings.push(create_range( - main_document - .line_index - .line_col_lsp_range(node.text_range()), - )); - } - } + DocumentData::Bib(data) => { + let root = data.root(db); + root.descendants() + .filter(|node| { + matches!( + node.kind(), + bibtex::PREAMBLE | bibtex::STRING | bibtex::ENTRY + ) + }) + .map(|node| create_range(line_index.line_col_lsp_range(node.text_range()))) + .collect() } - DocumentData::BuildLog(_) => {} - } - foldings + DocumentData::Log(_) => return None, + }; + + Some(foldings) } fn create_range(range: Range) -> FoldingRange { diff --git a/support/texlab/src/features/formatting.rs b/support/texlab/src/features/formatting.rs index 1107e5fd38..66375bd576 100644 --- a/support/texlab/src/features/formatting.rs +++ b/support/texlab/src/features/formatting.rs @@ -1,26 +1,31 @@ mod bibtex_internal; mod latexindent; -use lsp_types::{DocumentFormattingParams, TextEdit}; +use lsp_types::{FormattingOptions, TextEdit, Url}; -use crate::{BibtexFormatter, LatexFormatter}; +use crate::{ + db::{Language, Workspace}, + BibtexFormatter, Db, LatexFormatter, +}; use self::{bibtex_internal::format_bibtex_internal, latexindent::format_with_latexindent}; -use super::FeatureRequest; - pub fn format_source_code( - request: FeatureRequest<DocumentFormattingParams>, + db: &dyn Db, + uri: &Url, + options: &FormattingOptions, ) -> Option<Vec<TextEdit>> { - let mut edits = None; - if request.workspace.environment.options.bibtex_formatter == BibtexFormatter::Texlab { - edits = edits.or_else(|| format_bibtex_internal(&request)); - } - - if request.workspace.environment.options.latex_formatter == LatexFormatter::Texlab { - edits = edits.or_else(|| Some(vec![])); + let workspace = Workspace::get(db); + let document = workspace.lookup_uri(db, uri)?; + match document.language(db) { + Language::Tex => match workspace.options(db).latex_formatter { + LatexFormatter::Texlab => None, + LatexFormatter::Latexindent => format_with_latexindent(db, document), + }, + Language::Bib => match workspace.options(db).bibtex_formatter { + BibtexFormatter::Texlab => format_bibtex_internal(db, document, options), + BibtexFormatter::Latexindent => format_with_latexindent(db, document), + }, + Language::Log => None, } - - edits = edits.or_else(|| format_with_latexindent(&request)); - edits } diff --git a/support/texlab/src/features/formatting/bibtex_internal.rs b/support/texlab/src/features/formatting/bibtex_internal.rs index 2dcc507be9..8447778d90 100644 --- a/support/texlab/src/features/formatting/bibtex_internal.rs +++ b/support/texlab/src/features/formatting/bibtex_internal.rs @@ -1,63 +1,57 @@ -use lsp_types::{DocumentFormattingParams, TextEdit}; +use lsp_types::{FormattingOptions, TextEdit}; use rowan::{ast::AstNode, NodeOrToken}; use crate::{ - features::FeatureRequest, + db::{Document, Workspace}, syntax::bibtex::{self, HasName, HasType, HasValue}, - LineIndex, LineIndexExt, + util::{line_index::LineIndex, line_index_ext::LineIndexExt}, + Db, }; pub fn format_bibtex_internal( - request: &FeatureRequest<DocumentFormattingParams>, + db: &dyn Db, + document: Document, + options: &FormattingOptions, ) -> Option<Vec<TextEdit>> { let mut indent = String::new(); - if request.params.options.insert_spaces { - for _ in 0..request.params.options.tab_size { + + if options.insert_spaces { + for _ in 0..options.tab_size { indent.push(' '); } } else { indent.push('\t'); } - let line_length = request - .workspace - .environment - .options + let line_length = Workspace::get(db) + .options(db) .formatter_line_length - .map(|value| { + .map_or(80, |value| { if value <= 0 { usize::MAX } else { value as usize } - }) - .unwrap_or(80); + }); - let document = request.main_document(); - let data = document.data.as_bibtex()?; + let line_index = document.contents(db).line_index(db); + let data = document.parse(db).as_bib()?; let mut edits = Vec::new(); - for node in bibtex::SyntaxNode::new_root(data.green.clone()) - .children() - .filter(|node| { - matches!( - node.kind(), - bibtex::PREAMBLE | bibtex::STRING | bibtex::ENTRY - ) - }) - { + for node in data.root(db).children().filter(|node| { + matches!( + node.kind(), + bibtex::PREAMBLE | bibtex::STRING | bibtex::ENTRY + ) + }) { let range = node.text_range(); - let mut formatter = Formatter::new( - indent.clone(), - request.params.options.tab_size, - line_length, - &document.line_index, - ); + let mut formatter = + Formatter::new(indent.clone(), options.tab_size, line_length, line_index); formatter.visit_node(node); edits.push(TextEdit { - range: document.line_index.line_col_lsp_range(range), + range: line_index.line_col_lsp_range(range), new_text: formatter.output, }); } diff --git a/support/texlab/src/features/formatting/latexindent.rs b/support/texlab/src/features/formatting/latexindent.rs index 4898aa4415..3dab10c923 100644 --- a/support/texlab/src/features/formatting/latexindent.rs +++ b/support/texlab/src/features/formatting/latexindent.rs @@ -1,94 +1,78 @@ use std::{ - fs, + path::Path, process::{Command, Stdio}, }; -use lsp_types::{DocumentFormattingParams, TextEdit}; +use lsp_types::TextEdit; use rowan::{TextLen, TextRange}; use tempfile::tempdir; -use crate::{features::FeatureRequest, DocumentLanguage, LineIndexExt}; - -pub fn format_with_latexindent( - request: &FeatureRequest<DocumentFormattingParams>, -) -> Option<Vec<TextEdit>> { - let directory = tempdir().ok()?; - let document = request.main_document(); +use crate::{ + db::{Document, Language, Workspace}, + util::line_index_ext::LineIndexExt, + Db, LatexindentOptions, +}; - let options = &request.workspace.environment.options; - let current_dir = options - .root_directory - .as_ref() - .cloned() - .or_else(|| { - if document.uri.scheme() == "file" { - document - .uri - .to_file_path() - .unwrap() - .parent() - .map(ToOwned::to_owned) - } else { - None - } - }) - .unwrap_or_else(|| ".".into()); +pub fn format_with_latexindent(db: &dyn Db, document: Document) -> Option<Vec<TextEdit>> { + let workspace = Workspace::get(db); + let options = workspace.options(db); + let target_dir = tempdir().ok()?; + let source_dir = workspace + .working_dir(db, document.directory(db)) + .path(db) + .as_deref()?; - let local = match &options.latexindent.local { - Some(local) => format!("--local={}", local), - None => "-l".to_string(), - }; + let target_file = target_dir + .path() + .join(if document.language(db) == Language::Bib { + "file.bib" + } else { + "file.tex" + }); + std::fs::write(&target_file, document.contents(db).text(db)).ok()?; - let modify_line_breaks = options.latexindent.modify_line_breaks; + let args = build_arguments(&options.latexindent, &target_file); - let path = directory.path(); - let _ = fs::copy( - current_dir.join("localSettings.yaml"), - path.join("localSettings.yaml"), - ); - let _ = fs::copy( - current_dir.join(".localSettings.yaml"), - path.join(".localSettings.yaml"), - ); - let _ = fs::copy( - current_dir.join("latexindent.yaml"), - path.join("latexindent.yaml"), + log::debug!( + "Running latexindent in folder \"{}\" with args: {:?}", + source_dir.display(), + args, ); - let name = if document.data.language() == DocumentLanguage::Bibtex { - "file.bib" - } else { - "file.tex" - }; - - fs::write(directory.path().join(name), document.text.as_str()).ok()?; - - let mut args = Vec::new(); - if modify_line_breaks { - args.push("--modifylinebreaks"); - } - args.push(&local); - args.push(name); - let output = Command::new("latexindent") .args(&args) - .current_dir(current_dir) .stdin(Stdio::null()) .stdout(Stdio::piped()) .stderr(Stdio::null()) - .current_dir(directory.path()) + .current_dir(source_dir) .output() .ok()?; + let old_text = document.contents(db).text(db); let new_text = String::from_utf8_lossy(&output.stdout).into_owned(); if new_text.is_empty() { None } else { + let line_index = document.contents(db).line_index(db); Some(vec![TextEdit { - range: document - .line_index - .line_col_lsp_range(TextRange::new(0.into(), document.text.text_len())), + range: line_index.line_col_lsp_range(TextRange::new(0.into(), old_text.text_len())), new_text, }]) } } + +fn build_arguments(options: &LatexindentOptions, target_file: &Path) -> Vec<String> { + let mut args = Vec::new(); + + args.push(match &options.local { + Some(yaml_file) => format!("--local={yaml_file}"), + None => "--local".to_string(), + }); + + if options.modify_line_breaks { + args.push("--modifylinebreaks".to_string()); + } + + args.push(target_file.display().to_string()); + args +} diff --git a/support/texlab/src/features/forward_search.rs b/support/texlab/src/features/forward_search.rs index 54629d0dc0..47be702659 100644 --- a/support/texlab/src/features/forward_search.rs +++ b/support/texlab/src/features/forward_search.rs @@ -1,94 +1,120 @@ use std::{ io, - path::Path, - process::{Command, Stdio}, + path::{Path, PathBuf}, + process::Stdio, }; use log::error; -use lsp_types::TextDocumentPositionParams; -use serde::{Deserialize, Serialize}; -use serde_repr::{Deserialize_repr, Serialize_repr}; - -use super::FeatureRequest; - -#[derive(Debug, PartialEq, Eq, Clone, Copy, Serialize_repr, Deserialize_repr)] -#[repr(i32)] -pub enum ForwardSearchStatus { - SUCCESS = 0, - ERROR = 1, - FAILURE = 2, - UNCONFIGURED = 3, +use lsp_types::{Position, Url}; +use thiserror::Error; + +use crate::{db::Workspace, util::line_index_ext::LineIndexExt, Db}; + +#[derive(Debug, Error)] +pub enum Error { + #[error("TeX document '{0}' not found")] + TexNotFound(Url), + + #[error("PDF document '{0}' not found")] + PdfNotFound(PathBuf), + + #[error("TeX document '{0}' is not a local file")] + NoLocalFile(Url), + + #[error("PDF viewer is not configured")] + Unconfigured, + + #[error("Failed to spawn process: {0}")] + Spawn(io::Error), } -#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)] -pub struct ForwardSearchResult { - pub status: ForwardSearchStatus, +pub struct Command { + executable: String, + args: Vec<String>, } -pub fn execute_forward_search( - request: FeatureRequest<TextDocumentPositionParams>, -) -> Option<ForwardSearchResult> { - let options = &request.workspace.environment.options.forward_search; +impl Command { + pub fn configure(db: &dyn Db, uri: &Url, position: Option<Position>) -> Result<Self, Error> { + let workspace = Workspace::get(db); + let child = workspace + .lookup_uri(db, uri) + .ok_or_else(|| Error::TexNotFound(uri.clone()))?; + + let parent = workspace + .parents(db, child) + .iter() + .copied() + .next() + .unwrap_or(child); + + let output_dir = workspace + .output_dir(db, workspace.working_dir(db, parent.directory(db))) + .path(db) + .as_deref() + .ok_or_else(|| Error::NoLocalFile(uri.clone()))?; + + let tex_path = child + .location(db) + .path(db) + .as_deref() + .ok_or_else(|| Error::NoLocalFile(uri.clone()))?; + + let pdf_name = format!("{}.pdf", parent.location(db).stem(db).unwrap()); + let pdf_path = output_dir.join(pdf_name); + if !pdf_path.exists() { + return Err(Error::PdfNotFound(pdf_path)); + } - if options.executable.is_none() || options.args.is_none() { - return Some(ForwardSearchResult { - status: ForwardSearchStatus::UNCONFIGURED, + let position = position.unwrap_or_else(|| { + child + .contents(db) + .line_index(db) + .line_col_lsp(child.cursor(db)) }); + + let options = &workspace.options(db).forward_search; + + let executable = options + .executable + .as_deref() + .ok_or(Error::Unconfigured)? + .to_string(); + + let args: Vec<_> = options + .args + .as_deref() + .ok_or(Error::Unconfigured)? + .iter() + .flat_map(|arg| replace_placeholder(tex_path, &pdf_path, position.line, arg)) + .collect(); + + Ok(Self { executable, args }) } +} - let root_document = request - .workspace - .documents_by_uri - .values() - .find(|document| { - if let Some(data) = document.data.as_latex() { - data.extras.has_document_environment - && !data - .extras - .explicit_links - .iter() - .filter_map(|link| link.as_component_name()) - .any(|name| name == "subfiles.cls") - } else { - false - } - }) - .filter(|document| document.uri.scheme() == "file")?; - - let data = root_document.data.as_latex()?; - let pdf_path = data - .extras - .implicit_links - .pdf - .iter() - .filter_map(|uri| uri.to_file_path().ok()) - .find(|path| path.exists())?; - - let tex_path = request.main_document().uri.to_file_path().ok()?; - - let args: Vec<String> = options - .args - .as_ref() - .unwrap() - .iter() - .flat_map(|arg| { - replace_placeholder(&tex_path, &pdf_path, request.params.position.line, arg) - }) - .collect(); - - let status = match run_process(options.executable.as_ref().unwrap(), args) { - Ok(()) => ForwardSearchStatus::SUCCESS, - Err(why) => { - error!("Unable to execute forward search: {}", why); - ForwardSearchStatus::FAILURE - } - }; - Some(ForwardSearchResult { status }) +impl Command { + pub fn run(self) -> Result<(), Error> { + log::debug!( + "Executing forward search: {} {:?}", + self.executable, + self.args + ); + + std::process::Command::new(self.executable) + .args(self.args) + .stdin(Stdio::null()) + .stdout(Stdio::null()) + .stderr(Stdio::null()) + .status() + .map_err(Error::Spawn)?; + + Ok(()) + } } /// Iterate overs chunks of a string. Either returns a slice of the /// original string, or the placeholder replacement. -pub struct PlaceHolderIterator<'a> { +struct PlaceHolderIterator<'a> { remainder: &'a str, tex_file: &'a str, pdf_file: &'a str, @@ -168,13 +194,3 @@ fn replace_placeholder( }; Some(result) } - -fn run_process(executable: &str, args: Vec<String>) -> io::Result<()> { - Command::new(executable) - .args(args) - .stdin(Stdio::null()) - .stdout(Stdio::null()) - .stderr(Stdio::null()) - .status()?; - Ok(()) -} diff --git a/support/texlab/src/features/highlight.rs b/support/texlab/src/features/highlight.rs index b2c5794461..52746a040f 100644 --- a/support/texlab/src/features/highlight.rs +++ b/support/texlab/src/features/highlight.rs @@ -1,14 +1,10 @@ mod label; -use lsp_types::{DocumentHighlight, DocumentHighlightParams}; +use lsp_types::{DocumentHighlight, Position, Url}; -use self::label::find_label_highlights; +use crate::{util::cursor::CursorContext, Db}; -use super::{cursor::CursorContext, FeatureRequest}; - -pub fn find_document_highlights( - request: FeatureRequest<DocumentHighlightParams>, -) -> Option<Vec<DocumentHighlight>> { - let context = CursorContext::new(request); - find_label_highlights(&context) +pub fn find_all(db: &dyn Db, uri: &Url, position: Position) -> Option<Vec<DocumentHighlight>> { + let context = CursorContext::new(db, uri, position, ())?; + label::find_highlights(&context) } diff --git a/support/texlab/src/features/highlight/label.rs b/support/texlab/src/features/highlight/label.rs index cb51abdd68..2ae66d5c47 100644 --- a/support/texlab/src/features/highlight/label.rs +++ b/support/texlab/src/features/highlight/label.rs @@ -1,78 +1,31 @@ -use lsp_types::{DocumentHighlight, DocumentHighlightKind, DocumentHighlightParams}; -use rowan::ast::AstNode; +use lsp_types::{DocumentHighlight, DocumentHighlightKind}; -use crate::{features::cursor::CursorContext, syntax::latex, LineIndexExt}; +use crate::{ + db::analysis::label, + util::{cursor::CursorContext, line_index_ext::LineIndexExt}, +}; -pub fn find_label_highlights( - context: &CursorContext<DocumentHighlightParams>, -) -> Option<Vec<DocumentHighlight>> { +pub fn find_highlights(context: &CursorContext) -> Option<Vec<DocumentHighlight>> { + let db = context.db; let (name_text, _) = context.find_label_name_key()?; - - let main_document = context.request.main_document(); - let data = main_document.data.as_latex()?; + let data = context.document.parse(db).as_tex()?; let mut highlights = Vec::new(); - for node in latex::SyntaxNode::new_root(data.green.clone()).descendants() { - if let Some(label_name) = latex::LabelDefinition::cast(node.clone()) - .and_then(|label| label.name()) - .and_then(|label_name| label_name.key()) - .filter(|label_name| label_name.to_string() == name_text) - { - let range = main_document - .line_index - .line_col_lsp_range(latex::small_range(&label_name)); - - highlights.push(DocumentHighlight { - range, - kind: Some(DocumentHighlightKind::WRITE), - }); - } else if let Some(label) = latex::LabelReference::cast(node.clone()) { - for label_name in label - .name_list() - .into_iter() - .flat_map(|name| name.keys()) - .filter(|label_name| label_name.to_string() == name_text) - { - let range = main_document - .line_index - .line_col_lsp_range(latex::small_range(&label_name)); - - highlights.push(DocumentHighlight { - range, - kind: Some(DocumentHighlightKind::READ), - }); - } - } else if let Some(label) = latex::LabelReferenceRange::cast(node.clone()) { - if let Some(label_name) = label - .from() - .and_then(|label_name| label_name.key()) - .filter(|label_name| label_name.to_string() == name_text) - { - let range = main_document - .line_index - .line_col_lsp_range(latex::small_range(&label_name)); - - highlights.push(DocumentHighlight { - range, - kind: Some(DocumentHighlightKind::READ), - }); - } - - if let Some(label_name) = label - .to() - .and_then(|label_name| label_name.key()) - .filter(|label_name| label_name.to_string() == name_text) - { - let range = main_document - .line_index - .line_col_lsp_range(latex::small_range(&label_name)); - - highlights.push(DocumentHighlight { - range, - kind: Some(DocumentHighlightKind::READ), - }); - } - } + let line_index = context.document.contents(db).line_index(db); + for label in data + .analyze(db) + .labels(db) + .iter() + .filter(|label| label.name(db).text(db) == &name_text) + { + let range = line_index.line_col_lsp_range(label.range(db)); + let kind = Some(match label.origin(db) { + label::Origin::Definition(_) => DocumentHighlightKind::WRITE, + label::Origin::Reference(_) => DocumentHighlightKind::READ, + label::Origin::ReferenceRange(_) => DocumentHighlightKind::READ, + }); + + highlights.push(DocumentHighlight { range, kind }); } Some(highlights) diff --git a/support/texlab/src/features/hover.rs b/support/texlab/src/features/hover.rs index 8663f6256d..27d07f74cd 100644 --- a/support/texlab/src/features/hover.rs +++ b/support/texlab/src/features/hover.rs @@ -5,43 +5,32 @@ mod field; mod label; mod string_ref; -use lsp_types::{Hover, HoverContents, HoverParams, MarkupContent, MarkupKind}; +use lsp_types::{Hover, HoverContents, MarkupContent, MarkupKind, Position, Url}; use rowan::TextRange; use crate::{ - features::{cursor::CursorContext, hover::citation::find_citation_hover}, - LineIndexExt, + util::{cursor::CursorContext, line_index_ext::LineIndexExt}, + Db, }; -use self::{ - component::find_component_hover, entry_type::find_entry_type_hover, field::find_field_hover, - label::find_label_hover, string_ref::find_string_reference_hover, -}; - -use super::FeatureRequest; - -pub fn find_hover(request: FeatureRequest<HoverParams>) -> Option<Hover> { - let context = CursorContext::new(request); +pub fn find(db: &dyn Db, uri: &Url, position: Position) -> Option<Hover> { + let context = CursorContext::new(db, uri, position, ())?; log::debug!("[Hover] Cursor: {:?}", context.cursor); - let result = find_label_hover(&context) - .or_else(|| find_citation_hover(&context)) - .or_else(|| find_component_hover(&context)) - .or_else(|| find_string_reference_hover(&context)) - .or_else(|| find_field_hover(&context)) - .or_else(|| find_entry_type_hover(&context))?; + let result = label::find_hover(&context) + .or_else(|| citation::find_hover(&context)) + .or_else(|| component::find_hover(&context)) + .or_else(|| string_ref::find_hover(&context)) + .or_else(|| field::find_hover(&context)) + .or_else(|| entry_type::find_hover(&context))?; + + let line_index = context.document.contents(db).line_index(db); Some(Hover { contents: HoverContents::Markup(MarkupContent { kind: result.value_kind, value: result.value, }), - range: Some( - context - .request - .main_document() - .line_index - .line_col_lsp_range(result.range), - ), + range: Some(line_index.line_col_lsp_range(result.range)), }) } diff --git a/support/texlab/src/features/hover/citation.rs b/support/texlab/src/features/hover/citation.rs index 5e86019eee..e0e17176d5 100644 --- a/support/texlab/src/features/hover/citation.rs +++ b/support/texlab/src/features/hover/citation.rs @@ -1,28 +1,23 @@ -use lsp_types::{HoverParams, MarkupKind}; +use lsp_types::MarkupKind; use rowan::ast::AstNode; -use crate::{citation, features::cursor::CursorContext, syntax::bibtex}; +use crate::{citation, syntax::bibtex, util::cursor::CursorContext}; use super::HoverResult; -pub(super) fn find_citation_hover(context: &CursorContext<HoverParams>) -> Option<HoverResult> { +pub(super) fn find_hover(context: &CursorContext) -> Option<HoverResult> { let (key, range) = context .find_citation_key_word() .or_else(|| context.find_citation_key_command()) .or_else(|| context.find_entry_key())?; - let value = context - .request - .workspace - .documents_by_uri - .values() - .find_map(|document| { - let data = document.data.as_bibtex()?; - let root = bibtex::SyntaxNode::new_root(data.green.clone()); - let root = bibtex::Root::cast(root)?; - let entry = root.find_entry(&key)?; - citation::render(&entry) - })?; + let value = context.related().find_map(|document| { + let data = document.parse(context.db).as_bib()?; + let root = data.root(context.db); + let root = bibtex::Root::cast(root)?; + let entry = root.find_entry(&key)?; + citation::render(&entry) + })?; Some(HoverResult { range, diff --git a/support/texlab/src/features/hover/component.rs b/support/texlab/src/features/hover/component.rs index 737a99d3ea..61a428a9ce 100644 --- a/support/texlab/src/features/hover/component.rs +++ b/support/texlab/src/features/hover/component.rs @@ -1,25 +1,28 @@ -use lsp_types::{HoverParams, MarkupKind}; +use lsp_types::MarkupKind; -use crate::{component_db::COMPONENT_DATABASE, features::cursor::CursorContext, syntax::latex}; +use crate::{ + db::analysis::TexLinkKind, + util::{components::COMPONENT_DATABASE, cursor::CursorContext}, +}; use super::HoverResult; -pub(super) fn find_component_hover(context: &CursorContext<HoverParams>) -> Option<HoverResult> { - let data = context.request.main_document().data.as_latex()?; - for link in &data.extras.explicit_links { - if matches!( - link.kind, - latex::ExplicitLinkKind::Package | latex::ExplicitLinkKind::Class - ) && link.stem_range.contains_inclusive(context.offset) - { - let value = COMPONENT_DATABASE.documentation(&link.stem)?.value; - return Some(HoverResult { +pub(super) fn find_hover(context: &CursorContext) -> Option<HoverResult> { + let db = context.db; + let links = context.document.parse(db).as_tex()?.analyze(db).links(db); + links + .iter() + .filter(|link| matches!(link.kind(db), TexLinkKind::Sty | TexLinkKind::Cls)) + .filter(|link| link.range(db).contains_inclusive(context.offset)) + .find_map(|link| { + let value = COMPONENT_DATABASE + .documentation(link.path(db).text(db))? + .value; + + Some(HoverResult { value, value_kind: MarkupKind::PlainText, - range: link.stem_range, - }); - } - } - - None + range: link.range(db), + }) + }) } diff --git a/support/texlab/src/features/hover/entry_type.rs b/support/texlab/src/features/hover/entry_type.rs index 41a561395c..0f4ccbdb72 100644 --- a/support/texlab/src/features/hover/entry_type.rs +++ b/support/texlab/src/features/hover/entry_type.rs @@ -1,13 +1,16 @@ -use lsp_types::{HoverParams, MarkupKind}; +use lsp_types::MarkupKind; -use crate::{features::cursor::CursorContext, syntax::bibtex, LANGUAGE_DATA}; +use crate::{ + syntax::bibtex, + util::{cursor::CursorContext, lang_data::LANGUAGE_DATA}, +}; use super::HoverResult; -pub(super) fn find_entry_type_hover(context: &CursorContext<HoverParams>) -> Option<HoverResult> { +pub(super) fn find_hover(context: &CursorContext) -> Option<HoverResult> { let name = context .cursor - .as_bibtex() + .as_bib() .filter(|token| token.kind() == bibtex::TYPE)?; let docs = LANGUAGE_DATA.entry_type_documentation(&name.text()[1..])?; diff --git a/support/texlab/src/features/hover/field.rs b/support/texlab/src/features/hover/field.rs index 6102bd6b68..48193997d6 100644 --- a/support/texlab/src/features/hover/field.rs +++ b/support/texlab/src/features/hover/field.rs @@ -1,14 +1,17 @@ -use lsp_types::{HoverParams, MarkupKind}; +use lsp_types::MarkupKind; use rowan::ast::AstNode; -use crate::{features::cursor::CursorContext, syntax::bibtex, LANGUAGE_DATA}; +use crate::{ + syntax::bibtex, + util::{cursor::CursorContext, lang_data::LANGUAGE_DATA}, +}; use super::HoverResult; -pub(super) fn find_field_hover(context: &CursorContext<HoverParams>) -> Option<HoverResult> { +pub(super) fn find_hover(context: &CursorContext) -> Option<HoverResult> { let name = context .cursor - .as_bibtex() + .as_bib() .filter(|token| token.kind() == bibtex::NAME)?; bibtex::Field::cast(name.parent()?)?; diff --git a/support/texlab/src/features/hover/label.rs b/support/texlab/src/features/hover/label.rs index 2f8489d769..eafc104de6 100644 --- a/support/texlab/src/features/hover/label.rs +++ b/support/texlab/src/features/hover/label.rs @@ -1,19 +1,23 @@ -use lsp_types::{HoverParams, MarkupKind}; +use lsp_types::MarkupKind; -use crate::{features::cursor::CursorContext, render_label}; +use crate::{ + db::Word, + util::{self, cursor::CursorContext}, +}; use super::HoverResult; -pub(super) fn find_label_hover(context: &CursorContext<HoverParams>) -> Option<HoverResult> { +pub(super) fn find_hover(context: &CursorContext) -> Option<HoverResult> { let (name_text, range) = context .find_label_name_key() .or_else(|| context.find_label_name_command())?; - let label = render_label(&context.request.workspace, &name_text, None)?; - - Some(HoverResult { - range, - value: label.reference(), - value_kind: MarkupKind::PlainText, - }) + let db = context.db; + util::label::find_label_definition(db, context.document, Word::new(db, name_text)) + .and_then(|(document, label)| util::label::render(db, document, label)) + .map(|label| HoverResult { + range, + value: label.reference(db), + value_kind: MarkupKind::PlainText, + }) } diff --git a/support/texlab/src/features/hover/string_ref.rs b/support/texlab/src/features/hover/string_ref.rs index adccdd556c..41c4c5bddb 100644 --- a/support/texlab/src/features/hover/string_ref.rs +++ b/support/texlab/src/features/hover/string_ref.rs @@ -1,29 +1,28 @@ -use lsp_types::{HoverParams, MarkupKind}; +use lsp_types::MarkupKind; use rowan::ast::AstNode; use crate::{ citation::field::text::TextFieldData, - features::cursor::CursorContext, syntax::bibtex::{self, HasName, HasValue}, + util::cursor::CursorContext, }; use super::HoverResult; -pub(super) fn find_string_reference_hover( - context: &CursorContext<HoverParams>, -) -> Option<HoverResult> { - let data = context.request.main_document().data.as_bibtex()?; +pub(super) fn find_hover(context: &CursorContext) -> Option<HoverResult> { + let data = context.document.parse(context.db).as_bib()?; let name = context .cursor - .as_bibtex() + .as_bib() .filter(|token| token.kind() == bibtex::NAME) .filter(|token| { let parent = token.parent().unwrap(); bibtex::Value::can_cast(parent.kind()) || bibtex::StringDef::can_cast(parent.kind()) })?; - for string in bibtex::SyntaxNode::new_root(data.green.clone()) + for string in data + .root(context.db) .children() .filter_map(bibtex::StringDef::cast) { diff --git a/support/texlab/src/features/inlay_hint.rs b/support/texlab/src/features/inlay_hint.rs new file mode 100644 index 0000000000..6d53259900 --- /dev/null +++ b/support/texlab/src/features/inlay_hint.rs @@ -0,0 +1,45 @@ +mod label; + +use lsp_types::{InlayHint, InlayHintLabel, Range, Url}; +use rowan::TextSize; + +use crate::{ + db::Workspace, + util::{line_index::LineIndex, line_index_ext::LineIndexExt}, + Db, +}; + +pub fn find_all(db: &dyn Db, uri: &Url, range: Range) -> Option<Vec<InlayHint>> { + let document = Workspace::get(db).lookup_uri(db, uri)?; + let line_index = document.contents(db).line_index(db); + + let mut builder = InlayHintBuilder { + line_index, + hints: Vec::new(), + }; + + let range = line_index.offset_lsp_range(range); + label::find_hints(db, document, range, &mut builder); + Some(builder.hints) +} + +struct InlayHintBuilder<'db> { + line_index: &'db LineIndex, + hints: Vec<InlayHint>, +} + +impl<'db> InlayHintBuilder<'db> { + pub fn push(&mut self, offset: TextSize, text: String) { + let position = self.line_index.line_col_lsp(offset); + self.hints.push(InlayHint { + position, + label: InlayHintLabel::String(text), + kind: None, + text_edits: None, + tooltip: None, + padding_left: Some(true), + padding_right: None, + data: None, + }); + } +} diff --git a/support/texlab/src/features/inlay_hint/label.rs b/support/texlab/src/features/inlay_hint/label.rs new file mode 100644 index 0000000000..5654f79bf4 --- /dev/null +++ b/support/texlab/src/features/inlay_hint/label.rs @@ -0,0 +1,31 @@ +use rowan::TextRange; + +use crate::{ + db::{analysis::label, Document}, + util, Db, +}; + +use super::InlayHintBuilder; + +pub(super) fn find_hints( + db: &dyn Db, + document: Document, + range: TextRange, + builder: &mut InlayHintBuilder, +) -> Option<()> { + let data = document.parse(db).as_tex()?; + for label in data + .analyze(db) + .labels(db) + .iter() + .copied() + .filter(|label| matches!(label.origin(db), label::Origin::Definition(_))) + .filter(|label| label.range(db).intersect(range).is_some()) + { + if let Some(rendered) = util::label::render(db, document, label) { + builder.push(label.range(db).end(), rendered.reference(db)); + } + } + + Some(()) +} diff --git a/support/texlab/src/features/link.rs b/support/texlab/src/features/link.rs index c4ce4413f5..71bba58ba7 100644 --- a/support/texlab/src/features/link.rs +++ b/support/texlab/src/features/link.rs @@ -1,33 +1,41 @@ mod include; -use std::sync::Arc; - -use lsp_types::{DocumentLink, DocumentLinkParams, Url}; +use lsp_types::{DocumentLink, Url}; use rowan::TextRange; -use crate::LineIndexExt; +use crate::{ + db::{Document, Workspace}, + util::{line_index::LineIndex, line_index_ext::LineIndexExt}, + Db, +}; -use self::include::find_include_links; +pub fn find_all(db: &dyn Db, uri: &Url) -> Option<Vec<DocumentLink>> { + let document = Workspace::get(db).lookup_uri(db, uri)?; + let mut builder = LinkBuilder { + db, + line_index: document.contents(db).line_index(db), + links: Vec::new(), + }; -use super::FeatureRequest; + include::find_links(db, document, &mut builder); + Some(builder.links) +} -pub fn find_document_links(request: FeatureRequest<DocumentLinkParams>) -> Vec<DocumentLink> { - let document = request.main_document(); - let mut results = Vec::new(); - find_include_links(&request, &mut results); - results - .into_iter() - .map(|result| DocumentLink { - range: document.line_index.line_col_lsp_range(result.range), - target: Some(result.target.as_ref().clone()), - tooltip: None, - data: None, - }) - .collect() +struct LinkBuilder<'db> { + db: &'db dyn Db, + line_index: &'db LineIndex, + links: Vec<DocumentLink>, } -#[derive(Debug, Clone)] -struct LinkResult { - range: TextRange, - target: Arc<Url>, +impl<'db> LinkBuilder<'db> { + pub fn push(&mut self, range: TextRange, target: Document) { + let range = self.line_index.line_col_lsp_range(range); + let target = Some(target.location(self.db).uri(self.db).clone()); + self.links.push(DocumentLink { + range, + target, + tooltip: None, + data: None, + }); + } } diff --git a/support/texlab/src/features/link/include.rs b/support/texlab/src/features/link/include.rs index b4d1804cce..f0c9d147fb 100644 --- a/support/texlab/src/features/link/include.rs +++ b/support/texlab/src/features/link/include.rs @@ -1,31 +1,23 @@ -use std::sync::Arc; +use crate::{ + db::{dependency_graph, Document, Workspace}, + Db, +}; -use lsp_types::DocumentLinkParams; +use super::LinkBuilder; -use crate::features::FeatureRequest; +pub(super) fn find_links(db: &dyn Db, document: Document, builder: &mut LinkBuilder) -> Option<()> { + let workspace = Workspace::get(db); + let parent = workspace + .parents(db, document) + .iter() + .next() + .copied() + .unwrap_or(document); -use super::LinkResult; - -pub(super) fn find_include_links( - request: &FeatureRequest<DocumentLinkParams>, - results: &mut Vec<LinkResult>, -) -> Option<()> { - let data = request.main_document().data.as_latex()?; - - for include in &data.extras.explicit_links { - for target in &include.targets { - if request - .workspace - .documents_by_uri - .values() - .any(|document| document.uri.as_ref() == target.as_ref()) - { - results.push(LinkResult { - range: include.stem_range, - target: Arc::clone(target), - }); - break; - } + let graph = dependency_graph(db, parent); + for edge in graph.edges.iter().filter(|edge| edge.source == document) { + if let Some(origin) = edge.origin { + builder.push(origin.link.range(db), edge.target); } } diff --git a/support/texlab/src/features/reference.rs b/support/texlab/src/features/reference.rs index f84a3f67d5..54a5fefb27 100644 --- a/support/texlab/src/features/reference.rs +++ b/support/texlab/src/features/reference.rs @@ -2,40 +2,45 @@ mod entry; mod label; mod string; -use std::sync::Arc; - -use lsp_types::{Location, ReferenceParams, Url}; +use lsp_types::{Location, Position, ReferenceContext, Url}; use rowan::TextRange; -use crate::LineIndexExt; - -use self::{ - entry::find_entry_references, label::find_label_references, string::find_string_references, +use crate::{ + db::Document, + util::{cursor::CursorContext, line_index_ext::LineIndexExt}, + Db, }; -use super::{cursor::CursorContext, FeatureRequest}; - -pub fn find_all_references(request: FeatureRequest<ReferenceParams>) -> Vec<Location> { +pub fn find_all( + db: &dyn Db, + uri: &Url, + position: Position, + params: &ReferenceContext, +) -> Option<Vec<Location>> { let mut results = Vec::new(); - let context = CursorContext::new(request); + let context = CursorContext::new(db, uri, position, params)?; log::debug!("[References] Cursor: {:?}", context.cursor); - find_label_references(&context, &mut results); - find_entry_references(&context, &mut results); - find_string_references(&context, &mut results); + label::find_all_references(&context, &mut results); + entry::find_all_references(&context, &mut results); + string::find_all_references(&context, &mut results); - results + let locations = results .into_iter() .map(|result| Location { - uri: result.uri.as_ref().clone(), - range: context.request.workspace.documents_by_uri[&result.uri] - .line_index + uri: result.document.location(db).uri(db).clone(), + range: result + .document + .contents(db) + .line_index(db) .line_col_lsp_range(result.range), }) - .collect() + .collect(); + + Some(locations) } #[derive(Debug, Clone)] struct ReferenceResult { - uri: Arc<Url>, + document: Document, range: TextRange, } diff --git a/support/texlab/src/features/reference/entry.rs b/support/texlab/src/features/reference/entry.rs index 0144d2d074..3dfa10da5b 100644 --- a/support/texlab/src/features/reference/entry.rs +++ b/support/texlab/src/features/reference/entry.rs @@ -1,32 +1,31 @@ -use std::sync::Arc; - -use lsp_types::ReferenceParams; +use lsp_types::ReferenceContext; use rowan::ast::AstNode; use crate::{ - features::cursor::CursorContext, + db::parse::DocumentData, syntax::{ bibtex::{self, HasName}, latex, }, - DocumentData, + util::cursor::CursorContext, }; use super::ReferenceResult; -pub(super) fn find_entry_references( - context: &CursorContext<ReferenceParams>, +pub(super) fn find_all_references( + context: &CursorContext<&ReferenceContext>, results: &mut Vec<ReferenceResult>, ) -> Option<()> { + let db = context.db; let (key_text, _) = context .find_citation_key_word() .or_else(|| context.find_citation_key_command()) .or_else(|| context.find_entry_key())?; - for document in context.request.workspace.documents_by_uri.values() { - match &document.data { - DocumentData::Latex(data) => { - latex::SyntaxNode::new_root(data.green.clone()) + for document in context.related() { + match document.parse(db) { + DocumentData::Tex(data) => { + data.root(db) .descendants() .filter_map(latex::Citation::cast) .filter_map(|citation| citation.key_list()) @@ -34,24 +33,22 @@ pub(super) fn find_entry_references( .filter(|key| key.to_string() == key_text) .map(|key| latex::small_range(&key)) .for_each(|range| { - let uri = Arc::clone(&document.uri); - results.push(ReferenceResult { uri, range }); + results.push(ReferenceResult { document, range }); }); } - DocumentData::Bibtex(data) if context.request.params.context.include_declaration => { - bibtex::SyntaxNode::new_root(data.green.clone()) + DocumentData::Bib(data) if context.params.include_declaration => { + data.root(db) .children() .filter_map(bibtex::Entry::cast) .filter_map(|entry| entry.name_token()) .filter(|key| key.text() == key_text) .map(|key| key.text_range()) .for_each(|range| { - let uri = Arc::clone(&document.uri); - results.push(ReferenceResult { uri, range }); + results.push(ReferenceResult { document, range }); }); } - DocumentData::Bibtex(_) | DocumentData::BuildLog(_) => {} - } + DocumentData::Bib(_) | DocumentData::Log(_) => {} + }; } Some(()) diff --git a/support/texlab/src/features/reference/label.rs b/support/texlab/src/features/reference/label.rs index 3dadada08b..394542320c 100644 --- a/support/texlab/src/features/reference/label.rs +++ b/support/texlab/src/features/reference/label.rs @@ -1,33 +1,32 @@ -use std::sync::Arc; +use lsp_types::ReferenceContext; -use lsp_types::ReferenceParams; - -use crate::features::cursor::CursorContext; +use crate::util::cursor::CursorContext; use super::ReferenceResult; -pub(super) fn find_label_references( - context: &CursorContext<ReferenceParams>, +pub(super) fn find_all_references( + context: &CursorContext<&ReferenceContext>, results: &mut Vec<ReferenceResult>, ) -> Option<()> { + let db = context.db; let (name_text, _) = context .find_label_name_key() .or_else(|| context.find_label_name_command())?; - for document in context.request.workspace.documents_by_uri.values() { - if let Some(data) = document.data.as_latex() { - for name in data - .extras - .label_names + for document in context.related() { + if let Some(data) = document.parse(db).as_tex() { + for label in data + .analyze(db) + .labels(db) .iter() - .filter(|name| name.text == name_text) - .filter(|name| { - !name.is_definition || context.request.params.context.include_declaration + .filter(|label| label.name(db).text(db) == &name_text) + .filter(|label| { + label.origin(db).as_definition().is_none() || context.params.include_declaration }) { results.push(ReferenceResult { - uri: Arc::clone(&document.uri), - range: name.range, + document, + range: label.range(db), }); } } diff --git a/support/texlab/src/features/reference/string.rs b/support/texlab/src/features/reference/string.rs index c00cf93546..c4bc6ded3d 100644 --- a/support/texlab/src/features/reference/string.rs +++ b/support/texlab/src/features/reference/string.rs @@ -1,22 +1,21 @@ -use std::sync::Arc; - -use lsp_types::ReferenceParams; +use lsp_types::ReferenceContext; use rowan::ast::AstNode; use crate::{ - features::cursor::CursorContext, syntax::bibtex::{self, HasName}, + util::cursor::CursorContext, }; use super::ReferenceResult; -pub(super) fn find_string_references( - context: &CursorContext<ReferenceParams>, +pub(super) fn find_all_references( + context: &CursorContext<&ReferenceContext>, results: &mut Vec<ReferenceResult>, ) -> Option<()> { + let db = context.db; let name_text = context .cursor - .as_bibtex() + .as_bib() .filter(|token| token.kind() == bibtex::NAME) .filter(|token| { let parent = token.parent().unwrap(); @@ -24,14 +23,11 @@ pub(super) fn find_string_references( })? .text(); - let document = context.request.main_document(); - let data = document.data.as_bibtex()?; - for node in bibtex::SyntaxNode::new_root(data.green.clone()).descendants() { + let data = context.document.parse(db).as_bib()?; + for node in data.root(db).descendants() { if let Some(name) = bibtex::StringDef::cast(node.clone()) .and_then(|string| string.name_token()) - .filter(|name| { - context.request.params.context.include_declaration && name.text() == name_text - }) + .filter(|name| context.params.include_declaration && name.text() == name_text) .or_else(|| { bibtex::Value::cast(node) .and_then(|token| token.syntax().first_token()) @@ -39,7 +35,7 @@ pub(super) fn find_string_references( }) { results.push(ReferenceResult { - uri: Arc::clone(&document.uri), + document: context.document, range: name.text_range(), }); } diff --git a/support/texlab/src/features/rename.rs b/support/texlab/src/features/rename.rs index c21faf262e..57e1ef5763 100644 --- a/support/texlab/src/features/rename.rs +++ b/support/texlab/src/features/rename.rs @@ -2,57 +2,61 @@ mod command; mod entry; mod label; -use std::sync::Arc; - -use lsp_types::{Range, RenameParams, TextDocumentPositionParams, TextEdit, Url, WorkspaceEdit}; +use lsp_types::{Position, Range, TextEdit, Url, WorkspaceEdit}; use rowan::TextRange; use rustc_hash::FxHashMap; -use crate::LineIndexExt; - -use self::{ - command::{prepare_command_rename, rename_command}, - entry::{prepare_entry_rename, rename_entry}, - label::{prepare_label_rename, rename_label}, +use crate::{ + db::Document, + util::{cursor::CursorContext, line_index_ext::LineIndexExt}, + Db, }; -use super::{cursor::CursorContext, FeatureRequest}; - -pub fn prepare_rename_all(request: FeatureRequest<TextDocumentPositionParams>) -> Option<Range> { - let context = CursorContext::new(request); - let range = prepare_entry_rename(&context) - .or_else(|| prepare_label_rename(&context)) - .or_else(|| prepare_command_rename(&context))?; +pub fn prepare_rename_all(db: &dyn Db, uri: &Url, position: Position) -> Option<Range> { + let context = CursorContext::new(db, uri, position, ())?; + let range = entry::prepare_rename(&context) + .or_else(|| label::prepare_rename(&context)) + .or_else(|| command::prepare_rename(&context))?; - let line_index = &context.request.main_document().line_index; + let line_index = context.document.contents(db).line_index(db); Some(line_index.line_col_lsp_range(range)) } -pub fn rename_all(request: FeatureRequest<RenameParams>) -> Option<WorkspaceEdit> { - let context = CursorContext::new(request); - let result = rename_entry(&context) - .or_else(|| rename_label(&context)) - .or_else(|| rename_command(&context))?; +pub fn rename_all( + db: &dyn Db, + uri: &Url, + position: Position, + new_name: String, +) -> Option<WorkspaceEdit> { + let context = CursorContext::new(db, uri, position, Params { new_name })?; + let result = entry::rename(&context) + .or_else(|| label::rename(&context)) + .or_else(|| command::rename(&context))?; let changes = result .changes .into_iter() - .map(|(uri, old_edits)| { - let document = &context.request.workspace.documents_by_uri[&uri]; + .map(|(document, old_edits)| { + let line_index = document.contents(db).line_index(db); let new_edits = old_edits .into_iter() .map(|Indel { delete, insert }| { - TextEdit::new(document.line_index.line_col_lsp_range(delete), insert) + TextEdit::new(line_index.line_col_lsp_range(delete), insert) }) .collect(); - (uri.as_ref().clone(), new_edits) + (document.location(db).uri(db).clone(), new_edits) }) .collect(); Some(WorkspaceEdit::new(changes)) } +#[derive(Debug)] +struct Params { + new_name: String, +} + #[derive(Debug, PartialEq, Eq, Clone)] struct Indel { delete: TextRange, @@ -61,5 +65,5 @@ struct Indel { #[derive(Debug, PartialEq, Eq, Clone)] struct RenameResult { - changes: FxHashMap<Arc<Url>, Vec<Indel>>, + changes: FxHashMap<Document, Vec<Indel>>, } diff --git a/support/texlab/src/features/rename/command.rs b/support/texlab/src/features/rename/command.rs index aaa08f8cb4..5610b2f7ee 100644 --- a/support/texlab/src/features/rename/command.rs +++ b/support/texlab/src/features/rename/command.rs @@ -1,29 +1,21 @@ -use std::sync::Arc; - -use lsp_types::RenameParams; use rowan::{TextRange, TextSize}; use rustc_hash::FxHashMap; -use crate::{ - features::cursor::{CursorContext, HasPosition}, - syntax::latex, -}; +use crate::util::cursor::CursorContext; -use super::{Indel, RenameResult}; +use super::{Indel, Params, RenameResult}; -pub(super) fn prepare_command_rename<P: HasPosition>( - context: &CursorContext<P>, -) -> Option<TextRange> { +pub(super) fn prepare_rename<T>(context: &CursorContext<T>) -> Option<TextRange> { context.cursor.command_range(context.offset) } -pub(super) fn rename_command(context: &CursorContext<RenameParams>) -> Option<RenameResult> { - prepare_command_rename(context)?; - let name = context.cursor.as_latex()?.text(); +pub(super) fn rename(context: &CursorContext<Params>) -> Option<RenameResult> { + prepare_rename(context)?; + let name = context.cursor.as_tex()?.text(); let mut changes = FxHashMap::default(); - for document in context.request.workspace.documents_by_uri.values() { - if let Some(data) = document.data.as_latex() { - let root = latex::SyntaxNode::new_root(data.green.clone()); + for document in context.related() { + if let Some(data) = document.parse(context.db).as_tex() { + let root = data.root(context.db); let edits = root .descendants_with_tokens() .filter_map(|element| element.into_token()) @@ -32,12 +24,12 @@ pub(super) fn rename_command(context: &CursorContext<RenameParams>) -> Option<Re let range = token.text_range(); Indel { delete: TextRange::new(range.start() + TextSize::from(1), range.end()), - insert: context.request.params.new_name.clone(), + insert: context.params.new_name.clone(), } }) .collect(); - changes.insert(Arc::clone(&document.uri), edits); + changes.insert(document, edits); } } diff --git a/support/texlab/src/features/rename/entry.rs b/support/texlab/src/features/rename/entry.rs index 6eac79030b..79ee25ac71 100644 --- a/support/texlab/src/features/rename/entry.rs +++ b/support/texlab/src/features/rename/entry.rs @@ -1,23 +1,18 @@ -use std::sync::Arc; - -use lsp_types::RenameParams; use rowan::{ast::AstNode, TextRange}; use rustc_hash::FxHashMap; use crate::{ - features::cursor::{CursorContext, HasPosition}, + db::parse::DocumentData, syntax::{ bibtex::{self, HasName}, latex, }, - DocumentData, + util::cursor::CursorContext, }; -use super::{Indel, RenameResult}; +use super::{Indel, Params, RenameResult}; -pub(super) fn prepare_entry_rename<P: HasPosition>( - context: &CursorContext<P>, -) -> Option<TextRange> { +pub(super) fn prepare_rename<T>(context: &CursorContext<T>) -> Option<TextRange> { let (_, range) = context .find_citation_key_word() .or_else(|| context.find_entry_key())?; @@ -25,18 +20,17 @@ pub(super) fn prepare_entry_rename<P: HasPosition>( Some(range) } -pub(super) fn rename_entry(context: &CursorContext<RenameParams>) -> Option<RenameResult> { - prepare_entry_rename(context)?; +pub(super) fn rename(context: &CursorContext<Params>) -> Option<RenameResult> { + prepare_rename(context)?; let (key_text, _) = context .find_citation_key_word() .or_else(|| context.find_entry_key())?; let mut changes = FxHashMap::default(); - for document in context.request.workspace.documents_by_uri.values() { - let uri = Arc::clone(&document.uri); - match &document.data { - DocumentData::Latex(data) => { - let root = latex::SyntaxNode::new_root(data.green.clone()); + for document in context.related() { + match document.parse(context.db) { + DocumentData::Tex(data) => { + let root = data.root(context.db); let edits: Vec<_> = root .descendants() .filter_map(latex::Citation::cast) @@ -45,13 +39,13 @@ pub(super) fn rename_entry(context: &CursorContext<RenameParams>) -> Option<Rena .filter(|key| key.to_string() == key_text) .map(|key| Indel { delete: latex::small_range(&key), - insert: context.request.params.new_name.clone(), + insert: context.params.new_name.clone(), }) .collect(); - changes.insert(uri, edits); + changes.insert(document, edits); } - DocumentData::Bibtex(data) => { - let root = bibtex::SyntaxNode::new_root(data.green.clone()); + DocumentData::Bib(data) => { + let root = data.root(context.db); let edits: Vec<_> = root .descendants() .filter_map(bibtex::Entry::cast) @@ -59,12 +53,12 @@ pub(super) fn rename_entry(context: &CursorContext<RenameParams>) -> Option<Rena .filter(|key| key.text() == key_text) .map(|key| Indel { delete: key.text_range(), - insert: context.request.params.new_name.clone(), + insert: context.params.new_name.clone(), }) .collect(); - changes.insert(uri, edits); + changes.insert(document, edits); } - DocumentData::BuildLog(_) => {} + DocumentData::Log(_) => {} } } diff --git a/support/texlab/src/features/rename/label.rs b/support/texlab/src/features/rename/label.rs index 30a99c3b36..d38d13ae93 100644 --- a/support/texlab/src/features/rename/label.rs +++ b/support/texlab/src/features/rename/label.rs @@ -1,32 +1,24 @@ -use std::sync::Arc; - -use lsp_types::RenameParams; use rowan::{ast::AstNode, TextRange}; use rustc_hash::FxHashMap; -use crate::{ - features::cursor::{CursorContext, HasPosition}, - syntax::latex, -}; +use crate::{syntax::latex, util::cursor::CursorContext}; -use super::{Indel, RenameResult}; +use super::{Indel, Params, RenameResult}; -pub(super) fn prepare_label_rename<P: HasPosition>( - context: &CursorContext<P>, -) -> Option<TextRange> { +pub(super) fn prepare_rename<T>(context: &CursorContext<T>) -> Option<TextRange> { let (_, range) = context.find_label_name_key()?; Some(range) } -pub(super) fn rename_label(context: &CursorContext<RenameParams>) -> Option<RenameResult> { - prepare_label_rename(context)?; +pub(super) fn rename(context: &CursorContext<Params>) -> Option<RenameResult> { + prepare_rename(context)?; let (name_text, _) = context.find_label_name_key()?; let mut changes = FxHashMap::default(); - for document in context.request.workspace.documents_by_uri.values() { - if let Some(data) = document.data.as_latex() { + for document in context.related() { + if let Some(data) = document.parse(context.db).as_tex() { let mut edits = Vec::new(); - for node in latex::SyntaxNode::new_root(data.green.clone()).descendants() { + for node in data.root(context.db).descendants() { if let Some(range) = latex::LabelDefinition::cast(node.clone()) .and_then(|label| label.name()) .and_then(|name| name.key()) @@ -35,7 +27,7 @@ pub(super) fn rename_label(context: &CursorContext<RenameParams>) -> Option<Rena { edits.push(Indel { delete: range, - insert: context.request.params.new_name.clone(), + insert: context.params.new_name.clone(), }); } @@ -47,7 +39,7 @@ pub(super) fn rename_label(context: &CursorContext<RenameParams>) -> Option<Rena .for_each(|name| { edits.push(Indel { delete: latex::small_range(&name), - insert: context.request.params.new_name.clone(), + insert: context.params.new_name.clone(), }); }); @@ -59,7 +51,7 @@ pub(super) fn rename_label(context: &CursorContext<RenameParams>) -> Option<Rena { edits.push(Indel { delete: latex::small_range(&name1), - insert: context.request.params.new_name.clone(), + insert: context.params.new_name.clone(), }); } @@ -70,13 +62,13 @@ pub(super) fn rename_label(context: &CursorContext<RenameParams>) -> Option<Rena { edits.push(Indel { delete: latex::small_range(&name2), - insert: context.request.params.new_name.clone(), + insert: context.params.new_name.clone(), }); } } } - changes.insert(Arc::clone(&document.uri), edits); + changes.insert(document, edits); } } diff --git a/support/texlab/src/features/symbol.rs b/support/texlab/src/features/symbol.rs index 24d599c3e1..c16193efcb 100644 --- a/support/texlab/src/features/symbol.rs +++ b/support/texlab/src/features/symbol.rs @@ -3,49 +3,44 @@ mod latex; mod project_order; mod types; -use std::{cmp::Reverse, sync::Arc}; +use std::cmp::Reverse; -use lsp_types::{ - DocumentSymbolParams, DocumentSymbolResponse, PartialResultParams, SymbolInformation, - TextDocumentIdentifier, WorkDoneProgressParams, WorkspaceSymbolParams, -}; +use lsp_types::{DocumentSymbolResponse, SymbolInformation, Url, WorkspaceSymbolParams}; -use crate::{ClientCapabilitiesExt, Workspace}; +use crate::{db::Workspace, util::capabilities::ClientCapabilitiesExt, Db}; -use self::{ - bibtex::find_bibtex_symbols, latex::find_latex_symbols, project_order::ProjectOrdering, - types::InternalSymbol, -}; +use self::project_order::ProjectOrdering; -use super::FeatureRequest; +pub fn find_document_symbols(db: &dyn Db, uri: &Url) -> Option<DocumentSymbolResponse> { + let workspace = Workspace::get(db); + let document = workspace.lookup_uri(db, uri)?; -#[must_use] -pub fn find_document_symbols(req: FeatureRequest<DocumentSymbolParams>) -> DocumentSymbolResponse { let mut buf = Vec::new(); - find_latex_symbols(&req, &mut buf); - find_bibtex_symbols(&req, &mut buf); - if req - .workspace - .environment - .client_capabilities + latex::find_symbols(db, document, &mut buf); + bibtex::find_symbols(db, document, &mut buf); + if workspace + .client_capabilities(db) .has_hierarchical_document_symbol_support() { - DocumentSymbolResponse::Nested( - buf.into_iter() - .map(InternalSymbol::into_document_symbol) - .collect(), - ) + let symbols = buf + .into_iter() + .map(|symbol| symbol.into_document_symbol(db)) + .collect(); + + Some(DocumentSymbolResponse::Nested(symbols)) } else { let mut new_buf = Vec::new(); for symbol in buf { symbol.flatten(&mut new_buf); } + let mut new_buf: Vec<_> = new_buf .into_iter() - .map(|symbol| symbol.into_symbol_info(req.main_document().uri.as_ref().clone())) + .map(|symbol| symbol.into_symbol_info(uri.clone())) .collect(); - sort_symbols(&req.workspace, &mut new_buf); - DocumentSymbolResponse::Flat(new_buf) + + sort_symbols(db, &mut new_buf); + Some(DocumentSymbolResponse::Flat(new_buf)) } } @@ -57,25 +52,16 @@ struct WorkspaceSymbol { #[must_use] pub fn find_workspace_symbols( - workspace: &Workspace, + db: &dyn Db, params: &WorkspaceSymbolParams, ) -> Vec<SymbolInformation> { let mut symbols = Vec::new(); - for document in workspace.documents_by_uri.values() { - let request = FeatureRequest { - uri: Arc::clone(&document.uri), - params: DocumentSymbolParams { - text_document: TextDocumentIdentifier::new(document.uri.as_ref().clone()), - partial_result_params: PartialResultParams::default(), - work_done_progress_params: WorkDoneProgressParams::default(), - }, - workspace: workspace.slice(&document.uri), - }; - + let workspace = Workspace::get(db); + for document in workspace.documents(db).iter().copied() { let mut buf = Vec::new(); - find_latex_symbols(&request, &mut buf); - find_bibtex_symbols(&request, &mut buf); + latex::find_symbols(db, document, &mut buf); + bibtex::find_symbols(db, document, &mut buf); let mut new_buf = Vec::new(); for symbol in buf { @@ -85,7 +71,7 @@ pub fn find_workspace_symbols( for symbol in new_buf { symbols.push(WorkspaceSymbol { search_text: symbol.search_text(), - info: symbol.into_symbol_info(document.uri.as_ref().clone()), + info: symbol.into_symbol_info(document.location(db).uri(db).clone()), }); } } @@ -95,6 +81,7 @@ pub fn find_workspace_symbols( .split_whitespace() .map(str::to_lowercase) .collect(); + let mut filtered = Vec::new(); for symbol in symbols { let mut included = true; @@ -109,20 +96,21 @@ pub fn find_workspace_symbols( filtered.push(symbol.info); } } - sort_symbols(workspace, &mut filtered); + + sort_symbols(db, &mut filtered); filtered } -fn sort_symbols(workspace: &Workspace, symbols: &mut [SymbolInformation]) { - let ordering = ProjectOrdering::from(workspace); +fn sort_symbols(db: &dyn Db, symbols: &mut [SymbolInformation]) { + let ordering = ProjectOrdering::new(db); symbols.sort_by(|left, right| { let left_key = ( - ordering.get(&left.location.uri), + ordering.get(db, &left.location.uri), left.location.range.start, Reverse(left.location.range.end), ); let right_key = ( - ordering.get(&right.location.uri), + ordering.get(db, &right.location.uri), right.location.range.start, Reverse(right.location.range.end), ); diff --git a/support/texlab/src/features/symbol/bibtex.rs b/support/texlab/src/features/symbol/bibtex.rs index bbc9026b0b..6a92405f17 100644 --- a/support/texlab/src/features/symbol/bibtex.rs +++ b/support/texlab/src/features/symbol/bibtex.rs @@ -1,82 +1,87 @@ -use lsp_types::DocumentSymbolParams; use rowan::ast::AstNode; use crate::{ - features::FeatureRequest, + db::Document, syntax::bibtex::{self, HasName, HasType}, - BibtexEntryTypeCategory, LineIndexExt, LANGUAGE_DATA, + util::{ + lang_data::{BibtexEntryTypeCategory, LANGUAGE_DATA}, + line_index::LineIndex, + line_index_ext::LineIndexExt, + }, + Db, }; use super::types::{InternalSymbol, InternalSymbolKind}; -pub fn find_bibtex_symbols( - request: &FeatureRequest<DocumentSymbolParams>, +pub fn find_symbols(db: &dyn Db, document: Document, buf: &mut Vec<InternalSymbol>) -> Option<()> { + let data = document.parse(db).as_bib()?; + let line_index = document.contents(db).line_index(db); + for node in data.root(db).children() { + process_string(node.clone(), line_index, buf) + .or_else(|| process_entry(node, line_index, buf)); + } + + Some(()) +} + +fn process_string( + node: bibtex::SyntaxNode, + line_index: &LineIndex, buf: &mut Vec<InternalSymbol>, ) -> Option<()> { - let main_document = request.main_document(); - let data = main_document.data.as_bibtex()?; - - for node in bibtex::SyntaxNode::new_root(data.green.clone()).children() { - if let Some(string) = bibtex::StringDef::cast(node.clone()) { - if let Some(name) = string.name_token() { - buf.push(InternalSymbol { - name: name.text().into(), - label: None, - kind: InternalSymbolKind::String, - deprecated: false, - full_range: main_document - .line_index - .line_col_lsp_range(string.syntax().text_range()), - selection_range: main_document - .line_index - .line_col_lsp_range(name.text_range()), - children: Vec::new(), - }) - } - } else if let Some(entry) = bibtex::Entry::cast(node) { - if let Some(ty) = entry.type_token() { - if let Some(key) = entry.name_token() { - let mut children = Vec::new(); - for field in entry.fields() { - if let Some(name) = field.name_token() { - let symbol = InternalSymbol { - name: name.text().to_string(), - label: None, - kind: InternalSymbolKind::Field, - deprecated: false, - full_range: main_document - .line_index - .line_col_lsp_range(field.syntax().text_range()), - selection_range: main_document - .line_index - .line_col_lsp_range(name.text_range()), - children: Vec::new(), - }; - children.push(symbol); - } - } + let string = bibtex::StringDef::cast(node)?; + let name = string.name_token()?; + buf.push(InternalSymbol { + name: name.text().into(), + label: None, + kind: InternalSymbolKind::String, + deprecated: false, + full_range: line_index.line_col_lsp_range(string.syntax().text_range()), + selection_range: line_index.line_col_lsp_range(name.text_range()), + children: Vec::new(), + }); - let category = LANGUAGE_DATA - .find_entry_type(&ty.text()[1..]) - .map(|ty| ty.category) - .unwrap_or(BibtexEntryTypeCategory::Misc); + Some(()) +} - buf.push(InternalSymbol { - name: key.to_string(), - label: None, - kind: InternalSymbolKind::Entry(category), - deprecated: false, - full_range: main_document - .line_index - .line_col_lsp_range(entry.syntax().text_range()), - selection_range: main_document - .line_index - .line_col_lsp_range(key.text_range()), - children, - }); - } - } +fn process_entry( + node: bibtex::SyntaxNode, + line_index: &LineIndex, + buf: &mut Vec<InternalSymbol>, +) -> Option<()> { + let entry = bibtex::Entry::cast(node)?; + let ty = entry.type_token()?; + let key = entry.name_token()?; + let mut children = Vec::new(); + for field in entry.fields() { + if let Some(name) = field.name_token() { + let symbol = InternalSymbol { + name: name.text().to_string(), + label: None, + kind: InternalSymbolKind::Field, + deprecated: false, + full_range: line_index.line_col_lsp_range(field.syntax().text_range()), + selection_range: line_index.line_col_lsp_range(name.text_range()), + children: Vec::new(), + }; + children.push(symbol); } } + + let category = LANGUAGE_DATA + .find_entry_type(&ty.text()[1..]) + .map(|ty| ty.category) + .unwrap_or(BibtexEntryTypeCategory::Misc); + + buf.push(InternalSymbol { + name: key.to_string(), + label: None, + kind: InternalSymbolKind::Entry(category), + deprecated: false, + full_range: line_index.line_col_lsp_range(entry.syntax().text_range()), + selection_range: line_index.line_col_lsp_range(key.text_range()), + children, + }); + Some(()) } diff --git a/support/texlab/src/features/symbol/latex.rs b/support/texlab/src/features/symbol/latex.rs index 8a88ffb0d9..81927ab515 100644 --- a/support/texlab/src/features/symbol/latex.rs +++ b/support/texlab/src/features/symbol/latex.rs @@ -1,38 +1,30 @@ use std::str::FromStr; -use lsp_types::{DocumentSymbolParams, Range}; +use lsp_types::Range; use rowan::ast::AstNode; -use smol_str::SmolStr; use titlecase::titlecase; use crate::{ - features::FeatureRequest, - find_caption_by_parent, find_label_number, + db::{Document, Word, Workspace}, syntax::latex::{self, HasBrack, HasCurly}, - LabelledFloatKind, LatexDocumentData, LineIndexExt, LANGUAGE_DATA, + util::{ + label::{find_caption_by_parent, LabeledFloatKind}, + lang_data::LANGUAGE_DATA, + line_index_ext::LineIndexExt, + }, + Db, }; use super::types::{InternalSymbol, InternalSymbolKind}; -pub fn find_latex_symbols( - request: &FeatureRequest<DocumentSymbolParams>, - buf: &mut Vec<InternalSymbol>, -) -> Option<()> { - let data = request.main_document().data.as_latex()?; - let mut context = Context { request, data }; - - let root = context.data.green.clone(); - let mut symbols = visit(&mut context, latex::SyntaxNode::new_root(root)); +pub fn find_symbols(db: &dyn Db, document: Document, buf: &mut Vec<InternalSymbol>) -> Option<()> { + let data = document.parse(db).as_tex()?; + let mut symbols = visit(db, document, data.root(db)); buf.append(&mut symbols); Some(()) } -struct Context<'a> { - request: &'a FeatureRequest<DocumentSymbolParams>, - data: &'a LatexDocumentData, -} - -fn visit(context: &mut Context, node: latex::SyntaxNode) -> Vec<InternalSymbol> { +fn visit(db: &dyn Db, document: Document, node: latex::SyntaxNode) -> Vec<InternalSymbol> { let symbol = match node.kind() { latex::PART | latex::CHAPTER @@ -40,9 +32,9 @@ fn visit(context: &mut Context, node: latex::SyntaxNode) -> Vec<InternalSymbol> | latex::SUBSECTION | latex::SUBSUBSECTION | latex::PARAGRAPH - | latex::SUBPARAGRAPH => visit_section(context, node.clone()), - latex::ENUM_ITEM => visit_enum_item(context, node.clone()), - latex::EQUATION => visit_equation(context, node.clone()), + | latex::SUBPARAGRAPH => visit_section(db, document, node.clone()), + latex::ENUM_ITEM => visit_enum_item(db, document, node.clone()), + latex::EQUATION => visit_equation(db, document, node.clone()), latex::ENVIRONMENT => latex::Environment::cast(node.clone()) .and_then(|env| env.begin()) .and_then(|begin| begin.name()) @@ -54,17 +46,17 @@ fn visit(context: &mut Context, node: latex::SyntaxNode) -> Vec<InternalSymbol> .iter() .any(|env| env == &name) { - visit_equation_environment(context, node.clone()) + visit_equation_environment(db, document, node.clone()) } else if LANGUAGE_DATA .enum_environments .iter() .any(|env| env == &name) { - visit_enumeration(context, node.clone(), &name) - } else if let Ok(float_kind) = LabelledFloatKind::from_str(&name) { - visit_float(context, node.clone(), float_kind) + visit_enumeration(db, document, node.clone(), &name) + } else if let Ok(float_kind) = LabeledFloatKind::from_str(&name) { + visit_float(db, document, node.clone(), float_kind) } else { - visit_theorem(context, node.clone(), &name) + visit_theorem(db, document, node.clone(), &name) } }), _ => None, @@ -73,39 +65,42 @@ fn visit(context: &mut Context, node: latex::SyntaxNode) -> Vec<InternalSymbol> match symbol { Some(mut parent) => { for child in node.children() { - parent.children.append(&mut visit(context, child)); + parent.children.append(&mut visit(db, document, child)); } vec![parent] } None => { let mut symbols = Vec::new(); for child in node.children() { - symbols.append(&mut visit(context, child)); + symbols.append(&mut visit(db, document, child)); } symbols } } } -fn visit_section(context: &mut Context, node: latex::SyntaxNode) -> Option<InternalSymbol> { +fn visit_section( + db: &dyn Db, + document: Document, + node: latex::SyntaxNode, +) -> Option<InternalSymbol> { let section = latex::Section::cast(node)?; - let full_range = context - .request - .main_document() - .line_index + let full_range = document + .contents(db) + .line_index(db) .line_col_lsp_range(latex::small_range(§ion)); let group = section.name()?; let group_text = group.content_text()?; - let symbol = match find_label_by_parent(context, section.syntax()) { + let symbol = match find_label_by_parent(db, document, section.syntax()) { Some(NumberedLabel { name: label, range: selection_range, number, }) => { let name = match number { - Some(number) => format!("{} {}", number, group_text), + Some(number) => format!("{} {}", number.text(db), group_text), None => group_text, }; @@ -129,10 +124,15 @@ fn visit_section(context: &mut Context, node: latex::SyntaxNode) -> Option<Inter children: Vec::new(), }, }; + Some(symbol) } -fn visit_enum_item(context: &mut Context, node: latex::SyntaxNode) -> Option<InternalSymbol> { +fn visit_enum_item( + db: &dyn Db, + document: Document, + node: latex::SyntaxNode, +) -> Option<InternalSymbol> { let enum_item = latex::EnumItem::cast(node.clone())?; if !enum_item .syntax() @@ -151,10 +151,9 @@ fn visit_enum_item(context: &mut Context, node: latex::SyntaxNode) -> Option<Int return None; } - let full_range = context - .request - .main_document() - .line_index + let full_range = document + .contents(db) + .line_index(db) .line_col_lsp_range(latex::small_range(&enum_item)); let name = enum_item @@ -162,13 +161,15 @@ fn visit_enum_item(context: &mut Context, node: latex::SyntaxNode) -> Option<Int .and_then(|label| label.content_text()) .unwrap_or_else(|| "Item".to_string()); - let symbol = match find_label_by_parent(context, &node) { + let symbol = match find_label_by_parent(db, document, &node) { Some(NumberedLabel { name: label, range: selection_range, number, }) => InternalSymbol { - name: number.map(Into::into).unwrap_or_else(|| name.to_string()), + name: number + .map(|num| num.text(db).clone()) + .unwrap_or_else(|| name.clone()), label: Some(label), kind: InternalSymbolKind::EnumerationItem, deprecated: false, @@ -189,46 +190,50 @@ fn visit_enum_item(context: &mut Context, node: latex::SyntaxNode) -> Option<Int Some(symbol) } -fn visit_equation(context: &mut Context, node: latex::SyntaxNode) -> Option<InternalSymbol> { +fn visit_equation( + db: &dyn Db, + document: Document, + node: latex::SyntaxNode, +) -> Option<InternalSymbol> { let equation = latex::Equation::cast(node)?; - let full_range = context - .request - .main_document() - .line_index + let full_range = document + .contents(db) + .line_index(db) .line_col_lsp_range(latex::small_range(&equation)); - make_equation_symbol(context, equation.syntax(), full_range) + make_equation_symbol(db, document, equation.syntax(), full_range) } fn visit_equation_environment( - context: &mut Context, + db: &dyn Db, + document: Document, node: latex::SyntaxNode, ) -> Option<InternalSymbol> { let environment = latex::Environment::cast(node)?; - let full_range = context - .request - .main_document() - .line_index + let full_range = document + .contents(db) + .line_index(db) .line_col_lsp_range(latex::small_range(&environment)); - make_equation_symbol(context, environment.syntax(), full_range) + make_equation_symbol(db, document, environment.syntax(), full_range) } fn make_equation_symbol( - context: &mut Context, + db: &dyn Db, + document: Document, node: &latex::SyntaxNode, full_range: Range, ) -> Option<InternalSymbol> { - let symbol = match find_label_by_parent(context, node) { + let symbol = match find_label_by_parent(db, document, node) { Some(NumberedLabel { name: label, range: selection_range, number, }) => { let name = match number { - Some(number) => format!("Equation ({})", number), + Some(number) => format!("Equation ({})", number.text(db)), None => "Equation".to_string(), }; @@ -256,26 +261,26 @@ fn make_equation_symbol( } fn visit_enumeration( - context: &mut Context, + db: &dyn Db, + document: Document, node: latex::SyntaxNode, env_name: &str, ) -> Option<InternalSymbol> { let environment = latex::Environment::cast(node)?; - let full_range = context - .request - .main_document() - .line_index + let full_range = document + .contents(db) + .line_index(db) .line_col_lsp_range(latex::small_range(&environment)); let name = titlecase(env_name); - let symbol = match find_label_by_parent(context, environment.syntax()) { + let symbol = match find_label_by_parent(db, document, environment.syntax()) { Some(NumberedLabel { name: label, range: selection_range, number, }) => { let name = match number { - Some(number) => format!("{} {}", name, number), + Some(number) => format!("{} {}", name, number.text(db)), None => name, }; @@ -303,33 +308,33 @@ fn visit_enumeration( } fn visit_float( - context: &mut Context, + db: &dyn Db, + document: Document, node: latex::SyntaxNode, - float_kind: LabelledFloatKind, + float_kind: LabeledFloatKind, ) -> Option<InternalSymbol> { let environment = latex::Environment::cast(node)?; - let full_range = context - .request - .main_document() - .line_index + let full_range = document + .contents(db) + .line_index(db) .line_col_lsp_range(latex::small_range(&environment)); let (float_kind, symbol_kind) = match float_kind { - LabelledFloatKind::Algorithm => ("Algorithm", InternalSymbolKind::Algorithm), - LabelledFloatKind::Figure => ("Figure", InternalSymbolKind::Figure), - LabelledFloatKind::Listing => ("Listing", InternalSymbolKind::Listing), - LabelledFloatKind::Table => ("Table", InternalSymbolKind::Table), + LabeledFloatKind::Algorithm => ("Algorithm", InternalSymbolKind::Algorithm), + LabeledFloatKind::Figure => ("Figure", InternalSymbolKind::Figure), + LabeledFloatKind::Listing => ("Listing", InternalSymbolKind::Listing), + LabeledFloatKind::Table => ("Table", InternalSymbolKind::Table), }; let caption = find_caption_by_parent(environment.syntax())?; - let symbol = match find_label_by_parent(context, environment.syntax()) { + let symbol = match find_label_by_parent(db, document, environment.syntax()) { Some(NumberedLabel { name: label, range: selection_range, number, }) => { let name = match number { - Some(number) => format!("{} {}: {}", float_kind, number, caption), + Some(number) => format!("{} {}: {}", float_kind, number.text(db), caption), None => format!("{}: {}", float_kind, caption), }; @@ -358,23 +363,17 @@ fn visit_float( } fn visit_theorem( - context: &mut Context, + db: &dyn Db, + document: Document, node: latex::SyntaxNode, environment_name: &str, ) -> Option<InternalSymbol> { - let definition = context - .request - .workspace - .documents_by_uri - .values() - .filter_map(|document| document.data.as_latex()) - .find_map(|data| { - data.extras - .theorem_environments - .iter() - .find(|environment| environment.name == environment_name) - .cloned() - })?; + let definition = Workspace::get(db) + .related(db, document) + .iter() + .filter_map(|document| document.parse(db).as_tex()) + .flat_map(|data| data.analyze(db).theorem_environments(db)) + .find(|env| env.name(db).text(db) == environment_name)?; let node = latex::Environment::cast(node)?; let theorem_description = node @@ -382,13 +381,12 @@ fn visit_theorem( .options() .and_then(|option| option.content_text()); - let full_range = context - .request - .main_document() - .line_index + let full_range = document + .contents(db) + .line_index(db) .line_col_lsp_range(latex::small_range(&node)); - let symbol = match find_label_by_parent(context, node.syntax()) { + let symbol = match find_label_by_parent(db, document, node.syntax()) { Some(NumberedLabel { name: label, range: selection_range, @@ -396,11 +394,20 @@ fn visit_theorem( }) => { let name = match (number, theorem_description) { (Some(number), Some(desc)) => { - format!("{} {} ({})", definition.description, number, desc) + format!( + "{} {} ({})", + definition.description(db).text(db), + number.text(db), + desc + ) } - (Some(number), None) => format!("{} {}", definition.description, number), - (None, Some(desc)) => format!("{} ({})", definition.description, desc), - (None, None) => definition.description, + (Some(number), None) => format!( + "{} {}", + definition.description(db).text(db), + number.text(db) + ), + (None, Some(desc)) => format!("{} ({})", definition.description(db).text(db), desc), + (None, None) => definition.description(db).text(db).clone(), }; InternalSymbol { @@ -415,8 +422,8 @@ fn visit_theorem( } None => { let name = match theorem_description { - Some(desc) => format!("{} ({})", definition.description, desc), - None => definition.description, + Some(desc) => format!("{} ({})", definition.description(db).text(db), desc), + None => definition.description(db).text(db).clone(), }; InternalSymbol { name, @@ -434,28 +441,27 @@ fn visit_theorem( #[derive(Debug, PartialEq, Eq, Clone)] struct NumberedLabel { - name: String, + name: Word, range: Range, - number: Option<SmolStr>, + number: Option<Word>, } fn find_label_by_parent( - context: &mut Context, + db: &dyn Db, + document: Document, parent: &latex::SyntaxNode, ) -> Option<NumberedLabel> { let node = parent.children().find_map(latex::LabelDefinition::cast)?; - - let name = node.name()?.key()?.to_string(); - let range = context - .request - .main_document() - .line_index + let name = Word::new(db, node.name()?.key()?.to_string()); + let range = document + .contents(db) + .line_index(db) .line_col_lsp_range(latex::small_range(&node)); - let number = find_label_number(&context.request.workspace, &name); + let number = Workspace::get(db).number_of_label(db, document, name); Some(NumberedLabel { - name: name.to_string(), + name, range, - number: number.map(Into::into), + number, }) } diff --git a/support/texlab/src/features/symbol/project_order.rs b/support/texlab/src/features/symbol/project_order.rs index 794447ecf6..f4aeb63bca 100644 --- a/support/texlab/src/features/symbol/project_order.rs +++ b/support/texlab/src/features/symbol/project_order.rs @@ -1,209 +1,202 @@ -use std::{sync::Arc, usize}; - +use itertools::Itertools; use lsp_types::Url; -use petgraph::{algo::tarjan_scc, Directed, Graph}; -use rustc_hash::FxHashSet; -use crate::{Document, Workspace}; +use crate::{ + db::{dependency_graph, Document, Workspace}, + Db, +}; #[derive(Debug, PartialEq, Eq, Clone)] pub struct ProjectOrdering { - ordering: Vec<Arc<Url>>, + ordering: Vec<Document>, } impl ProjectOrdering { - pub fn get(&self, uri: &Url) -> usize { - self.ordering - .iter() - .position(|u| u.as_ref() == uri) - .unwrap_or(usize::MAX) - } -} - -impl From<&Workspace> for ProjectOrdering { - fn from(workspace: &Workspace) -> Self { - let mut ordering = Vec::new(); - let uris: FxHashSet<Arc<Url>> = workspace - .documents_by_uri - .values() - .map(|document| Arc::clone(&document.uri)) + pub fn new(db: &dyn Db) -> Self { + let workspace = Workspace::get(db); + + let ordering: Vec<_> = workspace + .index_files(db) + .chain(workspace.documents(db).iter().copied()) + .flat_map(|document| { + dependency_graph(db, document) + .preorder() + .rev() + .collect_vec() + }) + .unique() .collect(); - let comps = connected_components(workspace); - for comp in comps { - let (graph, documents) = build_dependency_graph(&comp); - - let mut visited = FxHashSet::default(); - let root_index = *graph.node_weight(tarjan_scc(&graph)[0][0]).unwrap(); - let mut stack = vec![Arc::clone(&documents[root_index].uri)]; - - while let Some(uri) = stack.pop() { - if !visited.insert(Arc::clone(&uri)) { - continue; - } - - ordering.push(Arc::clone(&uri)); - if let Some(document) = workspace.documents_by_uri.get(&uri) { - if let Some(data) = document.data.as_latex() { - for link in data.extras.explicit_links.iter().rev() { - for target in &link.targets { - if uris.contains(target.as_ref()) { - stack.push(Arc::clone(target)); - } - } - } - } - } - } - } - Self { ordering } } -} - -fn connected_components(workspace: &Workspace) -> Vec<Workspace> { - let mut components = Vec::new(); - let mut visited = FxHashSet::default(); - for root_document in workspace.documents_by_uri.values() { - if !visited.insert(Arc::clone(&root_document.uri)) { - continue; - } - - let slice = workspace.slice(&root_document.uri); - for uri in slice.documents_by_uri.keys() { - visited.insert(Arc::clone(uri)); - } - components.push(slice); - } - components -} -fn build_dependency_graph(workspace: &Workspace) -> (Graph<usize, (), Directed>, Vec<&Document>) { - let mut graph = Graph::new(); - let documents: Vec<_> = workspace.documents_by_uri.values().collect(); - let nodes: Vec<_> = (0..documents.len()).map(|i| graph.add_node(i)).collect(); - - for (i, document) in documents.iter().enumerate() { - if let Some(data) = document.data.as_latex() { - for link in &data.extras.explicit_links { - for target in &link.targets { - if let Some(j) = documents - .iter() - .position(|document| document.uri.as_ref() == target.as_ref()) - { - graph.add_edge(nodes[j], nodes[i], ()); - break; - } - } - } - } + pub fn get(&self, db: &dyn Db, uri: &Url) -> usize { + self.ordering + .iter() + .position(|doc| doc.location(db).uri(db) == uri) + .unwrap_or(std::usize::MAX) } - - (graph, documents) } #[cfg(test)] mod tests { - use std::sync::Arc; - - use anyhow::Result; - - use crate::DocumentLanguage; + use crate::{ + db::{Language, Owner}, + Database, + }; use super::*; #[test] - fn test_no_cycles() -> Result<()> { - let mut workspace = Workspace::default(); + fn test_no_cycles() { + let mut db = Database::default(); + let workspace = Workspace::get(&db); let a = workspace.open( - Arc::new(Url::parse("http://example.com/a.tex")?), - Arc::new(String::new()), - DocumentLanguage::Latex, - )?; + &mut db, + Url::parse("http://example.com/a.tex").unwrap(), + String::new(), + Language::Tex, + Owner::Client, + ); let b = workspace.open( - Arc::new(Url::parse("http://example.com/b.tex")?), - Arc::new(String::new()), - DocumentLanguage::Latex, - )?; + &mut db, + Url::parse("http://example.com/b.tex").unwrap(), + String::new(), + Language::Tex, + Owner::Client, + ); let c = workspace.open( - Arc::new(Url::parse("http://example.com/c.tex")?), - Arc::new(r#"\include{b}\include{a}"#.to_string()), - DocumentLanguage::Latex, - )?; - - let ordering = ProjectOrdering::from(&workspace); - - assert_eq!(ordering.get(&a.uri), 2); - assert_eq!(ordering.get(&b.uri), 1); - assert_eq!(ordering.get(&c.uri), 0); - Ok(()) + &mut db, + Url::parse("http://example.com/c.tex").unwrap(), + r#"\documentclass{article}\include{b}\include{a}"#.to_string(), + Language::Tex, + Owner::Client, + ); + + let ordering = ProjectOrdering::new(&db); + + assert_eq!(ordering.get(&db, a.location(&db).uri(&db)), 0); + assert_eq!(ordering.get(&db, b.location(&db).uri(&db)), 1); + assert_eq!(ordering.get(&db, c.location(&db).uri(&db)), 2); } #[test] - fn test_cycles() -> Result<()> { - let mut workspace = Workspace::default(); + fn test_two_layers() { + let mut db = Database::default(); + let workspace = Workspace::get(&db); let a = workspace.open( - Arc::new(Url::parse("http://example.com/a.tex")?), - Arc::new(r#"\include{b}"#.to_string()), - DocumentLanguage::Latex, - )?; + &mut db, + Url::parse("http://example.com/a.tex").unwrap(), + String::new(), + Language::Tex, + Owner::Client, + ); let b = workspace.open( - Arc::new(Url::parse("http://example.com/b.tex")?), - Arc::new(r#"\include{a}"#.to_string()), - DocumentLanguage::Latex, - )?; + &mut db, + Url::parse("http://example.com/b.tex").unwrap(), + r#"\include{a}"#.to_string(), + Language::Tex, + Owner::Client, + ); let c = workspace.open( - Arc::new(Url::parse("http://example.com/c.tex")?), - Arc::new(r#"\include{a}"#.to_string()), - DocumentLanguage::Latex, - )?; + &mut db, + Url::parse("http://example.com/c.tex").unwrap(), + r#"\documentclass{article}\include{b}"#.to_string(), + Language::Tex, + Owner::Client, + ); + + let ordering = ProjectOrdering::new(&db); + + assert_eq!(ordering.get(&db, a.location(&db).uri(&db)), 0); + assert_eq!(ordering.get(&db, b.location(&db).uri(&db)), 1); + assert_eq!(ordering.get(&db, c.location(&db).uri(&db)), 2); + } - let ordering = ProjectOrdering::from(&workspace); + #[test] + fn test_cycles() { + let mut db = Database::default(); + let workspace = Workspace::get(&db); - assert_eq!(ordering.get(&a.uri), 1); - assert_eq!(ordering.get(&b.uri), 2); - assert_eq!(ordering.get(&c.uri), 0); - Ok(()) + let a = workspace.open( + &mut db, + Url::parse("http://example.com/a.tex").unwrap(), + r#"\documentclass{article}\include{b}"#.to_string(), + Language::Tex, + Owner::Client, + ); + + workspace.open( + &mut db, + Url::parse("http://example.com/b.tex").unwrap(), + r#"\include{a}"#.to_string(), + Language::Tex, + Owner::Client, + ); + + workspace.open( + &mut db, + Url::parse("http://example.com/c.tex").unwrap(), + r#"\include{a}"#.to_string(), + Language::Tex, + Owner::Client, + ); + + let ordering = ProjectOrdering::new(&db); + assert_ne!(ordering.get(&db, a.location(&db).uri(&db)), 0); } #[test] - fn test_multiple_roots() -> Result<()> { - let mut workspace = Workspace::default(); + fn test_multiple_roots() { + let mut db = Database::default(); + let workspace = Workspace::get(&db); let a = workspace.open( - Arc::new(Url::parse("http://example.com/a.tex")?), - Arc::new(r#"\include{b}"#.to_string()), - DocumentLanguage::Latex, - )?; + &mut db, + Url::parse("http://example.com/a.tex").unwrap(), + r#"\documentclass{article}\include{b}"#.to_string(), + Language::Tex, + Owner::Client, + ); let b = workspace.open( - Arc::new(Url::parse("http://example.com/b.tex")?), - Arc::new(r#""#.to_string()), - DocumentLanguage::Latex, - )?; + &mut db, + Url::parse("http://example.com/b.tex").unwrap(), + String::new(), + Language::Tex, + Owner::Client, + ); let c = workspace.open( - Arc::new(Url::parse("http://example.com/c.tex")?), - Arc::new(r#""#.to_string()), - DocumentLanguage::Latex, - )?; + &mut db, + Url::parse("http://example.com/c.tex").unwrap(), + String::new(), + Language::Tex, + Owner::Client, + ); let d = workspace.open( - Arc::new(Url::parse("http://example.com/d.tex")?), - Arc::new(r#"\include{c}"#.to_string()), - DocumentLanguage::Latex, - )?; - - let ordering = ProjectOrdering::from(&workspace); - - assert!(ordering.get(&a.uri) < ordering.get(&b.uri)); - assert!(ordering.get(&d.uri) < ordering.get(&c.uri)); - Ok(()) + &mut db, + Url::parse("http://example.com/d.tex").unwrap(), + r#"\documentclass{article}\include{c}"#.to_string(), + Language::Tex, + Owner::Client, + ); + + let ordering = ProjectOrdering::new(&db); + assert!( + ordering.get(&db, b.location(&db).uri(&db)) + < ordering.get(&db, a.location(&db).uri(&db)) + ); + assert!( + ordering.get(&db, c.location(&db).uri(&db)) + < ordering.get(&db, d.location(&db).uri(&db)) + ); } } diff --git a/support/texlab/src/features/symbol/types.rs b/support/texlab/src/features/symbol/types.rs index 88e7ffcb86..be0ffeceda 100644 --- a/support/texlab/src/features/symbol/types.rs +++ b/support/texlab/src/features/symbol/types.rs @@ -1,6 +1,10 @@ use lsp_types::{DocumentSymbol, Location, Range, SymbolInformation, SymbolKind, Url}; -use crate::{features::lsp_kinds::Structure, BibtexEntryTypeCategory}; +use crate::{ + db::Word, + util::{lang_data::BibtexEntryTypeCategory, lsp_enums::Structure}, + Db, +}; #[derive(Debug, PartialEq, Eq, Clone, Copy)] pub enum InternalSymbolKind { @@ -39,7 +43,7 @@ impl InternalSymbolKind { #[derive(Debug, PartialEq, Eq, Clone)] pub struct InternalSymbol { pub name: String, - pub label: Option<String>, + pub label: Option<Word>, pub kind: InternalSymbolKind, pub deprecated: bool, pub full_range: Range, @@ -76,16 +80,17 @@ impl InternalSymbol { buffer.push(self); } - pub fn into_document_symbol(self) -> DocumentSymbol { + pub fn into_document_symbol(self, db: &dyn Db) -> DocumentSymbol { let children = self .children .into_iter() - .map(|child| child.into_document_symbol()) + .map(|child| child.into_document_symbol(db)) .collect(); + #[allow(deprecated)] DocumentSymbol { name: self.name, - detail: self.label, + detail: self.label.map(|word| word.text(db).clone()), kind: self.kind.into_symbol_kind(), deprecated: Some(self.deprecated), range: self.full_range, diff --git a/support/texlab/src/features/workspace_command.rs b/support/texlab/src/features/workspace_command.rs new file mode 100644 index 0000000000..8d6732cd1c --- /dev/null +++ b/support/texlab/src/features/workspace_command.rs @@ -0,0 +1,103 @@ +use std::process::Stdio; + +use anyhow::{bail, Result}; +use lsp_types::{TextDocumentIdentifier, Url}; +use thiserror::Error; + +use crate::{db::Workspace, normalize_uri, Db}; + +pub fn select(db: &dyn Db, name: &str, args: Vec<serde_json::Value>) -> Result<CleanCommand> { + Ok(match name { + "texlab.cleanAuxiliary" => CleanCommand::new(db, CleanOptions::Auxiliary, args)?, + "texlab.cleanArtifacts" => CleanCommand::new(db, CleanOptions::Artifacts, args)?, + _ => bail!("Unknown command: {}", name), + }) +} + +#[derive(Debug, Error)] +pub enum CleanError { + #[error("document '{0}' not found")] + DocumentNotFound(Url), + + #[error("document '{0}' is not a local file")] + NoLocalFile(Url), + + #[error("document was not provided as an argument")] + MissingArg, + + #[error("invalid argument: {0}")] + InvalidArg(serde_json::Error), + + #[error("failed to spawn process: {0}")] + Spawn(std::io::Error), +} + +#[derive(Debug)] +pub struct CleanCommand { + executable: String, + args: Vec<String>, +} + +impl CleanCommand { + fn new(db: &dyn Db, options: CleanOptions, args: Vec<serde_json::Value>) -> Result<Self> { + let params: TextDocumentIdentifier = + serde_json::from_value(args.into_iter().next().ok_or(CleanError::MissingArg)?) + .map_err(CleanError::InvalidArg)?; + + let mut uri = params.uri; + normalize_uri(&mut uri); + + let workspace = Workspace::get(db); + + let document = workspace + .lookup_uri(db, &uri) + .ok_or_else(|| CleanError::DocumentNotFound(uri.clone()))?; + + let working_dir = workspace.working_dir(db, document.directory(db)); + + let output_dir = workspace + .output_dir(db, working_dir) + .path(db) + .as_deref() + .ok_or_else(|| CleanError::NoLocalFile(uri.clone()))?; + + let path = document + .location(db) + .path(db) + .as_deref() + .ok_or_else(|| CleanError::NoLocalFile(uri.clone()))?; + + let flag = match options { + CleanOptions::Auxiliary => "-c", + CleanOptions::Artifacts => "-C", + }; + + let executable = "latexmk".to_string(); + let args = vec![ + format!("-outdir={}", output_dir.display()), + flag.to_string(), + path.display().to_string(), + ]; + + Ok(Self { executable, args }) + } + + pub fn run(self) -> Result<(), CleanError> { + log::debug!("Cleaning output files: {} {:?}", self.executable, self.args); + std::process::Command::new(self.executable) + .args(self.args) + .stdin(Stdio::null()) + .stdout(Stdio::null()) + .stderr(Stdio::null()) + .status() + .map_err(CleanError::Spawn)?; + + Ok(()) + } +} + +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash)] +enum CleanOptions { + Auxiliary, + Artifacts, +} diff --git a/support/texlab/src/language.rs b/support/texlab/src/language.rs deleted file mode 100644 index 45ef22daba..0000000000 --- a/support/texlab/src/language.rs +++ /dev/null @@ -1,33 +0,0 @@ -use std::{ffi::OsStr, path::Path}; - -#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, PartialOrd, Ord)] -pub enum DocumentLanguage { - Latex, - Bibtex, - BuildLog, -} - -impl DocumentLanguage { - pub fn by_path(path: &Path) -> Option<Self> { - path.extension() - .and_then(OsStr::to_str) - .and_then(Self::by_extension) - } - - pub fn by_extension(extension: &str) -> Option<Self> { - match extension.to_lowercase().as_str() { - "tex" | "sty" | "cls" | "def" | "lco" | "aux" | "rnw" => Some(Self::Latex), - "bib" | "bibtex" => Some(Self::Bibtex), - "log" => Some(Self::BuildLog), - _ => None, - } - } - - pub fn by_language_id(language_id: &str) -> Option<Self> { - match language_id { - "latex" | "tex" => Some(Self::Latex), - "bibtex" | "bib" => Some(Self::Bibtex), - _ => None, - } - } -} diff --git a/support/texlab/src/lib.rs b/support/texlab/src/lib.rs index 1f3d22d7aa..9a7b587ab8 100644 --- a/support/texlab/src/lib.rs +++ b/support/texlab/src/lib.rs @@ -1,37 +1,120 @@ -mod capabilities; -pub mod citation; +#![allow(clippy::needless_lifetimes)] + +pub(crate) mod citation; mod client; -pub mod component_db; -mod debouncer; -mod diagnostics; -mod dispatch; -pub mod distro; -mod document; -mod environment; +pub mod db; +pub(crate) mod distro; pub mod features; -mod label; -mod lang_data; -mod language; -mod line_index; -mod line_index_ext; mod options; -mod range; -mod req_queue; +pub mod parser; mod server; pub mod syntax; -mod workspace; - -pub use self::{ - capabilities::ClientCapabilitiesExt, - document::*, - environment::Environment, - label::*, - lang_data::*, - language::DocumentLanguage, - line_index::{LineCol, LineColUtf16, LineIndex}, - line_index_ext::LineIndexExt, - options::*, - range::RangeExt, - server::Server, - workspace::{Workspace, WorkspaceEvent}, -}; +pub(crate) mod util; + +pub use self::{options::*, server::Server}; + +#[salsa::jar(db = Db)] +pub struct Jar( + db::Word, + db::Location, + db::Location_path, + db::Contents, + db::Contents_line_index, + db::LinterData, + db::Document, + db::Document_parse, + db::Document_can_be_index, + db::Document_can_be_built, + db::parse::TexDocumentData, + db::parse::TexDocumentData_analyze, + db::parse::BibDocumentData, + db::parse::LogDocumentData, + db::analysis::TexLink, + db::analysis::label::Number, + db::analysis::label::Name, + db::analysis::TheoremEnvironment, + db::analysis::GraphicsPath, + db::analysis::TexAnalysis, + db::MissingDependencies, + db::hidden_dependency, + db::source_dependency, + db::dependency_graph, + db::Workspace, + db::Workspace_working_dir, + db::Workspace_output_dir, + db::Workspace_parents, + db::Workspace_related, + db::Workspace_number_of_label, + db::diagnostics::tex::collect, + db::diagnostics::bib::collect, + db::diagnostics::log::collect, + db::diagnostics::collect, + db::diagnostics::collect_filtered, +); + +pub trait Db: salsa::DbWithJar<Jar> {} + +impl<DB> Db for DB where DB: ?Sized + salsa::DbWithJar<Jar> {} + +#[salsa::db(crate::Jar)] +pub struct Database { + storage: salsa::Storage<Self>, +} + +impl Default for Database { + fn default() -> Self { + let storage = salsa::Storage::default(); + let db = Self { storage }; + db::Workspace::new( + &db, + Default::default(), + Default::default(), + Default::default(), + Default::default(), + Default::default(), + Default::default(), + ); + + db + } +} + +impl salsa::Database for Database {} + +impl salsa::ParallelDatabase for Database { + fn snapshot(&self) -> salsa::Snapshot<Self> { + salsa::Snapshot::new(Self { + storage: self.storage.snapshot(), + }) + } +} + +pub(crate) fn normalize_uri(uri: &mut lsp_types::Url) { + fn fix_drive_letter(text: &str) -> Option<String> { + if !text.is_ascii() { + return None; + } + + match &text[1..] { + ":" => Some(text.to_ascii_uppercase()), + "%3A" | "%3a" => Some(format!("{}:", text[0..1].to_ascii_uppercase())), + _ => None, + } + } + + if let Some(mut segments) = uri.path_segments() { + if let Some(mut path) = segments.next().and_then(fix_drive_letter) { + for segment in segments { + path.push('/'); + path.push_str(segment); + } + + uri.set_path(&path); + } + } + + uri.set_fragment(None); +} + +#[cfg(test)] +mod tests; diff --git a/support/texlab/src/main.rs b/support/texlab/src/main.rs index 06cbba3f5d..ed807f8799 100644 --- a/support/texlab/src/main.rs +++ b/support/texlab/src/main.rs @@ -1,4 +1,4 @@ -use std::{env, fs::OpenOptions, io, path::PathBuf}; +use std::{fs::OpenOptions, io, path::PathBuf}; use anyhow::Result; use clap::{ArgAction, Parser}; @@ -21,10 +21,6 @@ struct Opts { /// Write the logging output to FILE #[clap(long, name = "FILE", value_parser)] log_file: Option<PathBuf>, - - /// Print version information and exit - #[clap(short = 'V', long)] - version: bool, } fn main() -> Result<()> { @@ -32,7 +28,7 @@ fn main() -> Result<()> { setup_logger(opts); let (connection, threads) = Connection::stdio(); - Server::with_connection(connection, env::current_dir()?, true).run()?; + Server::new(connection).run()?; threads.join()?; Ok(()) diff --git a/support/texlab/src/options.rs b/support/texlab/src/options.rs index 241126d908..cc0058fc68 100644 --- a/support/texlab/src/options.rs +++ b/support/texlab/src/options.rs @@ -1,47 +1,32 @@ -use std::path::PathBuf; +use std::{path::PathBuf, time::Duration}; use regex::Regex; use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] +#[serde(default)] pub struct Options { - #[serde(default)] pub root_directory: Option<PathBuf>, - - #[serde(default)] pub aux_directory: Option<PathBuf>, - - #[serde(default)] pub bibtex_formatter: BibtexFormatter, - - #[serde(default)] pub latex_formatter: LatexFormatter, - - #[serde(default)] pub formatter_line_length: Option<i32>, - - #[serde(default)] pub diagnostics: DiagnosticsOptions, - - #[serde(default = "default_diagnostics_delay")] - pub diagnostics_delay: u64, - - #[serde(default)] + pub diagnostics_delay: DiagnosticsDelay, pub build: BuildOptions, - - #[serde(default)] pub chktex: ChktexOptions, - - #[serde(default)] pub latexindent: LatexindentOptions, - - #[serde(default)] pub forward_search: ForwardSearchOptions, } -fn default_diagnostics_delay() -> u64 { - 300 +#[derive(Debug, PartialEq, Eq, Clone, Copy, Serialize, Deserialize)] +pub struct DiagnosticsDelay(#[serde(with = "serde_millis")] pub Duration); + +impl Default for DiagnosticsDelay { + fn default() -> Self { + Self(Duration::from_millis(300)) + } } #[derive(Debug, PartialEq, Eq, Clone, Copy, Serialize, Deserialize)] @@ -72,75 +57,77 @@ impl Default for LatexFormatter { #[derive(Debug, PartialEq, Eq, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] +#[serde(default)] pub struct LatexindentOptions { - #[serde(default)] pub local: Option<String>, - - #[serde(default)] pub modify_line_breaks: bool, } #[derive(Debug, PartialEq, Eq, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] +#[serde(default)] pub struct BuildOptions { - #[serde(default = "default_build_executable")] - pub executable: String, - - #[serde(default = "default_build_args")] - pub args: Vec<String>, - - #[serde(default)] - pub is_continuous: bool, - - #[serde(default)] + pub executable: BuildExecutable, + pub args: BuildArgs, pub on_save: bool, - - #[serde(default)] pub forward_search_after: bool, } -fn default_build_executable() -> String { - "latexmk".to_string() +#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)] +#[serde(transparent)] +pub struct BuildExecutable(pub String); + +impl Default for BuildExecutable { + fn default() -> Self { + Self("latexmk".to_string()) + } } -fn default_build_args() -> Vec<String> { - vec![ - "-pdf".to_string(), - "-interaction=nonstopmode".to_string(), - "-synctex=1".to_string(), - "%f".to_string(), - ] +#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)] +#[serde(transparent)] +pub struct BuildArgs(pub Vec<String>); + +impl Default for BuildArgs { + fn default() -> Self { + Self(vec![ + "-pdf".to_string(), + "-interaction=nonstopmode".to_string(), + "-synctex=1".to_string(), + "%f".to_string(), + ]) + } } #[derive(Debug, PartialEq, Eq, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] +#[serde(default)] pub struct ChktexOptions { - #[serde(default)] pub on_open_and_save: bool, - - #[serde(default)] pub on_edit: bool, } #[derive(Debug, PartialEq, Eq, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] +#[serde(default)] pub struct ForwardSearchOptions { - #[serde(default)] pub executable: Option<String>, - - #[serde(default)] pub args: Option<Vec<String>>, } #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] +#[serde(default)] pub struct DiagnosticsOptions { - #[serde(default)] pub allowed_patterns: Vec<DiagnosticsPattern>, - - #[serde(default)] pub ignored_patterns: Vec<DiagnosticsPattern>, } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct DiagnosticsPattern(#[serde(with = "serde_regex")] pub Regex); + +#[derive(Debug, PartialEq, Eq, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +#[serde(default)] +pub struct StartupOptions { + pub skip_distro: bool, +} diff --git a/support/texlab/src/parser.rs b/support/texlab/src/parser.rs new file mode 100644 index 0000000000..51d56475cf --- /dev/null +++ b/support/texlab/src/parser.rs @@ -0,0 +1,5 @@ +mod bibtex; +mod build_log; +mod latex; + +pub use self::{bibtex::parse_bibtex, build_log::parse_build_log, latex::parse_latex}; diff --git a/support/texlab/src/syntax/bibtex/parser.rs b/support/texlab/src/parser/bibtex.rs index 4a8a429b18..e03a39c9ae 100644 --- a/support/texlab/src/syntax/bibtex/parser.rs +++ b/support/texlab/src/parser/bibtex.rs @@ -1,12 +1,9 @@ -use logos::{Lexer, Logos}; +use logos::Logos; use rowan::{GreenNode, GreenNodeBuilder}; -use super::{ - lexer::*, - SyntaxKind::{self, *}, -}; +use crate::syntax::bibtex::SyntaxKind::{self, *}; -pub fn parse(input: &str) -> GreenNode { +pub fn parse_bibtex(input: &str) -> GreenNode { let mut ptr = TokenPtr { builder: GreenNodeBuilder::new(), lexer: RootToken::lexer(input), @@ -136,9 +133,9 @@ fn curly_group(mut ptr: TokenPtr<ContentToken>) -> TokenPtr<ContentToken> { | ContentToken::Nbsp | ContentToken::Comma | ContentToken::Integer + | ContentToken::Quote | ContentToken::Word => ptr.bump(), ContentToken::LCurly => ptr = curly_group(ptr), - ContentToken::Quote => ptr = quote_group(ptr), ContentToken::AccentName => ptr = accent(ptr), ContentToken::CommandName => ptr = command(ptr), }; @@ -205,7 +202,7 @@ fn command(mut ptr: TokenPtr<ContentToken>) -> TokenPtr<ContentToken> { struct TokenPtr<'a, T: Logos<'a>> { builder: GreenNodeBuilder<'static>, - lexer: Lexer<'a, T>, + lexer: logos::Lexer<'a, T>, token: Option<(T, &'a str)>, } @@ -262,3 +259,196 @@ where self.token } } + +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash, Logos)] +enum RootToken { + #[token(r"@preamble", ignore(ascii_case))] + Preamble, + + #[token(r"@string", ignore(ascii_case))] + String, + + #[token(r"@comment", ignore(ascii_case))] + Comment, + + #[regex(r"@[a-zA-Z]*")] + Entry, + + #[regex(r"[^@]+")] + #[error] + Junk, +} + +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash, Logos)] +enum BodyToken { + #[regex(r"\s+")] + Whitespace, + + #[token("{")] + #[token("(")] + LDelim, + + #[token("}")] + #[token(")")] + RDelim, + + #[token(",")] + Comma, + + #[token("=")] + Eq, + + #[regex(r"[^\s\(\)\{\}@,=]+")] + Name, + + #[error] + Error, +} + +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash, Logos)] +enum ValueToken { + #[regex(r"\s+")] + Whitespace, + + #[token("#")] + Pound, + + #[token(",")] + Comma, + + #[token("{")] + LCurly, + + #[token("}")] + RCurly, + + #[token("\"")] + Quote, + + #[regex(r"\d+", priority = 2)] + Integer, + + #[regex(r#"[^\s"\{\},]+"#)] + #[error] + Name, +} + +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash, Logos)] +enum ContentToken { + #[regex(r"\s+")] + Whitespace, + + #[token(",")] + Comma, + + #[token("{")] + LCurly, + + #[token("}")] + RCurly, + + #[token("\"")] + Quote, + + #[regex(r"\d+", priority = 2)] + Integer, + + #[token(r#"~"#)] + Nbsp, + + #[token(r#"\`"#)] + #[token(r#"\'"#)] + #[token(r#"\^"#)] + #[token(r#"\""#)] + #[token(r#"\H"#)] + #[token(r#"\~"#)] + #[token(r#"\c"#)] + #[token(r#"\k"#)] + #[token(r#"\="#)] + #[token(r#"\b"#)] + #[token(r#"\."#)] + #[token(r#"\d"#)] + #[token(r#"\r"#)] + #[token(r#"\u"#)] + #[token(r#"\v"#)] + #[token(r#"\t"#)] + AccentName, + + #[regex(r"\\([^\r\n]|[@a-zA-Z:_]+\*?)?")] + CommandName, + + #[regex(r#"[^\s"\{\}\\~,]+"#)] + #[error] + Word, +} + +impl From<RootToken> for SyntaxKind { + fn from(token: RootToken) -> Self { + match token { + RootToken::Preamble | RootToken::String | RootToken::Comment | RootToken::Entry => TYPE, + RootToken::Junk => JUNK, + } + } +} + +impl From<BodyToken> for SyntaxKind { + fn from(token: BodyToken) -> Self { + match token { + BodyToken::Whitespace => WHITESPACE, + BodyToken::LDelim => L_DELIM, + BodyToken::RDelim => R_DELIM, + BodyToken::Comma => COMMA, + BodyToken::Eq => EQ, + BodyToken::Name => NAME, + BodyToken::Error => unreachable!(), + } + } +} + +impl From<ValueToken> for SyntaxKind { + fn from(token: ValueToken) -> Self { + match token { + ValueToken::Whitespace => WHITESPACE, + ValueToken::Pound => POUND, + ValueToken::Comma => COMMA, + ValueToken::LCurly => L_CURLY, + ValueToken::RCurly => R_CURLY, + ValueToken::Quote => QUOTE, + ValueToken::Integer => INTEGER, + ValueToken::Name => NAME, + } + } +} + +impl From<ContentToken> for SyntaxKind { + fn from(token: ContentToken) -> Self { + match token { + ContentToken::Whitespace => WHITESPACE, + ContentToken::Comma => COMMA, + ContentToken::LCurly => L_CURLY, + ContentToken::RCurly => R_CURLY, + ContentToken::Quote => QUOTE, + ContentToken::Integer => INTEGER, + ContentToken::Nbsp => NBSP, + ContentToken::AccentName => ACCENT_NAME, + ContentToken::CommandName => COMMAND_NAME, + ContentToken::Word => WORD, + } + } +} + +#[cfg(test)] +mod tests { + use crate::syntax::bibtex; + + use super::parse_bibtex; + + #[test] + fn test_parse() { + insta::glob!("test_data/bibtex/{,**/}*.txt", |path| { + let text = std::fs::read_to_string(path).unwrap().replace("\r\n", "\n"); + let root = bibtex::SyntaxNode::new_root(parse_bibtex(&text)); + insta::assert_debug_snapshot!(root); + }); + } +} diff --git a/support/texlab/src/parser/build_log.rs b/support/texlab/src/parser/build_log.rs new file mode 100644 index 0000000000..5f99129cdb --- /dev/null +++ b/support/texlab/src/parser/build_log.rs @@ -0,0 +1,184 @@ +use std::{cmp::Ordering, path::PathBuf}; + +use once_cell::sync::Lazy; +use regex::{Match, Regex}; + +use crate::syntax::{BuildError, BuildErrorLevel, BuildLog}; + +const MAX_LINE_LENGTH: usize = 79; + +static PACKAGE_MESSAGE_REGEX: Lazy<Regex> = + Lazy::new(|| Regex::new("^\\([a-zA-Z_\\-]+\\)\\s*(?P<msg>.*)$").unwrap()); + +static FILE_REGEX: Lazy<Regex> = + Lazy::new(|| Regex::new("\\((?P<file>[^\r\n()]+\\.(tex|sty|cls))").unwrap()); + +static TEX_ERROR_REGEX: Lazy<Regex> = Lazy::new(|| { + Regex::new("(?m)^! ((?P<msg1>(.|\r|\n)*?)\r?\nl\\.(?P<line>\\d+)( (\\.\\.\\.)?(?P<hint>[^\r\n]+))?|(?P<msg2>[^\r\n]*))").unwrap() +}); + +static WARNING_REGEX: Lazy<Regex> = + Lazy::new(|| Regex::new("(LaTeX|Package [a-zA-Z_\\-]+) Warning: (?P<msg>[^\r\n]*)").unwrap()); + +static BAD_BOX_REGEX: Lazy<Regex> = Lazy::new(|| { + Regex::new("(?P<msg>(Ov|Und)erfull \\\\[hv]box[^\r\n]*lines? (?P<line>\\d+)[^\r\n]*)").unwrap() +}); + +pub fn parse_build_log(log: &str) -> BuildLog { + let log = prepare_log(log); + let mut ranges: Vec<FileRange> = FILE_REGEX + .find_iter(&log) + .map(|result| FileRange::create(&log, result)) + .collect(); + ranges.sort(); + + let tex_errors = extract_matches(&log, &ranges, &TEX_ERROR_REGEX, BuildErrorLevel::Error); + let warnings = extract_matches(&log, &ranges, &WARNING_REGEX, BuildErrorLevel::Warning); + let bad_boxes = extract_matches(&log, &ranges, &BAD_BOX_REGEX, BuildErrorLevel::Warning); + + let errors = vec![tex_errors, warnings, bad_boxes].concat(); + BuildLog { errors } +} + +fn extract_matches( + log: &str, + ranges: &[FileRange], + regex: &Regex, + level: BuildErrorLevel, +) -> Vec<BuildError> { + let mut errors = Vec::new(); + for result in regex.find_iter(log) { + let captures = regex.captures(&log[result.start()..result.end()]).unwrap(); + let message = captures + .name("msg") + .or_else(|| captures.name("msg1")) + .or_else(|| captures.name("msg2")) + .unwrap() + .as_str() + .lines() + .next() + .unwrap_or_default() + .to_owned(); + + if let Some(range) = ranges.iter().find(|range| range.contains(result.start())) { + let line = captures + .name("line") + .map(|result| result.as_str().parse::<u32>().unwrap() - 1); + + let hint: Option<String> = if line.is_some() { + captures + .name("hint") + .map(|r| String::from(r.as_str().trim())) + } else { + None + }; + + errors.push(BuildError { + relative_path: range.path.clone(), + level, + message, + line, + hint, + }); + } + } + errors +} + +fn prepare_log(log: &str) -> String { + let mut old_lines = log.lines(); + let mut new_lines: Vec<String> = Vec::new(); + while let Some(line) = old_lines.next() { + if PACKAGE_MESSAGE_REGEX.is_match(line) { + let captures = PACKAGE_MESSAGE_REGEX.captures(line).unwrap(); + if let Some(last_line) = new_lines.last_mut() { + last_line.push(' '); + last_line.push_str(captures.name("msg").unwrap().as_str()); + } + } else if line.ends_with("...") { + let mut new_line = line[line.len() - 3..].to_owned(); + if let Some(old_line) = old_lines.next() { + new_line.push_str(old_line); + } + new_lines.push(new_line); + } else if line.chars().count() == MAX_LINE_LENGTH { + let mut new_line = String::new(); + new_line.push_str(line); + if let Some(old_line) = old_lines.next() { + new_line.push_str(old_line); + } + new_lines.push(new_line); + } else { + new_lines.push(line.to_owned()); + } + } + new_lines.join("\n") +} + +#[derive(Debug, PartialEq, Eq, Clone)] +struct FileRange { + pub path: PathBuf, + pub start: usize, + pub end: usize, +} + +impl FileRange { + fn create(log: &str, result: Match) -> Self { + let mut balance = 1; + let mut end = result.start() + 1; + let chars = log[result.start() + 1..].chars(); + for c in chars { + if balance <= 0 { + break; + } + + if c == '(' { + balance += 1; + } else if c == ')' { + balance -= 1; + } + end += c.len_utf8(); + } + + let captures = FILE_REGEX.captures(result.as_str()).unwrap(); + let path = PathBuf::from(captures.name("file").unwrap().as_str()); + Self { + path, + start: result.start(), + end, + } + } + + fn len(&self) -> usize { + self.end - self.start + 1 + } + + fn contains(&self, index: usize) -> bool { + index >= self.start && index <= self.end + } +} + +impl Ord for FileRange { + fn cmp(&self, other: &Self) -> Ordering { + self.len().cmp(&other.len()) + } +} + +impl PartialOrd for FileRange { + fn partial_cmp(&self, other: &Self) -> Option<Ordering> { + Some(self.cmp(other)) + } +} + +#[cfg(test)] +mod tests { + use super::parse_build_log; + + #[test] + fn test_parse() { + insta::glob!("test_data/build_log/*.txt", |path| { + let text = std::fs::read_to_string(path).unwrap().replace("\r\n", "\n"); + insta::assert_debug_snapshot!(parse_build_log(&text)); + }); + } +} diff --git a/support/texlab/src/syntax/latex/parser.rs b/support/texlab/src/parser/latex.rs index a43a77ebc9..a103561685 100644 --- a/support/texlab/src/syntax/latex/parser.rs +++ b/support/texlab/src/parser/latex.rs @@ -1,14 +1,10 @@ +mod lexer; + use rowan::{GreenNode, GreenNodeBuilder}; -use super::{ - lexer::Lexer, - SyntaxKind::{self, *}, -}; +use crate::syntax::latex::SyntaxKind::{self, *}; -#[derive(Clone)] -pub struct Parse { - pub green: GreenNode, -} +use self::lexer::Lexer; #[derive(Debug, Clone, Copy)] struct ParserContext { @@ -80,15 +76,14 @@ impl<'a> Parser<'a> { } } - pub fn parse(mut self) -> Parse { + pub fn parse(mut self) -> GreenNode { self.builder.start_node(ROOT.into()); self.preamble(); while self.peek().is_some() { self.content(ParserContext::default()); } self.builder.finish_node(); - let green = self.builder.finish(); - Parse { green } + self.builder.finish() } fn content(&mut self, context: ParserContext) { @@ -177,7 +172,7 @@ impl<'a> Parser<'a> { self.eat(); while self .peek() - .filter(|&kind| !matches!(kind, R_CURLY | END_ENVIRONMENT_NAME)) + .filter(|&kind| !matches!(kind, R_CURLY)) .is_some() { self.content(ParserContext::default()); @@ -518,7 +513,7 @@ impl<'a> Parser<'a> { while self .peek() - .filter(|&kind| kind != END_ENVIRONMENT_NAME) + .filter(|&kind| !matches!(kind, R_CURLY | END_ENVIRONMENT_NAME)) .is_some() { self.content(ParserContext::default()); @@ -854,11 +849,16 @@ impl<'a> Parser<'a> { fn curly_group_path(&mut self) { self.builder.start_node(CURLY_GROUP_WORD.into()); self.eat(); - while matches!( - self.peek(), - Some(WORD | L_BRACK | R_BRACK | GENERIC_COMMAND_NAME) - ) { - self.path(); + self.trivia(); + + while let Some(kind) = self.lexer.peek() { + match kind { + COMMENT | WORD | EQUALITY_SIGN | COMMA | L_BRACK | R_BRACK + | GENERIC_COMMAND_NAME => self.path(), + L_CURLY => self.curly_group_path(), + WHITESPACE => self.eat(), + _ => break, + }; } self.expect(R_CURLY); @@ -868,29 +868,17 @@ impl<'a> Parser<'a> { fn curly_group_path_list(&mut self) { self.builder.start_node(CURLY_GROUP_WORD_LIST.into()); self.eat(); + self.trivia(); - while self.peek().map_or(false, |kind| { - matches!( - kind, - LINE_BREAK - | WHITESPACE - | COMMENT - | WORD - | COMMA - | EQUALITY_SIGN - | L_BRACK - | R_BRACK - | GENERIC_COMMAND_NAME - ) - }) { - if matches!( - self.peek(), - Some(WORD | L_BRACK | R_BRACK | GENERIC_COMMAND_NAME) - ) { - self.path(); - } else { - self.eat(); - } + while let Some(kind) = self.peek() { + match kind { + COMMENT | WORD | EQUALITY_SIGN | L_BRACK | R_BRACK | GENERIC_COMMAND_NAME => { + self.path() + } + WHITESPACE | LINE_BREAK | COMMA => self.eat(), + L_CURLY => self.curly_group_path(), + _ => break, + }; } self.expect(R_CURLY); @@ -900,22 +888,16 @@ impl<'a> Parser<'a> { fn path(&mut self) { self.builder.start_node(KEY.into()); self.eat(); - while self.peek().map_or(false, |kind| { - matches!( - kind, - WHITESPACE - | COMMENT - | WORD - | EQUALITY_SIGN - | L_BRACK - | R_BRACK - | GENERIC_COMMAND_NAME - ) - }) { - self.eat(); + + while let Some(kind) = self.peek() { + match kind { + WHITESPACE | COMMENT | WORD | EQUALITY_SIGN | L_BRACK | R_BRACK + | GENERIC_COMMAND_NAME => self.eat(), + L_CURLY => self.curly_group_path(), + _ => break, + }; } - self.trivia(); self.builder.finish_node(); } @@ -1126,15 +1108,15 @@ impl<'a> Parser<'a> { if self.lexer.peek() == Some(L_CURLY) { self.curly_group_word(); - } else { - self.builder.token(MISSING.into(), ""); + } + + if self.lexer.peek() == Some(L_BRACK) { + self.brack_group(); } for _ in 0..2 { if self.lexer.peek() == Some(L_CURLY) { self.curly_group(); - } else { - self.builder.token(MISSING.into(), ""); } } @@ -1321,603 +1303,49 @@ impl<'a> Parser<'a> { self.eat(); self.trivia(); + let checkpoint = self.builder.checkpoint(); if self.lexer.peek() == Some(L_CURLY) { self.eat(); self.trivia(); - while matches!(self.lexer.peek(), Some(L_CURLY)) { - self.curly_group_path(); + if matches!( + self.lexer.peek(), + Some(WORD | EQUALITY_SIGN | L_BRACK | R_BRACK | GENERIC_COMMAND_NAME) + ) { + self.builder + .start_node_at(checkpoint, CURLY_GROUP_WORD.into()); + self.path(); + } else { + self.builder.start_node_at(checkpoint, CURLY_GROUP.into()); + while matches!(self.lexer.peek(), Some(L_CURLY)) { + self.curly_group_path(); + } } - } else { - self.builder.token(MISSING.into(), ""); + + self.expect(R_CURLY); + self.builder.finish_node(); } - self.expect(R_CURLY); self.builder.finish_node(); } } -pub fn parse(text: &str) -> Parse { +pub fn parse_latex(text: &str) -> GreenNode { Parser::new(text).parse() } #[cfg(test)] mod tests { - use insta::assert_debug_snapshot; - use crate::syntax::latex; - use super::*; - - fn setup(text: &str) -> latex::SyntaxNode { - latex::SyntaxNode::new_root(parse(&text.trim().replace('\r', "")).green) - } - - #[test] - fn test_empty() { - assert_debug_snapshot!(setup(r#""#)); - } - - #[test] - fn test_hello_world() { - assert_debug_snapshot!(setup(r#"Hello World!"#)); - } - - #[test] - fn test_generic_command_empty() { - assert_debug_snapshot!(setup(r#"\foo"#)); - } - - #[test] - fn test_generic_command_escape() { - assert_debug_snapshot!(setup(r#"\#"#)); - } - - #[test] - fn test_generic_command_args() { - assert_debug_snapshot!(setup(r#"\foo{bar}[qux]"#)); - } - - #[test] - fn test_inline() { - assert_debug_snapshot!(setup(r#"$x \in [0, \infty)$"#)); - } - - #[test] - fn test_inline_double_dollar() { - assert_debug_snapshot!(setup(r#"$$x \in [0, \infty)$$"#)); - } - - #[test] - fn test_brace_group_simple() { - assert_debug_snapshot!(setup(r#"{hello world}"#)); - } - - #[test] - fn test_brace_group_missing_end() { - assert_debug_snapshot!(setup(r#"{hello world"#)); - } - - #[test] - fn test_unmatched_braces() { - assert_debug_snapshot!(setup(r#"}{"#)); - } - - #[test] - fn test_unmatched_brackets() { - assert_debug_snapshot!(setup(r#"]["#)); - } - - #[test] - fn test_unmatched_brackets_with_group() { - assert_debug_snapshot!(setup(r#"{][}"#)); - } - - #[test] - fn test_escaped_brackets() { - assert_debug_snapshot!(setup(r#"{[}{]}"#)); - } - - #[test] - fn test_parameter() { - assert_debug_snapshot!(setup(r#"#1"#)); - } - - #[test] - fn test_parameter_error() { - assert_debug_snapshot!(setup(r#"#"#)); - } - - #[test] - fn test_environment_simple() { - assert_debug_snapshot!(setup(r#"\begin{foo} Hello World \end{bar}"#)); - } - - #[test] - fn test_environment_nested() { - assert_debug_snapshot!(setup(r#"\begin{foo} \begin{qux} \end{baz} \end{bar}"#)); - } - - #[test] - fn test_environment_nested_missing_braces() { - assert_debug_snapshot!(setup( - r#"\begin{foo \begin{qux Hello World \end{baz} \end{bar"# - )); - } - - #[test] - fn test_structure_siblings() { - assert_debug_snapshot!(setup(r#"\section{Foo} Foo \section{Bar} Bar"#)); - } - - #[test] - fn test_structure_nested() { - assert_debug_snapshot!(setup( - r#"\part{1}\chapter{2}\section{3}\subsection{4}\subsubsection{5}\paragraph{6}\subparagraph{7}"# - )); - } - - #[test] - fn test_structure_enum_item() { - assert_debug_snapshot!(setup( - r#"\begin{enumerate} \item 1 \item[2] 2 \item 3 \end{enumerate}"# - )); - } - - #[test] - fn test_structure_invalid_nesting() { - assert_debug_snapshot!(setup(r#"\section{Foo} \chapter{Bar}"#)); - } - - #[test] - fn test_equation() { - assert_debug_snapshot!(setup(r#"\[ foo bar \]"#)); - } - - #[test] - fn test_equation_missing_end() { - assert_debug_snapshot!(setup(r#"\begin{a} \[ foo bar \end{b}"#)); - } - - #[test] - fn test_equation_missing_begin() { - assert_debug_snapshot!(setup(r#"\begin{a} foo bar \] \end{b}"#)); - } - - #[test] - fn test_caption_minimal() { - assert_debug_snapshot!(setup(r#"\caption{Foo \Bar Baz}"#)); - } - - #[test] - fn test_caption_minimal_error() { - assert_debug_snapshot!(setup(r#"\caption{Foo \Bar Baz"#)); - } - - #[test] - fn test_caption() { - assert_debug_snapshot!(setup(r#"\caption[qux]{Foo \Bar Baz}"#)); - } - - #[test] - fn test_caption_error() { - assert_debug_snapshot!(setup(r#"\caption[qux]{Foo \Bar Baz"#)); - } - - #[test] - fn test_caption_figure() { - assert_debug_snapshot!(setup(r#"\begin{figure}\caption{Foo}\end{figure}"#)); - } - - #[test] - fn test_citation_empty() { - assert_debug_snapshot!(setup(r#"\cite{}"#)); - } - - #[test] - fn test_citation_simple() { - assert_debug_snapshot!(setup(r#"\cite{foo}"#)); - } - - #[test] - fn test_citation_multiple_keys() { - assert_debug_snapshot!(setup(r#"\cite{foo, bar}"#)); - } - - #[test] - fn test_citation_star() { - assert_debug_snapshot!(setup(r#"\nocite{*}"#)); - } - - #[test] - fn test_citation_prenote() { - assert_debug_snapshot!(setup(r#"\cite[foo]{bar}"#)); - } - - #[test] - fn test_citation_prenote_postnote() { - assert_debug_snapshot!(setup(r#"\cite[foo][bar]{baz}"#)); - } - - #[test] - fn test_citation_missing_brace() { - assert_debug_snapshot!(setup(r#"\cite{foo"#)); - } - - #[test] - fn test_citation_redundant_comma() { - assert_debug_snapshot!(setup(r#"\cite{,foo,}"#)); - } - - #[test] - fn test_package_include_empty() { - assert_debug_snapshot!(setup(r#"\usepackage{}"#)); - } - - #[test] - fn test_package_include_simple() { - assert_debug_snapshot!(setup(r#"\usepackage{amsmath}"#)); - } - - #[test] - fn test_package_include_multiple() { - assert_debug_snapshot!(setup(r#"\usepackage{amsmath, lipsum}"#)); - } - - #[test] - fn test_package_include_options() { - assert_debug_snapshot!(setup(r#"\usepackage[foo = bar, baz, qux]{amsmath}"#)); - } - - #[test] - fn test_class_include_empty() { - assert_debug_snapshot!(setup(r#"\documentclass{}"#)); - } - - #[test] - fn test_class_include_simple() { - assert_debug_snapshot!(setup(r#"\documentclass{article}"#)); - } - - #[test] - fn test_class_include_options() { - assert_debug_snapshot!(setup(r#"\documentclass[foo = bar, baz, qux]{article}"#)); - } - - #[test] - fn test_latex_include_simple() { - assert_debug_snapshot!(setup(r#"\include{foo/bar}"#)); - } - - #[test] - fn test_latex_include_equality_sign() { - assert_debug_snapshot!(setup(r#"\include{foo=bar}"#)); - } - - #[test] - fn test_latex_input_simple() { - assert_debug_snapshot!(setup(r#"\input{foo/bar.tex}"#)); - } - - #[test] - fn test_latex_input_path_with_brackets() { - assert_debug_snapshot!(setup(r#"\input{foo[bar].tex}"#)); - } - - #[test] - fn test_biblatex_include_simple() { - assert_debug_snapshot!(setup(r#"\addbibresource{foo/bar.bib}"#)); - } - - #[test] - fn test_biblatex_include_options() { - assert_debug_snapshot!(setup(r#"\addbibresource[foo=bar, baz]{foo/bar.bib}"#)); - } - - #[test] - fn test_bibtex_include_simple() { - assert_debug_snapshot!(setup(r#"\bibliography{foo/bar}"#)); - } - - #[test] - fn test_graphics_include_simple() { - assert_debug_snapshot!(setup(r#"\includegraphics{foo/bar.pdf}"#)); - } - - #[test] - fn test_graphics_include_options() { - assert_debug_snapshot!(setup(r#"\includegraphics[scale=.5]{foo/bar.pdf}"#)); - } - - #[test] - fn test_graphics_include_complicated_options() { - assert_debug_snapshot!(setup(r#"\includegraphics[width=0.5\textwidth]{}"#)); - } - - #[test] - fn test_graphics_include_command() { - assert_debug_snapshot!(setup( - r#"\includegraphics[width=0.5\textwidth]{\foo.\bar.pdf}"# - )); - } - - #[test] - fn test_svg_include_simple() { - assert_debug_snapshot!(setup(r#"\includesvg{foo/bar.svg}"#)); - } - - #[test] - fn test_svg_include_options() { - assert_debug_snapshot!(setup(r#"\includesvg[scale=.5]{foo/bar.svg}"#)); - } - - #[test] - fn test_inkscape_include_simple() { - assert_debug_snapshot!(setup(r#"\includesvg{foo/bar}"#)); - } - - #[test] - fn test_inkscape_include_options() { - assert_debug_snapshot!(setup(r#"\includesvg[scale=.5]{foo/bar}"#)); - } - - #[test] - fn test_verbatim_include_simple() { - assert_debug_snapshot!(setup(r#"\verbatiminput{foo/bar.txt}"#)); - } - - #[test] - fn test_import_simple() { - assert_debug_snapshot!(setup(r#"\import{foo}{bar}"#)); - } - - #[test] - fn test_import_incomplete() { - assert_debug_snapshot!(setup(r#"\import{foo"#)); - } - - #[test] - fn test_label_definition_simple() { - assert_debug_snapshot!(setup(r#"\label{foo}"#)); - } - - #[test] - fn test_label_reference_simple() { - assert_debug_snapshot!(setup(r#"\ref{foo}"#)); - } - - #[test] - fn test_label_reference_multiple() { - assert_debug_snapshot!(setup(r#"\ref{foo, bar}"#)); - } - - #[test] - fn test_label_reference_incomplete() { - assert_debug_snapshot!(setup(r#"Equation \eqref{eq is a \emph{useful} identity."#)); - } - - #[test] - fn test_equation_label_reference_simple() { - assert_debug_snapshot!(setup(r#"\eqref{foo}"#)); - } - - #[test] - fn test_label_reference_range_simple() { - assert_debug_snapshot!(setup(r#"\crefrange{foo}{bar}"#)); - } - - #[test] - fn test_label_reference_range_incomplete() { - assert_debug_snapshot!(setup(r#"\crefrange{foo}"#)); - } - - #[test] - fn test_label_reference_range_error() { - assert_debug_snapshot!(setup(r#"\crefrange{foo{bar}"#)); - } - - #[test] - fn test_label_number() { - assert_debug_snapshot!(setup(r#"\newlabel{foo}{{1.1}}"#)); - } - - #[test] - fn test_command_definition_simple() { - assert_debug_snapshot!(setup(r#"\newcommand[1]{\id}{#1}"#)); - } - - #[test] - fn test_command_definition_optional() { - assert_debug_snapshot!(setup(r#"\newcommand{\foo}[1][def]{#1}"#)); - } - - #[test] - fn test_command_definition_no_argc() { - assert_debug_snapshot!(setup(r#"\newcommand{\foo}{foo}"#)); - } - - #[test] - fn test_command_definition_no_impl() { - assert_debug_snapshot!(setup(r#"\newcommand{\foo}"#)); - } - - #[test] - fn test_command_definition_no_impl_error() { - assert_debug_snapshot!(setup(r#"\newcommand{\foo"#)); - } - - #[test] - fn test_command_definition_with_begin() { - assert_debug_snapshot!(setup( - r#"\newcommand{\CVSubHeadingListStart}{\begin{itemize}[leftmargin=0.5cm, label={}]}"# - )); - } - - #[test] - fn test_math_operator_simple() { - assert_debug_snapshot!(setup(r#"\DeclareMathOperator{\foo}{foo}"#)); - } - - #[test] - fn test_math_operator_no_impl() { - assert_debug_snapshot!(setup(r#"\DeclareMathOperator{\foo}"#)); - } - - #[test] - fn test_glossary_entry_definition_simple() { - assert_debug_snapshot!(setup(r#"\newglossaryentry{foo}{bar = baz, qux,}"#)); - } - - #[test] - fn test_glossary_entry_reference_simple() { - assert_debug_snapshot!(setup(r#"\gls{foo}"#)); - } - - #[test] - fn test_glossary_entry_reference_options() { - assert_debug_snapshot!(setup(r#"\gls[foo = bar, qux]{baz}"#)); - } - - #[test] - fn test_acroynm_definition_simple() { - assert_debug_snapshot!(setup(r#"\newacronym{fpsLabel}{FPS}{Frame per Second}"#)); - } - - #[test] - fn test_acroynm_definition_options() { - assert_debug_snapshot!(setup( - r#"\newacronym[longplural={Frames per Second}]{fpsLabel}{FPS}{Frame per Second}"# - )); - } - - #[test] - fn test_acroynm_reference_simple() { - assert_debug_snapshot!(setup(r#"\acrshort{fpsLabel}"#)); - } - - #[test] - fn test_acroynm_reference_options() { - assert_debug_snapshot!(setup(r#"\acrshort[foo=bar,baz]{fpsLabel}"#)); - } - - #[test] - fn test_theorem_definition_only_name() { - assert_debug_snapshot!(setup(r#"\newtheorem{foo}"#)); - } - - #[test] - fn test_theorem_definition_name_with_description() { - assert_debug_snapshot!(setup(r#"\newtheorem{foo}{Foo}"#)); - } - - #[test] - fn test_theorem_definition_name_with_description_and_counter() { - assert_debug_snapshot!(setup(r#"\newtheorem{foo}[bar]{Foo}"#)); - } - - #[test] - fn test_theorem_definition_name_with_counter() { - assert_debug_snapshot!(setup(r#"\newtheorem{foo}[bar]"#)); - } - - #[test] - fn test_theorem_definition_full() { - assert_debug_snapshot!(setup(r#"\newtheorem{foo}[bar]{Foo}[baz]"#)); - } - - #[test] - fn test_color_reference_simple() { - assert_debug_snapshot!(setup(r#"\color{black}"#)); - } - - #[test] - fn test_color_definition_simple() { - assert_debug_snapshot!(setup(r#"\definecolor{foo}{rgb}{255,168,0}"#)); - } - - #[test] - fn test_color_set_definition_simple() { - assert_debug_snapshot!(setup(r#"\definecolorset[ty]{rgb,HTML}{foo}{bar}{baz}"#)); - } - - #[test] - fn test_color_set_definition_error1() { - assert_debug_snapshot!(setup(r#"\definecolorset[ty]{rgb,HTML}{foo}{bar}"#)); - } - - #[test] - fn test_color_set_definition_error2() { - assert_debug_snapshot!(setup(r#"\definecolorset{rgb,HTML}{foo}"#)); - } - - #[test] - fn test_color_set_definition_error3() { - assert_debug_snapshot!(setup(r#"\definecolorset{rgb,HTML}"#)); - } - - #[test] - fn test_color_set_definition_error4() { - assert_debug_snapshot!(setup(r#"\definecolorset"#)); - } - - #[test] - fn test_pgf_library_import_simple() { - assert_debug_snapshot!(setup(r#"\usepgflibrary{foo}"#)); - } - - #[test] - fn test_tikz_library_import_simple() { - assert_debug_snapshot!(setup(r#"\usetikzlibrary{foo}"#)); - } - - #[test] - fn test_environment_definition() { - assert_debug_snapshot!(setup(r#"\newenvironment{bar}[1]{\begin{foo}}{\end{foo}}"#)); - } - - #[test] - fn test_environment_definition_optional_arg() { - assert_debug_snapshot!(setup(r#"\newenvironment{foo}[1][default]{begin}{end}"#)); - } - - #[test] - fn test_acronym_declaration() { - assert_debug_snapshot!(setup( - r#"\DeclareAcronym{eg}{short = e.g,long = for example,tag = abbrev}"# - )); - } - - #[test] - fn test_label_definition_line_break() { - assert_debug_snapshot!(setup("\\label{hello\nworld}")); - } - - #[test] - fn test_block_comments() { - assert_debug_snapshot!(setup( - r#"Foo -\iffalse -Test1 -\fi -Bar -\iffalse -\fii -\fi -Baz"# - )); - } - - #[test] - fn test_asymptote() { - assert_debug_snapshot!(setup( - r#"\begin{asy} - printf("Hello World\n"); -\end{asy}"# - )); - } + use super::parse_latex; #[test] - fn test_graphics_path() { - assert_debug_snapshot!(setup(r#"\graphicspath{{../figures/}}"#)); + fn test_parse() { + insta::glob!("test_data/latex/{,**/}*.txt", |path| { + let text = std::fs::read_to_string(path).unwrap().replace("\r\n", "\n"); + let root = latex::SyntaxNode::new_root(parse_latex(&text)); + insta::assert_debug_snapshot!(root); + }); } } diff --git a/support/texlab/src/syntax/latex/lexer.rs b/support/texlab/src/parser/latex/lexer.rs index 39196375b1..9b0a6726eb 100644 --- a/support/texlab/src/syntax/latex/lexer.rs +++ b/support/texlab/src/parser/latex/lexer.rs @@ -1,9 +1,8 @@ use logos::Logos; -use super::kind::SyntaxKind; +use crate::syntax::latex::SyntaxKind; #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, PartialOrd, Ord, Logos)] -#[allow(non_camel_case_types)] #[repr(u16)] enum RootToken { #[regex(r"[\r\n]+", priority = 2)] @@ -299,6 +298,15 @@ enum CommandNameToken { GlossaryEntryReference, #[token("\\newacronym")] + #[token("\\newacro")] + #[token("\\acrodef")] + #[token("\\acro")] + #[token("\\newacroindefinite")] + #[token("\\acrodefindefinite")] + #[token("\\acroindefinite")] + #[token("\\acroplural")] + #[token("\\newacroplural")] + #[token("\\acrodefplural")] AcronymDefinition, #[token("\\DeclareAcronym")] @@ -332,11 +340,42 @@ enum CommandNameToken { #[token("\\Aclp")] #[token("\\acf")] #[token("\\Acf")] + #[token("\\acfi")] + #[token("\\Acfi")] #[token("\\acfp")] #[token("\\Acfp")] #[token("\\ac")] #[token("\\Ac")] #[token("\\acp")] + #[token("\\Acp")] + #[token("\\acused")] + #[token("\\acsu")] + #[token("\\Aclu")] + #[token("\\iac")] + #[token("\\Iac")] + #[token("\\acs*")] + #[token("\\Acs*")] + #[token("\\acsp*")] + #[token("\\Acsp*")] + #[token("\\acl*")] + #[token("\\Acl*")] + #[token("\\aclp*")] + #[token("\\Aclp*")] + #[token("\\acf*")] + #[token("\\Acf*")] + #[token("\\acfi*")] + #[token("\\Acfi*")] + #[token("\\acfp*")] + #[token("\\Acfp*")] + #[token("\\ac*")] + #[token("\\Ac*")] + #[token("\\acp*")] + #[token("\\Acp*")] + #[token("\\acused*")] + #[token("\\acsu*")] + #[token("\\Aclu*")] + #[token("\\iac*")] + #[token("\\Iac*")] #[token("\\glsentrylong")] #[token("\\Glsentrylong")] #[token("\\glsentrylongpl")] @@ -600,75 +639,3 @@ fn tokenize_verbatim_environment<'a>( &input[end..] } - -#[cfg(test)] -mod tests { - use insta::assert_debug_snapshot; - - use super::*; - - fn verify(text: &str) -> Vec<(SyntaxKind, &str)> { - let mut tokens = Lexer::new(text).tokens; - tokens.reverse(); - tokens - } - - #[test] - fn test_empty() { - assert_debug_snapshot!(verify(r#""#)); - } - - #[test] - fn test_delimiters() { - assert_debug_snapshot!(verify(r#"{foo} (bar) [baz, qux = foo-bar]"#)); - } - - #[test] - fn test_command_with_parameter() { - assert_debug_snapshot!(verify(r#"\newcommand{\id}[1]{#1}"#)); - } - - #[test] - fn test_command_with_star() { - assert_debug_snapshot!(verify(r#"\section*{Foo}"#)); - } - - #[test] - fn test_escape_sequence() { - assert_debug_snapshot!(verify(r#"\% hello"#)); - } - - #[test] - fn test_formula() { - assert_debug_snapshot!(verify(r#"$ f(x) = y $$"#)); - } - - #[test] - fn test_comment() { - assert_debug_snapshot!(verify("hello %world\r\ntest %test")); - } - - #[test] - fn test_invalid_parameter() { - assert_debug_snapshot!(verify(r#"#"#)) - } - - #[test] - fn test_line_break() { - assert_debug_snapshot!(verify("hello\nworld")); - } - - #[test] - fn test_block_comment() { - assert_debug_snapshot!(verify("Foo\\iffalse\n\\Bar{Baz}\n\\fi\\Qux")); - } - - #[test] - fn test_asymptote() { - assert_debug_snapshot!(verify( - r#"\begin{asy} - printf("Hello World\n"); -\end{asy}"# - )); - } -} diff --git a/support/texlab/src/parser/snapshots/texlab__parser__bibtex__tests__parse@comment.txt.snap b/support/texlab/src/parser/snapshots/texlab__parser__bibtex__tests__parse@comment.txt.snap new file mode 100644 index 0000000000..f2e1163eff --- /dev/null +++ b/support/texlab/src/parser/snapshots/texlab__parser__bibtex__tests__parse@comment.txt.snap @@ -0,0 +1,10 @@ +--- +source: src/parser/bibtex.rs +expression: root +input_file: src/parser/test_data/bibtex/comment.txt +--- +ROOT@0..82 + JUNK@0..16 "Some junk here\n\n" + TYPE@16..24 "@comment" + JUNK@24..82 "{foo,\n author = {F ..." + diff --git a/support/texlab/src/parser/snapshots/texlab__parser__bibtex__tests__parse@issue_809.txt.snap b/support/texlab/src/parser/snapshots/texlab__parser__bibtex__tests__parse@issue_809.txt.snap new file mode 100644 index 0000000000..922e926cef --- /dev/null +++ b/support/texlab/src/parser/snapshots/texlab__parser__bibtex__tests__parse@issue_809.txt.snap @@ -0,0 +1,31 @@ +--- +source: src/parser/bibtex.rs +expression: root +--- +ROOT@0..50 + ENTRY@0..50 + TYPE@0..8 "@article" + L_DELIM@8..9 "{" + NAME@9..18 "issue_809" + COMMA@18..19 "," + WHITESPACE@19..22 "\n " + FIELD@22..48 + NAME@22..27 "title" + WHITESPACE@27..28 " " + EQ@28..29 "=" + WHITESPACE@29..30 " " + CURLY_GROUP@30..47 + L_CURLY@30..31 "{" + WORD@31..34 "foo" + WHITESPACE@34..35 " " + WORD@35..36 "(" + QUOTE@36..37 "\"" + WHITESPACE@37..38 " " + WORD@38..42 "bar)" + WHITESPACE@42..43 " " + WORD@43..46 "baz" + R_CURLY@46..47 "}" + COMMA@47..48 "," + WHITESPACE@48..49 "\n" + R_DELIM@49..50 "}" + diff --git a/support/texlab/src/syntax/bibtex/snapshots/texlab__syntax__bibtex__tests__preamble.snap b/support/texlab/src/parser/snapshots/texlab__parser__bibtex__tests__parse@preamble.txt.snap index 596a9d108a..26d8a919ba 100644 --- a/support/texlab/src/syntax/bibtex/snapshots/texlab__syntax__bibtex__tests__preamble.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__bibtex__tests__parse@preamble.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/bibtex/tests.rs -assertion_line: 11 -expression: "setup(r#\"@preamble{\"Hello World!\"}\"#)" +source: src/parser/bibtex.rs +expression: root +input_file: src/parser/test_data/bibtex/preamble.txt --- ROOT@0..25 PREAMBLE@0..25 diff --git a/support/texlab/src/parser/snapshots/texlab__parser__bibtex__tests__parse@samples__aho_2006.txt.snap b/support/texlab/src/parser/snapshots/texlab__parser__bibtex__tests__parse@samples__aho_2006.txt.snap new file mode 100644 index 0000000000..d1d34942d8 --- /dev/null +++ b/support/texlab/src/parser/snapshots/texlab__parser__bibtex__tests__parse@samples__aho_2006.txt.snap @@ -0,0 +1,132 @@ +--- +source: src/parser/bibtex.rs +expression: root +input_file: src/parser/test_data/bibtex/samples/aho_2006.txt +--- +ROOT@0..314 + ENTRY@0..314 + TYPE@0..5 "@book" + L_DELIM@5..6 "{" + NAME@6..21 "10.5555/1177220" + COMMA@21..22 "," + WHITESPACE@22..27 "\n " + FIELD@27..111 + NAME@27..33 "author" + WHITESPACE@33..34 " " + EQ@34..35 "=" + WHITESPACE@35..36 " " + CURLY_GROUP@36..110 + L_CURLY@36..37 "{" + WORD@37..40 "Aho" + COMMA@40..41 "," + WHITESPACE@41..42 " " + WORD@42..48 "Alfred" + WHITESPACE@48..49 " " + WORD@49..51 "V." + WHITESPACE@51..52 " " + WORD@52..55 "and" + WHITESPACE@55..56 " " + WORD@56..59 "Lam" + COMMA@59..60 "," + WHITESPACE@60..61 " " + WORD@61..67 "Monica" + WHITESPACE@67..68 " " + WORD@68..70 "S." + WHITESPACE@70..71 " " + WORD@71..74 "and" + WHITESPACE@74..75 " " + WORD@75..80 "Sethi" + COMMA@80..81 "," + WHITESPACE@81..82 " " + WORD@82..86 "Ravi" + WHITESPACE@86..87 " " + WORD@87..90 "and" + WHITESPACE@90..91 " " + WORD@91..97 "Ullman" + COMMA@97..98 "," + WHITESPACE@98..99 " " + WORD@99..106 "Jeffrey" + WHITESPACE@106..107 " " + WORD@107..109 "D." + R_CURLY@109..110 "}" + COMMA@110..111 "," + WHITESPACE@111..116 "\n " + FIELD@116..185 + NAME@116..121 "title" + WHITESPACE@121..122 " " + EQ@122..123 "=" + WHITESPACE@123..124 " " + CURLY_GROUP@124..184 + L_CURLY@124..125 "{" + WORD@125..135 "Compilers:" + WHITESPACE@135..136 " " + WORD@136..146 "Principles" + COMMA@146..147 "," + WHITESPACE@147..148 " " + WORD@148..158 "Techniques" + COMMA@158..159 "," + WHITESPACE@159..160 " " + WORD@160..163 "and" + WHITESPACE@163..164 " " + WORD@164..169 "Tools" + WHITESPACE@169..170 " " + WORD@170..174 "(2nd" + WHITESPACE@174..175 " " + WORD@175..183 "Edition)" + R_CURLY@183..184 "}" + COMMA@184..185 "," + WHITESPACE@185..190 "\n " + FIELD@190..204 + NAME@190..194 "year" + WHITESPACE@194..195 " " + EQ@195..196 "=" + WHITESPACE@196..197 " " + CURLY_GROUP@197..203 + L_CURLY@197..198 "{" + INTEGER@198..202 "2006" + R_CURLY@202..203 "}" + COMMA@203..204 "," + WHITESPACE@204..209 "\n " + FIELD@209..229 + NAME@209..213 "isbn" + WHITESPACE@213..214 " " + EQ@214..215 "=" + WHITESPACE@215..216 " " + CURLY_GROUP@216..228 + L_CURLY@216..217 "{" + INTEGER@217..227 "0321486811" + R_CURLY@227..228 "}" + COMMA@228..229 "," + WHITESPACE@229..234 "\n " + FIELD@234..292 + NAME@234..243 "publisher" + WHITESPACE@243..244 " " + EQ@244..245 "=" + WHITESPACE@245..246 " " + CURLY_GROUP@246..291 + L_CURLY@246..247 "{" + WORD@247..261 "Addison-Wesley" + WHITESPACE@261..262 " " + WORD@262..269 "Longman" + WHITESPACE@269..270 " " + WORD@270..280 "Publishing" + WHITESPACE@280..281 " " + WORD@281..284 "Co." + COMMA@284..285 "," + WHITESPACE@285..286 " " + WORD@286..290 "Inc." + R_CURLY@290..291 "}" + COMMA@291..292 "," + WHITESPACE@292..297 "\n " + FIELD@297..313 + NAME@297..304 "address" + WHITESPACE@304..305 " " + EQ@305..306 "=" + WHITESPACE@306..307 " " + CURLY_GROUP@307..312 + L_CURLY@307..308 "{" + WORD@308..311 "USA" + R_CURLY@311..312 "}" + WHITESPACE@312..313 "\n" + R_DELIM@313..314 "}" + diff --git a/support/texlab/src/syntax/bibtex/snapshots/texlab__syntax__bibtex__tests__biblatex_examples_002.snap b/support/texlab/src/parser/snapshots/texlab__parser__bibtex__tests__parse@samples__aksin_2006.txt.snap index 5607e5a507..72e354e3c0 100644 --- a/support/texlab/src/syntax/bibtex/snapshots/texlab__syntax__bibtex__tests__biblatex_examples_002.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__bibtex__tests__parse@samples__aksin_2006.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/bibtex/tests.rs -assertion_line: 87 -expression: "setup(r#\"@string{jomch = {J.~Organomet. Chem.}}\n\n@article{aksin,\n author = {Aks{\\i}n, {\\\"O}zge and T{\\\"u}rkmen, Hayati and Artok, Levent\n and {\\c{C}}etinkaya, Bekir and Ni, Chaoying and\n B{\\\"u}y{\\\"u}kg{\\\"u}ng{\\\"o}r, Orhan and {\\\"O}zkal, Erhan},\n title = {Effect of immobilization on catalytic characteristics of\n saturated {Pd-N}-heterocyclic carbenes in {Mizoroki-Heck}\n reactions},\n journaltitle = jomch,\n date = 2006,\n volume = 691,\n number = 13,\n pages = {3027-3036},\n indextitle = {Effect of immobilization on catalytic characteristics},\n}\"#)" +source: src/parser/bibtex.rs +expression: root +input_file: src/parser/test_data/bibtex/samples/aksin_2006.txt --- ROOT@0..679 STRING@0..40 diff --git a/support/texlab/src/parser/snapshots/texlab__parser__bibtex__tests__parse@samples__almendro_1998.txt.snap b/support/texlab/src/parser/snapshots/texlab__parser__bibtex__tests__parse@samples__almendro_1998.txt.snap new file mode 100644 index 0000000000..cff0323cb4 --- /dev/null +++ b/support/texlab/src/parser/snapshots/texlab__parser__bibtex__tests__parse@samples__almendro_1998.txt.snap @@ -0,0 +1,246 @@ +--- +source: src/parser/bibtex.rs +expression: root +input_file: src/parser/test_data/bibtex/samples/almendro_1998.txt +--- +ROOT@0..706 + ENTRY@0..706 + TYPE@0..7 "@patent" + L_DELIM@7..8 "{" + NAME@8..16 "almendro" + COMMA@16..17 "," + WHITESPACE@17..22 "\n " + FIELD@22..150 + NAME@22..28 "author" + WHITESPACE@28..35 " " + EQ@35..36 "=" + WHITESPACE@36..37 " " + CURLY_GROUP@37..149 + L_CURLY@37..38 "{" + WORD@38..46 "Almendro" + COMMA@46..47 "," + WHITESPACE@47..48 " " + WORD@48..51 "Jos" + CURLY_GROUP@51..56 + L_CURLY@51..52 "{" + ACCENT@52..55 + ACCENT_NAME@52..54 "\\'" + WORD@54..55 "e" + R_CURLY@55..56 "}" + WHITESPACE@56..57 " " + WORD@57..59 "L." + WHITESPACE@59..60 " " + WORD@60..63 "and" + WHITESPACE@63..64 " " + WORD@64..68 "Mart" + CURLY_GROUP@68..73 + L_CURLY@68..69 "{" + ACCENT@69..72 + ACCENT_NAME@69..71 "\\'" + WORD@71..72 "i" + R_CURLY@72..73 "}" + WORD@73..74 "n" + COMMA@74..75 "," + WHITESPACE@75..76 " " + WORD@76..83 "Jacinto" + WHITESPACE@83..84 " " + WORD@84..87 "and" + WHITESPACE@87..88 " " + WORD@88..89 "S" + CURLY_GROUP@89..94 + L_CURLY@89..90 "{" + ACCENT@90..93 + ACCENT_NAME@90..92 "\\'" + WORD@92..93 "a" + R_CURLY@93..94 "}" + WORD@94..99 "nchez" + COMMA@99..100 "," + WHITESPACE@100..121 "\n " + WORD@121..128 "Alberto" + WHITESPACE@128..129 " " + WORD@129..132 "and" + WHITESPACE@132..133 " " + WORD@133..138 "Nozal" + COMMA@138..139 "," + WHITESPACE@139..140 " " + WORD@140..148 "Fernando" + R_CURLY@148..149 "}" + COMMA@149..150 "," + WHITESPACE@150..155 "\n " + FIELD@155..203 + NAME@155..160 "title" + WHITESPACE@160..168 " " + EQ@168..169 "=" + WHITESPACE@169..170 " " + CURLY_GROUP@170..202 + L_CURLY@170..171 "{" + WORD@171..190 "Elektromagnetisches" + WHITESPACE@190..191 " " + WORD@191..201 "Signalhorn" + R_CURLY@201..202 "}" + COMMA@202..203 "," + WHITESPACE@203..208 "\n " + FIELD@208..238 + NAME@208..214 "number" + WHITESPACE@214..221 " " + EQ@221..222 "=" + WHITESPACE@222..223 " " + CURLY_GROUP@223..237 + L_CURLY@223..224 "{" + WORD@224..236 "EU-29702195U" + R_CURLY@236..237 "}" + COMMA@237..238 "," + WHITESPACE@238..243 "\n " + FIELD@243..263 + NAME@243..247 "date" + WHITESPACE@247..256 " " + EQ@256..257 "=" + WHITESPACE@257..258 " " + LITERAL@258..262 + INTEGER@258..262 "1998" + COMMA@262..263 "," + WHITESPACE@263..268 "\n " + FIELD@268..323 + NAME@268..276 "location" + WHITESPACE@276..281 " " + EQ@281..282 "=" + WHITESPACE@282..283 " " + CURLY_GROUP@283..322 + L_CURLY@283..284 "{" + WORD@284..293 "countryfr" + WHITESPACE@293..294 " " + WORD@294..297 "and" + WHITESPACE@297..298 " " + WORD@298..307 "countryuk" + WHITESPACE@307..308 " " + WORD@308..311 "and" + WHITESPACE@311..312 " " + WORD@312..321 "countryde" + R_CURLY@321..322 "}" + COMMA@322..323 "," + WHITESPACE@323..328 "\n " + FIELD@328..352 + NAME@328..334 "langid" + WHITESPACE@334..341 " " + EQ@341..342 "=" + WHITESPACE@342..343 " " + CURLY_GROUP@343..351 + L_CURLY@343..344 "{" + WORD@344..350 "german" + R_CURLY@350..351 "}" + COMMA@351..352 "," + WHITESPACE@352..357 "\n " + FIELD@357..704 + NAME@357..367 "annotation" + WHITESPACE@367..370 " " + EQ@370..371 "=" + WHITESPACE@371..372 " " + CURLY_GROUP@372..703 + L_CURLY@372..373 "{" + WORD@373..377 "This" + WHITESPACE@377..378 " " + WORD@378..380 "is" + WHITESPACE@380..381 " " + WORD@381..382 "a" + WHITESPACE@382..383 " " + COMMAND@383..390 + COMMAND_NAME@383..390 "\\texttt" + CURLY_GROUP@390..398 + L_CURLY@390..391 "{" + WORD@391..397 "patent" + R_CURLY@397..398 "}" + WHITESPACE@398..399 " " + WORD@399..404 "entry" + WHITESPACE@404..405 " " + WORD@405..409 "with" + WHITESPACE@409..410 " " + WORD@410..411 "a" + WHITESPACE@411..412 " " + COMMAND@412..419 + COMMAND_NAME@412..419 "\\texttt" + CURLY_GROUP@419..429 + L_CURLY@419..420 "{" + WORD@420..428 "location" + R_CURLY@428..429 "}" + WHITESPACE@429..450 "\n " + WORD@450..456 "field." + WHITESPACE@456..457 " " + WORD@457..460 "The" + WHITESPACE@460..461 " " + WORD@461..467 "number" + WHITESPACE@467..468 " " + WORD@468..470 "is" + WHITESPACE@470..471 " " + WORD@471..476 "given" + WHITESPACE@476..477 " " + WORD@477..479 "in" + WHITESPACE@479..480 " " + WORD@480..483 "the" + WHITESPACE@483..484 " " + COMMAND@484..491 + COMMAND_NAME@484..491 "\\texttt" + CURLY_GROUP@491..499 + L_CURLY@491..492 "{" + WORD@492..498 "number" + R_CURLY@498..499 "}" + WHITESPACE@499..500 " " + WORD@500..506 "field." + WHITESPACE@506..507 " " + WORD@507..511 "Note" + WHITESPACE@511..532 "\n " + WORD@532..535 "the" + WHITESPACE@535..536 " " + WORD@536..542 "format" + WHITESPACE@542..543 " " + WORD@543..545 "of" + WHITESPACE@545..546 " " + WORD@546..549 "the" + WHITESPACE@549..550 " " + COMMAND@550..557 + COMMAND_NAME@550..557 "\\texttt" + CURLY_GROUP@557..567 + L_CURLY@557..558 "{" + WORD@558..566 "location" + R_CURLY@566..567 "}" + WHITESPACE@567..568 " " + WORD@568..573 "field" + WHITESPACE@573..574 " " + WORD@574..576 "in" + WHITESPACE@576..577 " " + WORD@577..580 "the" + WHITESPACE@580..581 " " + WORD@581..589 "database" + WHITESPACE@589..610 "\n " + WORD@610..615 "file." + WHITESPACE@615..616 " " + WORD@616..623 "Compare" + WHITESPACE@623..624 " " + COMMAND@624..631 + COMMAND_NAME@624..631 "\\texttt" + CURLY_GROUP@631..643 + L_CURLY@631..632 "{" + WORD@632..642 "laufenberg" + R_CURLY@642..643 "}" + COMMA@643..644 "," + WHITESPACE@644..645 " " + COMMAND@645..652 + COMMAND_NAME@645..652 "\\texttt" + CURLY_GROUP@652..660 + L_CURLY@652..653 "{" + WORD@653..659 "sorace" + R_CURLY@659..660 "}" + COMMA@660..661 "," + WHITESPACE@661..662 " " + WORD@662..665 "and" + WHITESPACE@665..686 "\n " + COMMAND@686..693 + COMMAND_NAME@686..693 "\\texttt" + CURLY_GROUP@693..702 + L_CURLY@693..694 "{" + WORD@694..701 "kowalik" + R_CURLY@701..702 "}" + R_CURLY@702..703 "}" + COMMA@703..704 "," + WHITESPACE@704..705 "\n" + R_DELIM@705..706 "}" + diff --git a/support/texlab/src/parser/snapshots/texlab__parser__bibtex__tests__parse@samples__averroes_1998.txt.snap b/support/texlab/src/parser/snapshots/texlab__parser__bibtex__tests__parse@samples__averroes_1998.txt.snap new file mode 100644 index 0000000000..c02d61d272 --- /dev/null +++ b/support/texlab/src/parser/snapshots/texlab__parser__bibtex__tests__parse@samples__averroes_1998.txt.snap @@ -0,0 +1,351 @@ +--- +source: src/parser/bibtex.rs +expression: root +input_file: src/parser/test_data/bibtex/samples/averroes_1998.txt +--- +ROOT@0..1008 + ENTRY@0..1008 + TYPE@0..5 "@book" + L_DELIM@5..6 "{" + NAME@6..20 "averroes/bland" + COMMA@20..21 "," + WHITESPACE@21..26 "\n " + FIELD@26..52 + NAME@26..32 "author" + WHITESPACE@32..39 " " + EQ@39..40 "=" + WHITESPACE@40..41 " " + CURLY_GROUP@41..51 + L_CURLY@41..42 "{" + WORD@42..50 "Averroes" + R_CURLY@50..51 "}" + COMMA@51..52 "," + WHITESPACE@52..57 "\n " + FIELD@57..220 + NAME@57..62 "title" + WHITESPACE@62..70 " " + EQ@70..71 "=" + WHITESPACE@71..72 " " + CURLY_GROUP@72..219 + L_CURLY@72..73 "{" + WORD@73..76 "The" + WHITESPACE@76..77 " " + WORD@77..84 "Epistle" + WHITESPACE@84..85 " " + WORD@85..87 "on" + WHITESPACE@87..88 " " + WORD@88..91 "the" + WHITESPACE@91..92 " " + WORD@92..103 "Possibility" + WHITESPACE@103..104 " " + WORD@104..106 "of" + WHITESPACE@106..107 " " + WORD@107..118 "Conjunction" + WHITESPACE@118..119 " " + WORD@119..123 "with" + WHITESPACE@123..124 " " + WORD@124..127 "the" + WHITESPACE@127..128 " " + WORD@128..134 "Active" + WHITESPACE@134..155 "\n " + WORD@155..164 "Intellect" + WHITESPACE@164..165 " " + WORD@165..167 "by" + WHITESPACE@167..168 " " + CURLY_GROUP@168..179 + L_CURLY@168..169 "{" + WORD@169..172 "Ibn" + WHITESPACE@172..173 " " + WORD@173..178 "Rushd" + R_CURLY@178..179 "}" + WHITESPACE@179..180 " " + WORD@180..184 "with" + WHITESPACE@184..185 " " + WORD@185..188 "the" + WHITESPACE@188..189 " " + WORD@189..199 "Commentary" + WHITESPACE@199..200 " " + WORD@200..202 "of" + WHITESPACE@202..203 " " + CURLY_GROUP@203..218 + L_CURLY@203..204 "{" + WORD@204..209 "Moses" + WHITESPACE@209..210 " " + WORD@210..217 "Narboni" + R_CURLY@217..218 "}" + R_CURLY@218..219 "}" + COMMA@219..220 "," + WHITESPACE@220..225 "\n " + FIELD@225..245 + NAME@225..229 "date" + WHITESPACE@229..238 " " + EQ@238..239 "=" + WHITESPACE@239..240 " " + LITERAL@240..244 + INTEGER@240..244 "1982" + COMMA@244..245 "," + WHITESPACE@245..250 "\n " + FIELD@250..284 + NAME@250..256 "editor" + WHITESPACE@256..263 " " + EQ@263..264 "=" + WHITESPACE@264..265 " " + CURLY_GROUP@265..283 + L_CURLY@265..266 "{" + WORD@266..271 "Bland" + COMMA@271..272 "," + WHITESPACE@272..273 " " + WORD@273..279 "Kalman" + WHITESPACE@279..280 " " + WORD@280..282 "P." + R_CURLY@282..283 "}" + COMMA@283..284 "," + WHITESPACE@284..289 "\n " + FIELD@289..323 + NAME@289..299 "translator" + WHITESPACE@299..302 " " + EQ@302..303 "=" + WHITESPACE@303..304 " " + CURLY_GROUP@304..322 + L_CURLY@304..305 "{" + WORD@305..310 "Bland" + COMMA@310..311 "," + WHITESPACE@311..312 " " + WORD@312..318 "Kalman" + WHITESPACE@318..319 " " + WORD@319..321 "P." + R_CURLY@321..322 "}" + COMMA@322..323 "," + WHITESPACE@323..328 "\n " + FIELD@328..407 + NAME@328..334 "series" + WHITESPACE@334..341 " " + EQ@341..342 "=" + WHITESPACE@342..343 " " + CURLY_GROUP@343..406 + L_CURLY@343..344 "{" + WORD@344..353 "Moreshet:" + WHITESPACE@353..354 " " + WORD@354..361 "Studies" + WHITESPACE@361..362 " " + WORD@362..364 "in" + WHITESPACE@364..365 " " + CURLY_GROUP@365..373 + L_CURLY@365..366 "{" + WORD@366..372 "Jewish" + R_CURLY@372..373 "}" + WHITESPACE@373..374 " " + WORD@374..381 "History" + COMMA@381..382 "," + WHITESPACE@382..383 " " + WORD@383..393 "Literature" + WHITESPACE@393..394 " " + WORD@394..397 "and" + WHITESPACE@397..398 " " + WORD@398..405 "Thought" + R_CURLY@405..406 "}" + COMMA@406..407 "," + WHITESPACE@407..412 "\n " + FIELD@412..429 + NAME@412..418 "number" + WHITESPACE@418..425 " " + EQ@425..426 "=" + WHITESPACE@426..427 " " + LITERAL@427..428 + INTEGER@427..428 "7" + COMMA@428..429 "," + WHITESPACE@429..434 "\n " + FIELD@434..490 + NAME@434..443 "publisher" + WHITESPACE@443..447 " " + EQ@447..448 "=" + WHITESPACE@448..449 " " + CURLY_GROUP@449..489 + L_CURLY@449..450 "{" + WORD@450..456 "Jewish" + WHITESPACE@456..457 " " + WORD@457..468 "Theological" + WHITESPACE@468..469 " " + WORD@469..477 "Seminary" + WHITESPACE@477..478 " " + WORD@478..480 "of" + WHITESPACE@480..481 " " + WORD@481..488 "America" + R_CURLY@488..489 "}" + COMMA@489..490 "," + WHITESPACE@490..495 "\n " + FIELD@495..521 + NAME@495..503 "location" + WHITESPACE@503..508 " " + EQ@508..509 "=" + WHITESPACE@509..510 " " + CURLY_GROUP@510..520 + L_CURLY@510..511 "{" + WORD@511..514 "New" + WHITESPACE@514..515 " " + WORD@515..519 "York" + R_CURLY@519..520 "}" + COMMA@520..521 "," + WHITESPACE@521..526 "\n " + FIELD@526..551 + NAME@526..534 "keywords" + WHITESPACE@534..539 " " + EQ@539..540 "=" + WHITESPACE@540..541 " " + CURLY_GROUP@541..550 + L_CURLY@541..542 "{" + WORD@542..549 "primary" + R_CURLY@549..550 "}" + COMMA@550..551 "," + WHITESPACE@551..556 "\n " + FIELD@556..581 + NAME@556..562 "langid" + WHITESPACE@562..569 " " + EQ@569..570 "=" + WHITESPACE@570..571 " " + CURLY_GROUP@571..580 + L_CURLY@571..572 "{" + WORD@572..579 "english" + R_CURLY@579..580 "}" + COMMA@580..581 "," + WHITESPACE@581..586 "\n " + FIELD@586..620 + NAME@586..596 "langidopts" + WHITESPACE@596..599 " " + EQ@599..600 "=" + WHITESPACE@600..601 " " + CURLY_GROUP@601..619 + L_CURLY@601..602 "{" + WORD@602..618 "variant=american" + R_CURLY@618..619 "}" + COMMA@619..620 "," + WHITESPACE@620..625 "\n " + FIELD@625..689 + NAME@625..635 "indextitle" + WHITESPACE@635..638 " " + EQ@638..639 "=" + WHITESPACE@639..640 " " + CURLY_GROUP@640..688 + L_CURLY@640..641 "{" + WORD@641..648 "Epistle" + WHITESPACE@648..649 " " + WORD@649..651 "on" + WHITESPACE@651..652 " " + WORD@652..655 "the" + WHITESPACE@655..656 " " + WORD@656..667 "Possibility" + WHITESPACE@667..668 " " + WORD@668..670 "of" + WHITESPACE@670..671 " " + WORD@671..682 "Conjunction" + COMMA@682..683 "," + WHITESPACE@683..684 " " + WORD@684..687 "The" + R_CURLY@687..688 "}" + COMMA@688..689 "," + WHITESPACE@689..694 "\n " + FIELD@694..738 + NAME@694..704 "shorttitle" + WHITESPACE@704..707 " " + EQ@707..708 "=" + WHITESPACE@708..709 " " + CURLY_GROUP@709..737 + L_CURLY@709..710 "{" + WORD@710..721 "Possibility" + WHITESPACE@721..722 " " + WORD@722..724 "of" + WHITESPACE@724..725 " " + WORD@725..736 "Conjunction" + R_CURLY@736..737 "}" + COMMA@737..738 "," + WHITESPACE@738..743 "\n " + FIELD@743..1006 + NAME@743..753 "annotation" + WHITESPACE@753..756 " " + EQ@756..757 "=" + WHITESPACE@757..758 " " + CURLY_GROUP@758..1005 + L_CURLY@758..759 "{" + WORD@759..760 "A" + WHITESPACE@760..761 " " + COMMAND@761..768 + COMMAND_NAME@761..768 "\\texttt" + CURLY_GROUP@768..774 + L_CURLY@768..769 "{" + WORD@769..773 "book" + R_CURLY@773..774 "}" + WHITESPACE@774..775 " " + WORD@775..780 "entry" + WHITESPACE@780..781 " " + WORD@781..785 "with" + WHITESPACE@785..786 " " + WORD@786..787 "a" + WHITESPACE@787..788 " " + COMMAND@788..795 + COMMAND_NAME@788..795 "\\texttt" + CURLY_GROUP@795..803 + L_CURLY@795..796 "{" + WORD@796..802 "series" + R_CURLY@802..803 "}" + WHITESPACE@803..804 " " + WORD@804..807 "and" + WHITESPACE@807..808 " " + WORD@808..809 "a" + WHITESPACE@809..830 "\n " + COMMAND@830..837 + COMMAND_NAME@830..837 "\\texttt" + CURLY_GROUP@837..845 + L_CURLY@837..838 "{" + WORD@838..844 "number" + R_CURLY@844..845 "}" + WORD@845..846 "." + WHITESPACE@846..847 " " + WORD@847..851 "Note" + WHITESPACE@851..852 " " + WORD@852..855 "the" + WHITESPACE@855..856 " " + WORD@856..869 "concatenation" + WHITESPACE@869..870 " " + WORD@870..872 "of" + WHITESPACE@872..873 " " + WORD@873..876 "the" + WHITESPACE@876..877 " " + COMMAND@877..884 + COMMAND_NAME@877..884 "\\texttt" + CURLY_GROUP@884..892 + L_CURLY@884..885 "{" + WORD@885..891 "editor" + R_CURLY@891..892 "}" + WHITESPACE@892..913 "\n " + WORD@913..916 "and" + WHITESPACE@916..917 " " + COMMAND@917..924 + COMMAND_NAME@917..924 "\\texttt" + CURLY_GROUP@924..936 + L_CURLY@924..925 "{" + WORD@925..935 "translator" + R_CURLY@935..936 "}" + WHITESPACE@936..937 " " + WORD@937..943 "fields" + WHITESPACE@943..944 " " + WORD@944..946 "as" + WHITESPACE@946..947 " " + WORD@947..951 "well" + WHITESPACE@951..952 " " + WORD@952..954 "as" + WHITESPACE@954..955 " " + WORD@955..958 "the" + WHITESPACE@958..979 "\n " + COMMAND@979..986 + COMMAND_NAME@979..986 "\\texttt" + CURLY_GROUP@986..998 + L_CURLY@986..987 "{" + WORD@987..997 "indextitle" + R_CURLY@997..998 "}" + WHITESPACE@998..999 " " + WORD@999..1004 "field" + R_CURLY@1004..1005 "}" + COMMA@1005..1006 "," + WHITESPACE@1006..1007 "\n" + R_DELIM@1007..1008 "}" + diff --git a/support/texlab/src/parser/snapshots/texlab__parser__bibtex__tests__parse@samples__betram_1996.txt.snap b/support/texlab/src/parser/snapshots/texlab__parser__bibtex__tests__parse@samples__betram_1996.txt.snap new file mode 100644 index 0000000000..c2748c1661 --- /dev/null +++ b/support/texlab/src/parser/snapshots/texlab__parser__bibtex__tests__parse@samples__betram_1996.txt.snap @@ -0,0 +1,208 @@ +--- +source: src/parser/bibtex.rs +expression: root +input_file: src/parser/test_data/bibtex/samples/betram_1996.txt +--- +ROOT@0..556 + STRING@0..40 + TYPE@0..7 "@string" + L_DELIM@7..8 "{" + NAME@8..12 "jams" + WHITESPACE@12..16 " " + EQ@16..17 "=" + WHITESPACE@17..18 " " + CURLY_GROUP@18..39 + L_CURLY@18..19 "{" + WORD@19..21 "J." + NBSP@21..22 "~" + WORD@22..27 "Amer." + WHITESPACE@27..28 " " + WORD@28..33 "Math." + WHITESPACE@33..34 " " + WORD@34..38 "Soc." + R_CURLY@38..39 "}" + R_DELIM@39..40 "}" + JUNK@40..42 "\n\n" + ENTRY@42..556 + TYPE@42..50 "@article" + L_DELIM@50..51 "{" + NAME@51..58 "bertram" + COMMA@58..59 "," + WHITESPACE@59..64 "\n " + FIELD@64..119 + NAME@64..70 "author" + WHITESPACE@70..77 " " + EQ@77..78 "=" + WHITESPACE@78..79 " " + CURLY_GROUP@79..118 + L_CURLY@79..80 "{" + WORD@80..87 "Bertram" + COMMA@87..88 "," + WHITESPACE@88..89 " " + WORD@89..94 "Aaron" + WHITESPACE@94..95 " " + WORD@95..98 "and" + WHITESPACE@98..99 " " + WORD@99..108 "Wentworth" + COMMA@108..109 "," + WHITESPACE@109..110 " " + WORD@110..117 "Richard" + R_CURLY@117..118 "}" + COMMA@118..119 "," + WHITESPACE@119..124 "\n " + FIELD@124..202 + NAME@124..129 "title" + WHITESPACE@129..137 " " + EQ@137..138 "=" + WHITESPACE@138..139 " " + CURLY_GROUP@139..201 + L_CURLY@139..140 "{" + WORD@140..146 "Gromov" + WHITESPACE@146..147 " " + WORD@147..157 "invariants" + WHITESPACE@157..158 " " + WORD@158..161 "for" + WHITESPACE@161..162 " " + WORD@162..173 "holomorphic" + WHITESPACE@173..174 " " + WORD@174..178 "maps" + WHITESPACE@178..179 " " + WORD@179..181 "on" + WHITESPACE@181..182 " " + CURLY_GROUP@182..191 + L_CURLY@182..183 "{" + WORD@183..190 "Riemann" + R_CURLY@190..191 "}" + WHITESPACE@191..192 " " + WORD@192..200 "surfaces" + R_CURLY@200..201 "}" + COMMA@201..202 "," + WHITESPACE@202..207 "\n " + FIELD@207..227 + NAME@207..219 "journaltitle" + WHITESPACE@219..220 " " + EQ@220..221 "=" + WHITESPACE@221..222 " " + LITERAL@222..226 + NAME@222..226 "jams" + COMMA@226..227 "," + WHITESPACE@227..232 "\n " + FIELD@232..252 + NAME@232..236 "date" + WHITESPACE@236..245 " " + EQ@245..246 "=" + WHITESPACE@246..247 " " + LITERAL@247..251 + INTEGER@247..251 "1996" + COMMA@251..252 "," + WHITESPACE@252..257 "\n " + FIELD@257..274 + NAME@257..263 "volume" + WHITESPACE@263..270 " " + EQ@270..271 "=" + WHITESPACE@271..272 " " + LITERAL@272..273 + INTEGER@272..273 "9" + COMMA@273..274 "," + WHITESPACE@274..279 "\n " + FIELD@279..296 + NAME@279..285 "number" + WHITESPACE@285..292 " " + EQ@292..293 "=" + WHITESPACE@293..294 " " + LITERAL@294..295 + INTEGER@294..295 "2" + COMMA@295..296 "," + WHITESPACE@296..301 "\n " + FIELD@301..326 + NAME@301..306 "pages" + WHITESPACE@306..314 " " + EQ@314..315 "=" + WHITESPACE@315..316 " " + CURLY_GROUP@316..325 + L_CURLY@316..317 "{" + WORD@317..324 "529-571" + R_CURLY@324..325 "}" + COMMA@325..326 "," + WHITESPACE@326..331 "\n " + FIELD@331..356 + NAME@331..337 "langid" + WHITESPACE@337..344 " " + EQ@344..345 "=" + WHITESPACE@345..346 " " + CURLY_GROUP@346..355 + L_CURLY@346..347 "{" + WORD@347..354 "english" + R_CURLY@354..355 "}" + COMMA@355..356 "," + WHITESPACE@356..361 "\n " + FIELD@361..395 + NAME@361..371 "langidopts" + WHITESPACE@371..374 " " + EQ@374..375 "=" + WHITESPACE@375..376 " " + CURLY_GROUP@376..394 + L_CURLY@376..377 "{" + WORD@377..393 "variant=american" + R_CURLY@393..394 "}" + COMMA@394..395 "," + WHITESPACE@395..400 "\n " + FIELD@400..435 + NAME@400..410 "shorttitle" + WHITESPACE@410..413 " " + EQ@413..414 "=" + WHITESPACE@414..415 " " + CURLY_GROUP@415..434 + L_CURLY@415..416 "{" + WORD@416..422 "Gromov" + WHITESPACE@422..423 " " + WORD@423..433 "invariants" + R_CURLY@433..434 "}" + COMMA@434..435 "," + WHITESPACE@435..440 "\n " + FIELD@440..554 + NAME@440..450 "annotation" + WHITESPACE@450..453 " " + EQ@453..454 "=" + WHITESPACE@454..455 " " + CURLY_GROUP@455..553 + L_CURLY@455..456 "{" + WORD@456..458 "An" + WHITESPACE@458..459 " " + COMMAND@459..466 + COMMAND_NAME@459..466 "\\texttt" + CURLY_GROUP@466..475 + L_CURLY@466..467 "{" + WORD@467..474 "article" + R_CURLY@474..475 "}" + WHITESPACE@475..476 " " + WORD@476..481 "entry" + WHITESPACE@481..482 " " + WORD@482..486 "with" + WHITESPACE@486..487 " " + WORD@487..488 "a" + WHITESPACE@488..489 " " + COMMAND@489..496 + COMMAND_NAME@489..496 "\\texttt" + CURLY_GROUP@496..504 + L_CURLY@496..497 "{" + WORD@497..503 "volume" + R_CURLY@503..504 "}" + WHITESPACE@504..505 " " + WORD@505..508 "and" + WHITESPACE@508..509 " " + WORD@509..510 "a" + WHITESPACE@510..531 "\n " + COMMAND@531..538 + COMMAND_NAME@531..538 "\\texttt" + CURLY_GROUP@538..546 + L_CURLY@538..539 "{" + WORD@539..545 "number" + R_CURLY@545..546 "}" + WHITESPACE@546..547 " " + WORD@547..552 "field" + R_CURLY@552..553 "}" + COMMA@553..554 "," + WHITESPACE@554..555 "\n" + R_DELIM@555..556 "}" + diff --git a/support/texlab/src/parser/snapshots/texlab__parser__bibtex__tests__parse@samples__blom_2021.txt.snap b/support/texlab/src/parser/snapshots/texlab__parser__bibtex__tests__parse@samples__blom_2021.txt.snap new file mode 100644 index 0000000000..417bda4ec9 --- /dev/null +++ b/support/texlab/src/parser/snapshots/texlab__parser__bibtex__tests__parse@samples__blom_2021.txt.snap @@ -0,0 +1,223 @@ +--- +source: src/parser/bibtex.rs +expression: root +input_file: src/parser/test_data/bibtex/samples/blom_2021.txt +--- +ROOT@0..860 + ENTRY@0..860 + TYPE@0..8 "@article" + L_DELIM@8..9 "{" + NAME@9..42 "DBLP:journals/corr/ab ..." + COMMA@42..43 "," + WHITESPACE@43..48 "\n " + FIELD@48..322 + NAME@48..54 "author" + WHITESPACE@54..58 " " + EQ@58..59 "=" + WHITESPACE@59..60 " " + CURLY_GROUP@60..321 + L_CURLY@60..61 "{" + WORD@61..69 "Michelle" + WHITESPACE@69..70 " " + WORD@70..72 "L." + WHITESPACE@72..73 " " + WORD@73..77 "Blom" + WHITESPACE@77..78 " " + WORD@78..81 "and" + WHITESPACE@81..102 "\n " + WORD@102..109 "Jurlind" + WHITESPACE@109..110 " " + WORD@110..119 "Budurushi" + WHITESPACE@119..120 " " + WORD@120..123 "and" + WHITESPACE@123..144 "\n " + WORD@144..150 "Ronald" + WHITESPACE@150..151 " " + WORD@151..153 "L." + WHITESPACE@153..154 " " + WORD@154..160 "Rivest" + WHITESPACE@160..161 " " + WORD@161..164 "and" + WHITESPACE@164..185 "\n " + WORD@185..191 "Philip" + WHITESPACE@191..192 " " + WORD@192..194 "B." + WHITESPACE@194..195 " " + WORD@195..200 "Stark" + WHITESPACE@200..201 " " + WORD@201..204 "and" + WHITESPACE@204..225 "\n " + WORD@225..230 "Peter" + WHITESPACE@230..231 " " + WORD@231..233 "J." + WHITESPACE@233..234 " " + WORD@234..241 "Stuckey" + WHITESPACE@241..242 " " + WORD@242..245 "and" + WHITESPACE@245..266 "\n " + WORD@266..273 "Vanessa" + WHITESPACE@273..274 " " + WORD@274..280 "Teague" + WHITESPACE@280..281 " " + WORD@281..284 "and" + WHITESPACE@284..305 "\n " + WORD@305..311 "Damjan" + WHITESPACE@311..312 " " + WORD@312..320 "Vukcevic" + R_CURLY@320..321 "}" + COMMA@321..322 "," + WHITESPACE@322..327 "\n " + FIELD@327..473 + NAME@327..332 "title" + WHITESPACE@332..337 " " + EQ@337..338 "=" + WHITESPACE@338..339 " " + CURLY_GROUP@339..472 + L_CURLY@339..340 "{" + WORD@340..355 "Assertion-based" + WHITESPACE@355..356 " " + WORD@356..366 "Approaches" + WHITESPACE@366..367 " " + WORD@367..369 "to" + WHITESPACE@369..370 " " + WORD@370..378 "Auditing" + WHITESPACE@378..379 " " + WORD@379..386 "Complex" + WHITESPACE@386..387 " " + WORD@387..396 "Elections" + COMMA@396..397 "," + WHITESPACE@397..398 " " + WORD@398..402 "with" + WHITESPACE@402..403 " " + WORD@403..414 "application" + WHITESPACE@414..435 "\n " + WORD@435..437 "to" + WHITESPACE@437..438 " " + WORD@438..448 "party-list" + WHITESPACE@448..449 " " + WORD@449..461 "proportional" + WHITESPACE@461..462 " " + WORD@462..471 "elections" + R_CURLY@471..472 "}" + COMMA@472..473 "," + WHITESPACE@473..478 "\n " + FIELD@478..497 + NAME@478..485 "journal" + WHITESPACE@485..488 " " + EQ@488..489 "=" + WHITESPACE@489..490 " " + CURLY_GROUP@490..496 + L_CURLY@490..491 "{" + WORD@491..495 "CoRR" + R_CURLY@495..496 "}" + COMMA@496..497 "," + WHITESPACE@497..502 "\n " + FIELD@502..531 + NAME@502..508 "volume" + WHITESPACE@508..512 " " + EQ@512..513 "=" + WHITESPACE@513..514 " " + CURLY_GROUP@514..530 + L_CURLY@514..515 "{" + WORD@515..529 "abs/2107.11903" + R_CURLY@529..530 "}" + COMMA@530..531 "," + WHITESPACE@531..536 "\n " + FIELD@536..555 + NAME@536..540 "year" + WHITESPACE@540..546 " " + EQ@546..547 "=" + WHITESPACE@547..548 " " + CURLY_GROUP@548..554 + L_CURLY@548..549 "{" + INTEGER@549..553 "2021" + R_CURLY@553..554 "}" + COMMA@554..555 "," + WHITESPACE@555..560 "\n " + FIELD@560..607 + NAME@560..563 "url" + WHITESPACE@563..570 " " + EQ@570..571 "=" + WHITESPACE@571..572 " " + CURLY_GROUP@572..606 + L_CURLY@572..573 "{" + WORD@573..605 "https://arxiv.org/abs ..." + R_CURLY@605..606 "}" + COMMA@606..607 "," + WHITESPACE@607..612 "\n " + FIELD@612..633 + NAME@612..622 "eprinttype" + WHITESPACE@622..623 " " + EQ@623..624 "=" + WHITESPACE@624..625 " " + CURLY_GROUP@625..632 + L_CURLY@625..626 "{" + WORD@626..631 "arXiv" + R_CURLY@631..632 "}" + COMMA@632..633 "," + WHITESPACE@633..638 "\n " + FIELD@638..663 + NAME@638..644 "eprint" + WHITESPACE@644..648 " " + EQ@648..649 "=" + WHITESPACE@649..650 " " + CURLY_GROUP@650..662 + L_CURLY@650..651 "{" + WORD@651..661 "2107.11903" + R_CURLY@661..662 "}" + COMMA@662..663 "," + WHITESPACE@663..668 "\n " + FIELD@668..714 + NAME@668..677 "timestamp" + WHITESPACE@677..678 " " + EQ@678..679 "=" + WHITESPACE@679..680 " " + CURLY_GROUP@680..713 + L_CURLY@680..681 "{" + WORD@681..684 "Thu" + COMMA@684..685 "," + WHITESPACE@685..686 " " + INTEGER@686..688 "29" + WHITESPACE@688..689 " " + WORD@689..692 "Jul" + WHITESPACE@692..693 " " + INTEGER@693..697 "2021" + WHITESPACE@697..698 " " + WORD@698..706 "16:14:15" + WHITESPACE@706..707 " " + WORD@707..712 "+0200" + R_CURLY@712..713 "}" + COMMA@713..714 "," + WHITESPACE@714..719 "\n " + FIELD@719..787 + NAME@719..725 "biburl" + WHITESPACE@725..729 " " + EQ@729..730 "=" + WHITESPACE@730..731 " " + CURLY_GROUP@731..786 + L_CURLY@731..732 "{" + WORD@732..785 "https://dblp.org/rec/ ..." + R_CURLY@785..786 "}" + COMMA@786..787 "," + WHITESPACE@787..792 "\n " + FIELD@792..859 + NAME@792..801 "bibsource" + WHITESPACE@801..802 " " + EQ@802..803 "=" + WHITESPACE@803..804 " " + CURLY_GROUP@804..858 + L_CURLY@804..805 "{" + WORD@805..809 "dblp" + WHITESPACE@809..810 " " + WORD@810..818 "computer" + WHITESPACE@818..819 " " + WORD@819..826 "science" + WHITESPACE@826..827 " " + WORD@827..839 "bibliography" + COMMA@839..840 "," + WHITESPACE@840..841 " " + WORD@841..857 "https://dblp.org" + R_CURLY@857..858 "}" + WHITESPACE@858..859 "\n" + R_DELIM@859..860 "}" + diff --git a/support/texlab/src/parser/snapshots/texlab__parser__bibtex__tests__parse@samples__combi_2004.txt.snap b/support/texlab/src/parser/snapshots/texlab__parser__bibtex__tests__parse@samples__combi_2004.txt.snap new file mode 100644 index 0000000000..82f58a700f --- /dev/null +++ b/support/texlab/src/parser/snapshots/texlab__parser__bibtex__tests__parse@samples__combi_2004.txt.snap @@ -0,0 +1,251 @@ +--- +source: src/parser/bibtex.rs +expression: root +input_file: src/parser/test_data/bibtex/samples/combi_2004.txt +--- +ROOT@0..674 + ENTRY@0..674 + TYPE@0..14 "@inproceedings" + L_DELIM@14..15 "{" + NAME@15..36 "10.1145/967900.968040" + COMMA@36..37 "," + WHITESPACE@37..42 "\n " + FIELD@42..86 + NAME@42..48 "author" + WHITESPACE@48..49 " " + EQ@49..50 "=" + WHITESPACE@50..51 " " + CURLY_GROUP@51..85 + L_CURLY@51..52 "{" + WORD@52..57 "Combi" + COMMA@57..58 "," + WHITESPACE@58..59 " " + WORD@59..64 "Carlo" + WHITESPACE@64..65 " " + WORD@65..68 "and" + WHITESPACE@68..69 " " + WORD@69..74 "Pozzi" + COMMA@74..75 "," + WHITESPACE@75..76 " " + WORD@76..84 "Giuseppe" + R_CURLY@84..85 "}" + COMMA@85..86 "," + WHITESPACE@86..91 "\n " + FIELD@91..157 + NAME@91..96 "title" + WHITESPACE@96..97 " " + EQ@97..98 "=" + WHITESPACE@98..99 " " + CURLY_GROUP@99..156 + L_CURLY@99..100 "{" + WORD@100..113 "Architectures" + WHITESPACE@113..114 " " + WORD@114..117 "for" + WHITESPACE@117..118 " " + WORD@118..119 "a" + WHITESPACE@119..120 " " + WORD@120..128 "Temporal" + WHITESPACE@128..129 " " + WORD@129..137 "Workflow" + WHITESPACE@137..138 " " + WORD@138..148 "Management" + WHITESPACE@148..149 " " + WORD@149..155 "System" + R_CURLY@155..156 "}" + COMMA@156..157 "," + WHITESPACE@157..162 "\n " + FIELD@162..176 + NAME@162..166 "year" + WHITESPACE@166..167 " " + EQ@167..168 "=" + WHITESPACE@168..169 " " + CURLY_GROUP@169..175 + L_CURLY@169..170 "{" + INTEGER@170..174 "2004" + R_CURLY@174..175 "}" + COMMA@175..176 "," + WHITESPACE@176..181 "\n " + FIELD@181..201 + NAME@181..185 "isbn" + WHITESPACE@185..186 " " + EQ@186..187 "=" + WHITESPACE@187..188 " " + CURLY_GROUP@188..200 + L_CURLY@188..189 "{" + INTEGER@189..199 "1581138121" + R_CURLY@199..200 "}" + COMMA@200..201 "," + WHITESPACE@201..206 "\n " + FIELD@206..256 + NAME@206..215 "publisher" + WHITESPACE@215..216 " " + EQ@216..217 "=" + WHITESPACE@217..218 " " + CURLY_GROUP@218..255 + L_CURLY@218..219 "{" + WORD@219..230 "Association" + WHITESPACE@230..231 " " + WORD@231..234 "for" + WHITESPACE@234..235 " " + WORD@235..244 "Computing" + WHITESPACE@244..245 " " + WORD@245..254 "Machinery" + R_CURLY@254..255 "}" + COMMA@255..256 "," + WHITESPACE@256..261 "\n " + FIELD@261..291 + NAME@261..268 "address" + WHITESPACE@268..269 " " + EQ@269..270 "=" + WHITESPACE@270..271 " " + CURLY_GROUP@271..290 + L_CURLY@271..272 "{" + WORD@272..275 "New" + WHITESPACE@275..276 " " + WORD@276..280 "York" + COMMA@280..281 "," + WHITESPACE@281..282 " " + WORD@282..284 "NY" + COMMA@284..285 "," + WHITESPACE@285..286 " " + WORD@286..289 "USA" + R_CURLY@289..290 "}" + COMMA@290..291 "," + WHITESPACE@291..296 "\n " + FIELD@296..342 + NAME@296..299 "url" + WHITESPACE@299..300 " " + EQ@300..301 "=" + WHITESPACE@301..302 " " + CURLY_GROUP@302..341 + L_CURLY@302..303 "{" + WORD@303..340 "https://doi.org/10.11 ..." + R_CURLY@340..341 "}" + COMMA@341..342 "," + WHITESPACE@342..347 "\n " + FIELD@347..377 + NAME@347..350 "doi" + WHITESPACE@350..351 " " + EQ@351..352 "=" + WHITESPACE@352..353 " " + CURLY_GROUP@353..376 + L_CURLY@353..354 "{" + WORD@354..375 "10.1145/967900.968040" + R_CURLY@375..376 "}" + COMMA@376..377 "," + WHITESPACE@377..382 "\n " + FIELD@382..455 + NAME@382..391 "booktitle" + WHITESPACE@391..392 " " + EQ@392..393 "=" + WHITESPACE@393..394 " " + CURLY_GROUP@394..454 + L_CURLY@394..395 "{" + WORD@395..406 "Proceedings" + WHITESPACE@406..407 " " + WORD@407..409 "of" + WHITESPACE@409..410 " " + WORD@410..413 "the" + WHITESPACE@413..414 " " + INTEGER@414..418 "2004" + WHITESPACE@418..419 " " + WORD@419..422 "ACM" + WHITESPACE@422..423 " " + WORD@423..432 "Symposium" + WHITESPACE@432..433 " " + WORD@433..435 "on" + WHITESPACE@435..436 " " + WORD@436..443 "Applied" + WHITESPACE@443..444 " " + WORD@444..453 "Computing" + R_CURLY@453..454 "}" + COMMA@454..455 "," + WHITESPACE@455..460 "\n " + FIELD@460..478 + NAME@460..465 "pages" + WHITESPACE@465..466 " " + EQ@466..467 "=" + WHITESPACE@467..468 " " + CURLY_GROUP@468..477 + L_CURLY@468..469 "{" + WORD@469..476 "659-666" + R_CURLY@476..477 "}" + COMMA@477..478 "," + WHITESPACE@478..483 "\n " + FIELD@483..498 + NAME@483..491 "numpages" + WHITESPACE@491..492 " " + EQ@492..493 "=" + WHITESPACE@493..494 " " + CURLY_GROUP@494..497 + L_CURLY@494..495 "{" + INTEGER@495..496 "8" + R_CURLY@496..497 "}" + COMMA@497..498 "," + WHITESPACE@498..503 "\n " + FIELD@503..615 + NAME@503..511 "keywords" + WHITESPACE@511..512 " " + EQ@512..513 "=" + WHITESPACE@513..514 " " + CURLY_GROUP@514..614 + L_CURLY@514..515 "{" + WORD@515..521 "active" + WHITESPACE@521..522 " " + WORD@522..526 "DBMS" + COMMA@526..527 "," + WHITESPACE@527..528 " " + WORD@528..536 "temporal" + WHITESPACE@536..537 " " + WORD@537..541 "DBMS" + COMMA@541..542 "," + WHITESPACE@542..543 " " + WORD@543..551 "workflow" + WHITESPACE@551..552 " " + WORD@552..562 "management" + WHITESPACE@562..563 " " + WORD@563..569 "system" + WHITESPACE@569..570 " " + WORD@570..571 "-" + WHITESPACE@571..572 " " + WORD@572..576 "WfMS" + COMMA@576..577 "," + WHITESPACE@577..578 " " + WORD@578..586 "temporal" + WHITESPACE@586..587 " " + WORD@587..595 "workflow" + WHITESPACE@595..596 " " + WORD@596..606 "management" + WHITESPACE@606..607 " " + WORD@607..613 "system" + R_CURLY@613..614 "}" + COMMA@614..615 "," + WHITESPACE@615..620 "\n " + FIELD@620..649 + NAME@620..628 "location" + WHITESPACE@628..629 " " + EQ@629..630 "=" + WHITESPACE@630..631 " " + CURLY_GROUP@631..648 + L_CURLY@631..632 "{" + WORD@632..639 "Nicosia" + COMMA@639..640 "," + WHITESPACE@640..641 " " + WORD@641..647 "Cyprus" + R_CURLY@647..648 "}" + COMMA@648..649 "," + WHITESPACE@649..654 "\n " + FIELD@654..673 + NAME@654..660 "series" + WHITESPACE@660..661 " " + EQ@661..662 "=" + WHITESPACE@662..663 " " + CURLY_GROUP@663..672 + L_CURLY@663..664 "{" + WORD@664..667 "SAC" + WHITESPACE@667..668 " " + WORD@668..671 "'04" + R_CURLY@671..672 "}" + WHITESPACE@672..673 "\n" + R_DELIM@673..674 "}" + diff --git a/support/texlab/src/parser/snapshots/texlab__parser__bibtex__tests__parse@samples__erwin_2007.txt.snap b/support/texlab/src/parser/snapshots/texlab__parser__bibtex__tests__parse@samples__erwin_2007.txt.snap new file mode 100644 index 0000000000..58094d2f42 --- /dev/null +++ b/support/texlab/src/parser/snapshots/texlab__parser__bibtex__tests__parse@samples__erwin_2007.txt.snap @@ -0,0 +1,239 @@ +--- +source: src/parser/bibtex.rs +expression: root +input_file: src/parser/test_data/bibtex/samples/erwin_2007.txt +--- +ROOT@0..615 + ENTRY@0..615 + TYPE@0..14 "@inproceedings" + L_DELIM@14..15 "{" + NAME@15..38 "10.5555/1386993.1386994" + COMMA@38..39 "," + WHITESPACE@39..44 "\n " + FIELD@44..107 + NAME@44..50 "author" + WHITESPACE@50..51 " " + EQ@51..52 "=" + WHITESPACE@52..53 " " + CURLY_GROUP@53..106 + L_CURLY@53..54 "{" + WORD@54..59 "Erwin" + COMMA@59..60 "," + WHITESPACE@60..61 " " + WORD@61..65 "Alva" + WHITESPACE@65..66 " " + WORD@66..69 "and" + WHITESPACE@69..70 " " + WORD@70..77 "Gopalan" + COMMA@77..78 "," + WHITESPACE@78..79 " " + WORD@79..82 "Raj" + WHITESPACE@82..83 " " + WORD@83..85 "P." + WHITESPACE@85..86 " " + WORD@86..89 "and" + WHITESPACE@89..90 " " + WORD@90..98 "Achuthan" + COMMA@98..99 "," + WHITESPACE@99..100 " " + WORD@100..102 "N." + WHITESPACE@102..103 " " + WORD@103..105 "R." + R_CURLY@105..106 "}" + COMMA@106..107 "," + WHITESPACE@107..112 "\n " + FIELD@112..194 + NAME@112..117 "title" + WHITESPACE@117..118 " " + EQ@118..119 "=" + WHITESPACE@119..120 " " + CURLY_GROUP@120..193 + L_CURLY@120..121 "{" + WORD@121..122 "A" + WHITESPACE@122..123 " " + WORD@123..132 "Bottom-up" + WHITESPACE@132..133 " " + WORD@133..143 "Projection" + WHITESPACE@143..144 " " + WORD@144..149 "Based" + WHITESPACE@149..150 " " + WORD@150..159 "Algorithm" + WHITESPACE@159..160 " " + WORD@160..163 "for" + WHITESPACE@163..164 " " + WORD@164..170 "Mining" + WHITESPACE@170..171 " " + WORD@171..175 "High" + WHITESPACE@175..176 " " + WORD@176..183 "Utility" + WHITESPACE@183..184 " " + WORD@184..192 "Itemsets" + R_CURLY@192..193 "}" + COMMA@193..194 "," + WHITESPACE@194..199 "\n " + FIELD@199..213 + NAME@199..203 "year" + WHITESPACE@203..204 " " + EQ@204..205 "=" + WHITESPACE@205..206 " " + CURLY_GROUP@206..212 + L_CURLY@206..207 "{" + INTEGER@207..211 "2007" + R_CURLY@211..212 "}" + COMMA@212..213 "," + WHITESPACE@213..218 "\n " + FIELD@218..241 + NAME@218..222 "isbn" + WHITESPACE@222..223 " " + EQ@223..224 "=" + WHITESPACE@224..225 " " + CURLY_GROUP@225..240 + L_CURLY@225..226 "{" + INTEGER@226..239 "9781920682651" + R_CURLY@239..240 "}" + COMMA@240..241 "," + WHITESPACE@241..246 "\n " + FIELD@246..294 + NAME@246..255 "publisher" + WHITESPACE@255..256 " " + EQ@256..257 "=" + WHITESPACE@257..258 " " + CURLY_GROUP@258..293 + L_CURLY@258..259 "{" + WORD@259..269 "Australian" + WHITESPACE@269..270 " " + WORD@270..278 "Computer" + WHITESPACE@278..279 " " + WORD@279..286 "Society" + COMMA@286..287 "," + WHITESPACE@287..288 " " + WORD@288..292 "Inc." + R_CURLY@292..293 "}" + COMMA@293..294 "," + WHITESPACE@294..299 "\n " + FIELD@299..315 + NAME@299..306 "address" + WHITESPACE@306..307 " " + EQ@307..308 "=" + WHITESPACE@308..309 " " + CURLY_GROUP@309..314 + L_CURLY@309..310 "{" + WORD@310..313 "AUS" + R_CURLY@313..314 "}" + COMMA@314..315 "," + WHITESPACE@315..320 "\n " + FIELD@320..447 + NAME@320..329 "booktitle" + WHITESPACE@329..330 " " + EQ@330..331 "=" + WHITESPACE@331..332 " " + CURLY_GROUP@332..446 + L_CURLY@332..333 "{" + WORD@333..344 "Proceedings" + WHITESPACE@344..345 " " + WORD@345..347 "of" + WHITESPACE@347..348 " " + WORD@348..351 "the" + WHITESPACE@351..352 " " + WORD@352..355 "2nd" + WHITESPACE@355..356 " " + WORD@356..369 "International" + WHITESPACE@369..370 " " + WORD@370..378 "Workshop" + WHITESPACE@378..379 " " + WORD@379..381 "on" + WHITESPACE@381..382 " " + WORD@382..393 "Integrating" + WHITESPACE@393..394 " " + WORD@394..404 "Artificial" + WHITESPACE@404..405 " " + WORD@405..417 "Intelligence" + WHITESPACE@417..418 " " + WORD@418..421 "and" + WHITESPACE@421..422 " " + WORD@422..426 "Data" + WHITESPACE@426..427 " " + WORD@427..433 "Mining" + WHITESPACE@433..434 " " + WORD@434..435 "-" + WHITESPACE@435..436 " " + WORD@436..442 "Volume" + WHITESPACE@442..443 " " + INTEGER@443..445 "84" + R_CURLY@445..446 "}" + COMMA@446..447 "," + WHITESPACE@447..452 "\n " + FIELD@452..467 + NAME@452..457 "pages" + WHITESPACE@457..458 " " + EQ@458..459 "=" + WHITESPACE@459..460 " " + CURLY_GROUP@460..466 + L_CURLY@460..461 "{" + WORD@461..465 "3-11" + R_CURLY@465..466 "}" + COMMA@466..467 "," + WHITESPACE@467..472 "\n " + FIELD@472..487 + NAME@472..480 "numpages" + WHITESPACE@480..481 " " + EQ@481..482 "=" + WHITESPACE@482..483 " " + CURLY_GROUP@483..486 + L_CURLY@483..484 "{" + INTEGER@484..485 "9" + R_CURLY@485..486 "}" + COMMA@486..487 "," + WHITESPACE@487..492 "\n " + FIELD@492..549 + NAME@492..500 "keywords" + WHITESPACE@500..501 " " + EQ@501..502 "=" + WHITESPACE@502..503 " " + CURLY_GROUP@503..548 + L_CURLY@503..504 "{" + WORD@504..511 "pattern" + WHITESPACE@511..512 " " + WORD@512..518 "growth" + COMMA@518..519 "," + WHITESPACE@519..520 " " + WORD@520..524 "high" + WHITESPACE@524..525 " " + WORD@525..532 "utility" + WHITESPACE@532..533 " " + WORD@533..540 "itemset" + WHITESPACE@540..541 " " + WORD@541..547 "mining" + R_CURLY@547..548 "}" + COMMA@548..549 "," + WHITESPACE@549..554 "\n " + FIELD@554..589 + NAME@554..562 "location" + WHITESPACE@562..563 " " + EQ@563..564 "=" + WHITESPACE@564..565 " " + CURLY_GROUP@565..588 + L_CURLY@565..566 "{" + WORD@566..570 "Gold" + WHITESPACE@570..571 " " + WORD@571..576 "Coast" + COMMA@576..577 "," + WHITESPACE@577..578 " " + WORD@578..587 "Australia" + R_CURLY@587..588 "}" + COMMA@588..589 "," + WHITESPACE@589..594 "\n " + FIELD@594..614 + NAME@594..600 "series" + WHITESPACE@600..601 " " + EQ@601..602 "=" + WHITESPACE@602..603 " " + CURLY_GROUP@603..613 + L_CURLY@603..604 "{" + WORD@604..608 "AIDM" + WHITESPACE@608..609 " " + WORD@609..612 "'07" + R_CURLY@612..613 "}" + WHITESPACE@613..614 "\n" + R_DELIM@614..615 "}" + diff --git a/support/texlab/src/parser/snapshots/texlab__parser__bibtex__tests__parse@samples__jain_1999.txt.snap b/support/texlab/src/parser/snapshots/texlab__parser__bibtex__tests__parse@samples__jain_1999.txt.snap new file mode 100644 index 0000000000..d9f83b339a --- /dev/null +++ b/support/texlab/src/parser/snapshots/texlab__parser__bibtex__tests__parse@samples__jain_1999.txt.snap @@ -0,0 +1,267 @@ +--- +source: src/parser/bibtex.rs +expression: root +input_file: src/parser/test_data/bibtex/samples/jain_1999.txt +--- +ROOT@0..674 + ENTRY@0..674 + TYPE@0..8 "@article" + L_DELIM@8..9 "{" + NAME@9..30 "10.1145/331499.331504" + COMMA@30..31 "," + WHITESPACE@31..36 "\n " + FIELD@36..93 + NAME@36..42 "author" + WHITESPACE@42..43 " " + EQ@43..44 "=" + WHITESPACE@44..45 " " + CURLY_GROUP@45..92 + L_CURLY@45..46 "{" + WORD@46..50 "Jain" + COMMA@50..51 "," + WHITESPACE@51..52 " " + WORD@52..54 "A." + WHITESPACE@54..55 " " + WORD@55..57 "K." + WHITESPACE@57..58 " " + WORD@58..61 "and" + WHITESPACE@61..62 " " + WORD@62..67 "Murty" + COMMA@67..68 "," + WHITESPACE@68..69 " " + WORD@69..71 "M." + WHITESPACE@71..72 " " + WORD@72..74 "N." + WHITESPACE@74..75 " " + WORD@75..78 "and" + WHITESPACE@78..79 " " + WORD@79..84 "Flynn" + COMMA@84..85 "," + WHITESPACE@85..86 " " + WORD@86..88 "P." + WHITESPACE@88..89 " " + WORD@89..91 "J." + R_CURLY@91..92 "}" + COMMA@92..93 "," + WHITESPACE@93..98 "\n " + FIELD@98..134 + NAME@98..103 "title" + WHITESPACE@103..104 " " + EQ@104..105 "=" + WHITESPACE@105..106 " " + CURLY_GROUP@106..133 + L_CURLY@106..107 "{" + WORD@107..111 "Data" + WHITESPACE@111..112 " " + WORD@112..123 "Clustering:" + WHITESPACE@123..124 " " + WORD@124..125 "A" + WHITESPACE@125..126 " " + WORD@126..132 "Review" + R_CURLY@132..133 "}" + COMMA@133..134 "," + WHITESPACE@134..139 "\n " + FIELD@139..153 + NAME@139..143 "year" + WHITESPACE@143..144 " " + EQ@144..145 "=" + WHITESPACE@145..146 " " + CURLY_GROUP@146..152 + L_CURLY@146..147 "{" + INTEGER@147..151 "1999" + R_CURLY@151..152 "}" + COMMA@152..153 "," + WHITESPACE@153..158 "\n " + FIELD@158..184 + NAME@158..168 "issue_date" + WHITESPACE@168..169 " " + EQ@169..170 "=" + WHITESPACE@170..171 " " + CURLY_GROUP@171..183 + L_CURLY@171..172 "{" + WORD@172..177 "Sept." + WHITESPACE@177..178 " " + INTEGER@178..182 "1999" + R_CURLY@182..183 "}" + COMMA@183..184 "," + WHITESPACE@184..189 "\n " + FIELD@189..239 + NAME@189..198 "publisher" + WHITESPACE@198..199 " " + EQ@199..200 "=" + WHITESPACE@200..201 " " + CURLY_GROUP@201..238 + L_CURLY@201..202 "{" + WORD@202..213 "Association" + WHITESPACE@213..214 " " + WORD@214..217 "for" + WHITESPACE@217..218 " " + WORD@218..227 "Computing" + WHITESPACE@227..228 " " + WORD@228..237 "Machinery" + R_CURLY@237..238 "}" + COMMA@238..239 "," + WHITESPACE@239..244 "\n " + FIELD@244..274 + NAME@244..251 "address" + WHITESPACE@251..252 " " + EQ@252..253 "=" + WHITESPACE@253..254 " " + CURLY_GROUP@254..273 + L_CURLY@254..255 "{" + WORD@255..258 "New" + WHITESPACE@258..259 " " + WORD@259..263 "York" + COMMA@263..264 "," + WHITESPACE@264..265 " " + WORD@265..267 "NY" + COMMA@267..268 "," + WHITESPACE@268..269 " " + WORD@269..272 "USA" + R_CURLY@272..273 "}" + COMMA@273..274 "," + WHITESPACE@274..279 "\n " + FIELD@279..293 + NAME@279..285 "volume" + WHITESPACE@285..286 " " + EQ@286..287 "=" + WHITESPACE@287..288 " " + CURLY_GROUP@288..292 + L_CURLY@288..289 "{" + INTEGER@289..291 "31" + R_CURLY@291..292 "}" + COMMA@292..293 "," + WHITESPACE@293..298 "\n " + FIELD@298..311 + NAME@298..304 "number" + WHITESPACE@304..305 " " + EQ@305..306 "=" + WHITESPACE@306..307 " " + CURLY_GROUP@307..310 + L_CURLY@307..308 "{" + INTEGER@308..309 "3" + R_CURLY@309..310 "}" + COMMA@310..311 "," + WHITESPACE@311..316 "\n " + FIELD@316..335 + NAME@316..320 "issn" + WHITESPACE@320..321 " " + EQ@321..322 "=" + WHITESPACE@322..323 " " + CURLY_GROUP@323..334 + L_CURLY@323..324 "{" + WORD@324..333 "0360-0300" + R_CURLY@333..334 "}" + COMMA@334..335 "," + WHITESPACE@335..340 "\n " + FIELD@340..386 + NAME@340..343 "url" + WHITESPACE@343..344 " " + EQ@344..345 "=" + WHITESPACE@345..346 " " + CURLY_GROUP@346..385 + L_CURLY@346..347 "{" + WORD@347..384 "https://doi.org/10.11 ..." + R_CURLY@384..385 "}" + COMMA@385..386 "," + WHITESPACE@386..391 "\n " + FIELD@391..421 + NAME@391..394 "doi" + WHITESPACE@394..395 " " + EQ@395..396 "=" + WHITESPACE@396..397 " " + CURLY_GROUP@397..420 + L_CURLY@397..398 "{" + WORD@398..419 "10.1145/331499.331504" + R_CURLY@419..420 "}" + COMMA@420..421 "," + WHITESPACE@421..426 "\n " + FIELD@426..456 + NAME@426..433 "journal" + WHITESPACE@433..434 " " + EQ@434..435 "=" + WHITESPACE@435..436 " " + CURLY_GROUP@436..455 + L_CURLY@436..437 "{" + WORD@437..440 "ACM" + WHITESPACE@440..441 " " + WORD@441..448 "Comput." + WHITESPACE@448..449 " " + WORD@449..454 "Surv." + R_CURLY@454..455 "}" + COMMA@455..456 "," + WHITESPACE@456..461 "\n " + FIELD@461..475 + NAME@461..466 "month" + WHITESPACE@466..467 " " + EQ@467..468 "=" + WHITESPACE@468..469 " " + CURLY_GROUP@469..474 + L_CURLY@469..470 "{" + WORD@470..473 "sep" + R_CURLY@473..474 "}" + COMMA@474..475 "," + WHITESPACE@475..480 "\n " + FIELD@480..498 + NAME@480..485 "pages" + WHITESPACE@485..486 " " + EQ@486..487 "=" + WHITESPACE@487..488 " " + CURLY_GROUP@488..497 + L_CURLY@488..489 "{" + WORD@489..496 "264-323" + R_CURLY@496..497 "}" + COMMA@497..498 "," + WHITESPACE@498..503 "\n " + FIELD@503..519 + NAME@503..511 "numpages" + WHITESPACE@511..512 " " + EQ@512..513 "=" + WHITESPACE@513..514 " " + CURLY_GROUP@514..518 + L_CURLY@514..515 "{" + INTEGER@515..517 "60" + R_CURLY@517..518 "}" + COMMA@518..519 "," + WHITESPACE@519..524 "\n " + FIELD@524..673 + NAME@524..532 "keywords" + WHITESPACE@532..533 " " + EQ@533..534 "=" + WHITESPACE@534..535 " " + CURLY_GROUP@535..672 + L_CURLY@535..536 "{" + WORD@536..547 "incremental" + WHITESPACE@547..548 " " + WORD@548..558 "clustering" + COMMA@558..559 "," + WHITESPACE@559..560 " " + WORD@560..570 "clustering" + WHITESPACE@570..571 " " + WORD@571..583 "applications" + COMMA@583..584 "," + WHITESPACE@584..585 " " + WORD@585..596 "exploratory" + WHITESPACE@596..597 " " + WORD@597..601 "data" + WHITESPACE@601..602 " " + WORD@602..610 "analysis" + COMMA@610..611 "," + WHITESPACE@611..612 " " + WORD@612..619 "cluster" + WHITESPACE@619..620 " " + WORD@620..628 "analysis" + COMMA@628..629 "," + WHITESPACE@629..630 " " + WORD@630..640 "similarity" + WHITESPACE@640..641 " " + WORD@641..648 "indices" + COMMA@648..649 "," + WHITESPACE@649..650 " " + WORD@650..662 "unsupervised" + WHITESPACE@662..663 " " + WORD@663..671 "learning" + R_CURLY@671..672 "}" + WHITESPACE@672..673 "\n" + R_DELIM@673..674 "}" + diff --git a/support/texlab/src/parser/snapshots/texlab__parser__bibtex__tests__parse@samples__kastenholz_2006.txt.snap b/support/texlab/src/parser/snapshots/texlab__parser__bibtex__tests__parse@samples__kastenholz_2006.txt.snap new file mode 100644 index 0000000000..8d67f95096 --- /dev/null +++ b/support/texlab/src/parser/snapshots/texlab__parser__bibtex__tests__parse@samples__kastenholz_2006.txt.snap @@ -0,0 +1,302 @@ +--- +source: src/parser/bibtex.rs +expression: root +input_file: src/parser/test_data/bibtex/samples/kastenholz_2006.txt +--- +ROOT@0..898 + STRING@0..35 + TYPE@0..7 "@string" + L_DELIM@7..8 "{" + NAME@8..13 "jchph" + WHITESPACE@13..16 " " + EQ@16..17 "=" + WHITESPACE@17..18 " " + CURLY_GROUP@18..34 + L_CURLY@18..19 "{" + WORD@19..21 "J." + NBSP@21..22 "~" + WORD@22..27 "Chem." + WHITESPACE@27..28 " " + WORD@28..33 "Phys." + R_CURLY@33..34 "}" + R_DELIM@34..35 "}" + JUNK@35..37 "\n\n" + ENTRY@37..898 + TYPE@37..45 "@article" + L_DELIM@45..46 "{" + NAME@46..56 "kastenholz" + COMMA@56..57 "," + WHITESPACE@57..62 "\n " + FIELD@62..130 + NAME@62..68 "author" + WHITESPACE@68..75 " " + EQ@75..76 "=" + WHITESPACE@76..77 " " + CURLY_GROUP@77..129 + L_CURLY@77..78 "{" + WORD@78..88 "Kastenholz" + COMMA@88..89 "," + WHITESPACE@89..90 " " + WORD@90..92 "M." + WHITESPACE@92..93 " " + WORD@93..95 "A." + WHITESPACE@95..96 " " + WORD@96..99 "and" + WHITESPACE@99..100 " " + WORD@100..101 "H" + CURLY_GROUP@101..106 + L_CURLY@101..102 "{" + ACCENT@102..105 + ACCENT_NAME@102..104 "\\\"" + WORD@104..105 "u" + R_CURLY@105..106 "}" + WORD@106..115 "nenberger" + COMMA@115..116 "," + WHITESPACE@116..117 " " + WORD@117..125 "Philippe" + WHITESPACE@125..126 " " + WORD@126..128 "H." + R_CURLY@128..129 "}" + COMMA@129..130 "," + WHITESPACE@130..135 "\n " + FIELD@135..275 + NAME@135..140 "title" + WHITESPACE@140..148 " " + EQ@148..149 "=" + WHITESPACE@149..150 " " + CURLY_GROUP@150..274 + L_CURLY@150..151 "{" + WORD@151..162 "Computation" + WHITESPACE@162..163 " " + WORD@163..165 "of" + WHITESPACE@165..166 " " + WORD@166..177 "methodology" + COMMAND@177..184 + COMMAND_NAME@177..184 "\\hyphen" + WHITESPACE@184..185 " " + WORD@185..196 "independent" + WHITESPACE@196..197 " " + WORD@197..202 "ionic" + WHITESPACE@202..203 " " + WORD@203..212 "solvation" + WHITESPACE@212..233 "\n " + WORD@233..237 "free" + WHITESPACE@237..238 " " + WORD@238..246 "energies" + WHITESPACE@246..247 " " + WORD@247..251 "from" + WHITESPACE@251..252 " " + WORD@252..261 "molecular" + WHITESPACE@261..262 " " + WORD@262..273 "simulations" + R_CURLY@273..274 "}" + COMMA@274..275 "," + WHITESPACE@275..280 "\n " + FIELD@280..301 + NAME@280..292 "journaltitle" + WHITESPACE@292..293 " " + EQ@293..294 "=" + WHITESPACE@294..295 " " + LITERAL@295..300 + NAME@295..300 "jchph" + COMMA@300..301 "," + WHITESPACE@301..306 "\n " + FIELD@306..326 + NAME@306..310 "date" + WHITESPACE@310..319 " " + EQ@319..320 "=" + WHITESPACE@320..321 " " + LITERAL@321..325 + INTEGER@321..325 "2006" + COMMA@325..326 "," + WHITESPACE@326..331 "\n " + FIELD@331..404 + NAME@331..339 "subtitle" + WHITESPACE@339..344 " " + EQ@344..345 "=" + WHITESPACE@345..346 " " + CURLY_GROUP@346..403 + L_CURLY@346..347 "{" + CURLY_GROUP@347..350 + L_CURLY@347..348 "{" + WORD@348..349 "I" + R_CURLY@349..350 "}" + WORD@350..351 "." + WHITESPACE@351..352 " " + CURLY_GROUP@352..357 + L_CURLY@352..353 "{" + WORD@353..356 "The" + R_CURLY@356..357 "}" + WHITESPACE@357..358 " " + WORD@358..371 "electrostatic" + WHITESPACE@371..372 " " + WORD@372..381 "potential" + WHITESPACE@381..382 " " + WORD@382..384 "in" + WHITESPACE@384..385 " " + WORD@385..394 "molecular" + WHITESPACE@394..395 " " + WORD@395..402 "liquids" + R_CURLY@402..403 "}" + COMMA@403..404 "," + WHITESPACE@404..409 "\n " + FIELD@409..428 + NAME@409..415 "volume" + WHITESPACE@415..422 " " + EQ@422..423 "=" + WHITESPACE@423..424 " " + LITERAL@424..427 + INTEGER@424..427 "124" + COMMA@427..428 "," + WHITESPACE@428..433 "\n " + FIELD@433..455 + NAME@433..436 "eid" + WHITESPACE@436..446 " " + EQ@446..447 "=" + WHITESPACE@447..448 " " + LITERAL@448..454 + INTEGER@448..454 "124106" + COMMA@454..455 "," + WHITESPACE@455..460 "\n " + FIELD@460..495 + NAME@460..463 "doi" + WHITESPACE@463..473 " " + EQ@473..474 "=" + WHITESPACE@474..475 " " + CURLY_GROUP@475..494 + L_CURLY@475..476 "{" + WORD@476..493 "10.1063/1.2172593" + R_CURLY@493..494 "}" + COMMA@494..495 "," + WHITESPACE@495..500 "\n " + FIELD@500..525 + NAME@500..506 "langid" + WHITESPACE@506..513 " " + EQ@513..514 "=" + WHITESPACE@514..515 " " + CURLY_GROUP@515..524 + L_CURLY@515..516 "{" + WORD@516..523 "english" + R_CURLY@523..524 "}" + COMMA@524..525 "," + WHITESPACE@525..530 "\n " + FIELD@530..564 + NAME@530..540 "langidopts" + WHITESPACE@540..543 " " + EQ@543..544 "=" + WHITESPACE@544..545 " " + CURLY_GROUP@545..563 + L_CURLY@545..546 "{" + WORD@546..562 "variant=american" + R_CURLY@562..563 "}" + COMMA@563..564 "," + WHITESPACE@564..569 "\n " + FIELD@569..631 + NAME@569..579 "indextitle" + WHITESPACE@579..582 " " + EQ@582..583 "=" + WHITESPACE@583..584 " " + CURLY_GROUP@584..630 + L_CURLY@584..585 "{" + WORD@585..596 "Computation" + WHITESPACE@596..597 " " + WORD@597..599 "of" + WHITESPACE@599..600 " " + WORD@600..605 "ionic" + WHITESPACE@605..606 " " + WORD@606..615 "solvation" + WHITESPACE@615..616 " " + WORD@616..620 "free" + WHITESPACE@620..621 " " + WORD@621..629 "energies" + R_CURLY@629..630 "}" + COMMA@630..631 "," + WHITESPACE@631..636 "\n " + FIELD@636..896 + NAME@636..646 "annotation" + WHITESPACE@646..649 " " + EQ@649..650 "=" + WHITESPACE@650..651 " " + CURLY_GROUP@651..895 + L_CURLY@651..652 "{" + WORD@652..654 "An" + WHITESPACE@654..655 " " + COMMAND@655..662 + COMMAND_NAME@655..662 "\\texttt" + CURLY_GROUP@662..671 + L_CURLY@662..663 "{" + WORD@663..670 "article" + R_CURLY@670..671 "}" + WHITESPACE@671..672 " " + WORD@672..677 "entry" + WHITESPACE@677..678 " " + WORD@678..682 "with" + WHITESPACE@682..683 " " + WORD@683..685 "an" + WHITESPACE@685..686 " " + COMMAND@686..693 + COMMAND_NAME@686..693 "\\texttt" + CURLY_GROUP@693..698 + L_CURLY@693..694 "{" + WORD@694..697 "eid" + R_CURLY@697..698 "}" + WHITESPACE@698..699 " " + WORD@699..702 "and" + WHITESPACE@702..703 " " + WORD@703..704 "a" + WHITESPACE@704..725 "\n " + COMMAND@725..732 + COMMAND_NAME@725..732 "\\texttt" + CURLY_GROUP@732..737 + L_CURLY@732..733 "{" + WORD@733..736 "doi" + R_CURLY@736..737 "}" + WHITESPACE@737..738 " " + WORD@738..744 "field." + WHITESPACE@744..745 " " + WORD@745..749 "Note" + WHITESPACE@749..750 " " + WORD@750..754 "that" + WHITESPACE@754..755 " " + WORD@755..758 "the" + WHITESPACE@758..759 " " + COMMAND@759..766 + COMMAND_NAME@759..766 "\\textsc" + CURLY_GROUP@766..771 + L_CURLY@766..767 "{" + WORD@767..770 "doi" + R_CURLY@770..771 "}" + WHITESPACE@771..772 " " + WORD@772..774 "is" + WHITESPACE@774..775 " " + WORD@775..786 "transformed" + WHITESPACE@786..807 "\n " + WORD@807..811 "into" + WHITESPACE@811..812 " " + WORD@812..813 "a" + WHITESPACE@813..814 " " + WORD@814..823 "clickable" + WHITESPACE@823..824 " " + WORD@824..828 "link" + WHITESPACE@828..829 " " + WORD@829..831 "if" + WHITESPACE@831..832 " " + COMMAND@832..839 + COMMAND_NAME@832..839 "\\texttt" + CURLY_GROUP@839..849 + L_CURLY@839..840 "{" + WORD@840..848 "hyperref" + R_CURLY@848..849 "}" + WHITESPACE@849..850 " " + WORD@850..857 "support" + WHITESPACE@857..858 " " + WORD@858..861 "has" + WHITESPACE@861..862 " " + WORD@862..866 "been" + WHITESPACE@866..887 "\n " + WORD@887..894 "enabled" + R_CURLY@894..895 "}" + COMMA@895..896 "," + WHITESPACE@896..897 "\n" + R_DELIM@897..898 "}" + diff --git a/support/texlab/src/parser/snapshots/texlab__parser__bibtex__tests__parse@samples__knuth_1984.txt.snap b/support/texlab/src/parser/snapshots/texlab__parser__bibtex__tests__parse@samples__knuth_1984.txt.snap new file mode 100644 index 0000000000..2be9233f95 --- /dev/null +++ b/support/texlab/src/parser/snapshots/texlab__parser__bibtex__tests__parse@samples__knuth_1984.txt.snap @@ -0,0 +1,320 @@ +--- +source: src/parser/bibtex.rs +expression: root +input_file: src/parser/test_data/bibtex/samples/knuth_1984.txt +--- +ROOT@0..993 + ENTRY@0..993 + TYPE@0..5 "@book" + L_DELIM@5..6 "{" + NAME@6..16 "knuth:ct:a" + COMMA@16..17 "," + WHITESPACE@17..22 "\n " + FIELD@22..56 + NAME@22..28 "author" + WHITESPACE@28..35 " " + EQ@35..36 "=" + WHITESPACE@36..37 " " + CURLY_GROUP@37..55 + L_CURLY@37..38 "{" + WORD@38..43 "Knuth" + COMMA@43..44 "," + WHITESPACE@44..45 " " + WORD@45..51 "Donald" + WHITESPACE@51..52 " " + WORD@52..54 "E." + R_CURLY@54..55 "}" + COMMA@55..56 "," + WHITESPACE@56..61 "\n " + FIELD@61..94 + NAME@61..66 "title" + WHITESPACE@66..74 " " + EQ@74..75 "=" + WHITESPACE@75..76 " " + CURLY_GROUP@76..93 + L_CURLY@76..77 "{" + WORD@77..80 "The" + WHITESPACE@80..81 " " + CURLY_GROUP@81..92 + L_CURLY@81..82 "{" + COMMAND@82..86 + COMMAND_NAME@82..86 "\\TeX" + WHITESPACE@86..87 " " + WORD@87..91 "book" + R_CURLY@91..92 "}" + R_CURLY@92..93 "}" + COMMA@93..94 "," + WHITESPACE@94..99 "\n " + FIELD@99..119 + NAME@99..103 "date" + WHITESPACE@103..112 " " + EQ@112..113 "=" + WHITESPACE@113..114 " " + LITERAL@114..118 + INTEGER@114..118 "1984" + COMMA@118..119 "," + WHITESPACE@119..124 "\n " + FIELD@124..166 + NAME@124..133 "maintitle" + WHITESPACE@133..137 " " + EQ@137..138 "=" + WHITESPACE@138..139 " " + CURLY_GROUP@139..165 + L_CURLY@139..140 "{" + WORD@140..149 "Computers" + WHITESPACE@149..150 " " + COMMAND@150..152 + COMMAND_NAME@150..152 "\\&" + WHITESPACE@152..153 " " + WORD@153..164 "Typesetting" + R_CURLY@164..165 "}" + COMMA@165..166 "," + WHITESPACE@166..171 "\n " + FIELD@171..190 + NAME@171..177 "volume" + WHITESPACE@177..184 " " + EQ@184..185 "=" + WHITESPACE@185..186 " " + CURLY_GROUP@186..189 + L_CURLY@186..187 "{" + WORD@187..188 "A" + R_CURLY@188..189 "}" + COMMA@189..190 "," + WHITESPACE@190..195 "\n " + FIELD@195..227 + NAME@195..204 "publisher" + WHITESPACE@204..208 " " + EQ@208..209 "=" + WHITESPACE@209..210 " " + CURLY_GROUP@210..226 + L_CURLY@210..211 "{" + WORD@211..225 "Addison-Wesley" + R_CURLY@225..226 "}" + COMMA@226..227 "," + WHITESPACE@227..232 "\n " + FIELD@232..264 + NAME@232..240 "location" + WHITESPACE@240..245 " " + EQ@245..246 "=" + WHITESPACE@246..247 " " + CURLY_GROUP@247..263 + L_CURLY@247..248 "{" + WORD@248..255 "Reading" + COMMA@255..256 "," + WHITESPACE@256..257 " " + WORD@257..262 "Mass." + R_CURLY@262..263 "}" + COMMA@263..264 "," + WHITESPACE@264..269 "\n " + FIELD@269..294 + NAME@269..275 "langid" + WHITESPACE@275..282 " " + EQ@282..283 "=" + WHITESPACE@283..284 " " + CURLY_GROUP@284..293 + L_CURLY@284..285 "{" + WORD@285..292 "english" + R_CURLY@292..293 "}" + COMMA@293..294 "," + WHITESPACE@294..299 "\n " + FIELD@299..333 + NAME@299..309 "langidopts" + WHITESPACE@309..312 " " + EQ@312..313 "=" + WHITESPACE@313..314 " " + CURLY_GROUP@314..332 + L_CURLY@314..315 "{" + WORD@315..331 "variant=american" + R_CURLY@331..332 "}" + COMMA@332..333 "," + WHITESPACE@333..338 "\n " + FIELD@338..381 + NAME@338..347 "sorttitle" + WHITESPACE@347..351 " " + EQ@351..352 "=" + WHITESPACE@352..353 " " + CURLY_GROUP@353..380 + L_CURLY@353..354 "{" + WORD@354..363 "Computers" + WHITESPACE@363..364 " " + WORD@364..365 "&" + WHITESPACE@365..366 " " + WORD@366..377 "Typesetting" + WHITESPACE@377..378 " " + WORD@378..379 "A" + R_CURLY@379..380 "}" + COMMA@380..381 "," + WHITESPACE@381..386 "\n " + FIELD@386..416 + NAME@386..400 "indexsorttitle" + EQ@400..401 "=" + WHITESPACE@401..402 " " + CURLY_GROUP@402..415 + L_CURLY@402..403 "{" + WORD@403..406 "The" + WHITESPACE@406..407 " " + WORD@407..414 "TeXbook" + R_CURLY@414..415 "}" + COMMA@415..416 "," + WHITESPACE@416..421 "\n " + FIELD@421..461 + NAME@421..431 "indextitle" + WHITESPACE@431..434 " " + EQ@434..435 "=" + WHITESPACE@435..436 " " + CURLY_GROUP@436..460 + L_CURLY@436..437 "{" + COMMAND@437..445 + COMMAND_NAME@437..445 "\\protect" + COMMAND@445..449 + COMMAND_NAME@445..449 "\\TeX" + WHITESPACE@449..450 " " + WORD@450..454 "book" + COMMA@454..455 "," + WHITESPACE@455..456 " " + WORD@456..459 "The" + R_CURLY@459..460 "}" + COMMA@460..461 "," + WHITESPACE@461..466 "\n " + FIELD@466..493 + NAME@466..476 "shorttitle" + WHITESPACE@476..479 " " + EQ@479..480 "=" + WHITESPACE@480..481 " " + CURLY_GROUP@481..492 + L_CURLY@481..482 "{" + COMMAND@482..486 + COMMAND_NAME@482..486 "\\TeX" + WHITESPACE@486..487 " " + WORD@487..491 "book" + R_CURLY@491..492 "}" + COMMA@492..493 "," + WHITESPACE@493..498 "\n " + FIELD@498..991 + NAME@498..508 "annotation" + WHITESPACE@508..511 " " + EQ@511..512 "=" + WHITESPACE@512..513 " " + CURLY_GROUP@513..990 + L_CURLY@513..514 "{" + WORD@514..517 "The" + WHITESPACE@517..518 " " + WORD@518..523 "first" + WHITESPACE@523..524 " " + WORD@524..530 "volume" + WHITESPACE@530..531 " " + WORD@531..533 "of" + WHITESPACE@533..534 " " + WORD@534..535 "a" + WHITESPACE@535..536 " " + WORD@536..547 "five-volume" + WHITESPACE@547..548 " " + WORD@548..553 "book." + WHITESPACE@553..554 " " + WORD@554..558 "Note" + WHITESPACE@558..559 " " + WORD@559..562 "the" + WHITESPACE@562..583 "\n " + COMMAND@583..590 + COMMAND_NAME@583..590 "\\texttt" + CURLY_GROUP@590..601 + L_CURLY@590..591 "{" + WORD@591..600 "sorttitle" + R_CURLY@600..601 "}" + WHITESPACE@601..602 " " + WORD@602..608 "field." + WHITESPACE@608..609 " " + WORD@609..611 "We" + WHITESPACE@611..612 " " + WORD@612..616 "want" + WHITESPACE@616..617 " " + WORD@617..621 "this" + WHITESPACE@621..642 "\n " + WORD@642..648 "volume" + WHITESPACE@648..649 " " + WORD@649..651 "to" + WHITESPACE@651..652 " " + WORD@652..654 "be" + WHITESPACE@654..655 " " + WORD@655..661 "listed" + WHITESPACE@661..662 " " + WORD@662..667 "after" + WHITESPACE@667..668 " " + WORD@668..671 "the" + WHITESPACE@671..672 " " + WORD@672..677 "entry" + WHITESPACE@677..678 " " + WORD@678..687 "referring" + WHITESPACE@687..688 " " + WORD@688..690 "to" + WHITESPACE@690..691 " " + WORD@691..694 "the" + WHITESPACE@694..695 " " + WORD@695..701 "entire" + WHITESPACE@701..722 "\n " + WORD@722..733 "five-volume" + WHITESPACE@733..734 " " + WORD@734..738 "set." + WHITESPACE@738..739 " " + WORD@739..743 "Also" + WHITESPACE@743..744 " " + WORD@744..748 "note" + WHITESPACE@748..749 " " + WORD@749..752 "the" + WHITESPACE@752..753 " " + COMMAND@753..760 + COMMAND_NAME@753..760 "\\texttt" + CURLY_GROUP@760..772 + L_CURLY@760..761 "{" + WORD@761..771 "indextitle" + R_CURLY@771..772 "}" + WHITESPACE@772..773 " " + WORD@773..776 "and" + WHITESPACE@776..797 "\n " + COMMAND@797..804 + COMMAND_NAME@797..804 "\\texttt" + CURLY_GROUP@804..820 + L_CURLY@804..805 "{" + WORD@805..819 "indexsorttitle" + R_CURLY@819..820 "}" + WHITESPACE@820..821 " " + WORD@821..828 "fields." + WHITESPACE@828..829 " " + WORD@829..837 "Indexing" + WHITESPACE@837..838 " " + WORD@838..846 "packages" + WHITESPACE@846..847 " " + WORD@847..851 "that" + WHITESPACE@851..852 " " + WORD@852..857 "don't" + WHITESPACE@857..878 "\n " + WORD@878..886 "generate" + WHITESPACE@886..887 " " + WORD@887..893 "robust" + WHITESPACE@893..894 " " + WORD@894..899 "index" + WHITESPACE@899..900 " " + WORD@900..907 "entries" + WHITESPACE@907..908 " " + WORD@908..915 "require" + WHITESPACE@915..916 " " + WORD@916..920 "some" + WHITESPACE@920..921 " " + WORD@921..928 "control" + WHITESPACE@928..929 " " + WORD@929..938 "sequences" + WHITESPACE@938..959 "\n " + WORD@959..961 "to" + WHITESPACE@961..962 " " + WORD@962..964 "be" + WHITESPACE@964..965 " " + WORD@965..974 "protected" + WHITESPACE@974..975 " " + WORD@975..979 "from" + WHITESPACE@979..980 " " + WORD@980..989 "expansion" + R_CURLY@989..990 "}" + COMMA@990..991 "," + WHITESPACE@991..992 "\n" + R_DELIM@992..993 "}" + diff --git a/support/texlab/src/parser/snapshots/texlab__parser__bibtex__tests__parse@samples__matuz_1990.txt.snap b/support/texlab/src/parser/snapshots/texlab__parser__bibtex__tests__parse@samples__matuz_1990.txt.snap new file mode 100644 index 0000000000..1e2b67f36c --- /dev/null +++ b/support/texlab/src/parser/snapshots/texlab__parser__bibtex__tests__parse@samples__matuz_1990.txt.snap @@ -0,0 +1,176 @@ +--- +source: src/parser/bibtex.rs +expression: root +input_file: src/parser/test_data/bibtex/samples/matuz_1990.txt +--- +ROOT@0..517 + ENTRY@0..517 + TYPE@0..11 "@collection" + L_DELIM@11..12 "{" + NAME@12..23 "matuz:doody" + COMMA@23..24 "," + WHITESPACE@24..29 "\n " + FIELD@29..59 + NAME@29..35 "editor" + WHITESPACE@35..42 " " + EQ@42..43 "=" + WHITESPACE@43..44 " " + CURLY_GROUP@44..58 + L_CURLY@44..45 "{" + WORD@45..50 "Matuz" + COMMA@50..51 "," + WHITESPACE@51..52 " " + WORD@52..57 "Roger" + R_CURLY@57..58 "}" + COMMA@58..59 "," + WHITESPACE@59..64 "\n " + FIELD@64..113 + NAME@64..69 "title" + WHITESPACE@69..77 " " + EQ@77..78 "=" + WHITESPACE@78..79 " " + CURLY_GROUP@79..112 + L_CURLY@79..80 "{" + WORD@80..92 "Contemporary" + WHITESPACE@92..93 " " + WORD@93..101 "Literary" + WHITESPACE@101..102 " " + WORD@102..111 "Criticism" + R_CURLY@111..112 "}" + COMMA@112..113 "," + WHITESPACE@113..118 "\n " + FIELD@118..138 + NAME@118..122 "year" + WHITESPACE@122..131 " " + EQ@131..132 "=" + WHITESPACE@132..133 " " + LITERAL@133..137 + INTEGER@133..137 "1990" + COMMA@137..138 "," + WHITESPACE@138..143 "\n " + FIELD@143..161 + NAME@143..149 "volume" + WHITESPACE@149..156 " " + EQ@156..157 "=" + WHITESPACE@157..158 " " + LITERAL@158..160 + INTEGER@158..160 "61" + COMMA@160..161 "," + WHITESPACE@161..166 "\n " + FIELD@166..188 + NAME@166..175 "publisher" + WHITESPACE@175..179 " " + EQ@179..180 "=" + WHITESPACE@180..181 " " + CURLY_GROUP@181..187 + L_CURLY@181..182 "{" + WORD@182..186 "Gale" + R_CURLY@186..187 "}" + COMMA@187..188 "," + WHITESPACE@188..193 "\n " + FIELD@193..218 + NAME@193..201 "location" + WHITESPACE@201..206 " " + EQ@206..207 "=" + WHITESPACE@207..208 " " + CURLY_GROUP@208..217 + L_CURLY@208..209 "{" + WORD@209..216 "Detroit" + R_CURLY@216..217 "}" + COMMA@217..218 "," + WHITESPACE@218..223 "\n " + FIELD@223..248 + NAME@223..228 "pages" + WHITESPACE@228..236 " " + EQ@236..237 "=" + WHITESPACE@237..238 " " + CURLY_GROUP@238..247 + L_CURLY@238..239 "{" + WORD@239..246 "204-208" + R_CURLY@246..247 "}" + COMMA@247..248 "," + WHITESPACE@248..253 "\n " + FIELD@253..278 + NAME@253..259 "langid" + WHITESPACE@259..266 " " + EQ@266..267 "=" + WHITESPACE@267..268 " " + CURLY_GROUP@268..277 + L_CURLY@268..269 "{" + WORD@269..276 "english" + R_CURLY@276..277 "}" + COMMA@277..278 "," + WHITESPACE@278..283 "\n " + FIELD@283..317 + NAME@283..293 "langidopts" + WHITESPACE@293..296 " " + EQ@296..297 "=" + WHITESPACE@297..298 " " + CURLY_GROUP@298..316 + L_CURLY@298..299 "{" + WORD@299..315 "variant=american" + R_CURLY@315..316 "}" + COMMA@316..317 "," + WHITESPACE@317..322 "\n " + FIELD@322..515 + NAME@322..332 "annotation" + WHITESPACE@332..335 " " + EQ@335..336 "=" + WHITESPACE@336..337 " " + CURLY_GROUP@337..514 + L_CURLY@337..338 "{" + WORD@338..339 "A" + WHITESPACE@339..340 " " + COMMAND@340..347 + COMMAND_NAME@340..347 "\\texttt" + CURLY_GROUP@347..359 + L_CURLY@347..348 "{" + WORD@348..358 "collection" + R_CURLY@358..359 "}" + WHITESPACE@359..360 " " + WORD@360..365 "entry" + WHITESPACE@365..366 " " + WORD@366..375 "providing" + WHITESPACE@375..376 " " + WORD@376..379 "the" + WHITESPACE@379..380 " " + WORD@380..387 "excerpt" + WHITESPACE@387..388 " " + WORD@388..399 "information" + WHITESPACE@399..420 "\n " + WORD@420..423 "for" + WHITESPACE@423..424 " " + WORD@424..427 "the" + WHITESPACE@427..428 " " + COMMAND@428..435 + COMMAND_NAME@428..435 "\\texttt" + CURLY_GROUP@435..442 + L_CURLY@435..436 "{" + WORD@436..441 "doody" + R_CURLY@441..442 "}" + WHITESPACE@442..443 " " + WORD@443..449 "entry." + WHITESPACE@449..450 " " + WORD@450..454 "Note" + WHITESPACE@454..455 " " + WORD@455..458 "the" + WHITESPACE@458..459 " " + WORD@459..465 "format" + WHITESPACE@465..466 " " + WORD@466..468 "of" + WHITESPACE@468..469 " " + WORD@469..472 "the" + WHITESPACE@472..493 "\n " + COMMAND@493..500 + COMMAND_NAME@493..500 "\\texttt" + CURLY_GROUP@500..507 + L_CURLY@500..501 "{" + WORD@501..506 "pages" + R_CURLY@506..507 "}" + WHITESPACE@507..508 " " + WORD@508..513 "field" + R_CURLY@513..514 "}" + COMMA@514..515 "," + WHITESPACE@515..516 "\n" + R_DELIM@516..517 "}" + diff --git a/support/texlab/src/parser/snapshots/texlab__parser__bibtex__tests__parse@samples__nietzsche_1998.txt.snap b/support/texlab/src/parser/snapshots/texlab__parser__bibtex__tests__parse@samples__nietzsche_1998.txt.snap new file mode 100644 index 0000000000..40d1f230af --- /dev/null +++ b/support/texlab/src/parser/snapshots/texlab__parser__bibtex__tests__parse@samples__nietzsche_1998.txt.snap @@ -0,0 +1,368 @@ +--- +source: src/parser/bibtex.rs +expression: root +input_file: src/parser/test_data/bibtex/samples/nietzsche_1998.txt +--- +ROOT@0..1112 + STRING@0..49 + TYPE@0..7 "@string" + L_DELIM@7..8 "{" + NAME@8..11 "dtv" + WHITESPACE@11..16 " " + EQ@16..17 "=" + WHITESPACE@17..18 " " + CURLY_GROUP@18..48 + L_CURLY@18..19 "{" + WORD@19..28 "Deutscher" + WHITESPACE@28..29 " " + WORD@29..47 "Taschenbuch-Verlag" + R_CURLY@47..48 "}" + R_DELIM@48..49 "}" + JUNK@49..51 "\n\n" + ENTRY@51..1112 + TYPE@51..58 "@mvbook" + L_DELIM@58..59 "{" + NAME@59..72 "nietzsche:ksa" + COMMA@72..73 "," + WHITESPACE@73..78 "\n " + FIELD@78..116 + NAME@78..84 "author" + WHITESPACE@84..91 " " + EQ@91..92 "=" + WHITESPACE@92..93 " " + CURLY_GROUP@93..115 + L_CURLY@93..94 "{" + WORD@94..103 "Nietzsche" + COMMA@103..104 "," + WHITESPACE@104..105 " " + WORD@105..114 "Friedrich" + R_CURLY@114..115 "}" + COMMA@115..116 "," + WHITESPACE@116..121 "\n " + FIELD@121..158 + NAME@121..126 "title" + WHITESPACE@126..134 " " + EQ@134..135 "=" + WHITESPACE@135..136 " " + CURLY_GROUP@136..157 + L_CURLY@136..137 "{" + WORD@137..138 "S" + CURLY_GROUP@138..143 + L_CURLY@138..139 "{" + ACCENT@139..142 + ACCENT_NAME@139..141 "\\\"" + WORD@141..142 "a" + R_CURLY@142..143 "}" + WORD@143..150 "mtliche" + WHITESPACE@150..151 " " + WORD@151..156 "Werke" + R_CURLY@156..157 "}" + COMMA@157..158 "," + WHITESPACE@158..163 "\n " + FIELD@163..183 + NAME@163..167 "date" + WHITESPACE@167..176 " " + EQ@176..177 "=" + WHITESPACE@177..178 " " + LITERAL@178..182 + INTEGER@178..182 "1988" + COMMA@182..183 "," + WHITESPACE@183..188 "\n " + FIELD@188..243 + NAME@188..194 "editor" + WHITESPACE@194..201 " " + EQ@201..202 "=" + WHITESPACE@202..203 " " + CURLY_GROUP@203..242 + L_CURLY@203..204 "{" + WORD@204..209 "Colli" + COMMA@209..210 "," + WHITESPACE@210..211 " " + WORD@211..218 "Giorgio" + WHITESPACE@218..219 " " + WORD@219..222 "and" + WHITESPACE@222..223 " " + WORD@223..232 "Montinari" + COMMA@232..233 "," + WHITESPACE@233..234 " " + WORD@234..241 "Mazzino" + R_CURLY@241..242 "}" + COMMA@242..243 "," + WHITESPACE@243..248 "\n " + FIELD@248..265 + NAME@248..255 "edition" + WHITESPACE@255..261 " " + EQ@261..262 "=" + WHITESPACE@262..263 " " + LITERAL@263..264 + INTEGER@263..264 "2" + COMMA@264..265 "," + WHITESPACE@265..270 "\n " + FIELD@270..288 + NAME@270..277 "volumes" + WHITESPACE@277..283 " " + EQ@283..284 "=" + WHITESPACE@284..285 " " + LITERAL@285..287 + INTEGER@285..287 "15" + COMMA@287..288 "," + WHITESPACE@288..293 "\n " + FIELD@293..339 + NAME@293..302 "publisher" + WHITESPACE@302..306 " " + EQ@306..307 "=" + WHITESPACE@307..308 " " + JOIN@308..338 + LITERAL@308..311 + NAME@308..311 "dtv" + WHITESPACE@311..312 " " + POUND@312..313 "#" + WHITESPACE@313..314 " " + CURLY_GROUP@314..338 + L_CURLY@314..315 "{" + WHITESPACE@315..316 " " + WORD@316..319 "and" + WHITESPACE@319..320 " " + WORD@320..326 "Walter" + WHITESPACE@326..327 " " + WORD@327..329 "de" + WHITESPACE@329..330 " " + WORD@330..337 "Gruyter" + R_CURLY@337..338 "}" + COMMA@338..339 "," + WHITESPACE@339..344 "\n " + FIELD@344..397 + NAME@344..352 "location" + WHITESPACE@352..357 " " + EQ@357..358 "=" + WHITESPACE@358..359 " " + CURLY_GROUP@359..396 + L_CURLY@359..360 "{" + WORD@360..361 "M" + CURLY_GROUP@361..366 + L_CURLY@361..362 "{" + ACCENT@362..365 + ACCENT_NAME@362..364 "\\\"" + WORD@364..365 "u" + R_CURLY@365..366 "}" + WORD@366..371 "nchen" + WHITESPACE@371..372 " " + WORD@372..375 "and" + WHITESPACE@375..376 " " + WORD@376..382 "Berlin" + WHITESPACE@382..383 " " + WORD@383..386 "and" + WHITESPACE@386..387 " " + WORD@387..390 "New" + WHITESPACE@390..391 " " + WORD@391..395 "York" + R_CURLY@395..396 "}" + COMMA@396..397 "," + WHITESPACE@397..402 "\n " + FIELD@402..426 + NAME@402..408 "langid" + WHITESPACE@408..415 " " + EQ@415..416 "=" + WHITESPACE@416..417 " " + CURLY_GROUP@417..425 + L_CURLY@417..418 "{" + WORD@418..424 "german" + R_CURLY@424..425 "}" + COMMA@425..426 "," + WHITESPACE@426..431 "\n " + FIELD@431..461 + NAME@431..440 "sorttitle" + WHITESPACE@440..444 " " + EQ@444..445 "=" + WHITESPACE@445..446 " " + CURLY_GROUP@446..460 + L_CURLY@446..447 "{" + WORD@447..459 "Werke-00-000" + R_CURLY@459..460 "}" + COMMA@460..461 "," + WHITESPACE@461..466 "\n " + FIELD@466..500 + NAME@466..480 "indexsorttitle" + EQ@480..481 "=" + WHITESPACE@481..482 " " + CURLY_GROUP@482..499 + L_CURLY@482..483 "{" + WORD@483..492 "Samtliche" + WHITESPACE@492..493 " " + WORD@493..498 "Werke" + R_CURLY@498..499 "}" + COMMA@499..500 "," + WHITESPACE@500..505 "\n " + FIELD@505..547 + NAME@505..513 "subtitle" + WHITESPACE@513..518 " " + EQ@518..519 "=" + WHITESPACE@519..520 " " + CURLY_GROUP@520..546 + L_CURLY@520..521 "{" + WORD@521..530 "Kritische" + WHITESPACE@530..531 " " + WORD@531..545 "Studienausgabe" + R_CURLY@545..546 "}" + COMMA@546..547 "," + WHITESPACE@547..552 "\n " + FIELD@552..1110 + NAME@552..562 "annotation" + WHITESPACE@562..565 " " + EQ@565..566 "=" + WHITESPACE@566..567 " " + CURLY_GROUP@567..1109 + L_CURLY@567..568 "{" + WORD@568..571 "The" + WHITESPACE@571..572 " " + WORD@572..580 "critical" + WHITESPACE@580..581 " " + WORD@581..588 "edition" + WHITESPACE@588..589 " " + WORD@589..591 "of" + WHITESPACE@591..592 " " + WORD@592..603 "Nietzsche's" + WHITESPACE@603..604 " " + WORD@604..610 "works." + WHITESPACE@610..611 " " + WORD@611..615 "This" + WHITESPACE@615..616 " " + WORD@616..618 "is" + WHITESPACE@618..619 " " + WORD@619..620 "a" + WHITESPACE@620..641 "\n " + COMMAND@641..648 + COMMAND_NAME@641..648 "\\texttt" + CURLY_GROUP@648..656 + L_CURLY@648..649 "{" + WORD@649..655 "mvbook" + R_CURLY@655..656 "}" + WHITESPACE@656..657 " " + WORD@657..662 "entry" + WHITESPACE@662..663 " " + WORD@663..672 "referring" + WHITESPACE@672..673 " " + WORD@673..675 "to" + WHITESPACE@675..676 " " + WORD@676..677 "a" + WHITESPACE@677..678 " " + WORD@678..687 "15-volume" + WHITESPACE@687..688 " " + WORD@688..692 "work" + WHITESPACE@692..693 " " + WORD@693..695 "as" + WHITESPACE@695..696 " " + WORD@696..697 "a" + WHITESPACE@697..718 "\n " + WORD@718..724 "whole." + WHITESPACE@724..725 " " + WORD@725..729 "Note" + WHITESPACE@729..730 " " + WORD@730..733 "the" + WHITESPACE@733..734 " " + COMMAND@734..741 + COMMAND_NAME@734..741 "\\texttt" + CURLY_GROUP@741..750 + L_CURLY@741..742 "{" + WORD@742..749 "volumes" + R_CURLY@749..750 "}" + WHITESPACE@750..751 " " + WORD@751..756 "field" + WHITESPACE@756..757 " " + WORD@757..760 "and" + WHITESPACE@760..761 " " + WORD@761..764 "the" + WHITESPACE@764..765 " " + WORD@765..771 "format" + WHITESPACE@771..772 " " + WORD@772..774 "of" + WHITESPACE@774..775 " " + WORD@775..778 "the" + WHITESPACE@778..799 "\n " + COMMAND@799..806 + COMMAND_NAME@799..806 "\\texttt" + CURLY_GROUP@806..817 + L_CURLY@806..807 "{" + WORD@807..816 "publisher" + R_CURLY@816..817 "}" + WHITESPACE@817..818 " " + WORD@818..821 "and" + WHITESPACE@821..822 " " + COMMAND@822..829 + COMMAND_NAME@822..829 "\\texttt" + CURLY_GROUP@829..839 + L_CURLY@829..830 "{" + WORD@830..838 "location" + R_CURLY@838..839 "}" + WHITESPACE@839..840 " " + WORD@840..846 "fields" + WHITESPACE@846..847 " " + WORD@847..849 "in" + WHITESPACE@849..850 " " + WORD@850..853 "the" + WHITESPACE@853..874 "\n " + WORD@874..882 "database" + WHITESPACE@882..883 " " + WORD@883..888 "file." + WHITESPACE@888..889 " " + WORD@889..893 "Also" + WHITESPACE@893..894 " " + WORD@894..898 "note" + WHITESPACE@898..899 " " + WORD@899..902 "the" + WHITESPACE@902..903 " " + COMMAND@903..910 + COMMAND_NAME@903..910 "\\texttt" + CURLY_GROUP@910..921 + L_CURLY@910..911 "{" + WORD@911..920 "sorttitle" + R_CURLY@920..921 "}" + WHITESPACE@921..922 " " + WORD@922..925 "and" + WHITESPACE@925..946 "\n " + WORD@946..951 "field" + WHITESPACE@951..952 " " + WORD@952..957 "which" + WHITESPACE@957..958 " " + WORD@958..960 "is" + WHITESPACE@960..961 " " + WORD@961..965 "used" + WHITESPACE@965..966 " " + WORD@966..968 "to" + WHITESPACE@968..969 " " + WORD@969..978 "fine-tune" + WHITESPACE@978..979 " " + WORD@979..982 "the" + WHITESPACE@982..1003 "\n " + WORD@1003..1010 "sorting" + WHITESPACE@1010..1011 " " + WORD@1011..1016 "order" + WHITESPACE@1016..1017 " " + WORD@1017..1019 "of" + WHITESPACE@1019..1020 " " + WORD@1020..1023 "the" + WHITESPACE@1023..1024 " " + WORD@1024..1037 "bibliography." + WHITESPACE@1037..1038 " " + WORD@1038..1040 "We" + WHITESPACE@1040..1041 " " + WORD@1041..1045 "want" + WHITESPACE@1045..1046 " " + WORD@1046..1050 "this" + WHITESPACE@1050..1051 " " + WORD@1051..1055 "item" + WHITESPACE@1055..1056 " " + WORD@1056..1062 "listed" + WHITESPACE@1062..1083 "\n " + WORD@1083..1088 "first" + WHITESPACE@1088..1089 " " + WORD@1089..1091 "in" + WHITESPACE@1091..1092 " " + WORD@1092..1095 "the" + WHITESPACE@1095..1096 " " + WORD@1096..1108 "bibliography" + R_CURLY@1108..1109 "}" + COMMA@1109..1110 "," + WHITESPACE@1110..1111 "\n" + R_DELIM@1111..1112 "}" + diff --git a/support/texlab/src/parser/snapshots/texlab__parser__bibtex__tests__parse@samples__rivest_1978.txt.snap b/support/texlab/src/parser/snapshots/texlab__parser__bibtex__tests__parse@samples__rivest_1978.txt.snap new file mode 100644 index 0000000000..b296d9cd4b --- /dev/null +++ b/support/texlab/src/parser/snapshots/texlab__parser__bibtex__tests__parse@samples__rivest_1978.txt.snap @@ -0,0 +1,232 @@ +--- +source: src/parser/bibtex.rs +expression: root +input_file: src/parser/test_data/bibtex/samples/rivest_1978.txt +--- +ROOT@0..557 + ENTRY@0..557 + TYPE@0..8 "@article" + L_DELIM@8..9 "{" + NAME@9..30 "10.1145/359340.359342" + COMMA@30..31 "," + WHITESPACE@31..36 "\n " + FIELD@36..92 + NAME@36..42 "author" + WHITESPACE@42..43 " " + EQ@43..44 "=" + WHITESPACE@44..45 " " + CURLY_GROUP@45..91 + L_CURLY@45..46 "{" + WORD@46..52 "Rivest" + COMMA@52..53 "," + WHITESPACE@53..54 " " + WORD@54..56 "R." + WHITESPACE@56..57 " " + WORD@57..59 "L." + WHITESPACE@59..60 " " + WORD@60..63 "and" + WHITESPACE@63..64 " " + WORD@64..70 "Shamir" + COMMA@70..71 "," + WHITESPACE@71..72 " " + WORD@72..74 "A." + WHITESPACE@74..75 " " + WORD@75..78 "and" + WHITESPACE@78..79 " " + WORD@79..86 "Adleman" + COMMA@86..87 "," + WHITESPACE@87..88 " " + WORD@88..90 "L." + R_CURLY@90..91 "}" + COMMA@91..92 "," + WHITESPACE@92..97 "\n " + FIELD@97..178 + NAME@97..102 "title" + WHITESPACE@102..103 " " + EQ@103..104 "=" + WHITESPACE@104..105 " " + CURLY_GROUP@105..177 + L_CURLY@105..106 "{" + WORD@106..107 "A" + WHITESPACE@107..108 " " + WORD@108..114 "Method" + WHITESPACE@114..115 " " + WORD@115..118 "for" + WHITESPACE@118..119 " " + WORD@119..128 "Obtaining" + WHITESPACE@128..129 " " + WORD@129..136 "Digital" + WHITESPACE@136..137 " " + WORD@137..147 "Signatures" + WHITESPACE@147..148 " " + WORD@148..151 "and" + WHITESPACE@151..152 " " + WORD@152..162 "Public-Key" + WHITESPACE@162..163 " " + WORD@163..176 "Cryptosystems" + R_CURLY@176..177 "}" + COMMA@177..178 "," + WHITESPACE@178..183 "\n " + FIELD@183..197 + NAME@183..187 "year" + WHITESPACE@187..188 " " + EQ@188..189 "=" + WHITESPACE@189..190 " " + CURLY_GROUP@190..196 + L_CURLY@190..191 "{" + INTEGER@191..195 "1978" + R_CURLY@195..196 "}" + COMMA@196..197 "," + WHITESPACE@197..202 "\n " + FIELD@202..227 + NAME@202..212 "issue_date" + WHITESPACE@212..213 " " + EQ@213..214 "=" + WHITESPACE@214..215 " " + CURLY_GROUP@215..226 + L_CURLY@215..216 "{" + WORD@216..220 "Feb." + WHITESPACE@220..221 " " + INTEGER@221..225 "1978" + R_CURLY@225..226 "}" + COMMA@226..227 "," + WHITESPACE@227..232 "\n " + FIELD@232..282 + NAME@232..241 "publisher" + WHITESPACE@241..242 " " + EQ@242..243 "=" + WHITESPACE@243..244 " " + CURLY_GROUP@244..281 + L_CURLY@244..245 "{" + WORD@245..256 "Association" + WHITESPACE@256..257 " " + WORD@257..260 "for" + WHITESPACE@260..261 " " + WORD@261..270 "Computing" + WHITESPACE@270..271 " " + WORD@271..280 "Machinery" + R_CURLY@280..281 "}" + COMMA@281..282 "," + WHITESPACE@282..287 "\n " + FIELD@287..317 + NAME@287..294 "address" + WHITESPACE@294..295 " " + EQ@295..296 "=" + WHITESPACE@296..297 " " + CURLY_GROUP@297..316 + L_CURLY@297..298 "{" + WORD@298..301 "New" + WHITESPACE@301..302 " " + WORD@302..306 "York" + COMMA@306..307 "," + WHITESPACE@307..308 " " + WORD@308..310 "NY" + COMMA@310..311 "," + WHITESPACE@311..312 " " + WORD@312..315 "USA" + R_CURLY@315..316 "}" + COMMA@316..317 "," + WHITESPACE@317..322 "\n " + FIELD@322..336 + NAME@322..328 "volume" + WHITESPACE@328..329 " " + EQ@329..330 "=" + WHITESPACE@330..331 " " + CURLY_GROUP@331..335 + L_CURLY@331..332 "{" + INTEGER@332..334 "21" + R_CURLY@334..335 "}" + COMMA@335..336 "," + WHITESPACE@336..341 "\n " + FIELD@341..354 + NAME@341..347 "number" + WHITESPACE@347..348 " " + EQ@348..349 "=" + WHITESPACE@349..350 " " + CURLY_GROUP@350..353 + L_CURLY@350..351 "{" + INTEGER@351..352 "2" + R_CURLY@352..353 "}" + COMMA@353..354 "," + WHITESPACE@354..359 "\n " + FIELD@359..378 + NAME@359..363 "issn" + WHITESPACE@363..364 " " + EQ@364..365 "=" + WHITESPACE@365..366 " " + CURLY_GROUP@366..377 + L_CURLY@366..367 "{" + WORD@367..376 "0001-0782" + R_CURLY@376..377 "}" + COMMA@377..378 "," + WHITESPACE@378..383 "\n " + FIELD@383..429 + NAME@383..386 "url" + WHITESPACE@386..387 " " + EQ@387..388 "=" + WHITESPACE@388..389 " " + CURLY_GROUP@389..428 + L_CURLY@389..390 "{" + WORD@390..427 "https://doi.org/10.11 ..." + R_CURLY@427..428 "}" + COMMA@428..429 "," + WHITESPACE@429..434 "\n " + FIELD@434..464 + NAME@434..437 "doi" + WHITESPACE@437..438 " " + EQ@438..439 "=" + WHITESPACE@439..440 " " + CURLY_GROUP@440..463 + L_CURLY@440..441 "{" + WORD@441..462 "10.1145/359340.359342" + R_CURLY@462..463 "}" + COMMA@463..464 "," + WHITESPACE@464..469 "\n " + FIELD@469..493 + NAME@469..476 "journal" + WHITESPACE@476..477 " " + EQ@477..478 "=" + WHITESPACE@478..479 " " + CURLY_GROUP@479..492 + L_CURLY@479..480 "{" + WORD@480..487 "Commun." + WHITESPACE@487..488 " " + WORD@488..491 "ACM" + R_CURLY@491..492 "}" + COMMA@492..493 "," + WHITESPACE@493..498 "\n " + FIELD@498..512 + NAME@498..503 "month" + WHITESPACE@503..504 " " + EQ@504..505 "=" + WHITESPACE@505..506 " " + CURLY_GROUP@506..511 + L_CURLY@506..507 "{" + WORD@507..510 "feb" + R_CURLY@510..511 "}" + COMMA@511..512 "," + WHITESPACE@512..517 "\n " + FIELD@517..535 + NAME@517..522 "pages" + WHITESPACE@522..523 " " + EQ@523..524 "=" + WHITESPACE@524..525 " " + CURLY_GROUP@525..534 + L_CURLY@525..526 "{" + WORD@526..533 "120-126" + R_CURLY@533..534 "}" + COMMA@534..535 "," + WHITESPACE@535..540 "\n " + FIELD@540..555 + NAME@540..548 "numpages" + WHITESPACE@548..549 " " + EQ@549..550 "=" + WHITESPACE@550..551 " " + CURLY_GROUP@551..554 + L_CURLY@551..552 "{" + INTEGER@552..553 "7" + R_CURLY@553..554 "}" + COMMA@554..555 "," + WHITESPACE@555..556 "\n" + R_DELIM@556..557 "}" + diff --git a/support/texlab/src/parser/snapshots/texlab__parser__build_log__tests__parse@001.txt.snap b/support/texlab/src/parser/snapshots/texlab__parser__build_log__tests__parse@001.txt.snap new file mode 100644 index 0000000000..1d91ff7fff --- /dev/null +++ b/support/texlab/src/parser/snapshots/texlab__parser__build_log__tests__parse@001.txt.snap @@ -0,0 +1,27 @@ +--- +source: src/parser/build_log.rs +expression: parse_build_log(&text) +input_file: src/parser/test_data/build_log/001.txt +--- +BuildLog { + errors: [ + BuildError { + relative_path: "./parent.tex", + level: Warning, + message: "Overfull \\hbox (200.00162pt too wide) in paragraph at lines 8--9", + hint: None, + line: Some( + 7, + ), + }, + BuildError { + relative_path: "./parent.tex", + level: Warning, + message: "Overfull \\vbox (3.19998pt too high) detected at line 23", + hint: None, + line: Some( + 22, + ), + }, + ], +} diff --git a/support/texlab/src/parser/snapshots/texlab__parser__build_log__tests__parse@002.txt.snap b/support/texlab/src/parser/snapshots/texlab__parser__build_log__tests__parse@002.txt.snap new file mode 100644 index 0000000000..91fa71d636 --- /dev/null +++ b/support/texlab/src/parser/snapshots/texlab__parser__build_log__tests__parse@002.txt.snap @@ -0,0 +1,20 @@ +--- +source: src/parser/build_log.rs +expression: parse_build_log(&text) +input_file: src/parser/test_data/build_log/002.txt +--- +BuildLog { + errors: [ + BuildError { + relative_path: "./child.tex", + level: Error, + message: "Undefined control sequence.", + hint: Some( + "\\foo", + ), + line: Some( + 0, + ), + }, + ], +} diff --git a/support/texlab/src/parser/snapshots/texlab__parser__build_log__tests__parse@003.txt.snap b/support/texlab/src/parser/snapshots/texlab__parser__build_log__tests__parse@003.txt.snap new file mode 100644 index 0000000000..d2024a8cd3 --- /dev/null +++ b/support/texlab/src/parser/snapshots/texlab__parser__build_log__tests__parse@003.txt.snap @@ -0,0 +1,23 @@ +--- +source: src/parser/build_log.rs +expression: parse_build_log(&text) +input_file: src/parser/test_data/build_log/003.txt +--- +BuildLog { + errors: [ + BuildError { + relative_path: "./parent.tex", + level: Warning, + message: "Citation `foo' on page 1 undefined on input line 6.", + hint: None, + line: None, + }, + BuildError { + relative_path: "./parent.tex", + level: Warning, + message: "There were undefined references.", + hint: None, + line: None, + }, + ], +} diff --git a/support/texlab/src/parser/snapshots/texlab__parser__build_log__tests__parse@004.txt.snap b/support/texlab/src/parser/snapshots/texlab__parser__build_log__tests__parse@004.txt.snap new file mode 100644 index 0000000000..83219b5fff --- /dev/null +++ b/support/texlab/src/parser/snapshots/texlab__parser__build_log__tests__parse@004.txt.snap @@ -0,0 +1,31 @@ +--- +source: src/parser/build_log.rs +expression: parse_build_log(&text) +input_file: src/parser/test_data/build_log/004.txt +--- +BuildLog { + errors: [ + BuildError { + relative_path: "/TexLive/texmf-dist/tex/generic/babel/babel.sty", + level: Error, + message: "Package babel Error: Unknown option `foo'. Either you misspelled it or the language definition file foo.ldf was not found.", + hint: Some( + "\\ProcessOptions*", + ), + line: Some( + 392, + ), + }, + BuildError { + relative_path: "/TexLive/texmf-dist/tex/generic/babel/babel.sty", + level: Error, + message: "Package babel Error: You haven't specified a language option.", + hint: Some( + "ry to proceed from here, type x to quit.}", + ), + line: Some( + 425, + ), + }, + ], +} diff --git a/support/texlab/src/parser/snapshots/texlab__parser__build_log__tests__parse@005.txt.snap b/support/texlab/src/parser/snapshots/texlab__parser__build_log__tests__parse@005.txt.snap new file mode 100644 index 0000000000..e4857d00d8 --- /dev/null +++ b/support/texlab/src/parser/snapshots/texlab__parser__build_log__tests__parse@005.txt.snap @@ -0,0 +1,30 @@ +--- +source: src/parser/build_log.rs +expression: parse_build_log(&text) +input_file: src/parser/test_data/build_log/005.txt +--- +BuildLog { + errors: [ + BuildError { + relative_path: "./parent.tex", + level: Warning, + message: "'babel/polyglossia' detected but 'csquotes' missing. Loading 'csquotes' recommended.", + hint: None, + line: None, + }, + BuildError { + relative_path: "./parent.tex", + level: Warning, + message: "There were undefined references.", + hint: None, + line: None, + }, + BuildError { + relative_path: "./parent.tex", + level: Warning, + message: "Please (re)run Biber on the file: parent and rerun LaTeX afterwards.", + hint: None, + line: None, + }, + ], +} diff --git a/support/texlab/src/parser/snapshots/texlab__parser__build_log__tests__parse@006.txt.snap b/support/texlab/src/parser/snapshots/texlab__parser__build_log__tests__parse@006.txt.snap new file mode 100644 index 0000000000..837aa9c295 --- /dev/null +++ b/support/texlab/src/parser/snapshots/texlab__parser__build_log__tests__parse@006.txt.snap @@ -0,0 +1,69 @@ +--- +source: src/parser/build_log.rs +expression: parse_build_log(&text) +input_file: src/parser/test_data/build_log/006.txt +--- +BuildLog { + errors: [ + BuildError { + relative_path: "./parent.tex", + level: Error, + message: "Undefined control sequence.", + hint: Some( + "\\foo", + ), + line: Some( + 6, + ), + }, + BuildError { + relative_path: "./parent.tex", + level: Error, + message: "Missing $ inserted.", + hint: Some( + "\\bar", + ), + line: Some( + 7, + ), + }, + BuildError { + relative_path: "./parent.tex", + level: Error, + message: "Undefined control sequence.", + hint: Some( + "\\baz", + ), + line: Some( + 8, + ), + }, + BuildError { + relative_path: "./parent.tex", + level: Error, + message: "Missing { inserted.", + hint: None, + line: Some( + 9, + ), + }, + BuildError { + relative_path: "./parent.tex", + level: Error, + message: "Missing $ inserted.", + hint: None, + line: Some( + 9, + ), + }, + BuildError { + relative_path: "./parent.tex", + level: Error, + message: "Missing } inserted.", + hint: None, + line: Some( + 9, + ), + }, + ], +} diff --git a/support/texlab/src/parser/snapshots/texlab__parser__build_log__tests__parse@007.txt.snap b/support/texlab/src/parser/snapshots/texlab__parser__build_log__tests__parse@007.txt.snap new file mode 100644 index 0000000000..d509a01bd4 --- /dev/null +++ b/support/texlab/src/parser/snapshots/texlab__parser__build_log__tests__parse@007.txt.snap @@ -0,0 +1,19 @@ +--- +source: src/parser/build_log.rs +expression: parse_build_log(&text) +--- +BuildLog { + errors: [ + BuildError { + relative_path: "/some/folder/a.tex", + level: Error, + message: "Undefined control sequence.", + hint: Some( + "\\lsdkfjlskdfj", + ), + line: Some( + 3, + ), + }, + ], +} diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__block_comments.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@block_comments.txt.snap index 355a93ebad..14c73e7da5 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__block_comments.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@block_comments.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -assertion_line: 1814 -expression: "setup(r#\"Foo\n\\iffalse\nTest1\n\\fi\nBar\n\\iffalse\n\\fii\n\\fi\nBaz\"#)" +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/block_comments.txt --- ROOT@0..48 PREAMBLE@0..48 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__caption.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@caption__caption_default.txt.snap index f598a8f7e9..33e119c524 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__caption.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@caption__caption_default.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"\\caption[qux]{Foo \\Bar Baz}\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/caption/caption_default.txt --- ROOT@0..27 PREAMBLE@0..27 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__caption_error.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@caption__caption_default_error.txt.snap index 13697e882b..a016dcebed 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__caption_error.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@caption__caption_default_error.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"\\caption[qux]{Foo \\Bar Baz\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/caption/caption_default_error.txt --- ROOT@0..26 PREAMBLE@0..26 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__caption_figure.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@caption__caption_figure.txt.snap index b3bf7589d8..9303bd3ebe 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__caption_figure.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@caption__caption_figure.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"\\begin{figure}\\caption{Foo}\\end{figure}\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/caption/caption_figure.txt --- ROOT@0..39 PREAMBLE@0..39 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__caption_minimal.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@caption__caption_minimal.txt.snap index bf9e795e18..6af368cc21 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__caption_minimal.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@caption__caption_minimal.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"\\caption{Foo \\Bar Baz}\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/caption/caption_minimal.txt --- ROOT@0..22 PREAMBLE@0..22 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__caption_minimal_error.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@caption__caption_minimal_error.txt.snap index 6c932ce883..68fc629613 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__caption_minimal_error.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@caption__caption_minimal_error.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"\\caption{Foo \\Bar Baz\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/caption/caption_minimal_error.txt --- ROOT@0..21 PREAMBLE@0..21 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__citation_empty.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@citation__citation_empty.txt.snap index faad4c0039..fbf2b5123e 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__citation_empty.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@citation__citation_empty.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"\\cite{}\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/citation/citation_empty.txt --- ROOT@0..7 PREAMBLE@0..7 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__citation_missing_brace.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@citation__citation_missing_brace.txt.snap index 61cd6d8f0b..72bd618594 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__citation_missing_brace.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@citation__citation_missing_brace.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"\\cite{foo\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/citation/citation_missing_brace.txt --- ROOT@0..9 PREAMBLE@0..9 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__citation_multiple_keys.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@citation__citation_multiple_keys.txt.snap index 7195e8992e..81716cf8b1 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__citation_multiple_keys.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@citation__citation_multiple_keys.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"\\cite{foo, bar}\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/citation/citation_multiple_keys.txt --- ROOT@0..15 PREAMBLE@0..15 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__citation_prenote.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@citation__citation_prenote.txt.snap index b5d92886aa..f5afdca536 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__citation_prenote.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@citation__citation_prenote.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"\\cite[foo]{bar}\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/citation/citation_prenote.txt --- ROOT@0..15 PREAMBLE@0..15 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__citation_prenote_postnote.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@citation__citation_prenote_postnote.txt.snap index ba99b66e35..feecca0435 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__citation_prenote_postnote.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@citation__citation_prenote_postnote.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"\\cite[foo][bar]{baz}\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/citation/citation_prenote_postnote.txt --- ROOT@0..20 PREAMBLE@0..20 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__citation_redundant_comma.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@citation__citation_redundant_comma.txt.snap index 9062479f7a..2a8acd1173 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__citation_redundant_comma.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@citation__citation_redundant_comma.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"\\cite{,foo,}\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/citation/citation_redundant_comma.txt --- ROOT@0..12 PREAMBLE@0..12 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__citation_simple.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@citation__citation_simple.txt.snap index 335b9d461c..faa2e07155 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__citation_simple.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@citation__citation_simple.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"\\cite{foo}\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/citation/citation_simple.txt --- ROOT@0..10 PREAMBLE@0..10 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__citation_star.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@citation__citation_star.txt.snap index e6d5dad128..3bcd74701c 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__citation_star.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@citation__citation_star.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"\\nocite{*}\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/citation/citation_star.txt --- ROOT@0..10 PREAMBLE@0..10 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__color_definition_simple.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@color__color_definition_simple.txt.snap index 64eee4351b..163ea09071 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__color_definition_simple.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@color__color_definition_simple.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"\\definecolor{foo}{rgb}{255,168,0}\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/color/color_definition_simple.txt --- ROOT@0..33 PREAMBLE@0..33 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__color_reference_simple.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@color__color_reference_simple.txt.snap index cb0ee151b9..0c68b5eae0 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__color_reference_simple.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@color__color_reference_simple.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"\\color{black}\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/color/color_reference_simple.txt --- ROOT@0..13 PREAMBLE@0..13 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__color_set_definition_error1.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@color__color_set_definition_error1.txt.snap index 59688f0902..2e3be43ecb 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__color_set_definition_error1.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@color__color_set_definition_error1.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"\\definecolorset[ty]{rgb,HTML}{foo}{bar}\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/color/color_set_definition_error1.txt --- ROOT@0..39 PREAMBLE@0..39 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__color_set_definition_error2.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@color__color_set_definition_error2.txt.snap index cbbeacb649..ee15174688 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__color_set_definition_error2.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@color__color_set_definition_error2.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"\\definecolorset{rgb,HTML}{foo}\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/color/color_set_definition_error2.txt --- ROOT@0..30 PREAMBLE@0..30 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__color_set_definition_error3.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@color__color_set_definition_error3.txt.snap index 826bea28b6..3416786dda 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__color_set_definition_error3.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@color__color_set_definition_error3.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"\\definecolorset{rgb,HTML}\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/color/color_set_definition_error3.txt --- ROOT@0..25 PREAMBLE@0..25 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__color_set_definition_error4.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@color__color_set_definition_error4.txt.snap index 3cafa81bae..5c16d9d7a5 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__color_set_definition_error4.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@color__color_set_definition_error4.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"\\definecolorset\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/color/color_set_definition_error4.txt --- ROOT@0..15 PREAMBLE@0..15 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__color_set_definition_simple.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@color__color_set_definition_simple.txt.snap index 9d32e127ef..a4cff9c7a1 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__color_set_definition_simple.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@color__color_set_definition_simple.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"\\definecolorset[ty]{rgb,HTML}{foo}{bar}{baz}\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/color/color_set_definition_simple.txt --- ROOT@0..44 PREAMBLE@0..44 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__command_definition_no_argc.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@command_definition__command_definition_no_argc.txt.snap index 2ff3896080..a10287b262 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__command_definition_no_argc.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@command_definition__command_definition_no_argc.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"\\newcommand{\\foo}{foo}\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/command_definition/command_definition_no_argc.txt --- ROOT@0..22 PREAMBLE@0..22 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__command_definition_no_impl.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@command_definition__command_definition_no_impl.txt.snap index 4602a7a688..ae9b54e0c8 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__command_definition_no_impl.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@command_definition__command_definition_no_impl.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"\\newcommand{\\foo}\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/command_definition/command_definition_no_impl.txt --- ROOT@0..17 PREAMBLE@0..17 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__command_definition_no_impl_error.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@command_definition__command_definition_no_impl_error.txt.snap index 4a20be7d7c..2e1f2f2956 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__command_definition_no_impl_error.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@command_definition__command_definition_no_impl_error.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"\\newcommand{\\foo\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/command_definition/command_definition_no_impl_error.txt --- ROOT@0..16 PREAMBLE@0..16 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__command_definition_optional.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@command_definition__command_definition_optional.txt.snap index 66c263e49a..fe1a3ad6ec 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__command_definition_optional.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@command_definition__command_definition_optional.txt.snap @@ -1,8 +1,7 @@ --- -source: src/syntax/latex/parser.rs -assertion_line: 1579 -expression: "setup(r#\"\\newcommand{\\foo}[1][def]{#1}\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/command_definition/command_definition_optional.txt --- ROOT@0..29 PREAMBLE@0..29 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__command_definition_simple.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@command_definition__command_definition_simple.txt.snap index b6b8380155..422fdd0d5b 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__command_definition_simple.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@command_definition__command_definition_simple.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"\\newcommand[1]{\\id}{#1}\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/command_definition/command_definition_simple.txt --- ROOT@0..23 PREAMBLE@0..23 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__command_definition_with_begin.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@command_definition__command_definition_with_begin.txt.snap index 6b7724c0aa..9ee38a1796 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__command_definition_with_begin.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@command_definition__command_definition_with_begin.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -assertion_line: 1723 -expression: "setup(r#\"\\newcommand{\\CVSubHeadingListStart}{\\begin{itemize}[leftmargin=0.5cm, label={}]}\"#)" +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/command_definition/command_definition_with_begin.txt --- ROOT@0..80 PREAMBLE@0..80 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__math_operator_no_impl.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@command_definition__math_operator_no_impl.txt.snap index 2e39ee899c..371d1272c4 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__math_operator_no_impl.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@command_definition__math_operator_no_impl.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"\\DeclareMathOperator{\\foo}\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/command_definition/math_operator_no_impl.txt --- ROOT@0..26 PREAMBLE@0..26 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__math_operator_simple.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@command_definition__math_operator_simple.txt.snap index bb44005153..004e6918e4 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__math_operator_simple.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@command_definition__math_operator_simple.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"\\DeclareMathOperator{\\foo}{foo}\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/command_definition/math_operator_simple.txt --- ROOT@0..31 PREAMBLE@0..31 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__asymptote.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@environment__environment_asymptote.txt.snap index a735d71e73..abbc71e6ed 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__asymptote.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@environment__environment_asymptote.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -assertion_line: 1829 -expression: "setup(r#\"\\begin{asy}\n printf(\"Hello World\\n\");\n\\end{asy}\"#)" +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/environment/environment_asymptote.txt --- ROOT@0..50 PREAMBLE@0..50 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__environment_definition.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@environment__environment_definition.txt.snap index 5d977db814..fb45f5d35b 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__environment_definition.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@environment__environment_definition.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -assertion_line: 1792 -expression: "setup(r#\"\\newenvironment{bar}[1]{\\begin{foo}}{\\end{foo}}\"#)" +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/environment/environment_definition.txt --- ROOT@0..47 PREAMBLE@0..47 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__environment_definition_optional_arg.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@environment__environment_definition_optional_arg.txt.snap index 1a064fefe3..10009e851b 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__environment_definition_optional_arg.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@environment__environment_definition_optional_arg.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -assertion_line: 1797 -expression: "setup(r#\"\\newenvironment{foo}[1][default]{begin}{end}\"#)" +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/environment/environment_definition_optional_arg.txt --- ROOT@0..44 PREAMBLE@0..44 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__environment_nested.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@environment__environment_nested.txt.snap index 3a65af3a2b..e3274ef70e 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__environment_nested.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@environment__environment_nested.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"\\begin{foo} \\begin{qux} \\end{baz} \\end{bar}\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/environment/environment_nested.txt --- ROOT@0..43 PREAMBLE@0..43 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__environment_nested_missing_braces.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@environment__environment_nested_missing_braces.txt.snap index 973e6e9a9f..698be0eae7 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__environment_nested_missing_braces.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@environment__environment_nested_missing_braces.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"\\begin{foo \\begin{qux Hello World \\end{baz} \\end{bar\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/environment/environment_nested_missing_braces.txt --- ROOT@0..52 PREAMBLE@0..52 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__environment_simple.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@environment__environment_simple.txt.snap index b8b85f1348..db57d39580 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__environment_simple.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@environment__environment_simple.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"\\begin{foo} Hello World \\end{bar}\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/environment/environment_simple.txt --- ROOT@0..33 PREAMBLE@0..33 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__equation.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@equation.txt.snap index e146fcaee6..0974c69449 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__equation.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@equation.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"\\[ foo bar \\]\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/equation.txt --- ROOT@0..13 PREAMBLE@0..13 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__equation_missing_begin.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@equation_missing_begin.txt.snap index 9a2af78417..c649fc6a6a 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__equation_missing_begin.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@equation_missing_begin.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"\\begin{a} foo bar \\] \\end{b}\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/equation_missing_begin.txt --- ROOT@0..28 PREAMBLE@0..28 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__generic_command_args.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@generic_command_args.txt.snap index b62c8c2559..9fee38a855 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__generic_command_args.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@generic_command_args.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"\\foo{bar}[qux]\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/generic_command_args.txt --- ROOT@0..14 PREAMBLE@0..14 diff --git a/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@generic_command_empty.txt.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@generic_command_empty.txt.snap new file mode 100644 index 0000000000..dcd2382d02 --- /dev/null +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@generic_command_empty.txt.snap @@ -0,0 +1,10 @@ +--- +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/generic_command_empty.txt +--- +ROOT@0..4 + PREAMBLE@0..4 + GENERIC_COMMAND@0..4 + GENERIC_COMMAND_NAME@0..4 "\\foo" + diff --git a/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@generic_command_escape.txt.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@generic_command_escape.txt.snap new file mode 100644 index 0000000000..d7d88a32ce --- /dev/null +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@generic_command_escape.txt.snap @@ -0,0 +1,10 @@ +--- +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/generic_command_escape.txt +--- +ROOT@0..2 + PREAMBLE@0..2 + GENERIC_COMMAND@0..2 + GENERIC_COMMAND_NAME@0..2 "\\#" + diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__acronym_declaration.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@glossary__acronym_declaration.txt.snap index a92180efb3..c1298e50fc 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__acronym_declaration.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@glossary__acronym_declaration.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"\\DeclareAcronym{eg}{short = e.g,long = for example,tag = abbrev}\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/glossary/acronym_declaration.txt --- ROOT@0..64 PREAMBLE@0..64 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__acroynm_definition_options.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@glossary__acronym_definition_options.txt.snap index 80043c18e7..eac9b6e3ba 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__acroynm_definition_options.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@glossary__acronym_definition_options.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"\\newacronym[longplural={Frames per Second}]{fpsLabel}{FPS}{Frame per Second}\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/glossary/acronym_definition_options.txt --- ROOT@0..76 PREAMBLE@0..76 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__acroynm_definition_simple.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@glossary__acronym_definition_simple.txt.snap index 74ae2219de..e6bfe2a9d5 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__acroynm_definition_simple.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@glossary__acronym_definition_simple.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"\\newacronym{fpsLabel}{FPS}{Frame per Second}\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/glossary/acronym_definition_simple.txt --- ROOT@0..44 PREAMBLE@0..44 diff --git a/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@glossary__acronym_package.txt.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@glossary__acronym_package.txt.snap new file mode 100644 index 0000000000..9babc04165 --- /dev/null +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@glossary__acronym_package.txt.snap @@ -0,0 +1,30 @@ +--- +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/glossary/acronym_package.txt +--- +ROOT@0..35 + PREAMBLE@0..35 + ACRONYM_DEFINITION@0..35 + ACRONYM_DEFINITION_NAME@0..5 "\\acro" + CURLY_GROUP_WORD@5..10 + L_CURLY@5..6 "{" + KEY@6..9 + WORD@6..9 "fps" + R_CURLY@9..10 "}" + BRACK_GROUP@10..15 + L_BRACK@10..11 "[" + TEXT@11..14 + WORD@11..14 "FPS" + R_BRACK@14..15 "]" + CURLY_GROUP@15..35 + L_CURLY@15..16 "{" + TEXT@16..33 + WORD@16..22 "Frames" + WHITESPACE@22..23 " " + WORD@23..26 "per" + WHITESPACE@26..27 " " + WORD@27..33 "Second" + R_CURLY@33..34 "}" + LINE_BREAK@34..35 "\n" + diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__acroynm_reference_options.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@glossary__acronym_reference_options.txt.snap index 6a1c2cdcbe..99a8fbc562 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__acroynm_reference_options.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@glossary__acronym_reference_options.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"\\acrshort[foo=bar,baz]{fpsLabel}\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/glossary/acronym_reference_options.txt --- ROOT@0..32 PREAMBLE@0..32 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__acroynm_reference_simple.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@glossary__acronym_reference_simple.txt.snap index 9924c7175c..08effadf7e 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__acroynm_reference_simple.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@glossary__acronym_reference_simple.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"\\acrshort{fpsLabel}\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/glossary/acronym_reference_simple.txt --- ROOT@0..19 PREAMBLE@0..19 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__glossary_entry_definition_simple.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@glossary__glossary_entry_definition_simple.txt.snap index 519abf75e8..4ab51a0db3 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__glossary_entry_definition_simple.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@glossary__glossary_entry_definition_simple.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"\\newglossaryentry{foo}{bar = baz, qux,}\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/glossary/glossary_entry_definition_simple.txt --- ROOT@0..39 PREAMBLE@0..39 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__glossary_entry_reference_options.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@glossary__glossary_entry_reference_options.txt.snap index 494c0be0a0..d97e984b77 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__glossary_entry_reference_options.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@glossary__glossary_entry_reference_options.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"\\gls[foo = bar, qux]{baz}\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/glossary/glossary_entry_reference_options.txt --- ROOT@0..25 PREAMBLE@0..25 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__glossary_entry_reference_simple.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@glossary__glossary_entry_reference_simple.txt.snap index 94af3796fc..8c8fb0c1e2 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__glossary_entry_reference_simple.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@glossary__glossary_entry_reference_simple.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"\\gls{foo}\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/glossary/glossary_entry_reference_simple.txt --- ROOT@0..9 PREAMBLE@0..9 diff --git a/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@graphics_path.txt.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@graphics_path.txt.snap new file mode 100644 index 0000000000..9067d36c7d --- /dev/null +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@graphics_path.txt.snap @@ -0,0 +1,18 @@ +--- +source: src/parser/latex.rs +assertion_line: 1361 +expression: root +--- +ROOT@0..28 + PREAMBLE@0..28 + GRAPHICS_PATH@0..28 + GRAPHICS_PATH_NAME@0..13 "\\graphicspath" + CURLY_GROUP@13..28 + L_CURLY@13..14 "{" + CURLY_GROUP_WORD@14..27 + L_CURLY@14..15 "{" + KEY@15..26 + WORD@15..26 "../figures/" + R_CURLY@26..27 "}" + R_CURLY@27..28 "}" + diff --git a/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@graphics_path_command.txt.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@graphics_path_command.txt.snap new file mode 100644 index 0000000000..4092b2e8e9 --- /dev/null +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@graphics_path_command.txt.snap @@ -0,0 +1,23 @@ +--- +source: src/parser/latex.rs +assertion_line: 1348 +expression: root +--- +ROOT@0..32 + PREAMBLE@0..32 + GRAPHICS_PATH@0..32 + GRAPHICS_PATH_NAME@0..13 "\\graphicspath" + CURLY_GROUP@13..32 + L_CURLY@13..14 "{" + CURLY_GROUP_WORD@14..31 + L_CURLY@14..15 "{" + KEY@15..30 + GENERIC_COMMAND_NAME@15..22 "\\subfix" + CURLY_GROUP_WORD@22..30 + L_CURLY@22..23 "{" + KEY@23..29 + WORD@23..29 "./img/" + R_CURLY@29..30 "}" + R_CURLY@30..31 "}" + R_CURLY@31..32 "}" + diff --git a/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@graphics_path_options.txt.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@graphics_path_options.txt.snap new file mode 100644 index 0000000000..0eb034bbb3 --- /dev/null +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@graphics_path_options.txt.snap @@ -0,0 +1,23 @@ +--- +source: src/parser/latex.rs +assertion_line: 1348 +expression: root +--- +ROOT@0..33 + PREAMBLE@0..33 + GRAPHICS_PATH@0..13 + GRAPHICS_PATH_NAME@0..13 "\\graphicspath" + MIXED_GROUP@13..18 + L_BRACK@13..14 "[" + TEXT@14..17 + WORD@14..17 "foo" + R_BRACK@17..18 "]" + CURLY_GROUP@18..33 + L_CURLY@18..19 "{" + CURLY_GROUP@19..32 + L_CURLY@19..20 "{" + TEXT@20..31 + WORD@20..31 "../figures/" + R_CURLY@31..32 "}" + R_CURLY@32..33 "}" + diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__brace_group_missing_end.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@group__curly_group_missing_end.txt.snap index c5fc46ec4d..68969f9c11 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__brace_group_missing_end.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@group__curly_group_missing_end.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"{hello world\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/group/curly_group_missing_end.txt --- ROOT@0..12 PREAMBLE@0..12 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__brace_group_simple.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@group__curly_group_simple.txt.snap index 10ebc4418e..156ec2e0a2 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__brace_group_simple.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@group__curly_group_simple.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"{hello world}\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/group/curly_group_simple.txt --- ROOT@0..13 PREAMBLE@0..13 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__equation_missing_end.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@group__equation_missing_end.txt.snap index 3085037fac..eae04433d1 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__equation_missing_end.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@group__equation_missing_end.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"\\begin{a} \\[ foo bar \\end{b}\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/group/equation_missing_end.txt --- ROOT@0..28 PREAMBLE@0..28 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__escaped_brackets.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@group__escaped_brackets.txt.snap index c595828583..a396d2e984 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__escaped_brackets.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@group__escaped_brackets.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"{[}{]}\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/group/escaped_brackets.txt --- ROOT@0..6 PREAMBLE@0..6 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__unmatched_braces.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@group__unmatched_braces.txt.snap index df463f501a..82d7e9db45 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__unmatched_braces.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@group__unmatched_braces.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"}{\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/group/unmatched_braces.txt --- ROOT@0..2 PREAMBLE@0..2 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__unmatched_brackets.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@group__unmatched_brackets.txt.snap index 578cbf6099..7dd82d48bc 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__unmatched_brackets.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@group__unmatched_brackets.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"][\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/group/unmatched_brackets.txt --- ROOT@0..2 PREAMBLE@0..2 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__unmatched_brackets_with_group.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@group__unmatched_brackets_with_group.txt.snap index d929c98c46..3c45c0c14c 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__unmatched_brackets_with_group.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@group__unmatched_brackets_with_group.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"{][}\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/group/unmatched_brackets_with_group.txt --- ROOT@0..4 PREAMBLE@0..4 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__hello_world.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@hello_world.txt.snap index ee25cb5453..7c1ff02b81 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__hello_world.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@hello_world.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"Hello World!\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/hello_world.txt --- ROOT@0..12 PREAMBLE@0..12 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__biblatex_include_options.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@include__biblatex_include_options.txt.snap index 3189cabd46..897d693fd0 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__biblatex_include_options.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@include__biblatex_include_options.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"\\addbibresource[foo=bar, baz]{foo/bar.bib}\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/include/biblatex_include_options.txt --- ROOT@0..42 PREAMBLE@0..42 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__biblatex_include_simple.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@include__biblatex_include_simple.txt.snap index 3166d13aff..a4be9c38cb 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__biblatex_include_simple.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@include__biblatex_include_simple.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"\\addbibresource{foo/bar.bib}\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/include/biblatex_include_simple.txt --- ROOT@0..28 PREAMBLE@0..28 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__bibtex_include_simple.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@include__bibtex_include_simple.txt.snap index db58621c75..0a8f9cd3f6 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__bibtex_include_simple.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@include__bibtex_include_simple.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"\\bibliography{foo/bar}\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/include/bibtex_include_simple.txt --- ROOT@0..22 PREAMBLE@0..22 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__class_include_empty.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@include__class_include_empty.txt.snap index 7d84653225..37ea745308 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__class_include_empty.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@include__class_include_empty.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"\\documentclass{}\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/include/class_include_empty.txt --- ROOT@0..16 PREAMBLE@0..16 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__class_include_options.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@include__class_include_options.txt.snap index ac20c4b8ac..ff95f8358f 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__class_include_options.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@include__class_include_options.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"\\documentclass[foo = bar, baz, qux]{article}\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/include/class_include_options.txt --- ROOT@0..44 PREAMBLE@0..44 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__class_include_simple.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@include__class_include_simple.txt.snap index 07c426101e..670fa2b902 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__class_include_simple.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@include__class_include_simple.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"\\documentclass{article}\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/include/class_include_simple.txt --- ROOT@0..23 PREAMBLE@0..23 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__graphics_include_command.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@include__graphics_include_command.txt.snap index d279eda7f7..0332499c66 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__graphics_include_command.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@include__graphics_include_command.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -assertion_line: 1639 -expression: "setup(r#\"\\includegraphics[width=0.5\\textwidth]{\\foo.\\bar.pdf}\"#)" +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/include/graphics_include_command.txt --- ROOT@0..52 PREAMBLE@0..52 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__graphics_include_complicated_options.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@include__graphics_include_complicated_options.txt.snap index a79c7f925e..5259eb5072 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__graphics_include_complicated_options.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@include__graphics_include_complicated_options.txt.snap @@ -1,8 +1,7 @@ --- -source: src/syntax/latex/parser.rs -assertion_line: 1547 -expression: "setup(r#\"\\includegraphics[width=0.5\\textwidth]{}\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/include/graphics_include_complicated_options.txt --- ROOT@0..39 PREAMBLE@0..39 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__graphics_include_options.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@include__graphics_include_options.txt.snap index 14e2413323..5ed7df9cfc 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__graphics_include_options.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@include__graphics_include_options.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"\\includegraphics[scale=.5]{foo/bar.pdf}\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/include/graphics_include_options.txt --- ROOT@0..39 PREAMBLE@0..39 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__graphics_include_simple.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@include__graphics_include_simple.txt.snap index f4c640bca8..cabb065d24 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__graphics_include_simple.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@include__graphics_include_simple.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"\\includegraphics{foo/bar.pdf}\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/include/graphics_include_simple.txt --- ROOT@0..29 PREAMBLE@0..29 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__import_incomplete.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@include__import_incomplete.txt.snap index c8634d6269..dad78222c2 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__import_incomplete.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@include__import_incomplete.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"\\import{foo\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/include/import_incomplete.txt --- ROOT@0..11 PREAMBLE@0..11 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__import_simple.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@include__import_simple.txt.snap index c94f34eb3f..9e4fdeb284 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__import_simple.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@include__import_simple.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"\\import{foo}{bar}\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/include/import_simple.txt --- ROOT@0..17 PREAMBLE@0..17 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__inkscape_include_options.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@include__inkscape_include_options.txt.snap index 8b95509be6..d0e8321692 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__inkscape_include_options.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@include__inkscape_include_options.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"\\includesvg[scale=.5]{foo/bar}\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/include/inkscape_include_options.txt --- ROOT@0..30 PREAMBLE@0..30 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__inkscape_include_simple.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@include__inkscape_include_simple.txt.snap index e3d1f9bdfd..1d1e68f33c 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__inkscape_include_simple.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@include__inkscape_include_simple.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"\\includesvg{foo/bar}\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/include/inkscape_include_simple.txt --- ROOT@0..20 PREAMBLE@0..20 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__latex_include_equality_sign.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@include__latex_include_equality_sign.txt.snap index c6cfb5dda3..abf7865a42 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__latex_include_equality_sign.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@include__latex_include_equality_sign.txt.snap @@ -1,8 +1,7 @@ --- -source: src/syntax/latex/parser.rs -assertion_line: 1504 -expression: "setup(r#\"\\include{foo=bar}\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/include/latex_include_equality_sign.txt --- ROOT@0..17 PREAMBLE@0..17 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__latex_include_simple.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@include__latex_include_simple.txt.snap index dbdeaad2f7..2315a2ad7c 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__latex_include_simple.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@include__latex_include_simple.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"\\include{foo/bar}\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/include/latex_include_simple.txt --- ROOT@0..17 PREAMBLE@0..17 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__latex_input_path_with_brackets.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@include__latex_input_path_brackets.txt.snap index cb99f39728..0ba79f0c41 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__latex_input_path_with_brackets.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@include__latex_input_path_brackets.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -assertion_line: 1591 -expression: "setup(r#\"\\input{foo[bar].tex}\"#)" +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/include/latex_input_path_brackets.txt --- ROOT@0..20 PREAMBLE@0..20 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__package_include_empty.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@include__package_include_empty.txt.snap index b8851b6e1d..36e2ab5aeb 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__package_include_empty.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@include__package_include_empty.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"\\usepackage{}\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/include/package_include_empty.txt --- ROOT@0..13 PREAMBLE@0..13 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__package_include_multiple.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@include__package_include_multiple.txt.snap index 2df92fd909..876f7313d7 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__package_include_multiple.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@include__package_include_multiple.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"\\usepackage{amsmath, lipsum}\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/include/package_include_multiple.txt --- ROOT@0..28 PREAMBLE@0..28 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__package_include_options.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@include__package_include_options.txt.snap index 0f87570023..32a624f769 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__package_include_options.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@include__package_include_options.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"\\usepackage[foo = bar, baz, qux]{amsmath}\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/include/package_include_options.txt --- ROOT@0..41 PREAMBLE@0..41 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__package_include_simple.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@include__package_include_simple.txt.snap index a28dd39a13..014ed983dd 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__package_include_simple.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@include__package_include_simple.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"\\usepackage{amsmath}\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/include/package_include_simple.txt --- ROOT@0..20 PREAMBLE@0..20 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__pgf_library_import_simple.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@include__pgf_library_import_simple.txt.snap index c36bf857bb..7f5f78415e 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__pgf_library_import_simple.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@include__pgf_library_import_simple.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"\\usepgflibrary{foo}\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/include/pgf_library_import_simple.txt --- ROOT@0..19 PREAMBLE@0..19 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__svg_include_options.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@include__svg_include_options.txt.snap index 3140282630..2410aeaa5a 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__svg_include_options.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@include__svg_include_options.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"\\includesvg[scale=.5]{foo/bar.svg}\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/include/svg_include_options.txt --- ROOT@0..34 PREAMBLE@0..34 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__svg_include_simple.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@include__svg_include_simple.txt.snap index 2cf133b4d0..61dd22f045 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__svg_include_simple.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@include__svg_include_simple.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"\\includesvg{foo/bar.svg}\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/include/svg_include_simple.txt --- ROOT@0..24 PREAMBLE@0..24 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__tikz_library_import_simple.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@include__tikz_library_import_simple.txt.snap index 4cd63e6728..c68ff02964 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__tikz_library_import_simple.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@include__tikz_library_import_simple.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"\\usetikzlibrary{foo}\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/include/tikz_library_import_simple.txt --- ROOT@0..20 PREAMBLE@0..20 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__verbatim_include_simple.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@include__verbatim_include_simple.txt.snap index 48d6b816f3..3c35fddf18 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__verbatim_include_simple.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@include__verbatim_include_simple.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"\\verbatiminput{foo/bar.txt}\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/include/verbatim_include_simple.txt --- ROOT@0..27 PREAMBLE@0..27 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__inline.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@inline.txt.snap index b430de766e..c055d183bd 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__inline.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@inline.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"$x \\in [0, \\infty)$\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/inline.txt --- ROOT@0..19 PREAMBLE@0..19 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__inline_double_dollar.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@inline_double_dollar.txt.snap index 8da22f3ecb..7084156fce 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__inline_double_dollar.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@inline_double_dollar.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"$$x \\in [0, \\infty)$$\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/inline_double_dollar.txt --- ROOT@0..21 PREAMBLE@0..21 diff --git a/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@issue_745.txt.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@issue_745.txt.snap new file mode 100644 index 0000000000..8530953285 --- /dev/null +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@issue_745.txt.snap @@ -0,0 +1,120 @@ +--- +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/issue_745.txt +--- +ROOT@0..271 + PREAMBLE@0..271 + CLASS_INCLUDE@0..24 + CLASS_INCLUDE_NAME@0..14 "\\documentclass" + CURLY_GROUP_WORD_LIST@14..24 + L_CURLY@14..15 "{" + KEY@15..22 + WORD@15..22 "article" + R_CURLY@22..23 "}" + LINE_BREAK@23..24 "\n" + PACKAGE_INCLUDE@24..50 + PACKAGE_INCLUDE_NAME@24..35 "\\usepackage" + CURLY_GROUP_WORD_LIST@35..50 + L_CURLY@35..36 "{" + KEY@36..46 + WORD@36..46 "tabularray" + R_CURLY@46..47 "}" + WHITESPACE@47..50 " \n\n" + GENERIC_COMMAND@50..64 + GENERIC_COMMAND_NAME@50..63 "\\ExplSyntaxOn" + LINE_BREAK@63..64 "\n" + GENERIC_COMMAND@64..223 + GENERIC_COMMAND_NAME@64..87 "\\NewDocumentEnvironment" + CURLY_GROUP@87..96 + L_CURLY@87..88 "{" + TEXT@88..95 + WORD@88..95 "exptblr" + R_CURLY@95..96 "}" + CURLY_GROUP@96..107 + L_CURLY@96..97 "{" + TEXT@97..98 + WORD@97..98 "O" + CURLY_GROUP@98..100 + L_CURLY@98..99 "{" + R_CURLY@99..100 "}" + TEXT@100..101 + WORD@100..101 "m" + R_CURLY@101..102 "}" + WHITESPACE@102..107 "\n " + CURLY_GROUP@107..200 + L_CURLY@107..108 "{" + WHITESPACE@108..113 "\n " + GENERIC_COMMAND@113..194 + GENERIC_COMMAND_NAME@113..119 "\\use:x" + WHITESPACE@119..124 "\n " + CURLY_GROUP@124..194 + L_CURLY@124..125 "{" + WHITESPACE@125..130 "\n " + GENERIC_COMMAND@130..141 + GENERIC_COMMAND_NAME@130..140 "\\exp_not:N" + WHITESPACE@140..141 " " + ENVIRONMENT@141..188 + BEGIN@141..179 + BEGIN_ENVIRONMENT_NAME@141..147 "\\begin" + CURLY_GROUP_WORD@147..158 + L_CURLY@147..148 "{" + KEY@148..152 + WORD@148..152 "tblr" + R_CURLY@152..153 "}" + WHITESPACE@153..158 "\n " + BRACK_GROUP@158..179 + L_BRACK@158..159 "[" + GENERIC_COMMAND@159..173 + GENERIC_COMMAND_NAME@159..169 "\\exp_not:n" + CURLY_GROUP@169..173 + L_CURLY@169..170 "{" + TEXT@170..172 + WORD@170..172 "#1" + R_CURLY@172..173 "}" + R_BRACK@173..174 "]" + WHITESPACE@174..179 "\n " + CURLY_GROUP@179..188 + L_CURLY@179..180 "{" + TEXT@180..182 + WORD@180..182 "#2" + R_CURLY@182..183 "}" + WHITESPACE@183..188 "\n " + MISSING@188..188 "" + R_CURLY@188..189 "}" + WHITESPACE@189..194 "\n " + R_CURLY@194..195 "}" + WHITESPACE@195..200 "\n " + CURLY_GROUP@200..223 + L_CURLY@200..201 "{" + WHITESPACE@201..206 "\n " + GENERIC_COMMAND@206..221 + END_ENVIRONMENT_NAME@206..210 "\\end" + CURLY_GROUP@210..221 + L_CURLY@210..211 "{" + TEXT@211..215 + WORD@211..215 "tblr" + R_CURLY@215..216 "}" + WHITESPACE@216..221 "\n " + R_CURLY@221..222 "}" + LINE_BREAK@222..223 "\n" + GENERIC_COMMAND@223..239 + GENERIC_COMMAND_NAME@223..237 "\\ExplSyntaxOff" + LINE_BREAK@237..239 "\n\n" + ENVIRONMENT@239..271 + BEGIN@239..257 + BEGIN_ENVIRONMENT_NAME@239..245 "\\begin" + CURLY_GROUP_WORD@245..257 + L_CURLY@245..246 "{" + KEY@246..254 + WORD@246..254 "document" + R_CURLY@254..255 "}" + LINE_BREAK@255..257 "\n\n" + END@257..271 + END_ENVIRONMENT_NAME@257..261 "\\end" + CURLY_GROUP_WORD@261..271 + L_CURLY@261..262 "{" + KEY@262..270 + WORD@262..270 "document" + R_CURLY@270..271 "}" + diff --git a/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@issue_789.txt.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@issue_789.txt.snap new file mode 100644 index 0000000000..ff20c01008 --- /dev/null +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@issue_789.txt.snap @@ -0,0 +1,15 @@ +--- +source: src/parser/latex.rs +assertion_line: 1361 +expression: root +--- +ROOT@0..19 + PREAMBLE@0..19 + GRAPHICS_PATH@0..19 + GRAPHICS_PATH_NAME@0..13 "\\graphicspath" + CURLY_GROUP_WORD@13..19 + L_CURLY@13..14 "{" + KEY@14..18 + WORD@14..18 "test" + R_CURLY@18..19 "}" + diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__label_definition_line_break.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@label__label_definition_line_break.txt.snap index 47187fabcd..7f2ff377b8 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__label_definition_line_break.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@label__label_definition_line_break.txt.snap @@ -1,8 +1,7 @@ --- -source: src/syntax/latex/parser.rs -assertion_line: 1719 -expression: "setup(\"\\\\label{hello\\nworld}\")" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/label/label_definition_line_break.txt --- ROOT@0..19 PREAMBLE@0..19 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__label_definition_simple.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@label__label_definition_simple.txt.snap index 2d15533f87..a2e8b85b55 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__label_definition_simple.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@label__label_definition_simple.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"\\label{foo}\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/label/label_definition_simple.txt --- ROOT@0..11 PREAMBLE@0..11 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__label_number.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@label__label_number.txt.snap index a63752d80e..9afdf9e88e 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__label_number.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@label__label_number.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"\\newlabel{foo}{{1.1}}\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/label/label_number.txt --- ROOT@0..21 PREAMBLE@0..21 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__equation_label_reference_simple.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@label__label_reference_equation.txt.snap index 9123fafcf2..93580e846e 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__equation_label_reference_simple.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@label__label_reference_equation.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"\\eqref{foo}\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/label/label_reference_equation.txt --- ROOT@0..11 PREAMBLE@0..11 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__label_reference_incomplete.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@label__label_reference_incomplete.txt.snap index 047eea657d..64e2d9af44 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__label_reference_incomplete.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@label__label_reference_incomplete.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"Equation \\eqref{eq is a \\emph{useful} identity.\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/label/label_reference_incomplete.txt --- ROOT@0..47 PREAMBLE@0..47 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__label_reference_multiple.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@label__label_reference_multiple.txt.snap index 0176c770e8..27d56c6789 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__label_reference_multiple.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@label__label_reference_multiple.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"\\ref{foo, bar}\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/label/label_reference_multiple.txt --- ROOT@0..14 PREAMBLE@0..14 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__label_reference_range_error.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@label__label_reference_range_error.txt.snap index ee65f8a02f..ce5e6a49b5 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__label_reference_range_error.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@label__label_reference_range_error.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"\\crefrange{foo{bar}\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/label/label_reference_range_error.txt --- ROOT@0..19 PREAMBLE@0..19 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__label_reference_range_incomplete.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@label__label_reference_range_incomplete.txt.snap index 3dbe4bbab6..b682f40ebc 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__label_reference_range_incomplete.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@label__label_reference_range_incomplete.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"\\crefrange{foo}\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/label/label_reference_range_incomplete.txt --- ROOT@0..15 PREAMBLE@0..15 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__label_reference_range_simple.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@label__label_reference_range_simple.txt.snap index 094d0e2870..e76708bf43 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__label_reference_range_simple.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@label__label_reference_range_simple.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"\\crefrange{foo}{bar}\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/label/label_reference_range_simple.txt --- ROOT@0..20 PREAMBLE@0..20 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__label_reference_simple.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@label__label_reference_simple.txt.snap index 9b6e622ef9..398a6c1682 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__label_reference_simple.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@label__label_reference_simple.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"\\ref{foo}\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/label/label_reference_simple.txt --- ROOT@0..9 PREAMBLE@0..9 diff --git a/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@parameter.txt.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@parameter.txt.snap new file mode 100644 index 0000000000..333db9df78 --- /dev/null +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@parameter.txt.snap @@ -0,0 +1,10 @@ +--- +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/parameter.txt +--- +ROOT@0..2 + PREAMBLE@0..2 + TEXT@0..2 + WORD@0..2 "#1" + diff --git a/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@parameter_error.txt.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@parameter_error.txt.snap new file mode 100644 index 0000000000..8e3b45ad67 --- /dev/null +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@parameter_error.txt.snap @@ -0,0 +1,10 @@ +--- +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/parameter_error.txt +--- +ROOT@0..1 + PREAMBLE@0..1 + TEXT@0..1 + WORD@0..1 "#" + diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__structure_enum_item.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@structure__structure_enum_item.txt.snap index 0ca7421ac6..4c6222045c 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__structure_enum_item.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@structure__structure_enum_item.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"\\begin{enumerate} \\item 1 \\item[2] 2 \\item 3 \\end{enumerate}\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/structure/structure_enum_item.txt --- ROOT@0..60 PREAMBLE@0..60 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__structure_invalid_nesting.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@structure__structure_invalid_nesting.txt.snap index f999a50e9a..c5f7aede51 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__structure_invalid_nesting.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@structure__structure_invalid_nesting.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"\\section{Foo} \\chapter{Bar}\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/structure/structure_invalid_nesting.txt --- ROOT@0..27 PREAMBLE@0..27 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__structure_nested.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@structure__structure_nested.txt.snap index db5602e591..1f93b8c11f 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__structure_nested.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@structure__structure_nested.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"\\part{1}\\chapter{2}\\section{3}\\subsection{4}\\subsubsection{5}\\paragraph{6}\\subparagraph{7}\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/structure/structure_nested.txt --- ROOT@0..90 PREAMBLE@0..90 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__structure_siblings.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@structure__structure_siblings.txt.snap index 94d2ef40bd..03a29cb4bd 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__structure_siblings.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@structure__structure_siblings.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"\\section{Foo} Foo \\section{Bar} Bar\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/structure/structure_siblings.txt --- ROOT@0..35 PREAMBLE@0..35 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__theorem_definition_full.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@theorem_definition__theorem_definition_full.txt.snap index 7f21c0ef52..81b9c92758 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__theorem_definition_full.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@theorem_definition__theorem_definition_full.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"\\newtheorem{foo}[bar]{Foo}[baz]\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/theorem_definition/theorem_definition_full.txt --- ROOT@0..31 PREAMBLE@0..31 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__theorem_definition_name_with_counter.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@theorem_definition__theorem_definition_name_with_counter.txt.snap index d7bb29bf58..b422a2619f 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__theorem_definition_name_with_counter.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@theorem_definition__theorem_definition_name_with_counter.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"\\newtheorem{foo}[bar]\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/theorem_definition/theorem_definition_name_with_counter.txt --- ROOT@0..21 PREAMBLE@0..21 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__theorem_definition_name_with_description.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@theorem_definition__theorem_definition_name_with_description.txt.snap index 7c8b49efa1..0b1a3f3e48 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__theorem_definition_name_with_description.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@theorem_definition__theorem_definition_name_with_description.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"\\newtheorem{foo}{Foo}\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/theorem_definition/theorem_definition_name_with_description.txt --- ROOT@0..21 PREAMBLE@0..21 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__theorem_definition_name_with_description_and_counter.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@theorem_definition__theorem_definition_name_with_description_and_counter.txt.snap index 3322a9a116..1f84c653bd 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__theorem_definition_name_with_description_and_counter.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@theorem_definition__theorem_definition_name_with_description_and_counter.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"\\newtheorem{foo}[bar]{Foo}\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/theorem_definition/theorem_definition_name_with_description_and_counter.txt --- ROOT@0..26 PREAMBLE@0..26 diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__theorem_definition_only_name.snap b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@theorem_definition__theorem_definition_only_name.txt.snap index 0ba62df76c..8c85579665 100644 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__theorem_definition_only_name.snap +++ b/support/texlab/src/parser/snapshots/texlab__parser__latex__tests__parse@theorem_definition__theorem_definition_only_name.txt.snap @@ -1,7 +1,7 @@ --- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"\\newtheorem{foo}\"#)" - +source: src/parser/latex.rs +expression: root +input_file: src/parser/test_data/latex/theorem_definition/theorem_definition_only_name.txt --- ROOT@0..16 PREAMBLE@0..16 diff --git a/support/texlab/src/parser/test_data/bibtex/comment.txt b/support/texlab/src/parser/test_data/bibtex/comment.txt new file mode 100644 index 0000000000..f2ff586ab7 --- /dev/null +++ b/support/texlab/src/parser/test_data/bibtex/comment.txt @@ -0,0 +1,6 @@ +Some junk here + +@comment{foo, + author = {Foo Bar}, + title = {Some Title}, +} diff --git a/support/texlab/src/parser/test_data/bibtex/issue_809.txt b/support/texlab/src/parser/test_data/bibtex/issue_809.txt new file mode 100644 index 0000000000..c94b808fd5 --- /dev/null +++ b/support/texlab/src/parser/test_data/bibtex/issue_809.txt @@ -0,0 +1,3 @@ +@article{issue_809, + title = {foo (" bar) baz}, +}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/bibtex/preamble.txt b/support/texlab/src/parser/test_data/bibtex/preamble.txt new file mode 100644 index 0000000000..266b5ce228 --- /dev/null +++ b/support/texlab/src/parser/test_data/bibtex/preamble.txt @@ -0,0 +1 @@ +@preamble{"Hello World!"}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/bibtex/samples/aho_2006.txt b/support/texlab/src/parser/test_data/bibtex/samples/aho_2006.txt new file mode 100644 index 0000000000..ff829b40d1 --- /dev/null +++ b/support/texlab/src/parser/test_data/bibtex/samples/aho_2006.txt @@ -0,0 +1,8 @@ +@book{10.5555/1177220, + author = {Aho, Alfred V. and Lam, Monica S. and Sethi, Ravi and Ullman, Jeffrey D.}, + title = {Compilers: Principles, Techniques, and Tools (2nd Edition)}, + year = {2006}, + isbn = {0321486811}, + publisher = {Addison-Wesley Longman Publishing Co., Inc.}, + address = {USA} +}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/bibtex/samples/aksin_2006.txt b/support/texlab/src/parser/test_data/bibtex/samples/aksin_2006.txt new file mode 100644 index 0000000000..88ea701c22 --- /dev/null +++ b/support/texlab/src/parser/test_data/bibtex/samples/aksin_2006.txt @@ -0,0 +1,16 @@ +@string{jomch = {J.~Organomet. Chem.}} + +@article{aksin, + author = {Aks{\i}n, {\"O}zge and T{\"u}rkmen, Hayati and Artok, Levent + and {\c{C}}etinkaya, Bekir and Ni, Chaoying and + B{\"u}y{\"u}kg{\"u}ng{\"o}r, Orhan and {\"O}zkal, Erhan}, + title = {Effect of immobilization on catalytic characteristics of + saturated {Pd-N}-heterocyclic carbenes in {Mizoroki-Heck} + reactions}, + journaltitle = jomch, + date = 2006, + volume = 691, + number = 13, + pages = {3027-3036}, + indextitle = {Effect of immobilization on catalytic characteristics}, +}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/bibtex/samples/almendro_1998.txt b/support/texlab/src/parser/test_data/bibtex/samples/almendro_1998.txt new file mode 100644 index 0000000000..ed16d33c67 --- /dev/null +++ b/support/texlab/src/parser/test_data/bibtex/samples/almendro_1998.txt @@ -0,0 +1,14 @@ +@patent{almendro, + author = {Almendro, Jos{\'e} L. and Mart{\'i}n, Jacinto and S{\'a}nchez, + Alberto and Nozal, Fernando}, + title = {Elektromagnetisches Signalhorn}, + number = {EU-29702195U}, + date = 1998, + location = {countryfr and countryuk and countryde}, + langid = {german}, + annotation = {This is a \texttt{patent} entry with a \texttt{location} + field. The number is given in the \texttt{number} field. Note + the format of the \texttt{location} field in the database + file. Compare \texttt{laufenberg}, \texttt{sorace}, and + \texttt{kowalik}}, +}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/bibtex/samples/averroes_1998.txt b/support/texlab/src/parser/test_data/bibtex/samples/averroes_1998.txt new file mode 100644 index 0000000000..9f224353cc --- /dev/null +++ b/support/texlab/src/parser/test_data/bibtex/samples/averroes_1998.txt @@ -0,0 +1,21 @@ +@book{averroes/bland, + author = {Averroes}, + title = {The Epistle on the Possibility of Conjunction with the Active + Intellect by {Ibn Rushd} with the Commentary of {Moses Narboni}}, + date = 1982, + editor = {Bland, Kalman P.}, + translator = {Bland, Kalman P.}, + series = {Moreshet: Studies in {Jewish} History, Literature and Thought}, + number = 7, + publisher = {Jewish Theological Seminary of America}, + location = {New York}, + keywords = {primary}, + langid = {english}, + langidopts = {variant=american}, + indextitle = {Epistle on the Possibility of Conjunction, The}, + shorttitle = {Possibility of Conjunction}, + annotation = {A \texttt{book} entry with a \texttt{series} and a + \texttt{number}. Note the concatenation of the \texttt{editor} + and \texttt{translator} fields as well as the + \texttt{indextitle} field}, +}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/bibtex/samples/betram_1996.txt b/support/texlab/src/parser/test_data/bibtex/samples/betram_1996.txt new file mode 100644 index 0000000000..b2d77e216f --- /dev/null +++ b/support/texlab/src/parser/test_data/bibtex/samples/betram_1996.txt @@ -0,0 +1,16 @@ +@string{jams = {J.~Amer. Math. Soc.}} + +@article{bertram, + author = {Bertram, Aaron and Wentworth, Richard}, + title = {Gromov invariants for holomorphic maps on {Riemann} surfaces}, + journaltitle = jams, + date = 1996, + volume = 9, + number = 2, + pages = {529-571}, + langid = {english}, + langidopts = {variant=american}, + shorttitle = {Gromov invariants}, + annotation = {An \texttt{article} entry with a \texttt{volume} and a + \texttt{number} field}, +}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/bibtex/samples/blom_2021.txt b/support/texlab/src/parser/test_data/bibtex/samples/blom_2021.txt new file mode 100644 index 0000000000..a502e53e03 --- /dev/null +++ b/support/texlab/src/parser/test_data/bibtex/samples/blom_2021.txt @@ -0,0 +1,20 @@ +@article{DBLP:journals/corr/abs-2107-11903, + author = {Michelle L. Blom and + Jurlind Budurushi and + Ronald L. Rivest and + Philip B. Stark and + Peter J. Stuckey and + Vanessa Teague and + Damjan Vukcevic}, + title = {Assertion-based Approaches to Auditing Complex Elections, with application + to party-list proportional elections}, + journal = {CoRR}, + volume = {abs/2107.11903}, + year = {2021}, + url = {https://arxiv.org/abs/2107.11903}, + eprinttype = {arXiv}, + eprint = {2107.11903}, + timestamp = {Thu, 29 Jul 2021 16:14:15 +0200}, + biburl = {https://dblp.org/rec/journals/corr/abs-2107-11903.bib}, + bibsource = {dblp computer science bibliography, https://dblp.org} +}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/bibtex/samples/combi_2004.txt b/support/texlab/src/parser/test_data/bibtex/samples/combi_2004.txt new file mode 100644 index 0000000000..7d8545577d --- /dev/null +++ b/support/texlab/src/parser/test_data/bibtex/samples/combi_2004.txt @@ -0,0 +1,16 @@ +@inproceedings{10.1145/967900.968040, + author = {Combi, Carlo and Pozzi, Giuseppe}, + title = {Architectures for a Temporal Workflow Management System}, + year = {2004}, + isbn = {1581138121}, + publisher = {Association for Computing Machinery}, + address = {New York, NY, USA}, + url = {https://doi.org/10.1145/967900.968040}, + doi = {10.1145/967900.968040}, + booktitle = {Proceedings of the 2004 ACM Symposium on Applied Computing}, + pages = {659-666}, + numpages = {8}, + keywords = {active DBMS, temporal DBMS, workflow management system - WfMS, temporal workflow management system}, + location = {Nicosia, Cyprus}, + series = {SAC '04} +}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/bibtex/samples/erwin_2007.txt b/support/texlab/src/parser/test_data/bibtex/samples/erwin_2007.txt new file mode 100644 index 0000000000..116f5e7098 --- /dev/null +++ b/support/texlab/src/parser/test_data/bibtex/samples/erwin_2007.txt @@ -0,0 +1,14 @@ +@inproceedings{10.5555/1386993.1386994, + author = {Erwin, Alva and Gopalan, Raj P. and Achuthan, N. R.}, + title = {A Bottom-up Projection Based Algorithm for Mining High Utility Itemsets}, + year = {2007}, + isbn = {9781920682651}, + publisher = {Australian Computer Society, Inc.}, + address = {AUS}, + booktitle = {Proceedings of the 2nd International Workshop on Integrating Artificial Intelligence and Data Mining - Volume 84}, + pages = {3-11}, + numpages = {9}, + keywords = {pattern growth, high utility itemset mining}, + location = {Gold Coast, Australia}, + series = {AIDM '07} +}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/bibtex/samples/jain_1999.txt b/support/texlab/src/parser/test_data/bibtex/samples/jain_1999.txt new file mode 100644 index 0000000000..c367ef12ee --- /dev/null +++ b/support/texlab/src/parser/test_data/bibtex/samples/jain_1999.txt @@ -0,0 +1,18 @@ +@article{10.1145/331499.331504, + author = {Jain, A. K. and Murty, M. N. and Flynn, P. J.}, + title = {Data Clustering: A Review}, + year = {1999}, + issue_date = {Sept. 1999}, + publisher = {Association for Computing Machinery}, + address = {New York, NY, USA}, + volume = {31}, + number = {3}, + issn = {0360-0300}, + url = {https://doi.org/10.1145/331499.331504}, + doi = {10.1145/331499.331504}, + journal = {ACM Comput. Surv.}, + month = {sep}, + pages = {264-323}, + numpages = {60}, + keywords = {incremental clustering, clustering applications, exploratory data analysis, cluster analysis, similarity indices, unsupervised learning} +}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/bibtex/samples/kastenholz_2006.txt b/support/texlab/src/parser/test_data/bibtex/samples/kastenholz_2006.txt new file mode 100644 index 0000000000..457f871491 --- /dev/null +++ b/support/texlab/src/parser/test_data/bibtex/samples/kastenholz_2006.txt @@ -0,0 +1,20 @@ +@string{jchph = {J.~Chem. Phys.}} + +@article{kastenholz, + author = {Kastenholz, M. A. and H{\"u}nenberger, Philippe H.}, + title = {Computation of methodology\hyphen independent ionic solvation + free energies from molecular simulations}, + journaltitle = jchph, + date = 2006, + subtitle = {{I}. {The} electrostatic potential in molecular liquids}, + volume = 124, + eid = 124106, + doi = {10.1063/1.2172593}, + langid = {english}, + langidopts = {variant=american}, + indextitle = {Computation of ionic solvation free energies}, + annotation = {An \texttt{article} entry with an \texttt{eid} and a + \texttt{doi} field. Note that the \textsc{doi} is transformed + into a clickable link if \texttt{hyperref} support has been + enabled}, +}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/bibtex/samples/knuth_1984.txt b/support/texlab/src/parser/test_data/bibtex/samples/knuth_1984.txt new file mode 100644 index 0000000000..98c595e35c --- /dev/null +++ b/support/texlab/src/parser/test_data/bibtex/samples/knuth_1984.txt @@ -0,0 +1,22 @@ +@book{knuth:ct:a, + author = {Knuth, Donald E.}, + title = {The {\TeX book}}, + date = 1984, + maintitle = {Computers \& Typesetting}, + volume = {A}, + publisher = {Addison-Wesley}, + location = {Reading, Mass.}, + langid = {english}, + langidopts = {variant=american}, + sorttitle = {Computers & Typesetting A}, + indexsorttitle= {The TeXbook}, + indextitle = {\protect\TeX book, The}, + shorttitle = {\TeX book}, + annotation = {The first volume of a five-volume book. Note the + \texttt{sorttitle} field. We want this + volume to be listed after the entry referring to the entire + five-volume set. Also note the \texttt{indextitle} and + \texttt{indexsorttitle} fields. Indexing packages that don't + generate robust index entries require some control sequences + to be protected from expansion}, +}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/bibtex/samples/matuz_1990.txt b/support/texlab/src/parser/test_data/bibtex/samples/matuz_1990.txt new file mode 100644 index 0000000000..cb803aab51 --- /dev/null +++ b/support/texlab/src/parser/test_data/bibtex/samples/matuz_1990.txt @@ -0,0 +1,14 @@ +@collection{matuz:doody, + editor = {Matuz, Roger}, + title = {Contemporary Literary Criticism}, + year = 1990, + volume = 61, + publisher = {Gale}, + location = {Detroit}, + pages = {204-208}, + langid = {english}, + langidopts = {variant=american}, + annotation = {A \texttt{collection} entry providing the excerpt information + for the \texttt{doody} entry. Note the format of the + \texttt{pages} field}, +}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/bibtex/samples/nietzsche_1998.txt b/support/texlab/src/parser/test_data/bibtex/samples/nietzsche_1998.txt new file mode 100644 index 0000000000..e245be39bb --- /dev/null +++ b/support/texlab/src/parser/test_data/bibtex/samples/nietzsche_1998.txt @@ -0,0 +1,24 @@ +@string{dtv = {Deutscher Taschenbuch-Verlag}} + +@mvbook{nietzsche:ksa, + author = {Nietzsche, Friedrich}, + title = {S{\"a}mtliche Werke}, + date = 1988, + editor = {Colli, Giorgio and Montinari, Mazzino}, + edition = 2, + volumes = 15, + publisher = dtv # { and Walter de Gruyter}, + location = {M{\"u}nchen and Berlin and New York}, + langid = {german}, + sorttitle = {Werke-00-000}, + indexsorttitle= {Samtliche Werke}, + subtitle = {Kritische Studienausgabe}, + annotation = {The critical edition of Nietzsche's works. This is a + \texttt{mvbook} entry referring to a 15-volume work as a + whole. Note the \texttt{volumes} field and the format of the + \texttt{publisher} and \texttt{location} fields in the + database file. Also note the \texttt{sorttitle} and + field which is used to fine-tune the + sorting order of the bibliography. We want this item listed + first in the bibliography}, +}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/bibtex/samples/rivest_1978.txt b/support/texlab/src/parser/test_data/bibtex/samples/rivest_1978.txt new file mode 100644 index 0000000000..e1076145ea --- /dev/null +++ b/support/texlab/src/parser/test_data/bibtex/samples/rivest_1978.txt @@ -0,0 +1,17 @@ +@article{10.1145/359340.359342, + author = {Rivest, R. L. and Shamir, A. and Adleman, L.}, + title = {A Method for Obtaining Digital Signatures and Public-Key Cryptosystems}, + year = {1978}, + issue_date = {Feb. 1978}, + publisher = {Association for Computing Machinery}, + address = {New York, NY, USA}, + volume = {21}, + number = {2}, + issn = {0001-0782}, + url = {https://doi.org/10.1145/359340.359342}, + doi = {10.1145/359340.359342}, + journal = {Commun. ACM}, + month = {feb}, + pages = {120-126}, + numpages = {7}, +}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/build_log/001.txt b/support/texlab/src/parser/test_data/build_log/001.txt new file mode 100644 index 0000000000..fc9968af0f --- /dev/null +++ b/support/texlab/src/parser/test_data/build_log/001.txt @@ -0,0 +1,83 @@ +This is pdfTeX, Version 3.14159265-2.6-1.40.18 (TeX Live 2017/W32TeX) (preloaded format=pdflatex 2018.3.30) 26 DEC 2018 16:50 +entering extended mode +restricted \write18 enabled. +%&-line parsing enabled. +**./parent.tex +(./parent.tex +LaTeX2e <2017-04-15> +Babel <3.10> and hyphenation patterns for 84 language(s) loaded. +(/TexLive/texmf-dist/tex/latex/base/article.cls +Document Class: article 2014/09/29 v1.4h Standard LaTeX document class +(/TexLive/texmf-dist/tex/latex/base/size10.clo +File: size10.clo 2014/09/29 v1.4h Standard LaTeX file (size option) +) +\c@part=\count79 +\c@section=\count80 +\c@subsection=\count81 +\c@subsubsection=\count82 +\c@paragraph=\count83 +\c@subparagraph=\count84 +\c@figure=\count85 +\c@table=\count86 +\abovecaptionskip=\skip41 +\belowcaptionskip=\skip42 +\bibindent=\dimen102 +) +(/TexLive/texmf-dist/tex/latex/multirow/bigstrut.sty +Package: bigstrut 2016/11/25 v2.2 Provide larger struts in tabulars +\bigstrutjot=\dimen103 +) +(/TexLive/texmf-dist/tex/latex/multirow/multirow.sty +Package: multirow 2016/11/25 v2.2 Span multiple rows of a table +\multirow@colwidth=\skip43 +\multirow@cntb=\count87 +\multirow@dima=\skip44 +) (./parent.aux) +\openout1 = `parent.aux'. + +LaTeX Font Info: Checking defaults for OML/cmm/m/it on input line 6. +LaTeX Font Info: ... okay on input line 6. +LaTeX Font Info: Checking defaults for T1/cmr/m/n on input line 6. +LaTeX Font Info: ... okay on input line 6. +LaTeX Font Info: Checking defaults for OT1/cmr/m/n on input line 6. +LaTeX Font Info: ... okay on input line 6. +LaTeX Font Info: Checking defaults for OMS/cmsy/m/n on input line 6. +LaTeX Font Info: ... okay on input line 6. +LaTeX Font Info: Checking defaults for OMX/cmex/m/n on input line 6. +LaTeX Font Info: ... okay on input line 6. +LaTeX Font Info: Checking defaults for U/cmr/m/n on input line 6. +LaTeX Font Info: ... okay on input line 6. + +Overfull \hbox (200.00162pt too wide) in paragraph at lines 8--9 +[]\OT1/cmr/m/n/10 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +[] + +LaTeX Font Info: External font `cmex10' loaded for size +(Font) <7> on input line 11. +LaTeX Font Info: External font `cmex10' loaded for size +(Font) <5> on input line 11. + +Overfull \vbox (3.19998pt too high) detected at line 23 +[] + +[1 + +{/TexLive/texmf-var/fonts/map/pdftex/updmap/pdftex.map}] (./parent.aux) ) +Here is how much of TeX's memory you used: +265 strings out of 492995 +3121 string characters out of 6138727 +55074 words of memory out of 5000000 +3896 multiletter control sequences out of 15000+600000 +3640 words of font info for 14 fonts, out of 8000000 for 9000 +1141 hyphenation exceptions out of 8191 +23i,20n,20p,124b,282s stack positions out of 5000i,500n,10000p,200000b,80000s +</ +TexLive/texmf-dist/fonts/type1/public/amsfonts/cm/cmr10.pfb></TexLive/texmf-d +ist/fonts/type1/public/amsfonts/cm/cmr7.pfb> +Output written on parent.pdf (1 page, 17505 bytes). +PDF statistics: +16 PDF objects out of 1000 (max. 8388607) +10 compressed objects within 1 object stream +0 named destinations out of 1000 (max. 500000) +1 words of extra memory for PDF output out of 10000 (max. 10000000)
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/build_log/002.txt b/support/texlab/src/parser/test_data/build_log/002.txt new file mode 100644 index 0000000000..8d438d1f12 --- /dev/null +++ b/support/texlab/src/parser/test_data/build_log/002.txt @@ -0,0 +1,64 @@ +This is pdfTeX, Version 3.14159265-2.6-1.40.18 (TeX Live 2017/W32TeX) (preloaded format=pdflatex 2018.3.30) 26 DEC 2018 16:52 +entering extended mode +restricted \write18 enabled. +%&-line parsing enabled. +**./parent.tex +(./parent.tex +LaTeX2e <2017-04-15> +Babel <3.10> and hyphenation patterns for 84 language(s) loaded. +(/TexLive/texmf-dist/tex/latex/base/article.cls +Document Class: article 2014/09/29 v1.4h Standard LaTeX document class +(/TexLive/texmf-dist/tex/latex/base/size10.clo +File: size10.clo 2014/09/29 v1.4h Standard LaTeX file (size option) +) +\c@part=\count79 +\c@section=\count80 +\c@subsection=\count81 +\c@subsubsection=\count82 +\c@paragraph=\count83 +\c@subparagraph=\count84 +\c@figure=\count85 +\c@table=\count86 +\abovecaptionskip=\skip41 +\belowcaptionskip=\skip42 +\bibindent=\dimen102 +) (./parent.aux (./child.aux)) +\openout1 = `parent.aux'. + +LaTeX Font Info: Checking defaults for OML/cmm/m/it on input line 4. +LaTeX Font Info: ... okay on input line 4. +LaTeX Font Info: Checking defaults for T1/cmr/m/n on input line 4. +LaTeX Font Info: ... okay on input line 4. +LaTeX Font Info: Checking defaults for OT1/cmr/m/n on input line 4. +LaTeX Font Info: ... okay on input line 4. +LaTeX Font Info: Checking defaults for OMS/cmsy/m/n on input line 4. +LaTeX Font Info: ... okay on input line 4. +LaTeX Font Info: Checking defaults for OMX/cmex/m/n on input line 4. +LaTeX Font Info: ... okay on input line 4. +LaTeX Font Info: Checking defaults for U/cmr/m/n on input line 4. +LaTeX Font Info: ... okay on input line 4. +(./child.tex +! Undefined control sequence. +l.1 \foo + +The control sequence at the end of the top line +of your error message was never \def'ed. If you have +misspelled it (e.g., `\hobx'), type `I' and the correct +spelling (e.g., `I\hbox'). Otherwise just continue, +and I'll forget about whatever was undefined. + +) (./parent.aux) ) +Here is how much of TeX's memory you used: +205 strings out of 492995 +2149 string characters out of 6138727 +54074 words of memory out of 5000000 +3841 multiletter control sequences out of 15000+600000 +3640 words of font info for 14 fonts, out of 8000000 for 9000 +1141 hyphenation exceptions out of 8191 +23i,1n,17p,116b,36s stack positions out of 5000i,500n,10000p,200000b,80000s + +No pages of output. +PDF statistics: +0 PDF objects out of 1000 (max. 8388607) +0 named destinations out of 1000 (max. 500000) +1 words of extra memory for PDF output out of 10000 (max. 10000000)
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/build_log/003.txt b/support/texlab/src/parser/test_data/build_log/003.txt new file mode 100644 index 0000000000..220614b91c --- /dev/null +++ b/support/texlab/src/parser/test_data/build_log/003.txt @@ -0,0 +1,65 @@ +This is pdfTeX, Version 3.14159265-2.6-1.40.18 (TeX Live 2017/W32TeX) (preloaded format=pdflatex 2018.3.30) 26 DEC 2018 16:51 +entering extended mode +restricted \write18 enabled. +%&-line parsing enabled. +**./parent.tex +(./parent.tex +LaTeX2e <2017-04-15> +Babel <3.10> and hyphenation patterns for 84 language(s) loaded. +(/TexLive/texmf-dist/tex/latex/base/article.cls +Document Class: article 2014/09/29 v1.4h Standard LaTeX document class +(/TexLive/texmf-dist/tex/latex/base/size10.clo +File: size10.clo 2014/09/29 v1.4h Standard LaTeX file (size option) +) +\c@part=\count79 +\c@section=\count80 +\c@subsection=\count81 +\c@subsubsection=\count82 +\c@paragraph=\count83 +\c@subparagraph=\count84 +\c@figure=\count85 +\c@table=\count86 +\abovecaptionskip=\skip41 +\belowcaptionskip=\skip42 +\bibindent=\dimen102 +) (./parent.aux) +\openout1 = `parent.aux'. + +LaTeX Font Info: Checking defaults for OML/cmm/m/it on input line 4. +LaTeX Font Info: ... okay on input line 4. +LaTeX Font Info: Checking defaults for T1/cmr/m/n on input line 4. +LaTeX Font Info: ... okay on input line 4. +LaTeX Font Info: Checking defaults for OT1/cmr/m/n on input line 4. +LaTeX Font Info: ... okay on input line 4. +LaTeX Font Info: Checking defaults for OMS/cmsy/m/n on input line 4. +LaTeX Font Info: ... okay on input line 4. +LaTeX Font Info: Checking defaults for OMX/cmex/m/n on input line 4. +LaTeX Font Info: ... okay on input line 4. +LaTeX Font Info: Checking defaults for U/cmr/m/n on input line 4. +LaTeX Font Info: ... okay on input line 4. + +LaTeX Warning: Citation `foo' on page 1 undefined on input line 6. + +[1 + +{/TexLive/texmf-var/fonts/map/pdftex/updmap/pdftex.map}] (./parent.aux) + +LaTeX Warning: There were undefined references. + +) +Here is how much of TeX's memory you used: +204 strings out of 492995 +2142 string characters out of 6138727 +54074 words of memory out of 5000000 +3842 multiletter control sequences out of 15000+600000 +3948 words of font info for 15 fonts, out of 8000000 for 9000 +1141 hyphenation exceptions out of 8191 +23i,4n,21p,116b,107s stack positions out of 5000i,500n,10000p,200000b,80000s +</TexLive/texmf-dist/fonts/type1/public/amsfonts/cm/cmbx10.pfb></TexLive/ +texmf-dist/fonts/type1/public/amsfonts/cm/cmr10.pfb> +Output written on parent.pdf (1 page, 17339 bytes). +PDF statistics: +16 PDF objects out of 1000 (max. 8388607) +10 compressed objects within 1 object stream +0 named destinations out of 1000 (max. 500000) +1 words of extra memory for PDF output out of 10000 (max. 10000000)
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/build_log/004.txt b/support/texlab/src/parser/test_data/build_log/004.txt new file mode 100644 index 0000000000..4ab379cd53 --- /dev/null +++ b/support/texlab/src/parser/test_data/build_log/004.txt @@ -0,0 +1,83 @@ +This is pdfTeX, Version 3.14159265-2.6-1.40.18 (TeX Live 2017/W32TeX) (preloaded format=pdflatex 2018.3.30) 26 DEC 2018 16:40 +entering extended mode +restricted \write18 enabled. +%&-line parsing enabled. +**./parent.tex +(./parent.tex +LaTeX2e <2017-04-15> +Babel <3.10> and hyphenation patterns for 84 language(s) loaded. +(/TexLive/texmf-dist/tex/latex/base/article.cls +Document Class: article 2014/09/29 v1.4h Standard LaTeX document class +(/TexLive/texmf-dist/tex/latex/base/size10.clo +File: size10.clo 2014/09/29 v1.4h Standard LaTeX file (size option) +) +\c@part=\count79 +\c@section=\count80 +\c@subsection=\count81 +\c@subsubsection=\count82 +\c@paragraph=\count83 +\c@subparagraph=\count84 +\c@figure=\count85 +\c@table=\count86 +\abovecaptionskip=\skip41 +\belowcaptionskip=\skip42 +\bibindent=\dimen102 +) +(/TexLive/texmf-dist/tex/generic/babel/babel.sty +Package: babel 2017/05/19 3.10 The Babel package + +! Package babel Error: Unknown option `foo'. Either you misspelled it +(babel) or the language definition file foo.ldf was not found. + +See the babel package documentation for explanation. +Type H <return> for immediate help. +... + +l.393 \ProcessOptions* + +Valid options are: shorthands=, KeepShorthandsActive, +activeacute, activegrave, noconfigs, safe=, main=, math= +headfoot=, strings=, config=, hyphenmap=, or a language name. + +! Package babel Error: You haven't specified a language option. + +See the babel package documentation for explanation. +Type H <return> for immediate help. +... + +l.426 ...ry to proceed from here, type x to quit.} + +You need to specify a language, either as a global option +or as an optional argument to the \usepackage command; +You shouldn't try to proceed from here, type x to quit. + +) (./parent.aux) +\openout1 = `parent.aux'. + +LaTeX Font Info: Checking defaults for OML/cmm/m/it on input line 5. +LaTeX Font Info: ... okay on input line 5. +LaTeX Font Info: Checking defaults for T1/cmr/m/n on input line 5. +LaTeX Font Info: ... okay on input line 5. +LaTeX Font Info: Checking defaults for OT1/cmr/m/n on input line 5. +LaTeX Font Info: ... okay on input line 5. +LaTeX Font Info: Checking defaults for OMS/cmsy/m/n on input line 5. +LaTeX Font Info: ... okay on input line 5. +LaTeX Font Info: Checking defaults for OMX/cmex/m/n on input line 5. +LaTeX Font Info: ... okay on input line 5. +LaTeX Font Info: Checking defaults for U/cmr/m/n on input line 5. +LaTeX Font Info: ... okay on input line 5. +(./parent.aux) ) +Here is how much of TeX's memory you used: +304 strings out of 492995 +3421 string characters out of 6138727 +56035 words of memory out of 5000000 +3938 multiletter control sequences out of 15000+600000 +3640 words of font info for 14 fonts, out of 8000000 for 9000 +1141 hyphenation exceptions out of 8191 +23i,1n,17p,116b,36s stack positions out of 5000i,500n,10000p,200000b,80000s + +No pages of output. +PDF statistics: +0 PDF objects out of 1000 (max. 8388607) +0 named destinations out of 1000 (max. 500000) +1 words of extra memory for PDF output out of 10000 (max. 10000000)
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/build_log/005.txt b/support/texlab/src/parser/test_data/build_log/005.txt new file mode 100644 index 0000000000..07c95bfc6b --- /dev/null +++ b/support/texlab/src/parser/test_data/build_log/005.txt @@ -0,0 +1,385 @@ +This is pdfTeX, Version 3.14159265-2.6-1.40.18 (TeX Live 2017/W32TeX) (preloaded format=pdflatex 2018.3.30) 26 DEC 2018 16:45 +entering extended mode +restricted \write18 enabled. +%&-line parsing enabled. +**./parent.tex +(./parent.tex +LaTeX2e <2017-04-15> +Babel <3.10> and hyphenation patterns for 84 language(s) loaded. +(/TexLive/texmf-dist/tex/latex/base/article.cls +Document Class: article 2014/09/29 v1.4h Standard LaTeX document class +(/TexLive/texmf-dist/tex/latex/base/size10.clo +File: size10.clo 2014/09/29 v1.4h Standard LaTeX file (size option) +) +\c@part=\count79 +\c@section=\count80 +\c@subsection=\count81 +\c@subsubsection=\count82 +\c@paragraph=\count83 +\c@subparagraph=\count84 +\c@figure=\count85 +\c@table=\count86 +\abovecaptionskip=\skip41 +\belowcaptionskip=\skip42 +\bibindent=\dimen102 +) +(/TexLive/texmf-dist/tex/generic/babel/babel.sty +Package: babel 2017/05/19 3.10 The Babel package + +(/TexLive/texmf-dist/tex/generic/babel-spanish/spanish.ldf +Language: spanish.ldf 2016/03/03 v5.0p Spanish support from the babel system + +(/TexLive/texmf-dist/tex/generic/babel/babel.def +File: babel.def 2017/05/19 3.10 Babel common definitions +\babel@savecnt=\count87 +\U@D=\dimen103 +) +\es@quottoks=\toks14 +\es@quotdepth=\count88 +Package babel Info: Making " an active character on input line 561. +Package babel Info: Making . an active character on input line 662. +Package babel Info: Making < an active character on input line 707. +Package babel Info: Making > an active character on input line 707. +)) +(/TexLive/texmf-dist/tex/latex/biblatex/biblatex.sty +Package: biblatex 2016/12/05 v3.7 programmable bibliographies (PK/JW/AB) + +(/TexLive/texmf-dist/tex/generic/oberdiek/pdftexcmds.sty +Package: pdftexcmds 2017/03/19 v0.25 Utility functions of pdfTeX for LuaTeX (HO +) + +(/TexLive/texmf-dist/tex/generic/oberdiek/infwarerr.sty +Package: infwarerr 2016/05/16 v1.4 Providing info/warning/error messages (HO) +) +(/TexLive/texmf-dist/tex/generic/oberdiek/ifluatex.sty +Package: ifluatex 2016/05/16 v1.4 Provides the ifluatex switch (HO) +Package ifluatex Info: LuaTeX not detected. +) +(/TexLive/texmf-dist/tex/generic/oberdiek/ltxcmds.sty +Package: ltxcmds 2016/05/16 v1.23 LaTeX kernel commands for general use (HO) +) +(/TexLive/texmf-dist/tex/generic/oberdiek/ifpdf.sty +Package: ifpdf 2017/03/15 v3.2 Provides the ifpdf switch +) +Package pdftexcmds Info: LuaTeX not detected. +Package pdftexcmds Info: \pdf@primitive is available. +Package pdftexcmds Info: \pdf@ifprimitive is available. +Package pdftexcmds Info: \pdfdraftmode found. +) +(/TexLive/texmf-dist/tex/latex/etoolbox/etoolbox.sty +Package: etoolbox 2017/01/02 v2.4 e-TeX tools for LaTeX (JAW) +\etb@tempcnta=\count89 +) +(/TexLive/texmf-dist/tex/latex/graphics/keyval.sty +Package: keyval 2014/10/28 v1.15 key=value parser (DPC) +\KV@toks@=\toks15 +) +(/TexLive/texmf-dist/tex/latex/oberdiek/kvoptions.sty +Package: kvoptions 2016/05/16 v3.12 Key value format for package options (HO) + +(/TexLive/texmf-dist/tex/generic/oberdiek/kvsetkeys.sty +Package: kvsetkeys 2016/05/16 v1.17 Key value parser (HO) + +(/TexLive/texmf-dist/tex/generic/oberdiek/etexcmds.sty +Package: etexcmds 2016/05/16 v1.6 Avoid name clashes with e-TeX commands (HO) +Package etexcmds Info: Could not find \expanded. +(etexcmds) That can mean that you are not using pdfTeX 1.50 or +(etexcmds) that some package has redefined \expanded. +(etexcmds) In the latter case, load this package earlier. +))) +(/TexLive/texmf-dist/tex/latex/logreq/logreq.sty +Package: logreq 2010/08/04 v1.0 xml request logger +\lrq@indent=\count90 + +(/TexLive/texmf-dist/tex/latex/logreq/logreq.def +File: logreq.def 2010/08/04 v1.0 logreq spec v1.0 +)) +(/TexLive/texmf-dist/tex/latex/base/ifthen.sty +Package: ifthen 2014/09/29 v1.1c Standard LaTeX ifthen package (DPC) +) +(/TexLive/texmf-dist/tex/latex/url/url.sty +\Urlmuskip=\muskip10 +Package: url 2013/09/16 ver 3.4 Verb mode for urls, etc. +) +(/TexLive/texmf-dist/tex/generic/xstring/xstring.sty +(/TexLive/texmf-dist/tex/generic/xstring/xstring.tex +\@xs@message=\write3 +\integerpart=\count91 +\decimalpart=\count92 +) +Package: xstring 2013/10/13 v1.7c String manipulations (C Tellechea) +) +\c@tabx@nest=\count93 +\c@listtotal=\count94 +\c@listcount=\count95 +\c@liststart=\count96 +\c@liststop=\count97 +\c@citecount=\count98 +\c@citetotal=\count99 +\c@multicitecount=\count100 +\c@multicitetotal=\count101 +\c@instcount=\count102 +\c@maxnames=\count103 +\c@minnames=\count104 +\c@maxitems=\count105 +\c@minitems=\count106 +\c@citecounter=\count107 +\c@savedcitecounter=\count108 +\c@uniquelist=\count109 +\c@uniquename=\count110 +\c@refsection=\count111 +\c@refsegment=\count112 +\c@maxextratitle=\count113 +\c@maxextratitleyear=\count114 +\c@maxextrayear=\count115 +\c@maxextraalpha=\count116 +\c@abbrvpenalty=\count117 +\c@highnamepenalty=\count118 +\c@lownamepenalty=\count119 +\c@maxparens=\count120 +\c@parenlevel=\count121 +\blx@tempcnta=\count122 +\blx@tempcntb=\count123 +\blx@tempcntc=\count124 +\blx@maxsection=\count125 +\blx@maxsegment@0=\count126 +\blx@notetype=\count127 +\blx@parenlevel@text=\count128 +\blx@parenlevel@foot=\count129 +\blx@sectionciteorder@0=\count130 +\labelnumberwidth=\skip43 +\labelalphawidth=\skip44 +\biblabelsep=\skip45 +\bibitemsep=\skip46 +\bibnamesep=\skip47 +\bibinitsep=\skip48 +\bibparsep=\skip49 +\bibhang=\skip50 +\blx@bcfin=\read1 +\blx@bcfout=\write4 +\c@mincomprange=\count131 +\c@maxcomprange=\count132 +\c@mincompwidth=\count133 +Package biblatex Info: Trying to load biblatex default data model... +Package biblatex Info: ... file 'blx-dm.def' found. + +(/TexLive/texmf-dist/tex/latex/biblatex/blx-dm.def) +Package biblatex Info: Trying to load biblatex style data model... +Package biblatex Info: ... file 'ieee.dbx' not found. +Package biblatex Info: Trying to load biblatex custom data model... +Package biblatex Info: ... file 'biblatex-dm.cfg' not found. +\c@afterword=\count134 +\c@savedafterword=\count135 +\c@annotator=\count136 +\c@savedannotator=\count137 +\c@author=\count138 +\c@savedauthor=\count139 +\c@bookauthor=\count140 +\c@savedbookauthor=\count141 +\c@commentator=\count142 +\c@savedcommentator=\count143 +\c@editor=\count144 +\c@savededitor=\count145 +\c@editora=\count146 +\c@savededitora=\count147 +\c@editorb=\count148 +\c@savededitorb=\count149 +\c@editorc=\count150 +\c@savededitorc=\count151 +\c@foreword=\count152 +\c@savedforeword=\count153 +\c@holder=\count154 +\c@savedholder=\count155 +\c@introduction=\count156 +\c@savedintroduction=\count157 +\c@namea=\count158 +\c@savednamea=\count159 +\c@nameb=\count160 +\c@savednameb=\count161 +\c@namec=\count162 +\c@savednamec=\count163 +\c@translator=\count164 +\c@savedtranslator=\count165 +\c@shortauthor=\count166 +\c@savedshortauthor=\count167 +\c@shorteditor=\count168 +\c@savedshorteditor=\count169 +\c@labelname=\count170 +\c@savedlabelname=\count171 +\c@institution=\count172 +\c@savedinstitution=\count173 +\c@lista=\count174 +\c@savedlista=\count175 +\c@listb=\count176 +\c@savedlistb=\count177 +\c@listc=\count178 +\c@savedlistc=\count179 +\c@listd=\count180 +\c@savedlistd=\count181 +\c@liste=\count182 +\c@savedliste=\count183 +\c@listf=\count184 +\c@savedlistf=\count185 +\c@location=\count186 +\c@savedlocation=\count187 +\c@organization=\count188 +\c@savedorganization=\count189 +\c@origlocation=\count190 +\c@savedoriglocation=\count191 +\c@origpublisher=\count192 +\c@savedorigpublisher=\count193 +\c@publisher=\count194 +\c@savedpublisher=\count195 +\c@language=\count196 +\c@savedlanguage=\count197 +\c@pageref=\count198 +\c@savedpageref=\count199 +\shorthandwidth=\skip51 +\shortjournalwidth=\skip52 +\shortserieswidth=\skip53 +\shorttitlewidth=\skip54 +\shortauthorwidth=\skip55 +\shorteditorwidth=\skip56 +Package biblatex Info: Trying to load compatibility code... +Package biblatex Info: ... file 'blx-compat.def' found. + +(/TexLive/texmf-dist/tex/latex/biblatex/blx-compat.def +File: blx-compat.def 2016/12/05 v3.7 biblatex compatibility (PK/JW/AB) +) +Package biblatex Info: Trying to load generic definitions... +Package biblatex Info: ... file 'biblatex.def' found. + +(/TexLive/texmf-dist/tex/latex/biblatex/biblatex.def +File: biblatex.def 2016/12/05 v3.7 biblatex compatibility (PK/JW/AB) +\c@textcitecount=\count266 +\c@textcitetotal=\count267 +\c@textcitemaxnames=\count268 +\c@biburlnumpenalty=\count269 +\c@biburlucpenalty=\count270 +\c@biburllcpenalty=\count271 +\c@smartand=\count272 +) +Package biblatex Info: Trying to load bibliography style 'ieee'... +Package biblatex Info: ... file 'ieee.bbx' found. + +(/TexLive/texmf-dist/tex/latex/biblatex-ieee/ieee.bbx +File: ieee.bbx 2017/03/27 v1.2d biblatex bibliography style +Package biblatex Info: Trying to load bibliography style 'numeric-comp'... +Package biblatex Info: ... file 'numeric-comp.bbx' found. + +(/TexLive/texmf-dist/tex/latex/biblatex/bbx/numeric-comp.bbx +File: numeric-comp.bbx 2016/12/05 v3.7 biblatex bibliography style (PK/JW/AB) +Package biblatex Info: Trying to load bibliography style 'numeric'... +Package biblatex Info: ... file 'numeric.bbx' found. + +(/TexLive/texmf-dist/tex/latex/biblatex/bbx/numeric.bbx +File: numeric.bbx 2016/12/05 v3.7 biblatex bibliography style (PK/JW/AB) +Package biblatex Info: Trying to load bibliography style 'standard'... +Package biblatex Info: ... file 'standard.bbx' found. + +(/TexLive/texmf-dist/tex/latex/biblatex/bbx/standard.bbx +File: standard.bbx 2016/12/05 v3.7 biblatex bibliography style (PK/JW/AB) +\c@bbx:relatedcount=\count273 +\c@bbx:relatedtotal=\count274 +)))) +Package biblatex Info: Trying to load citation style 'ieee'... +Package biblatex Info: ... file 'ieee.cbx' found. + +(/TexLive/texmf-dist/tex/latex/biblatex-ieee/ieee.cbx +File: ieee.cbx 2017/03/27 v1.2d biblatex citation style +Package biblatex Info: Trying to load citation style 'numeric-comp'... +Package biblatex Info: ... file 'numeric-comp.cbx' found. + +(/TexLive/texmf-dist/tex/latex/biblatex/cbx/numeric-comp.cbx +File: numeric-comp.cbx 2016/12/05 v3.7 biblatex citation style (PK/JW/AB) +\c@cbx@tempcnta=\count275 +\c@cbx@tempcntb=\count276 +Package biblatex Info: Redefining '\cite'. +Package biblatex Info: Redefining '\parencite'. +Package biblatex Info: Redefining '\footcite'. +Package biblatex Info: Redefining '\footcitetext'. +Package biblatex Info: Redefining '\smartcite'. +Package biblatex Info: Redefining '\supercite'. +Package biblatex Info: Redefining '\textcite'. +Package biblatex Info: Redefining '\textcites'. +Package biblatex Info: Redefining '\cites'. +Package biblatex Info: Redefining '\parencites'. +Package biblatex Info: Redefining '\smartcites'. +) +Package biblatex Info: Redefining '\cite'. +Package biblatex Info: Redefining '\cites'. +) +Package biblatex Info: Trying to load configuration file... +Package biblatex Info: ... file 'biblatex.cfg' found. + +(/TexLive/texmf-dist/tex/latex/biblatex/biblatex.cfg +File: biblatex.cfg +)) +Package biblatex Info: Trying to load language 'spanish'... +Package biblatex Info: ... file 'spanish.lbx' found. + +(/TexLive/texmf-dist/tex/latex/biblatex/lbx/spanish.lbx +File: spanish.lbx 2016/12/05 v3.7 biblatex localization (PK/JW/AB) +) + +Package biblatex Warning: 'babel/polyglossia' detected but 'csquotes' missing. +(biblatex) Loading 'csquotes' recommended. + +\@quotelevel=\count277 +\@quotereset=\count278 +(./parent.aux) +\openout1 = `parent.aux'. + +LaTeX Font Info: Checking defaults for OML/cmm/m/it on input line 6. +LaTeX Font Info: ... okay on input line 6. +LaTeX Font Info: Checking defaults for T1/cmr/m/n on input line 6. +LaTeX Font Info: ... okay on input line 6. +LaTeX Font Info: Checking defaults for OT1/cmr/m/n on input line 6. +LaTeX Font Info: ... okay on input line 6. +LaTeX Font Info: Checking defaults for OMS/cmsy/m/n on input line 6. +LaTeX Font Info: ... okay on input line 6. +LaTeX Font Info: Checking defaults for OMX/cmex/m/n on input line 6. +LaTeX Font Info: ... okay on input line 6. +LaTeX Font Info: Checking defaults for U/cmr/m/n on input line 6. +LaTeX Font Info: ... okay on input line 6. +LaTeX Info: Redefining \sptext on input line 6. +LaTeX Info: Redefining \. on input line 6. +LaTeX Info: Redefining \% on input line 6. +Package biblatex Info: No input encoding detected. +(biblatex) Assuming 'ascii'. +Package biblatex Info: Automatic encoding selection. +(biblatex) Assuming data encoding 'ascii'. +\openout4 = `parent.bcf'. + +Package biblatex Info: Trying to load bibliographic data... +Package biblatex Info: ... file 'parent.bbl' not found. + +No file parent.bbl. +Package biblatex Info: Reference section=0 on input line 6. +Package biblatex Info: Reference segment=0 on input line 6. +(./parent.aux) + +LaTeX Warning: There were undefined references. + +Package biblatex Warning: Please (re)run Biber on the file: +(biblatex) parent +(biblatex) and rerun LaTeX afterwards. + +Package logreq Info: Writing requests to 'parent.run.xml'. +\openout1 = `parent.run.xml'. + +) +Here is how much of TeX's memory you used: +7717 strings out of 492995 +133301 string characters out of 6138727 +557258 words of memory out of 5000000 +11248 multiletter control sequences out of 15000+600000 +3640 words of font info for 14 fonts, out of 8000000 for 9000 +1141 hyphenation exceptions out of 8191 +35i,1n,30p,856b,700s stack positions out of 5000i,500n,10000p,200000b,80000s + +No pages of output. +PDF statistics: +0 PDF objects out of 1000 (max. 8388607) +0 named destinations out of 1000 (max. 500000) +1 words of extra memory for PDF output out of 10000 (max. 10000000)
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/build_log/006.txt b/support/texlab/src/parser/test_data/build_log/006.txt new file mode 100644 index 0000000000..3edb18b8c7 --- /dev/null +++ b/support/texlab/src/parser/test_data/build_log/006.txt @@ -0,0 +1,122 @@ +This is pdfTeX, Version 3.14159265-2.6-1.40.18 (TeX Live 2017/W32TeX) (preloaded format=pdflatex 2018.3.30) 26 DEC 2018 16:33 +entering extended mode +restricted \write18 enabled. +%&-line parsing enabled. +**./parent.tex +(./parent.tex +LaTeX2e <2017-04-15> +Babel <3.10> and hyphenation patterns for 84 language(s) loaded. +(/TexLive/texmf-dist/tex/latex/base/article.cls +Document Class: article 2014/09/29 v1.4h Standard LaTeX document class +(/TexLive/texmf-dist/tex/latex/base/size10.clo +File: size10.clo 2014/09/29 v1.4h Standard LaTeX file (size option) +) +\c@part=\count79 +\c@section=\count80 +\c@subsection=\count81 +\c@subsubsection=\count82 +\c@paragraph=\count83 +\c@subparagraph=\count84 +\c@figure=\count85 +\c@table=\count86 +\abovecaptionskip=\skip41 +\belowcaptionskip=\skip42 +\bibindent=\dimen102 +) (./parent.aux +(./child.tex.aux)) +\openout1 = `parent.aux'. + +LaTeX Font Info: Checking defaults for OML/cmm/m/it on input line 3. +LaTeX Font Info: ... okay on input line 3. +LaTeX Font Info: Checking defaults for T1/cmr/m/n on input line 3. +LaTeX Font Info: ... okay on input line 3. +LaTeX Font Info: Checking defaults for OT1/cmr/m/n on input line 3. +LaTeX Font Info: ... okay on input line 3. +LaTeX Font Info: Checking defaults for OMS/cmsy/m/n on input line 3. +LaTeX Font Info: ... okay on input line 3. +LaTeX Font Info: Checking defaults for OMX/cmex/m/n on input line 3. +LaTeX Font Info: ... okay on input line 3. +LaTeX Font Info: Checking defaults for U/cmr/m/n on input line 3. +LaTeX Font Info: ... okay on input line 3. +\openout2 = `child.aux'. + +(./child.tex) +! Undefined control sequence. +l.7 \foo + +The control sequence at the end of the top line +of your error message was never \def'ed. If you have +misspelled it (e.g., `\hobx'), type `I' and the correct +spelling (e.g., `I\hbox'). Otherwise just continue, +and I'll forget about whatever was undefined. + +! Missing $ inserted. +<inserted text> + $ +l.8 \bar + +I've inserted a begin-math/end-math symbol since I think +you left one out. Proceed, with fingers crossed. + +LaTeX Font Info: External font `cmex10' loaded for size +(Font) <7> on input line 8. +LaTeX Font Info: External font `cmex10' loaded for size +(Font) <5> on input line 8. +! Undefined control sequence. +l.9 \baz + +The control sequence at the end of the top line +of your error message was never \def'ed. If you have +misspelled it (e.g., `\hobx'), type `I' and the correct +spelling (e.g., `I\hbox'). Otherwise just continue, +and I'll forget about whatever was undefined. + +! Missing { inserted. +<to be read again> + \par +l.10 + +A left brace was mandatory here, so I've put one in. +You might want to delete and/or insert some corrections +so that I will find a matching right brace soon. +(If you're confused by all this, try typing `I}' now.) + +! Missing $ inserted. +<inserted text> + $ +l.10 + +I've inserted a begin-math/end-math symbol since I think +you left one out. Proceed, with fingers crossed. + +! Missing } inserted. +<inserted text> + } +l.10 + +I've inserted something that you may have forgotten. +(See the <inserted text> above.) +With luck, this will get me unwedged. But if you +really didn't forget anything, try typing `2' now; then +my insertion and my current dilemma will both disappear. + +[1 + +{/TexLive/texmf-var/fonts/map/pdftex/updmap/pdftex.map}] (./parent.aux +(./child.aux)) ) +Here is how much of TeX's memory you used: +212 strings out of 492995 +2238 string characters out of 6138727 +54074 words of memory out of 5000000 +3843 multiletter control sequences out of 15000+600000 +3640 words of font info for 14 fonts, out of 8000000 for 9000 +1141 hyphenation exceptions out of 8191 +23i,4n,17p,116b,107s stack positions out of 5000i,500n,10000p,200000b,80000s +</TexLive/texmf-dist/fonts/type1/public/amsfonts/cm/cmr10.pfb +> +Output written on parent.pdf (1 page, 8329 bytes). +PDF statistics: +12 PDF objects out of 1000 (max. 8388607) +7 compressed objects within 1 object stream +0 named destinations out of 1000 (max. 500000) +1 words of extra memory for PDF output out of 10000 (max. 10000000)
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/build_log/007.txt b/support/texlab/src/parser/test_data/build_log/007.txt new file mode 100644 index 0000000000..4c86405c0d --- /dev/null +++ b/support/texlab/src/parser/test_data/build_log/007.txt @@ -0,0 +1,176 @@ +This is pdfTeX, Version 3.141592653-2.6-1.40.22 (TeX Live 2021/W32TeX) (preloaded format=pdflatex 2021.6.19) 5 NOV 2021 19:10 +entering extended mode +restricted \write18 enabled. +%&-line parsing enabled. +**/some/folder/a.tex +(/some/folder/a.tex +LaTeX2e <2021-06-01> patch level 1 +L3 programming layer <2021-06-18> +(/texlive/2021/texmf-dist/tex/latex/koma-script/scrartcl.cls +Document Class: scrartcl 2021/03/17 v3.33 KOMA-Script document class (article) +(/texlive/2021/texmf-dist/tex/latex/koma-script/scrkbase.sty +Package: scrkbase 2021/03/17 v3.33 KOMA-Script package (KOMA-Script-dependent b +asics and keyval usage) + +(/texlive/2021/texmf-dist/tex/latex/koma-script/scrbase.sty +Package: scrbase 2021/03/17 v3.33 KOMA-Script package (KOMA-Script-independent +basics and keyval usage) + +(/texlive/2021/texmf-dist/tex/latex/koma-script/scrlfile.sty +Package: scrlfile 2021/03/17 v3.33 KOMA-Script package (file load hooks) + +(/texlive/2021/texmf-dist/tex/latex/koma-script/scrlfile-hook.sty +Package: scrlfile-hook 2021/03/17 v3.33 KOMA-Script package (using LaTeX hooks) + + +(/texlive/2021/texmf-dist/tex/latex/koma-script/scrlogo.sty +Package: scrlogo 2021/03/17 v3.33 KOMA-Script package (logo) +))) +(/texlive/2021/texmf-dist/tex/latex/graphics/keyval.sty +Package: keyval 2014/10/28 v1.15 key=value parser (DPC) +\KV@toks@=\toks16 +) +Applying: [2021/05/01] Usage of raw option list on input line 252. +Already applied: [0000/00/00] compatibility for LaTeX before 2021/05/01 on inpu +t line 337. +)) +==> First Aid for scrkbase.sty no longer applied! +(/texlive/2021/texmf-dist/tex/latex/koma-script/tocbasic.sty +Package: tocbasic 2021/03/17 v3.33 KOMA-Script package (handling toc-files) +\scr@dte@tocline@numberwidth=\skip47 +\scr@dte@tocline@numbox=\box50 +) +Package tocbasic Info: babel extension for `toc' omitted +(tocbasic) because of missing \bbl@set@language on input line 135. +Class scrartcl Info: File `scrsize11pt.clo' used instead of +(scrartcl) file `scrsize11.clo' to setup font sizes on input line 223 +9. + +(/texlive/2021/texmf-dist/tex/latex/koma-script/scrsize11pt.clo +File: scrsize11pt.clo 2021/03/17 v3.33 KOMA-Script font size class option (11pt +) +) +(/texlive/2021/texmf-dist/tex/latex/koma-script/typearea.sty +Package: typearea 2021/03/17 v3.33 KOMA-Script package (type area) +\ta@bcor=\skip48 +\ta@div=\count182 +\ta@hblk=\skip49 +\ta@vblk=\skip50 +\ta@temp=\skip51 +\footheight=\skip52 +Package typearea Info: These are the values describing the layout: +(typearea) DIV = 10 +(typearea) BCOR = 0.0pt +(typearea) \paperwidth = 597.50793pt +(typearea) \textwidth = 418.25555pt +(typearea) DIV departure = -6% +(typearea) \evensidemargin = 17.3562pt +(typearea) \oddsidemargin = 17.3562pt +(typearea) \paperheight = 845.04694pt +(typearea) \textheight = 595.80026pt +(typearea) \topmargin = -25.16531pt +(typearea) \headheight = 17.0pt +(typearea) \headsep = 20.40001pt +(typearea) \topskip = 11.0pt +(typearea) \footskip = 47.6pt +(typearea) \baselineskip = 13.6pt +(typearea) on input line 1741. +) +\c@part=\count183 +\c@section=\count184 +\c@subsection=\count185 +\c@subsubsection=\count186 +\c@paragraph=\count187 +\c@subparagraph=\count188 +\scr@dte@section@maxnumwidth=\skip53 +Class scrartcl Info: using compatibility default `runin=bysign' +(scrartcl) for `\section on input line 4846. +Class scrartcl Info: using compatibility default `afterindent=bysign' +(scrartcl) for `\section on input line 4846. +\scr@dte@part@maxnumwidth=\skip54 +Class scrartcl Info: using compatibility default `afterindent=false' +(scrartcl) for `\part on input line 4854. +\scr@dte@subsection@maxnumwidth=\skip55 +Class scrartcl Info: using compatibility default `runin=bysign' +(scrartcl) for `\subsection on input line 4864. +Class scrartcl Info: using compatibility default `afterindent=bysign' +(scrartcl) for `\subsection on input line 4864. +\scr@dte@subsubsection@maxnumwidth=\skip56 +Class scrartcl Info: using compatibility default `runin=bysign' +(scrartcl) for `\subsubsection on input line 4874. +Class scrartcl Info: using compatibility default `afterindent=bysign' +(scrartcl) for `\subsubsection on input line 4874. +\scr@dte@paragraph@maxnumwidth=\skip57 +Class scrartcl Info: using compatibility default `runin=bysign' +(scrartcl) for `\paragraph on input line 4885. +Class scrartcl Info: using compatibility default `afterindent=bysign' +(scrartcl) for `\paragraph on input line 4885. +\scr@dte@subparagraph@maxnumwidth=\skip58 +Class scrartcl Info: using compatibility default `runin=bysign' +(scrartcl) for `\subparagraph on input line 4895. +Class scrartcl Info: using compatibility default `afterindent=bysign' +(scrartcl) for `\subparagraph on input line 4895. +\abovecaptionskip=\skip59 +\belowcaptionskip=\skip60 +\c@pti@nb@sid@b@x=\box51 +Package tocbasic Info: babel extension for `lof' omitted +(tocbasic) because of missing \bbl@set@language on input line 6127. + +\scr@dte@figure@maxnumwidth=\skip61 +\c@figure=\count189 +Package tocbasic Info: babel extension for `lot' omitted +(tocbasic) because of missing \bbl@set@language on input line 6139. + +\scr@dte@table@maxnumwidth=\skip62 +\c@table=\count190 +Class scrartcl Info: Redefining `\numberline' on input line 6303. +\bibindent=\dimen138 +) +(/texlive/2021/texmf-dist/tex/latex/l3backend/l3backend-pdftex.def +File: l3backend-pdftex.def 2021-05-07 L3 backend support: PDF output (pdfTeX) +\l__color_backend_stack_int=\count191 +\l__pdf_internal_box=\box52 +) (./a.aux) +\openout1 = `a.aux'. + +LaTeX Font Info: Checking defaults for OML/cmm/m/it on input line 3. +LaTeX Font Info: ... okay on input line 3. +LaTeX Font Info: Checking defaults for OMS/cmsy/m/n on input line 3. +LaTeX Font Info: ... okay on input line 3. +LaTeX Font Info: Checking defaults for OT1/cmr/m/n on input line 3. +LaTeX Font Info: ... okay on input line 3. +LaTeX Font Info: Checking defaults for T1/cmr/m/n on input line 3. +LaTeX Font Info: ... okay on input line 3. +LaTeX Font Info: Checking defaults for TS1/cmr/m/n on input line 3. +LaTeX Font Info: ... okay on input line 3. +LaTeX Font Info: Checking defaults for OMX/cmex/m/n on input line 3. +LaTeX Font Info: ... okay on input line 3. +LaTeX Font Info: Checking defaults for U/cmr/m/n on input line 3. +LaTeX Font Info: ... okay on input line 3. +Package scrbase Info: activating english \contentsname on input line 3. +Package scrbase Info: activating english \listfigurename on input line 3. +Package scrbase Info: activating english \listtablename on input line 3. +! Undefined control sequence. +l.4 \lsdkfjlskdfj + +The control sequence at the end of the top line +of your error message was never \def'ed. If you have +misspelled it (e.g., `\hobx'), type `I' and the correct +spelling (e.g., `I\hbox'). Otherwise just continue, +and I'll forget about whatever was undefined. + +(./a.aux) ) +Here is how much of TeX's memory you used: +3199 strings out of 478510 +74549 string characters out of 5853586 +510929 words of memory out of 5000000 +21227 multiletter control sequences out of 15000+600000 +403730 words of font info for 28 fonts, out of 8000000 for 9000 +1141 hyphenation exceptions out of 8191 +108i,1n,108p,10625b,270s stack positions out of 5000i,500n,10000p,200000b,80000s + +No pages of output. +PDF statistics: +0 PDF objects out of 1000 (max. 8388607) +0 named destinations out of 1000 (max. 500000) +1 words of extra memory for PDF output out of 10000 (max. 10000000)
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/block_comments.txt b/support/texlab/src/parser/test_data/latex/block_comments.txt new file mode 100644 index 0000000000..d4e63ab1c8 --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/block_comments.txt @@ -0,0 +1,9 @@ +Foo +\iffalse +Test1 +\fi +Bar +\iffalse +\fii +\fi +Baz
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/caption/caption_default.txt b/support/texlab/src/parser/test_data/latex/caption/caption_default.txt new file mode 100644 index 0000000000..9084f143bf --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/caption/caption_default.txt @@ -0,0 +1 @@ +\caption[qux]{Foo \Bar Baz}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/caption/caption_default_error.txt b/support/texlab/src/parser/test_data/latex/caption/caption_default_error.txt new file mode 100644 index 0000000000..62e5962816 --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/caption/caption_default_error.txt @@ -0,0 +1 @@ +\caption[qux]{Foo \Bar Baz
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/caption/caption_figure.txt b/support/texlab/src/parser/test_data/latex/caption/caption_figure.txt new file mode 100644 index 0000000000..8a1d3067d8 --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/caption/caption_figure.txt @@ -0,0 +1 @@ +\begin{figure}\caption{Foo}\end{figure}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/caption/caption_minimal.txt b/support/texlab/src/parser/test_data/latex/caption/caption_minimal.txt new file mode 100644 index 0000000000..07af0af8ca --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/caption/caption_minimal.txt @@ -0,0 +1 @@ +\caption{Foo \Bar Baz}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/caption/caption_minimal_error.txt b/support/texlab/src/parser/test_data/latex/caption/caption_minimal_error.txt new file mode 100644 index 0000000000..747db731c1 --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/caption/caption_minimal_error.txt @@ -0,0 +1 @@ +\caption{Foo \Bar Baz
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/citation/citation_empty.txt b/support/texlab/src/parser/test_data/latex/citation/citation_empty.txt new file mode 100644 index 0000000000..06704b89a4 --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/citation/citation_empty.txt @@ -0,0 +1 @@ +\cite{}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/citation/citation_missing_brace.txt b/support/texlab/src/parser/test_data/latex/citation/citation_missing_brace.txt new file mode 100644 index 0000000000..1f8e4c9310 --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/citation/citation_missing_brace.txt @@ -0,0 +1 @@ +\cite{foo
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/citation/citation_multiple_keys.txt b/support/texlab/src/parser/test_data/latex/citation/citation_multiple_keys.txt new file mode 100644 index 0000000000..be5da02c62 --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/citation/citation_multiple_keys.txt @@ -0,0 +1 @@ +\cite{foo, bar}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/citation/citation_prenote.txt b/support/texlab/src/parser/test_data/latex/citation/citation_prenote.txt new file mode 100644 index 0000000000..5ae28c28ec --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/citation/citation_prenote.txt @@ -0,0 +1 @@ +\cite[foo]{bar}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/citation/citation_prenote_postnote.txt b/support/texlab/src/parser/test_data/latex/citation/citation_prenote_postnote.txt new file mode 100644 index 0000000000..23103b2476 --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/citation/citation_prenote_postnote.txt @@ -0,0 +1 @@ +\cite[foo][bar]{baz}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/citation/citation_redundant_comma.txt b/support/texlab/src/parser/test_data/latex/citation/citation_redundant_comma.txt new file mode 100644 index 0000000000..68e3c2d36e --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/citation/citation_redundant_comma.txt @@ -0,0 +1 @@ +\cite{,foo,}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/citation/citation_simple.txt b/support/texlab/src/parser/test_data/latex/citation/citation_simple.txt new file mode 100644 index 0000000000..cd5809ef25 --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/citation/citation_simple.txt @@ -0,0 +1 @@ +\cite{foo}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/citation/citation_star.txt b/support/texlab/src/parser/test_data/latex/citation/citation_star.txt new file mode 100644 index 0000000000..d1a2677021 --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/citation/citation_star.txt @@ -0,0 +1 @@ +\nocite{*}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/color/color_definition_simple.txt b/support/texlab/src/parser/test_data/latex/color/color_definition_simple.txt new file mode 100644 index 0000000000..e8b58c8162 --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/color/color_definition_simple.txt @@ -0,0 +1 @@ +\definecolor{foo}{rgb}{255,168,0}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/color/color_reference_simple.txt b/support/texlab/src/parser/test_data/latex/color/color_reference_simple.txt new file mode 100644 index 0000000000..4fea2b24ec --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/color/color_reference_simple.txt @@ -0,0 +1 @@ +\color{black}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/color/color_set_definition_error1.txt b/support/texlab/src/parser/test_data/latex/color/color_set_definition_error1.txt new file mode 100644 index 0000000000..f377ffcf2f --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/color/color_set_definition_error1.txt @@ -0,0 +1 @@ +\definecolorset[ty]{rgb,HTML}{foo}{bar}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/color/color_set_definition_error2.txt b/support/texlab/src/parser/test_data/latex/color/color_set_definition_error2.txt new file mode 100644 index 0000000000..0b5fa35868 --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/color/color_set_definition_error2.txt @@ -0,0 +1 @@ +\definecolorset{rgb,HTML}{foo}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/color/color_set_definition_error3.txt b/support/texlab/src/parser/test_data/latex/color/color_set_definition_error3.txt new file mode 100644 index 0000000000..fb695b4530 --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/color/color_set_definition_error3.txt @@ -0,0 +1 @@ +\definecolorset{rgb,HTML}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/color/color_set_definition_error4.txt b/support/texlab/src/parser/test_data/latex/color/color_set_definition_error4.txt new file mode 100644 index 0000000000..7c494133bf --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/color/color_set_definition_error4.txt @@ -0,0 +1 @@ +\definecolorset
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/color/color_set_definition_simple.txt b/support/texlab/src/parser/test_data/latex/color/color_set_definition_simple.txt new file mode 100644 index 0000000000..c812e61041 --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/color/color_set_definition_simple.txt @@ -0,0 +1 @@ +\definecolorset[ty]{rgb,HTML}{foo}{bar}{baz}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/command_definition/command_definition_no_argc.txt b/support/texlab/src/parser/test_data/latex/command_definition/command_definition_no_argc.txt new file mode 100644 index 0000000000..ef63ef62cb --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/command_definition/command_definition_no_argc.txt @@ -0,0 +1 @@ +\newcommand{\foo}{foo}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/command_definition/command_definition_no_impl.txt b/support/texlab/src/parser/test_data/latex/command_definition/command_definition_no_impl.txt new file mode 100644 index 0000000000..5ffc7e97c2 --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/command_definition/command_definition_no_impl.txt @@ -0,0 +1 @@ +\newcommand{\foo}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/command_definition/command_definition_no_impl_error.txt b/support/texlab/src/parser/test_data/latex/command_definition/command_definition_no_impl_error.txt new file mode 100644 index 0000000000..9323f5a313 --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/command_definition/command_definition_no_impl_error.txt @@ -0,0 +1 @@ +\newcommand{\foo
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/command_definition/command_definition_optional.txt b/support/texlab/src/parser/test_data/latex/command_definition/command_definition_optional.txt new file mode 100644 index 0000000000..c3fb7225f3 --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/command_definition/command_definition_optional.txt @@ -0,0 +1 @@ +\newcommand{\foo}[1][def]{#1}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/command_definition/command_definition_simple.txt b/support/texlab/src/parser/test_data/latex/command_definition/command_definition_simple.txt new file mode 100644 index 0000000000..ffce86f21c --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/command_definition/command_definition_simple.txt @@ -0,0 +1 @@ +\newcommand[1]{\id}{#1}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/command_definition/command_definition_with_begin.txt b/support/texlab/src/parser/test_data/latex/command_definition/command_definition_with_begin.txt new file mode 100644 index 0000000000..e7ce7984cb --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/command_definition/command_definition_with_begin.txt @@ -0,0 +1 @@ +\newcommand{\CVSubHeadingListStart}{\begin{itemize}[leftmargin=0.5cm, label={}]}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/command_definition/math_operator_no_impl.txt b/support/texlab/src/parser/test_data/latex/command_definition/math_operator_no_impl.txt new file mode 100644 index 0000000000..685be22ce6 --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/command_definition/math_operator_no_impl.txt @@ -0,0 +1 @@ +\DeclareMathOperator{\foo}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/command_definition/math_operator_simple.txt b/support/texlab/src/parser/test_data/latex/command_definition/math_operator_simple.txt new file mode 100644 index 0000000000..ffbf671f74 --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/command_definition/math_operator_simple.txt @@ -0,0 +1 @@ +\DeclareMathOperator{\foo}{foo}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/environment/environment_asymptote.txt b/support/texlab/src/parser/test_data/latex/environment/environment_asymptote.txt new file mode 100644 index 0000000000..76646075ea --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/environment/environment_asymptote.txt @@ -0,0 +1,3 @@ +\begin{asy} + printf("Hello World\n"); +\end{asy}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/environment/environment_definition.txt b/support/texlab/src/parser/test_data/latex/environment/environment_definition.txt new file mode 100644 index 0000000000..d3a5291dca --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/environment/environment_definition.txt @@ -0,0 +1 @@ +\newenvironment{bar}[1]{\begin{foo}}{\end{foo}}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/environment/environment_definition_optional_arg.txt b/support/texlab/src/parser/test_data/latex/environment/environment_definition_optional_arg.txt new file mode 100644 index 0000000000..bead3228a4 --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/environment/environment_definition_optional_arg.txt @@ -0,0 +1 @@ +\newenvironment{foo}[1][default]{begin}{end}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/environment/environment_nested.txt b/support/texlab/src/parser/test_data/latex/environment/environment_nested.txt new file mode 100644 index 0000000000..8d84019ac7 --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/environment/environment_nested.txt @@ -0,0 +1 @@ +\begin{foo} \begin{qux} \end{baz} \end{bar}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/environment/environment_nested_missing_braces.txt b/support/texlab/src/parser/test_data/latex/environment/environment_nested_missing_braces.txt new file mode 100644 index 0000000000..35ce901a83 --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/environment/environment_nested_missing_braces.txt @@ -0,0 +1 @@ +\begin{foo \begin{qux Hello World \end{baz} \end{bar
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/environment/environment_simple.txt b/support/texlab/src/parser/test_data/latex/environment/environment_simple.txt new file mode 100644 index 0000000000..309b559957 --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/environment/environment_simple.txt @@ -0,0 +1 @@ +\begin{foo} Hello World \end{bar}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/equation.txt b/support/texlab/src/parser/test_data/latex/equation.txt new file mode 100644 index 0000000000..7f85196961 --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/equation.txt @@ -0,0 +1 @@ +\[ foo bar \]
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/equation_missing_begin.txt b/support/texlab/src/parser/test_data/latex/equation_missing_begin.txt new file mode 100644 index 0000000000..9e5707b196 --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/equation_missing_begin.txt @@ -0,0 +1 @@ +\begin{a} foo bar \] \end{b}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/generic_command_args.txt b/support/texlab/src/parser/test_data/latex/generic_command_args.txt new file mode 100644 index 0000000000..2d62314c5c --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/generic_command_args.txt @@ -0,0 +1 @@ +\foo{bar}[qux]
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/generic_command_empty.txt b/support/texlab/src/parser/test_data/latex/generic_command_empty.txt new file mode 100644 index 0000000000..eeb4a48255 --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/generic_command_empty.txt @@ -0,0 +1 @@ +\foo
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/generic_command_escape.txt b/support/texlab/src/parser/test_data/latex/generic_command_escape.txt new file mode 100644 index 0000000000..133d674d1e --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/generic_command_escape.txt @@ -0,0 +1 @@ +\#
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/glossary/acronym_declaration.txt b/support/texlab/src/parser/test_data/latex/glossary/acronym_declaration.txt new file mode 100644 index 0000000000..abf12b6cae --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/glossary/acronym_declaration.txt @@ -0,0 +1 @@ +\DeclareAcronym{eg}{short = e.g,long = for example,tag = abbrev}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/glossary/acronym_definition_options.txt b/support/texlab/src/parser/test_data/latex/glossary/acronym_definition_options.txt new file mode 100644 index 0000000000..47a69067ca --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/glossary/acronym_definition_options.txt @@ -0,0 +1 @@ +\newacronym[longplural={Frames per Second}]{fpsLabel}{FPS}{Frame per Second}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/glossary/acronym_definition_simple.txt b/support/texlab/src/parser/test_data/latex/glossary/acronym_definition_simple.txt new file mode 100644 index 0000000000..4fbf285927 --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/glossary/acronym_definition_simple.txt @@ -0,0 +1 @@ +\newacronym{fpsLabel}{FPS}{Frame per Second}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/glossary/acronym_package.txt b/support/texlab/src/parser/test_data/latex/glossary/acronym_package.txt new file mode 100644 index 0000000000..86e60c4584 --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/glossary/acronym_package.txt @@ -0,0 +1 @@ +\acro{fps}[FPS]{Frames per Second} diff --git a/support/texlab/src/parser/test_data/latex/glossary/acronym_reference_options.txt b/support/texlab/src/parser/test_data/latex/glossary/acronym_reference_options.txt new file mode 100644 index 0000000000..43fd03f12b --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/glossary/acronym_reference_options.txt @@ -0,0 +1 @@ +\acrshort[foo=bar,baz]{fpsLabel}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/glossary/acronym_reference_simple.txt b/support/texlab/src/parser/test_data/latex/glossary/acronym_reference_simple.txt new file mode 100644 index 0000000000..d9fb5b9a25 --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/glossary/acronym_reference_simple.txt @@ -0,0 +1 @@ +\acrshort{fpsLabel}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/glossary/glossary_entry_definition_simple.txt b/support/texlab/src/parser/test_data/latex/glossary/glossary_entry_definition_simple.txt new file mode 100644 index 0000000000..fb1e12899a --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/glossary/glossary_entry_definition_simple.txt @@ -0,0 +1 @@ +\newglossaryentry{foo}{bar = baz, qux,}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/glossary/glossary_entry_reference_options.txt b/support/texlab/src/parser/test_data/latex/glossary/glossary_entry_reference_options.txt new file mode 100644 index 0000000000..fbae075e1d --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/glossary/glossary_entry_reference_options.txt @@ -0,0 +1 @@ +\gls[foo = bar, qux]{baz}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/glossary/glossary_entry_reference_simple.txt b/support/texlab/src/parser/test_data/latex/glossary/glossary_entry_reference_simple.txt new file mode 100644 index 0000000000..a603355f0f --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/glossary/glossary_entry_reference_simple.txt @@ -0,0 +1 @@ +\gls{foo}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/graphics_path.txt b/support/texlab/src/parser/test_data/latex/graphics_path.txt new file mode 100644 index 0000000000..0e9f431c36 --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/graphics_path.txt @@ -0,0 +1 @@ +\graphicspath{{../figures/}}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/graphics_path_command.txt b/support/texlab/src/parser/test_data/latex/graphics_path_command.txt new file mode 100644 index 0000000000..729ee51690 --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/graphics_path_command.txt @@ -0,0 +1 @@ +\graphicspath{{\subfix{./img/}}}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/graphics_path_options.txt b/support/texlab/src/parser/test_data/latex/graphics_path_options.txt new file mode 100644 index 0000000000..ae8aa84d86 --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/graphics_path_options.txt @@ -0,0 +1 @@ +\graphicspath[foo]{{../figures/}}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/group/curly_group_missing_end.txt b/support/texlab/src/parser/test_data/latex/group/curly_group_missing_end.txt new file mode 100644 index 0000000000..6c7b76c0f8 --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/group/curly_group_missing_end.txt @@ -0,0 +1 @@ +{hello world
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/group/curly_group_simple.txt b/support/texlab/src/parser/test_data/latex/group/curly_group_simple.txt new file mode 100644 index 0000000000..5084aae70a --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/group/curly_group_simple.txt @@ -0,0 +1 @@ +{hello world}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/group/equation_missing_end.txt b/support/texlab/src/parser/test_data/latex/group/equation_missing_end.txt new file mode 100644 index 0000000000..fcb715926a --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/group/equation_missing_end.txt @@ -0,0 +1 @@ +\begin{a} \[ foo bar \end{b}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/group/escaped_brackets.txt b/support/texlab/src/parser/test_data/latex/group/escaped_brackets.txt new file mode 100644 index 0000000000..144a5fdd6d --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/group/escaped_brackets.txt @@ -0,0 +1 @@ +{[}{]}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/group/unmatched_braces.txt b/support/texlab/src/parser/test_data/latex/group/unmatched_braces.txt new file mode 100644 index 0000000000..8f606b7dbe --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/group/unmatched_braces.txt @@ -0,0 +1 @@ +}{
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/group/unmatched_brackets.txt b/support/texlab/src/parser/test_data/latex/group/unmatched_brackets.txt new file mode 100644 index 0000000000..94ea4d5c96 --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/group/unmatched_brackets.txt @@ -0,0 +1 @@ +][
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/group/unmatched_brackets_with_group.txt b/support/texlab/src/parser/test_data/latex/group/unmatched_brackets_with_group.txt new file mode 100644 index 0000000000..ebf6229429 --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/group/unmatched_brackets_with_group.txt @@ -0,0 +1 @@ +{][}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/hello_world.txt b/support/texlab/src/parser/test_data/latex/hello_world.txt new file mode 100644 index 0000000000..c57eff55eb --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/hello_world.txt @@ -0,0 +1 @@ +Hello World!
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/include/biblatex_include_options.txt b/support/texlab/src/parser/test_data/latex/include/biblatex_include_options.txt new file mode 100644 index 0000000000..216e7ea165 --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/include/biblatex_include_options.txt @@ -0,0 +1 @@ +\addbibresource[foo=bar, baz]{foo/bar.bib}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/include/biblatex_include_simple.txt b/support/texlab/src/parser/test_data/latex/include/biblatex_include_simple.txt new file mode 100644 index 0000000000..fe10ce257d --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/include/biblatex_include_simple.txt @@ -0,0 +1 @@ +\addbibresource{foo/bar.bib}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/include/bibtex_include_simple.txt b/support/texlab/src/parser/test_data/latex/include/bibtex_include_simple.txt new file mode 100644 index 0000000000..955353f690 --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/include/bibtex_include_simple.txt @@ -0,0 +1 @@ +\bibliography{foo/bar}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/include/class_include_empty.txt b/support/texlab/src/parser/test_data/latex/include/class_include_empty.txt new file mode 100644 index 0000000000..144b418175 --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/include/class_include_empty.txt @@ -0,0 +1 @@ +\documentclass{}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/include/class_include_options.txt b/support/texlab/src/parser/test_data/latex/include/class_include_options.txt new file mode 100644 index 0000000000..32dc4279d7 --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/include/class_include_options.txt @@ -0,0 +1 @@ +\documentclass[foo = bar, baz, qux]{article}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/include/class_include_simple.txt b/support/texlab/src/parser/test_data/latex/include/class_include_simple.txt new file mode 100644 index 0000000000..15f3d6ea0a --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/include/class_include_simple.txt @@ -0,0 +1 @@ +\documentclass{article}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/include/graphics_include_command.txt b/support/texlab/src/parser/test_data/latex/include/graphics_include_command.txt new file mode 100644 index 0000000000..14a4a96216 --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/include/graphics_include_command.txt @@ -0,0 +1 @@ +\includegraphics[width=0.5\textwidth]{\foo.\bar.pdf}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/include/graphics_include_complicated_options.txt b/support/texlab/src/parser/test_data/latex/include/graphics_include_complicated_options.txt new file mode 100644 index 0000000000..d6b6910c14 --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/include/graphics_include_complicated_options.txt @@ -0,0 +1 @@ +\includegraphics[width=0.5\textwidth]{}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/include/graphics_include_options.txt b/support/texlab/src/parser/test_data/latex/include/graphics_include_options.txt new file mode 100644 index 0000000000..8d3c45f2a5 --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/include/graphics_include_options.txt @@ -0,0 +1 @@ +\includegraphics[scale=.5]{foo/bar.pdf}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/include/graphics_include_simple.txt b/support/texlab/src/parser/test_data/latex/include/graphics_include_simple.txt new file mode 100644 index 0000000000..629cf3e8a9 --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/include/graphics_include_simple.txt @@ -0,0 +1 @@ +\includegraphics{foo/bar.pdf}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/include/import_incomplete.txt b/support/texlab/src/parser/test_data/latex/include/import_incomplete.txt new file mode 100644 index 0000000000..3d6bc5f043 --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/include/import_incomplete.txt @@ -0,0 +1 @@ +\import{foo
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/include/import_simple.txt b/support/texlab/src/parser/test_data/latex/include/import_simple.txt new file mode 100644 index 0000000000..f38059d6c1 --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/include/import_simple.txt @@ -0,0 +1 @@ +\import{foo}{bar}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/include/inkscape_include_options.txt b/support/texlab/src/parser/test_data/latex/include/inkscape_include_options.txt new file mode 100644 index 0000000000..e6dd431c7c --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/include/inkscape_include_options.txt @@ -0,0 +1 @@ +\includesvg[scale=.5]{foo/bar}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/include/inkscape_include_simple.txt b/support/texlab/src/parser/test_data/latex/include/inkscape_include_simple.txt new file mode 100644 index 0000000000..4e3a4ea9ba --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/include/inkscape_include_simple.txt @@ -0,0 +1 @@ +\includesvg{foo/bar}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/include/latex_include_equality_sign.txt b/support/texlab/src/parser/test_data/latex/include/latex_include_equality_sign.txt new file mode 100644 index 0000000000..5a763b4e29 --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/include/latex_include_equality_sign.txt @@ -0,0 +1 @@ +\include{foo=bar}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/include/latex_include_simple.txt b/support/texlab/src/parser/test_data/latex/include/latex_include_simple.txt new file mode 100644 index 0000000000..c0d3d390df --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/include/latex_include_simple.txt @@ -0,0 +1 @@ +\include{foo/bar}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/include/latex_input_path_brackets.txt b/support/texlab/src/parser/test_data/latex/include/latex_input_path_brackets.txt new file mode 100644 index 0000000000..6585f50d52 --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/include/latex_input_path_brackets.txt @@ -0,0 +1 @@ +\input{foo[bar].tex}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/include/package_include_empty.txt b/support/texlab/src/parser/test_data/latex/include/package_include_empty.txt new file mode 100644 index 0000000000..09e02cc1cc --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/include/package_include_empty.txt @@ -0,0 +1 @@ +\usepackage{}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/include/package_include_multiple.txt b/support/texlab/src/parser/test_data/latex/include/package_include_multiple.txt new file mode 100644 index 0000000000..c1080aaf66 --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/include/package_include_multiple.txt @@ -0,0 +1 @@ +\usepackage{amsmath, lipsum}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/include/package_include_options.txt b/support/texlab/src/parser/test_data/latex/include/package_include_options.txt new file mode 100644 index 0000000000..83a50c12cf --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/include/package_include_options.txt @@ -0,0 +1 @@ +\usepackage[foo = bar, baz, qux]{amsmath}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/include/package_include_simple.txt b/support/texlab/src/parser/test_data/latex/include/package_include_simple.txt new file mode 100644 index 0000000000..3cf1b4edc0 --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/include/package_include_simple.txt @@ -0,0 +1 @@ +\usepackage{amsmath}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/include/pgf_library_import_simple.txt b/support/texlab/src/parser/test_data/latex/include/pgf_library_import_simple.txt new file mode 100644 index 0000000000..25a2b24720 --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/include/pgf_library_import_simple.txt @@ -0,0 +1 @@ +\usepgflibrary{foo}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/include/svg_include_options.txt b/support/texlab/src/parser/test_data/latex/include/svg_include_options.txt new file mode 100644 index 0000000000..3eb90568ab --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/include/svg_include_options.txt @@ -0,0 +1 @@ +\includesvg[scale=.5]{foo/bar.svg}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/include/svg_include_simple.txt b/support/texlab/src/parser/test_data/latex/include/svg_include_simple.txt new file mode 100644 index 0000000000..964a3adcd6 --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/include/svg_include_simple.txt @@ -0,0 +1 @@ +\includesvg{foo/bar.svg}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/include/tikz_library_import_simple.txt b/support/texlab/src/parser/test_data/latex/include/tikz_library_import_simple.txt new file mode 100644 index 0000000000..ff616ebd11 --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/include/tikz_library_import_simple.txt @@ -0,0 +1 @@ +\usetikzlibrary{foo}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/include/verbatim_include_simple.txt b/support/texlab/src/parser/test_data/latex/include/verbatim_include_simple.txt new file mode 100644 index 0000000000..a0b3fec843 --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/include/verbatim_include_simple.txt @@ -0,0 +1 @@ +\verbatiminput{foo/bar.txt}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/inline.txt b/support/texlab/src/parser/test_data/latex/inline.txt new file mode 100644 index 0000000000..81a429dc26 --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/inline.txt @@ -0,0 +1 @@ +$x \in [0, \infty)$
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/inline_double_dollar.txt b/support/texlab/src/parser/test_data/latex/inline_double_dollar.txt new file mode 100644 index 0000000000..c3a7fee9f6 --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/inline_double_dollar.txt @@ -0,0 +1 @@ +$$x \in [0, \infty)$$
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/issue_745.txt b/support/texlab/src/parser/test_data/latex/issue_745.txt new file mode 100644 index 0000000000..4cbebeb2d8 --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/issue_745.txt @@ -0,0 +1,21 @@ +\documentclass{article} +\usepackage{tabularray} + +\ExplSyntaxOn +\NewDocumentEnvironment{exptblr}{O{}m} + { + \use:x + { + \exp_not:N \begin{tblr} + [\exp_not:n{#1}] + {#2} + } + } + { + \end{tblr} + } +\ExplSyntaxOff + +\begin{document} + +\end{document}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/issue_789.txt b/support/texlab/src/parser/test_data/latex/issue_789.txt new file mode 100644 index 0000000000..612c6de786 --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/issue_789.txt @@ -0,0 +1 @@ +\graphicspath{test}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/label/label_definition_line_break.txt b/support/texlab/src/parser/test_data/latex/label/label_definition_line_break.txt new file mode 100644 index 0000000000..d567c6d25a --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/label/label_definition_line_break.txt @@ -0,0 +1,2 @@ +\label{hello +world}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/label/label_definition_simple.txt b/support/texlab/src/parser/test_data/latex/label/label_definition_simple.txt new file mode 100644 index 0000000000..43ebaf1cec --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/label/label_definition_simple.txt @@ -0,0 +1 @@ +\label{foo}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/label/label_number.txt b/support/texlab/src/parser/test_data/latex/label/label_number.txt new file mode 100644 index 0000000000..6e994af500 --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/label/label_number.txt @@ -0,0 +1 @@ +\newlabel{foo}{{1.1}}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/label/label_reference_equation.txt b/support/texlab/src/parser/test_data/latex/label/label_reference_equation.txt new file mode 100644 index 0000000000..ab386645df --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/label/label_reference_equation.txt @@ -0,0 +1 @@ +\eqref{foo}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/label/label_reference_incomplete.txt b/support/texlab/src/parser/test_data/latex/label/label_reference_incomplete.txt new file mode 100644 index 0000000000..1d0f79ec8e --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/label/label_reference_incomplete.txt @@ -0,0 +1 @@ +Equation \eqref{eq is a \emph{useful} identity.
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/label/label_reference_multiple.txt b/support/texlab/src/parser/test_data/latex/label/label_reference_multiple.txt new file mode 100644 index 0000000000..e8bb38ee9e --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/label/label_reference_multiple.txt @@ -0,0 +1 @@ +\ref{foo, bar}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/label/label_reference_range_error.txt b/support/texlab/src/parser/test_data/latex/label/label_reference_range_error.txt new file mode 100644 index 0000000000..9213da0460 --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/label/label_reference_range_error.txt @@ -0,0 +1 @@ +\crefrange{foo{bar}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/label/label_reference_range_incomplete.txt b/support/texlab/src/parser/test_data/latex/label/label_reference_range_incomplete.txt new file mode 100644 index 0000000000..841133d73a --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/label/label_reference_range_incomplete.txt @@ -0,0 +1 @@ +\crefrange{foo}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/label/label_reference_range_simple.txt b/support/texlab/src/parser/test_data/latex/label/label_reference_range_simple.txt new file mode 100644 index 0000000000..a0e985ea88 --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/label/label_reference_range_simple.txt @@ -0,0 +1 @@ +\crefrange{foo}{bar}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/label/label_reference_simple.txt b/support/texlab/src/parser/test_data/latex/label/label_reference_simple.txt new file mode 100644 index 0000000000..dde4f444f4 --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/label/label_reference_simple.txt @@ -0,0 +1 @@ +\ref{foo}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/parameter.txt b/support/texlab/src/parser/test_data/latex/parameter.txt new file mode 100644 index 0000000000..d44ac7b947 --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/parameter.txt @@ -0,0 +1 @@ +#1
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/parameter_error.txt b/support/texlab/src/parser/test_data/latex/parameter_error.txt new file mode 100644 index 0000000000..4287ca8617 --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/parameter_error.txt @@ -0,0 +1 @@ +#
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/structure/structure_enum_item.txt b/support/texlab/src/parser/test_data/latex/structure/structure_enum_item.txt new file mode 100644 index 0000000000..3288ec259b --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/structure/structure_enum_item.txt @@ -0,0 +1 @@ +\begin{enumerate} \item 1 \item[2] 2 \item 3 \end{enumerate}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/structure/structure_invalid_nesting.txt b/support/texlab/src/parser/test_data/latex/structure/structure_invalid_nesting.txt new file mode 100644 index 0000000000..7203dd2d24 --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/structure/structure_invalid_nesting.txt @@ -0,0 +1 @@ +\section{Foo} \chapter{Bar}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/structure/structure_nested.txt b/support/texlab/src/parser/test_data/latex/structure/structure_nested.txt new file mode 100644 index 0000000000..082f10765b --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/structure/structure_nested.txt @@ -0,0 +1 @@ +\part{1}\chapter{2}\section{3}\subsection{4}\subsubsection{5}\paragraph{6}\subparagraph{7}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/structure/structure_siblings.txt b/support/texlab/src/parser/test_data/latex/structure/structure_siblings.txt new file mode 100644 index 0000000000..d8e347c429 --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/structure/structure_siblings.txt @@ -0,0 +1 @@ +\section{Foo} Foo \section{Bar} Bar
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/theorem_definition/theorem_definition_full.txt b/support/texlab/src/parser/test_data/latex/theorem_definition/theorem_definition_full.txt new file mode 100644 index 0000000000..286d111ad1 --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/theorem_definition/theorem_definition_full.txt @@ -0,0 +1 @@ +\newtheorem{foo}[bar]{Foo}[baz]
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/theorem_definition/theorem_definition_name_with_counter.txt b/support/texlab/src/parser/test_data/latex/theorem_definition/theorem_definition_name_with_counter.txt new file mode 100644 index 0000000000..af1b6903a5 --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/theorem_definition/theorem_definition_name_with_counter.txt @@ -0,0 +1 @@ +\newtheorem{foo}[bar]
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/theorem_definition/theorem_definition_name_with_description.txt b/support/texlab/src/parser/test_data/latex/theorem_definition/theorem_definition_name_with_description.txt new file mode 100644 index 0000000000..e5d6551666 --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/theorem_definition/theorem_definition_name_with_description.txt @@ -0,0 +1 @@ +\newtheorem{foo}{Foo}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/theorem_definition/theorem_definition_name_with_description_and_counter.txt b/support/texlab/src/parser/test_data/latex/theorem_definition/theorem_definition_name_with_description_and_counter.txt new file mode 100644 index 0000000000..89c37d9497 --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/theorem_definition/theorem_definition_name_with_description_and_counter.txt @@ -0,0 +1 @@ +\newtheorem{foo}[bar]{Foo}
\ No newline at end of file diff --git a/support/texlab/src/parser/test_data/latex/theorem_definition/theorem_definition_only_name.txt b/support/texlab/src/parser/test_data/latex/theorem_definition/theorem_definition_only_name.txt new file mode 100644 index 0000000000..62adb2c4b9 --- /dev/null +++ b/support/texlab/src/parser/test_data/latex/theorem_definition/theorem_definition_only_name.txt @@ -0,0 +1 @@ +\newtheorem{foo}
\ No newline at end of file diff --git a/support/texlab/src/range.rs b/support/texlab/src/range.rs deleted file mode 100644 index c70a573f39..0000000000 --- a/support/texlab/src/range.rs +++ /dev/null @@ -1,20 +0,0 @@ -use lsp_types::{Position, Range}; - -pub trait RangeExt { - fn new_simple(start_line: u32, start_character: u32, end_line: u32, end_character: u32) - -> Self; -} - -impl RangeExt for Range { - fn new_simple( - start_line: u32, - start_character: u32, - end_line: u32, - end_character: u32, - ) -> Self { - Self { - start: Position::new(start_line, start_character), - end: Position::new(end_line, end_character), - } - } -} diff --git a/support/texlab/src/req_queue.rs b/support/texlab/src/req_queue.rs deleted file mode 100644 index c1eb7b9594..0000000000 --- a/support/texlab/src/req_queue.rs +++ /dev/null @@ -1,10 +0,0 @@ -use crossbeam_channel::Sender; -use lsp_server::ResponseError; - -pub struct IncomingData; - -pub struct OutgoingData { - pub(crate) sender: Sender<Result<serde_json::Value, ResponseError>>, -} - -pub type ReqQueue = lsp_server::ReqQueue<IncomingData, OutgoingData>; diff --git a/support/texlab/src/server.rs b/support/texlab/src/server.rs index 0d5d1f8fe1..93b35c69c6 100644 --- a/support/texlab/src/server.rs +++ b/support/texlab/src/server.rs @@ -1,83 +1,89 @@ +mod dispatch; +mod query; + use std::{ path::PathBuf, sync::{Arc, Mutex}, - time::Duration, }; use anyhow::Result; use crossbeam_channel::{Receiver, Sender}; -use log::{error, info, warn}; -use lsp_server::{Connection, Message, RequestId}; +use log::{error, info}; +use lsp_server::{Connection, ErrorCode, Message, RequestId}; use lsp_types::{notification::*, request::*, *}; -use serde::Serialize; +use once_cell::sync::Lazy; +use rowan::{ast::AstNode, TextSize}; +use rustc_hash::FxHashSet; +use serde::{Deserialize, Serialize}; +use serde_repr::{Deserialize_repr, Serialize_repr}; use threadpool::ThreadPool; use crate::{ - client::{send_notification, send_request}, - debouncer, - diagnostics::DiagnosticManager, - dispatch::{NotificationDispatcher, RequestDispatcher}, - distro::Distribution, + citation, + client::LspClient, + db::{self, discover_dependencies, Document, Language, Owner, Workspace}, + distro::Distro, features::{ - execute_command, find_all_references, find_document_highlights, find_document_links, - find_document_symbols, find_foldings, find_hover, find_workspace_symbols, - format_source_code, goto_definition, prepare_rename_all, rename_all, BuildEngine, - BuildParams, BuildResult, BuildStatus, FeatureRequest, ForwardSearchResult, - ForwardSearchStatus, + build::{self, BuildParams, BuildResult, BuildStatus}, + completion::{self, builder::CompletionItemData}, + definition, folding, formatting, forward_search, highlight, hover, inlay_hint, link, + reference, rename, symbol, workspace_command, + }, + normalize_uri, + syntax::bibtex, + util::{ + self, capabilities::ClientCapabilitiesExt, components::COMPONENT_DATABASE, + line_index_ext::LineIndexExt, }, - req_queue::{IncomingData, ReqQueue}, - ClientCapabilitiesExt, Document, DocumentData, DocumentLanguage, Environment, LineIndex, - LineIndexExt, Options, Workspace, WorkspaceEvent, + Db, Options, StartupOptions, }; #[derive(Debug)] enum InternalMessage { - SetDistro(Distribution), - SetOptions(Arc<Options>), + SetDistro(Distro), + SetOptions(Options), + FileEvent(notify::Event), + ForwardSearch(Url), + Diagnostics, + ChktexResult(Url, Vec<db::diagnostics::Diagnostic>), } -#[derive(Clone)] pub struct Server { connection: Arc<Connection>, internal_tx: Sender<InternalMessage>, internal_rx: Receiver<InternalMessage>, - req_queue: Arc<Mutex<ReqQueue>>, - workspace: Workspace, - diagnostic_tx: debouncer::Sender<Workspace>, - diagnostic_manager: DiagnosticManager, - pool: Arc<Mutex<ThreadPool>>, - load_resolver: bool, - build_engine: Arc<BuildEngine>, + client: LspClient, + engine: query::Engine, + watcher: FileWatcher, + pool: ThreadPool, } impl Server { - pub fn with_connection( - connection: Connection, - current_dir: PathBuf, - load_resolver: bool, - ) -> Self { - let req_queue = Arc::default(); - let workspace = Workspace::new(Environment::new(Arc::new(current_dir))); + pub fn new(connection: Connection) -> Self { + let client = LspClient::new(connection.sender.clone()); let (internal_tx, internal_rx) = crossbeam_channel::unbounded(); - let diagnostic_manager = DiagnosticManager::default(); - let diagnostic_tx = create_debouncer(connection.sender.clone(), diagnostic_manager.clone()); + let watcher = FileWatcher::new(internal_tx.clone()).expect("init file watcher"); Self { connection: Arc::new(connection), internal_tx, internal_rx, - req_queue, - workspace, - diagnostic_tx, - diagnostic_manager, - pool: Arc::new(Mutex::new(threadpool::Builder::new().build())), - load_resolver, - build_engine: Arc::default(), + client, + engine: query::Engine::default(), + watcher, + pool: threadpool::Builder::new().build(), } } - fn spawn(&self, job: impl FnOnce(Self) + Send + 'static) { - let server = self.clone(); - self.pool.lock().unwrap().execute(move || job(server)); + fn run_with_db<R, Q>(&self, id: RequestId, query: Q) + where + R: Serialize, + Q: FnOnce(&dyn Db) -> R + Send + 'static, + { + let client = self.client.clone(); + self.engine.fork(move |db| { + let response = lsp_server::Response::new_ok(id, query(db)); + client.send_response(response).unwrap(); + }); } fn capabilities(&self) -> ServerCapabilities { @@ -101,7 +107,6 @@ impl Server { definition_provider: Some(OneOf::Left(true)), references_provider: Some(OneOf::Left(true)), hover_provider: Some(HoverProviderCapability::Simple(true)), - #[cfg(feature = "completion")] completion_provider: Some(CompletionOptions { resolve_provider: Some(true), trigger_characters: Some(vec![ @@ -129,6 +134,7 @@ impl Server { ], ..Default::default() }), + inlay_hint_provider: Some(OneOf::Left(true)), ..ServerCapabilities::default() } } @@ -137,8 +143,29 @@ impl Server { let (id, params) = self.connection.initialize_start()?; let params: InitializeParams = serde_json::from_value(params)?; - self.workspace.environment.client_capabilities = Arc::new(params.capabilities); - self.workspace.environment.client_info = params.client_info.map(Arc::new); + let db = self.engine.write(); + let workspace = Workspace::get(db); + workspace + .set_client_capabilities(db) + .with_durability(salsa::Durability::HIGH) + .to(params.capabilities); + + workspace + .set_client_info(db) + .with_durability(salsa::Durability::HIGH) + .to(params.client_info); + + let root_dirs = params + .workspace_folders + .unwrap_or_default() + .into_iter() + .map(|folder| db::Location::new(db, folder.uri)) + .collect(); + + workspace + .set_root_dirs(db) + .with_durability(salsa::Durability::HIGH) + .to(root_dirs); let result = InitializeResult { capabilities: self.capabilities(), @@ -146,132 +173,109 @@ impl Server { name: "TexLab".to_owned(), version: Some(env!("CARGO_PKG_VERSION").to_owned()), }), + offset_encoding: None, }; self.connection .initialize_finish(id, serde_json::to_value(result)?)?; - if self.load_resolver { - self.spawn(move |server| { - let distro = Distribution::detect(); - info!("Detected distribution: {}", distro.kind); + let StartupOptions { skip_distro } = + serde_json::from_value(params.initialization_options.unwrap_or_default()) + .unwrap_or_default(); - server - .internal_tx - .send(InternalMessage::SetDistro(distro)) - .unwrap(); + if !skip_distro { + let sender = self.internal_tx.clone(); + self.pool.execute(move || { + let distro = Distro::detect().unwrap_or_else(|why| { + log::warn!("Unable to load distro files: {}", why); + Distro::default() + }); + + info!("Detected distribution: {:?}", distro.kind); + sender.send(InternalMessage::SetDistro(distro)).unwrap(); }); } - self.register_diagnostics_handler(); - - self.spawn(move |server| { - server.register_config_capability(); - server.register_file_watching(); - let _ = server.pull_config(); - }); - + self.register_configuration(); + self.pull_options(); Ok(()) } - fn register_file_watching(&self) { - if self - .workspace - .environment - .client_capabilities - .has_file_watching_support() - { - let options = DidChangeWatchedFilesRegistrationOptions { - watchers: vec![FileSystemWatcher { - glob_pattern: "**/*.{aux,log}".into(), - kind: Some(WatchKind::Create | WatchKind::Change | WatchKind::Delete), - }], - }; - - let reg = Registration { - id: "build-watch".to_string(), - method: DidChangeWatchedFiles::METHOD.to_string(), - register_options: Some(serde_json::to_value(options).unwrap()), - }; - - let params = RegistrationParams { - registrations: vec![reg], - }; - - if let Err(why) = - send_request::<RegisterCapability>(&self.req_queue, &self.connection.sender, params) - { - error!( - "Failed to register \"{}\" notification: {}", - DidChangeWatchedFiles::METHOD, - why - ); - } - } - } + fn register_configuration(&mut self) { + let db = self.engine.read(); - fn register_config_capability(&self) { - if self - .workspace - .environment - .client_capabilities + if Workspace::get(db) + .client_capabilities(db) .has_push_configuration_support() { - let reg = Registration { + let registration = Registration { id: "pull-config".to_string(), method: DidChangeConfiguration::METHOD.to_string(), register_options: None, }; let params = RegistrationParams { - registrations: vec![reg], + registrations: vec![registration], }; - if let Err(why) = - send_request::<RegisterCapability>(&self.req_queue, &self.connection.sender, params) - { - error!( - "Failed to register \"{}\" notification: {}", - DidChangeConfiguration::METHOD, - why - ); - } + let client = self.client.clone(); + self.pool.execute(move || { + if let Err(why) = client.send_request::<RegisterCapability>(params) { + log::error!( + "Failed to register \"{}\" notification: {}", + DidChangeConfiguration::METHOD, + why + ); + } + }); } } - fn register_diagnostics_handler(&mut self) { - let (event_sender, event_receiver) = crossbeam_channel::unbounded(); - let diagnostic_tx = self.diagnostic_tx.clone(); - let diagnostic_manager = self.diagnostic_manager.clone(); - std::thread::spawn(move || { - for event in event_receiver { - match event { - WorkspaceEvent::Changed(workspace, document) => { - diagnostic_manager.push_syntax(&workspace, &document.uri); - let delay = workspace.environment.options.diagnostics_delay; - diagnostic_tx - .send(workspace, Duration::from_millis(delay)) - .unwrap(); - } - }; - } - }); + fn update_workspace(&mut self) { + let db = self.engine.write(); + discover_dependencies(db); + self.watcher.watch(db); + self.publish_diagnostics_with_delay(); + } + + fn publish_diagnostics(&mut self) -> Result<()> { + let db = self.engine.read(); + + let all_diagnostics = db::diagnostics::collect_filtered(db, Workspace::get(db)); + + for (document, diagnostics) in all_diagnostics { + let uri = document.location(db).uri(db).clone(); + let version = None; + let params = PublishDiagnosticsParams { + uri, + diagnostics, + version, + }; + + self.client + .send_notification::<PublishDiagnostics>(params)?; + } - self.workspace.listeners.push(event_sender); + Ok(()) } - fn register_incoming_request(&self, id: RequestId) { - let mut req_queue = self.req_queue.lock().unwrap(); - req_queue.incoming.register(id, IncomingData); + fn publish_diagnostics_with_delay(&mut self) { + let db = self.engine.read(); + let sender = self.internal_tx.clone(); + let delay = Workspace::get(db).options(db).diagnostics_delay.0; + self.pool.execute(move || { + std::thread::sleep(delay); + sender.send(InternalMessage::Diagnostics).unwrap(); + }); } - fn pull_config(&self) -> Result<()> { - if !self - .workspace - .environment - .client_capabilities + fn pull_options(&mut self) { + let db = self.engine.read(); + let workspace = Workspace::get(db); + if !workspace + .client_capabilities(db) .has_pull_configuration_support() { - return Ok(()); + return; } let params = ConfigurationParams { @@ -281,108 +285,81 @@ impl Server { }], }; - match send_request::<WorkspaceConfiguration>( - &self.req_queue, - &self.connection.sender, - params, - ) { - Ok(mut json) => { - let value = json.pop().expect("invalid configuration request"); - let options = self.parse_options(value)?; - self.internal_tx - .send(InternalMessage::SetOptions(Arc::new(options))) - .unwrap(); - } - Err(why) => { - error!("Retrieving configuration failed: {}", why); - } - }; + let client = self.client.clone(); + let sender = self.internal_tx.clone(); + self.pool.execute(move || { + match client.send_request::<WorkspaceConfiguration>(params) { + Ok(mut json) => { + let options = client + .parse_options(json.pop().expect("invalid configuration request")) + .unwrap(); - Ok(()) + sender.send(InternalMessage::SetOptions(options)).unwrap(); + } + Err(why) => { + error!("Retrieving configuration failed: {}", why); + } + }; + }); } - fn parse_options(&self, value: serde_json::Value) -> Result<Options> { - let options = match serde_json::from_value(value) { - Ok(new_options) => new_options, - Err(why) => { - send_notification::<ShowMessage>( - &self.connection.sender, - ShowMessageParams { - message: format!( - "The texlab configuration is invalid; using the default settings instead.\nDetails: {why}" - ), - typ: MessageType::WARNING, - }, - )?; - - Options::default() - } - }; + fn update_options(&mut self, options: Options) { + let db = self.engine.write(); + let workspace = Workspace::get(db); + workspace + .set_options(db) + .with_durability(salsa::Durability::MEDIUM) + .to(options); - Ok(options) + self.watcher.watch(db); } - fn cancel(&self, params: CancelParams) -> Result<()> { - let id = match params.id { - NumberOrString::Number(id) => RequestId::from(id), - NumberOrString::String(id) => RequestId::from(id), - }; - - let mut req_queue = self.req_queue.lock().unwrap(); - req_queue.incoming.complete(id); - + fn cancel(&self, _params: CancelParams) -> Result<()> { Ok(()) } - fn did_change_watched_files(&mut self, params: DidChangeWatchedFilesParams) -> Result<()> { - for change in params.changes { - if let Ok(path) = change.uri.to_file_path() { - match change.typ { - FileChangeType::CREATED | FileChangeType::CHANGED => { - self.workspace.reload(path)?; - } - FileChangeType::DELETED => { - self.workspace.documents_by_uri.remove(&change.uri); - } - _ => {} - } - } - } - + fn did_change_watched_files(&mut self, _params: DidChangeWatchedFilesParams) -> Result<()> { Ok(()) } fn did_change_configuration(&mut self, params: DidChangeConfigurationParams) -> Result<()> { - if self - .workspace - .environment - .client_capabilities + let db = self.engine.read(); + let workspace = Workspace::get(db); + if workspace + .client_capabilities(db) .has_pull_configuration_support() { - self.spawn(move |server| { - let _ = server.pull_config(); - }); + self.pull_options(); } else { - let options = self.parse_options(params.settings)?; - self.workspace.environment.options = Arc::new(options); - self.reparse_all()?; + let options = self.client.parse_options(params.settings)?; + self.update_options(options); } Ok(()) } - fn did_open(&mut self, params: DidOpenTextDocumentParams) -> Result<()> { + fn did_open(&mut self, mut params: DidOpenTextDocumentParams) -> Result<()> { + normalize_uri(&mut params.text_document.uri); + + let db = self.engine.write(); + let workspace = Workspace::get(db); let language_id = ¶ms.text_document.language_id; - let language = DocumentLanguage::by_language_id(language_id); - let document = self.workspace.open( - Arc::new(params.text_document.uri), - Arc::new(params.text_document.text), - language.unwrap_or(DocumentLanguage::Latex), - )?; + let language = Language::from_id(language_id).unwrap_or(Language::Tex); + let document = workspace.open( + db, + params.text_document.uri, + params.text_document.text, + language, + Owner::Client, + ); - self.workspace.viewport.insert(Arc::clone(&document.uri)); + self.update_workspace(); - if self.workspace.environment.options.chktex.on_open_and_save { + if workspace + .options(self.engine.read()) + .chktex + .on_open_and_save + { self.run_chktex(document); } @@ -390,315 +367,299 @@ impl Server { } fn did_change(&mut self, params: DidChangeTextDocumentParams) -> Result<()> { - let uri = Arc::new(params.text_document.uri); - match self.workspace.documents_by_uri.get(&uri).cloned() { - Some(old_document) => { - let mut text = old_document.text.to_string(); - apply_document_edit(&mut text, params.content_changes); - let language = old_document.data.language(); - let new_document = - self.workspace - .open(Arc::clone(&uri), Arc::new(text), language)?; - self.workspace - .viewport - .insert(Arc::clone(&new_document.uri)); - - self.build_engine.positions_by_uri.insert( - Arc::clone(&uri), - Position::new( - old_document - .text - .lines() - .zip(new_document.text.lines()) - .position(|(a, b)| a != b) - .unwrap_or_default() as u32, - 0, - ), - ); - - if self.workspace.environment.options.chktex.on_edit { - self.run_chktex(new_document); - }; - } - None => match uri.to_file_path() { - Ok(path) => { - self.workspace.load(path)?; - } - Err(_) => return Ok(()), - }, + let mut uri = params.text_document.uri; + normalize_uri(&mut uri); + + let db = self.engine.write(); + let workspace = Workspace::get(db); + let document = match workspace.lookup_uri(db, &uri) { + Some(document) => document, + None => return Ok(()), }; + for change in params.content_changes { + match change.range { + Some(range) => { + let range = document.contents(db).line_index(db).offset_lsp_range(range); + document.edit(db, range, &change.text); + } + None => { + document + .contents(db) + .set_text(db) + .with_durability(salsa::Durability::LOW) + .to(change.text); + + document + .set_cursor(db) + .with_durability(salsa::Durability::LOW) + .to(TextSize::from(0)); + } + }; + } + + self.update_workspace(); + + if workspace.options(self.engine.read()).chktex.on_edit { + self.run_chktex(document); + } + Ok(()) } fn did_save(&mut self, params: DidSaveTextDocumentParams) -> Result<()> { - let uri = params.text_document.uri; - - if let Some(request) = self - .workspace - .documents_by_uri - .get(&uri) - .filter(|_| self.workspace.environment.options.build.on_save) - .map(|document| { - self.feature_request( - Arc::clone(&document.uri), - BuildParams { - text_document: TextDocumentIdentifier::new(uri.clone()), - }, - ) - }) - { - self.spawn(move |server| { - server - .build_engine - .build(request, &server.req_queue, &server.connection.sender) - .unwrap_or_else(|why| { - error!("Build failed: {}", why); - BuildResult { - status: BuildStatus::FAILURE, - } - }); - }); + let mut uri = params.text_document.uri; + normalize_uri(&mut uri); + + let db = self.engine.read(); + let workspace = Workspace::get(db); + if workspace.options(db).build.on_save { + self.build_internal(uri.clone(), |_| ())?; } - if let Some(document) = self - .workspace - .documents_by_uri - .get(&uri) - .filter(|_| self.workspace.environment.options.chktex.on_open_and_save) - .cloned() - { - self.run_chktex(document); + self.publish_diagnostics_with_delay(); + + let db = self.engine.read(); + if let Some(document) = workspace.lookup_uri(db, &uri) { + if workspace.options(db).chktex.on_open_and_save { + self.run_chktex(document); + } } Ok(()) } fn did_close(&mut self, params: DidCloseTextDocumentParams) -> Result<()> { - self.workspace.close(¶ms.text_document.uri); + let mut uri = params.text_document.uri; + normalize_uri(&mut uri); + + let db = self.engine.write(); + if let Some(document) = Workspace::get(db).lookup_uri(db, &uri) { + document + .set_owner(db) + .with_durability(salsa::Durability::LOW) + .to(Owner::Server); + } + + self.publish_diagnostics_with_delay(); Ok(()) } fn run_chktex(&mut self, document: Document) { - self.spawn(move |server| { - server - .diagnostic_manager - .push_chktex(&server.workspace, &document.uri); - - let delay = server.workspace.environment.options.diagnostics_delay; - server - .diagnostic_tx - .send(server.workspace.clone(), Duration::from_millis(delay)) - .unwrap(); - }); - } - - fn feature_request<P>(&self, uri: Arc<Url>, params: P) -> FeatureRequest<P> { - FeatureRequest { - params, - workspace: self.workspace.slice(&uri), - uri, - } - } - - fn handle_feature_request<P, R, H>( - &self, - id: RequestId, - params: P, - uri: Arc<Url>, - handler: H, - ) -> Result<()> - where - P: Send + 'static, - R: Serialize, - H: FnOnce(FeatureRequest<P>) -> R + Send + 'static, - { - self.spawn(move |server| { - let request = server.feature_request(uri, params); - if request.workspace.documents_by_uri.is_empty() { - let code = lsp_server::ErrorCode::InvalidRequest as i32; - let message = "unknown document".to_string(); - let response = lsp_server::Response::new_err(id, code, message); - server.connection.sender.send(response.into()).unwrap(); - } else { - let result = handler(request); - server - .connection - .sender - .send(lsp_server::Response::new_ok(id, result).into()) + let db = self.engine.read(); + if let Some(command) = util::chktex::Command::new(db, document) { + let sender = self.internal_tx.clone(); + let uri = document.location(db).uri(db).clone(); + self.pool.execute(move || { + let diagnostics = command.run().unwrap_or_default(); + sender + .send(InternalMessage::ChktexResult(uri, diagnostics)) .unwrap(); - } - }); - - Ok(()) + }); + } } fn document_link(&self, id: RequestId, params: DocumentLinkParams) -> Result<()> { - let uri = Arc::new(params.text_document.uri.clone()); - self.handle_feature_request(id, params, uri, find_document_links)?; + let mut uri = params.text_document.uri; + normalize_uri(&mut uri); + self.run_with_db(id, move |db| link::find_all(db, &uri).unwrap_or_default()); Ok(()) } fn document_symbols(&self, id: RequestId, params: DocumentSymbolParams) -> Result<()> { - let uri = Arc::new(params.text_document.uri.clone()); - self.handle_feature_request(id, params, uri, find_document_symbols)?; + let mut uri = params.text_document.uri; + normalize_uri(&mut uri); + self.run_with_db(id, move |db| symbol::find_document_symbols(db, &uri)); Ok(()) } fn workspace_symbols(&self, id: RequestId, params: WorkspaceSymbolParams) -> Result<()> { - self.spawn(move |server| { - let result = find_workspace_symbols(&server.workspace, ¶ms); - server - .connection - .sender - .send(lsp_server::Response::new_ok(id, result).into()) - .unwrap(); - }); + self.run_with_db(id, move |db| symbol::find_workspace_symbols(db, ¶ms)); Ok(()) } - #[cfg(feature = "completion")] - fn completion(&self, id: RequestId, params: CompletionParams) -> Result<()> { - let uri = Arc::new(params.text_document_position.text_document.uri.clone()); - - self.build_engine - .positions_by_uri - .insert(Arc::clone(&uri), params.text_document_position.position); - - self.handle_feature_request(id, params, uri, crate::features::complete)?; + fn completion(&mut self, id: RequestId, params: CompletionParams) -> Result<()> { + let mut uri = params.text_document_position.text_document.uri; + normalize_uri(&mut uri); + let position = params.text_document_position.position; + self.run_with_db(id, move |db| completion::complete(db, &uri, position)); Ok(()) } - #[cfg(feature = "completion")] fn completion_resolve(&self, id: RequestId, mut item: CompletionItem) -> Result<()> { - use rowan::ast::AstNode; - - use crate::{ - citation, component_db::COMPONENT_DATABASE, features::CompletionItemData, - syntax::bibtex, - }; - - self.spawn(move |server| { - match serde_json::from_value(item.data.clone().unwrap()).unwrap() { - CompletionItemData::Package | CompletionItemData::Class => { + self.run_with_db(id, move |db| { + match item + .data + .clone() + .map(|data| serde_json::from_value(data).unwrap()) + { + Some(CompletionItemData::Package | CompletionItemData::Class) => { item.documentation = COMPONENT_DATABASE .documentation(&item.label) .map(Documentation::MarkupContent); } - CompletionItemData::Citation { uri, key } => { - if let Some(document) = server.workspace.documents_by_uri.get(&uri) { - if let Some(data) = document.data.as_bibtex() { - let root = bibtex::SyntaxNode::new_root(data.green.clone()); - item.documentation = bibtex::Root::cast(root) - .and_then(|root| root.find_entry(&key)) - .and_then(|entry| citation::render(&entry)) - .map(|value| { - Documentation::MarkupContent(MarkupContent { - kind: MarkupKind::Markdown, - value, - }) - }); - } + Some(CompletionItemData::Citation { uri, key }) => { + if let Some(root) = Workspace::get(db) + .lookup_uri(db, &uri) + .and_then(|document| document.parse(db).as_bib().map(|data| data.root(db))) + { + item.documentation = bibtex::Root::cast(root) + .and_then(|root| root.find_entry(&key)) + .and_then(|entry| citation::render(&entry)) + .map(|value| { + Documentation::MarkupContent(MarkupContent { + kind: MarkupKind::Markdown, + value, + }) + }); } } - _ => {} + None => {} }; - server - .connection - .sender - .send(lsp_server::Response::new_ok(id, item).into()) - .unwrap(); + item }); + Ok(()) } fn folding_range(&self, id: RequestId, params: FoldingRangeParams) -> Result<()> { - let uri = Arc::new(params.text_document.uri.clone()); - self.handle_feature_request(id, params, uri, find_foldings)?; + let mut uri = params.text_document.uri; + normalize_uri(&mut uri); + self.run_with_db(id, move |db| { + folding::find_all(db, &uri).unwrap_or_default() + }); Ok(()) } fn references(&self, id: RequestId, params: ReferenceParams) -> Result<()> { - let uri = Arc::new(params.text_document_position.text_document.uri.clone()); - self.handle_feature_request(id, params, uri, find_all_references)?; + let mut uri = params.text_document_position.text_document.uri; + normalize_uri(&mut uri); + let position = params.text_document_position.position; + self.run_with_db(id, move |db| { + reference::find_all(db, &uri, position, ¶ms.context).unwrap_or_default() + }); + Ok(()) } - fn hover(&self, id: RequestId, params: HoverParams) -> Result<()> { - let uri = Arc::new( - params - .text_document_position_params - .text_document - .uri - .clone(), - ); - self.build_engine.positions_by_uri.insert( - Arc::clone(&uri), - params.text_document_position_params.position, - ); + fn hover(&mut self, id: RequestId, params: HoverParams) -> Result<()> { + let mut uri = params.text_document_position_params.text_document.uri; + normalize_uri(&mut uri); - self.handle_feature_request(id, params, uri, find_hover)?; + let db = self.engine.write(); + let workspace = Workspace::get(db); + if let Some(document) = workspace.lookup_uri(db, &uri) { + let position = document + .contents(db) + .line_index(db) + .offset_lsp(params.text_document_position_params.position); + + document + .set_cursor(db) + .with_durability(salsa::Durability::LOW) + .to(position); + } + + let position = params.text_document_position_params.position; + self.run_with_db(id, move |db| hover::find(db, &uri, position)); Ok(()) } fn goto_definition(&self, id: RequestId, params: GotoDefinitionParams) -> Result<()> { - let uri = Arc::new( - params - .text_document_position_params - .text_document - .uri - .clone(), - ); - self.handle_feature_request(id, params, uri, goto_definition)?; + let mut uri = params.text_document_position_params.text_document.uri; + normalize_uri(&mut uri); + let position = params.text_document_position_params.position; + self.run_with_db(id, move |db| { + definition::goto_definition(db, &uri, position) + }); + Ok(()) } fn prepare_rename(&self, id: RequestId, params: TextDocumentPositionParams) -> Result<()> { - let uri = Arc::new(params.text_document.uri.clone()); - self.handle_feature_request(id, params, uri, prepare_rename_all)?; + let mut uri = params.text_document.uri; + normalize_uri(&mut uri); + self.run_with_db(id, move |db| { + rename::prepare_rename_all(db, &uri, params.position) + }); + Ok(()) } fn rename(&self, id: RequestId, params: RenameParams) -> Result<()> { - let uri = Arc::new(params.text_document_position.text_document.uri.clone()); - self.handle_feature_request(id, params, uri, rename_all)?; + let mut uri = params.text_document_position.text_document.uri; + normalize_uri(&mut uri); + let position = params.text_document_position.position; + self.run_with_db(id, move |db| { + rename::rename_all(db, &uri, position, params.new_name) + }); + Ok(()) } fn document_highlight(&self, id: RequestId, params: DocumentHighlightParams) -> Result<()> { - let uri = Arc::new( - params - .text_document_position_params - .text_document - .uri - .clone(), - ); - self.handle_feature_request(id, params, uri, find_document_highlights)?; + let mut uri = params.text_document_position_params.text_document.uri; + normalize_uri(&mut uri); + let position = params.text_document_position_params.position; + self.run_with_db(id, move |db| { + highlight::find_all(db, &uri, position).unwrap_or_default() + }); Ok(()) } fn formatting(&self, id: RequestId, params: DocumentFormattingParams) -> Result<()> { - let uri = Arc::new(params.text_document.uri.clone()); - self.handle_feature_request(id, params, uri, format_source_code)?; + let mut uri = params.text_document.uri; + normalize_uri(&mut uri); + self.run_with_db(id, move |db| { + formatting::format_source_code(db, &uri, ¶ms.options) + }); + Ok(()) } - fn execute_command(&self, id: RequestId, params: ExecuteCommandParams) -> Result<()> { - self.spawn(move |server| { - let result = execute_command(&server.workspace, ¶ms.command, params.arguments); - let response = match result { - Ok(()) => lsp_server::Response::new_ok(id, ()), - Err(why) => lsp_server::Response::new_err( - id, - lsp_server::ErrorCode::InternalError as i32, - why.to_string(), - ), - }; + fn execute_command(&mut self, id: RequestId, params: ExecuteCommandParams) -> Result<()> { + let db = self.engine.read(); + match workspace_command::select(db, ¶ms.command, params.arguments) { + Ok(command) => { + let client = self.client.clone(); + self.pool.execute(move || { + match command.run() { + Ok(()) => { + client + .send_response(lsp_server::Response::new_ok(id, ())) + .unwrap(); + } + Err(why) => { + client + .send_error(id, ErrorCode::InternalError, why.to_string()) + .unwrap(); + } + }; + }); + } + Err(why) => { + self.client + .send_error(id, ErrorCode::InvalidParams, why.to_string()) + .unwrap(); + } + }; + + Ok(()) + } - server.connection.sender.send(response.into()).unwrap(); + fn inlay_hints(&self, id: RequestId, params: InlayHintParams) -> Result<()> { + let mut uri = params.text_document.uri; + normalize_uri(&mut uri); + self.run_with_db(id, move |db| { + inlay_hint::find_all(db, &uri, params.range).unwrap_or_default() }); + Ok(()) + } + fn inlay_hint_resolve(&self, id: RequestId, hint: InlayHint) -> Result<()> { + let response = lsp_server::Response::new_ok(id, hint); + self.connection.sender.send(response.into()).unwrap(); Ok(()) } @@ -710,52 +671,144 @@ impl Server { Ok(()) } - fn build(&self, id: RequestId, params: BuildParams) -> Result<()> { - let uri = Arc::new(params.text_document.uri.clone()); - let lsp_sender = self.connection.sender.clone(); - let req_queue = Arc::clone(&self.req_queue); - let build_engine = Arc::clone(&self.build_engine); - self.handle_feature_request(id, params, uri, move |request| { - build_engine - .build(request, &req_queue, &lsp_sender) - .unwrap_or_else(|why| { - error!("Build failed: {}", why); - BuildResult { - status: BuildStatus::FAILURE, - } - }) + fn build(&mut self, id: RequestId, params: BuildParams) -> Result<()> { + let mut uri = params.text_document.uri; + normalize_uri(&mut uri); + + let client = self.client.clone(); + self.build_internal(uri, move |status| { + let result = BuildResult { status }; + client + .send_response(lsp_server::Response::new_ok(id, result)) + .unwrap(); })?; + + Ok(()) + } + + fn build_internal( + &mut self, + uri: Url, + callback: impl FnOnce(BuildStatus) + Send + 'static, + ) -> Result<()> { + static LOCK: Lazy<Mutex<()>> = Lazy::new(|| Mutex::new(())); + + let db = self.engine.read(); + let compiler = match build::Command::new(db, uri.clone(), self.client.clone()) { + Some(compiler) => compiler, + None => { + callback(BuildStatus::FAILURE); + return Ok(()); + } + }; + + let forward_search_after = Workspace::get(db).options(db).build.forward_search_after; + + let sender = self.internal_tx.clone(); + self.pool.execute(move || { + let guard = LOCK.lock().unwrap(); + + let status = compiler.run(); + if forward_search_after { + sender.send(InternalMessage::ForwardSearch(uri)).unwrap(); + } + + drop(guard); + callback(status); + }); + Ok(()) } - fn forward_search(&self, id: RequestId, params: TextDocumentPositionParams) -> Result<()> { - let uri = Arc::new(params.text_document.uri.clone()); - self.handle_feature_request(id, params, uri, |req| { - crate::features::execute_forward_search(req).unwrap_or(ForwardSearchResult { - status: ForwardSearchStatus::ERROR, - }) + fn forward_search(&mut self, id: RequestId, params: TextDocumentPositionParams) -> Result<()> { + let mut uri = params.text_document.uri; + normalize_uri(&mut uri); + + let client = self.client.clone(); + self.forward_search_internal(uri, Some(params.position), move |status| { + let result = ForwardSearchResult { status }; + client + .send_response(lsp_server::Response::new_ok(id, result)) + .unwrap(); })?; + Ok(()) } - fn reparse_all(&mut self) -> Result<()> { - for document in self - .workspace - .documents_by_uri - .values() - .cloned() - .collect::<Vec<_>>() - { - self.workspace.open( - Arc::clone(&document.uri), - document.text.clone(), - document.data.language(), - )?; - } + fn forward_search_internal( + &mut self, + uri: Url, + position: Option<Position>, + callback: impl FnOnce(ForwardSearchStatus) + Send + 'static, + ) -> Result<()> { + let db = self.engine.read(); + let command = match forward_search::Command::configure(db, &uri, position) { + Ok(command) => command, + Err(why) => { + log::error!("Forward search failed: {}", why); + callback(why.into()); + return Ok(()); + } + }; + + self.pool.execute(move || { + let status = command + .run() + .map_or_else(ForwardSearchStatus::from, |()| ForwardSearchStatus::SUCCESS); + + callback(status); + }); Ok(()) } + fn handle_file_event(&mut self, event: notify::Event) { + let mut changed = false; + + let db = self.engine.write(); + let workspace = Workspace::get(db); + match event.kind { + notify::EventKind::Create(_) | notify::EventKind::Modify(_) => { + for path in event.paths { + if workspace + .lookup_path(db, &path) + .map_or(true, |document| document.owner(db) == Owner::Server) + { + if let Some(language) = Language::from_path(&path) { + workspace.load(db, &path, language, Owner::Server); + changed = true; + } + } + } + } + notify::EventKind::Remove(_) => { + for path in event.paths { + if let Some(document) = workspace.lookup_path(db, &path) { + if document.owner(db) == Owner::Server { + let mut documents = workspace + .set_documents(db) + .with_durability(salsa::Durability::LOW) + .to(FxHashSet::default()); + + documents.remove(&document); + workspace + .set_documents(db) + .with_durability(salsa::Durability::MEDIUM) + .to(documents); + + changed = true; + } + } + } + } + notify::EventKind::Any | notify::EventKind::Access(_) | notify::EventKind::Other => {} + }; + + if changed { + self.publish_diagnostics_with_delay(); + } + } + fn process_messages(&mut self) -> Result<()> { loop { crossbeam_channel::select! { @@ -766,8 +819,7 @@ impl Server { return Ok(()); } - self.register_incoming_request(request.id.clone()); - if let Some(response) = RequestDispatcher::new(request) + if let Some(response) = dispatch::RequestDispatcher::new(request) .on::<DocumentLinkRequest, _>(|id, params| self.document_link(id, params))? .on::<FoldingRangeRequest, _>(|id, params| self.folding_range(id, params))? .on::<References, _>(|id, params| self.references(id, params))? @@ -777,12 +829,10 @@ impl Server { })? .on::<WorkspaceSymbol, _>(|id, params| self.workspace_symbols(id, params))? .on::<Completion, _>(|id, params| { - #[cfg(feature = "completion")] self.completion(id, params)?; Ok(()) })? .on::<ResolveCompletionItem, _>(|id, params| { - #[cfg(feature = "completion")] self.completion_resolve(id, params)?; Ok(()) })? @@ -803,13 +853,19 @@ impl Server { .on::<SemanticTokensRangeRequest, _>(|id, params| { self.semantic_tokens_range(id, params) })? + .on::<InlayHintRequest, _>(|id,params| { + self.inlay_hints(id, params) + })? + .on::<InlayHintResolveRequest,_>(|id, params| { + self.inlay_hint_resolve(id, params) + })? .default() { self.connection.sender.send(response.into())?; } } Message::Notification(notification) => { - NotificationDispatcher::new(notification) + dispatch::NotificationDispatcher::new(notification) .on::<Cancel, _>(|params| self.cancel(params))? .on::<DidChangeConfiguration, _>(|params| { self.did_change_configuration(params) @@ -824,26 +880,39 @@ impl Server { .default(); } Message::Response(response) => { - let mut req_queue = self.req_queue.lock().unwrap(); - if let Some(data) = req_queue.outgoing.complete(response.id) { - let result = match response.error { - Some(error) => Err(error), - None => Ok(response.result.unwrap_or_default()), - }; - data.sender.send(result)?; - } + self.client.recv_response(response)?; } }; }, recv(&self.internal_rx) -> msg => { match msg? { InternalMessage::SetDistro(distro) => { - self.workspace.environment.resolver = Arc::new(distro.resolver); - self.reparse_all()?; + let db = self.engine.write(); + Workspace::get(db) + .set_file_name_db(db) + .with_durability(salsa::Durability::HIGH) + .to(distro.file_name_db); } InternalMessage::SetOptions(options) => { - self.workspace.environment.options = options; - self.reparse_all()?; + self.update_options(options); + } + InternalMessage::FileEvent(event) => { + self.handle_file_event(event); + } + InternalMessage::ForwardSearch(uri) => { + self.forward_search_internal(uri, None, |_| ())?; + } + InternalMessage::Diagnostics => { + self.publish_diagnostics()?; + } + InternalMessage::ChktexResult(uri, diagnostics) => { + let db = self.engine.write(); + let workspace = Workspace::get(db); + if let Some(document) = workspace.lookup_uri(db, &uri) { + document.linter(db).set_chktex(db).to(diagnostics); + } + + self.publish_diagnostics()?; } }; } @@ -854,63 +923,34 @@ impl Server { pub fn run(mut self) -> Result<()> { self.initialize()?; self.process_messages()?; - self.pool.lock().unwrap().join(); + self.pool.join(); + self.engine.finish(); Ok(()) } } -fn create_debouncer( - lsp_sender: Sender<Message>, - diagnostic_manager: DiagnosticManager, -) -> debouncer::Sender<Workspace> { - let (tx, rx) = debouncer::unbounded(); - std::thread::spawn(move || { - while let Ok(workspace) = rx.recv() { - if let Err(why) = publish_diagnostics(&lsp_sender, &diagnostic_manager, &workspace) { - warn!("Failed to publish diagnostics: {}", why); - } - } - }); - - tx +struct FileWatcher { + watcher: notify::RecommendedWatcher, + watched_dirs: FxHashSet<PathBuf>, } -fn publish_diagnostics( - lsp_sender: &Sender<lsp_server::Message>, - diagnostic_manager: &DiagnosticManager, - workspace: &Workspace, -) -> Result<()> { - for document in workspace.documents_by_uri.values() { - if matches!(document.data, DocumentData::BuildLog(_)) { - continue; - } +impl FileWatcher { + pub fn new(sender: Sender<InternalMessage>) -> Result<Self> { + let handle = move |event| { + if let Ok(event) = event { + sender.send(InternalMessage::FileEvent(event)).unwrap(); + } + }; - let diagnostics = diagnostic_manager.publish(workspace, &document.uri); - send_notification::<PublishDiagnostics>( - lsp_sender, - PublishDiagnosticsParams { - uri: document.uri.as_ref().clone(), - version: None, - diagnostics, - }, - )?; + Ok(Self { + watcher: notify::recommended_watcher(handle)?, + watched_dirs: FxHashSet::default(), + }) } - Ok(()) -} - -fn apply_document_edit(old_text: &mut String, changes: Vec<TextDocumentContentChangeEvent>) { - for change in changes { - let line_index = LineIndex::new(old_text); - match change.range { - Some(range) => { - let range = std::ops::Range::<usize>::from(line_index.offset_lsp_range(range)); - old_text.replace_range(range, &change.text); - } - None => { - *old_text = change.text; - } - }; + pub fn watch(&mut self, db: &dyn Db) { + let workspace = Workspace::get(db); + workspace.watch(db, &mut self.watcher, &mut self.watched_dirs); } } @@ -933,3 +973,29 @@ impl lsp_types::request::Request for ForwardSearchRequest { const METHOD: &'static str = "textDocument/forwardSearch"; } + +#[derive(Debug, PartialEq, Eq, Clone, Copy, Serialize_repr, Deserialize_repr)] +#[repr(i32)] +pub enum ForwardSearchStatus { + SUCCESS = 0, + ERROR = 1, + FAILURE = 2, + UNCONFIGURED = 3, +} + +impl From<forward_search::Error> for ForwardSearchStatus { + fn from(err: forward_search::Error) -> Self { + match err { + forward_search::Error::TexNotFound(_) => ForwardSearchStatus::FAILURE, + forward_search::Error::PdfNotFound(_) => ForwardSearchStatus::ERROR, + forward_search::Error::NoLocalFile(_) => ForwardSearchStatus::FAILURE, + forward_search::Error::Unconfigured => ForwardSearchStatus::UNCONFIGURED, + forward_search::Error::Spawn(_) => ForwardSearchStatus::ERROR, + } + } +} + +#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)] +pub struct ForwardSearchResult { + pub status: ForwardSearchStatus, +} diff --git a/support/texlab/src/dispatch.rs b/support/texlab/src/server/dispatch.rs index f5659ee3b4..f5659ee3b4 100644 --- a/support/texlab/src/dispatch.rs +++ b/support/texlab/src/server/dispatch.rs diff --git a/support/texlab/src/server/query.rs b/support/texlab/src/server/query.rs new file mode 100644 index 0000000000..f19d15f85b --- /dev/null +++ b/support/texlab/src/server/query.rs @@ -0,0 +1,32 @@ +use salsa::{DbWithJar, ParallelDatabase}; +use threadpool::ThreadPool; + +use crate::{Database, Db}; + +#[derive(Default)] +pub struct Engine { + db: Database, + pool: ThreadPool, +} + +impl Engine { + pub fn read(&self) -> &dyn Db { + &self.db + } + + pub fn write(&mut self) -> &mut dyn Db { + self.pool.join(); + &mut self.db + } + + pub fn fork<F: FnOnce(&dyn Db) + Send + 'static>(&self, action: F) { + let snapshot = self.db.snapshot(); + self.pool.execute(move || { + action(snapshot.as_jar_db()); + }); + } + + pub fn finish(self) { + self.pool.join(); + } +} diff --git a/support/texlab/src/syntax.rs b/support/texlab/src/syntax.rs index a0ae96089c..dc8761b73d 100644 --- a/support/texlab/src/syntax.rs +++ b/support/texlab/src/syntax.rs @@ -1,3 +1,22 @@ pub mod bibtex; -pub mod build_log; pub mod latex; + +#[derive(Debug, PartialEq, Eq, Clone, Copy, PartialOrd, Ord, Hash)] +pub enum BuildErrorLevel { + Error, + Warning, +} + +#[derive(Debug, PartialEq, Eq, Clone, Hash)] +pub struct BuildError { + pub relative_path: std::path::PathBuf, + pub level: BuildErrorLevel, + pub message: String, + pub hint: Option<String>, + pub line: Option<u32>, +} + +#[derive(Debug, PartialEq, Eq, Clone, Hash)] +pub struct BuildLog { + pub errors: Vec<BuildError>, +} diff --git a/support/texlab/src/syntax/bibtex.rs b/support/texlab/src/syntax/bibtex.rs index a35399419a..9b4b1ab77e 100644 --- a/support/texlab/src/syntax/bibtex.rs +++ b/support/texlab/src/syntax/bibtex.rs @@ -1,10 +1,4 @@ -mod ast; -mod lexer; -mod parser; -#[cfg(test)] -mod tests; - -pub use self::{ast::*, parser::parse, SyntaxKind::*}; +use rowan::{ast::AstNode, NodeOrToken}; #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash)] #[allow(non_camel_case_types)] @@ -42,6 +36,8 @@ pub enum SyntaxKind { ROOT, } +pub use SyntaxKind::*; + impl From<SyntaxKind> for rowan::SyntaxKind { fn from(kind: SyntaxKind) -> Self { Self(kind as u16) @@ -69,3 +65,240 @@ pub type SyntaxNode = rowan::SyntaxNode<Lang>; pub type SyntaxToken = rowan::SyntaxToken<Lang>; pub type SyntaxElement = rowan::SyntaxElement<Lang>; + +macro_rules! ast_node { + (name: $name:ident, kinds: [$($kind:pat),+], traits: [$($trait: ident),*]) => { + #[derive(Clone)] + pub struct $name { + node: SyntaxNode, + } + + impl AstNode for $name { + type Language = Lang; + + fn can_cast(kind: SyntaxKind) -> bool { + match kind { + $($kind => true,)+ + _ => false, + } + } + + fn cast(node: SyntaxNode) -> Option<Self> + where + Self: Sized, + { + match node.kind() { + $($kind => Some(Self { node}),)+ + _ => None, + } + } + + fn syntax(&self) -> &SyntaxNode { + &self.node + } + } + + $( + impl $trait for $name { } + )* + }; +} + +macro_rules! ast_node_enum { + (name: $name:ident, variants: [$($variant:ident),+]) => { + #[derive(Clone)] + pub enum $name { + $($variant($variant),)* + } + + impl AstNode for $name { + type Language = Lang; + + fn can_cast(kind: SyntaxKind) -> bool { + false $(|| $variant::can_cast(kind))+ + } + + fn cast(node: SyntaxNode) -> Option<Self> + where + Self: Sized, + { + None $(.or_else(|| $variant::cast(node.clone()).map(Self::$variant)))* + } + + fn syntax(&self) -> &SyntaxNode { + match self { + $(Self::$variant(node) => node.syntax(),)* + } + } + } + + $( + impl From<$variant> for $name { + fn from(node: $variant) -> Self { + Self::$variant(node) + } + } + )* + }; +} + +pub trait HasType: AstNode<Language = Lang> { + fn type_token(&self) -> Option<SyntaxToken> { + self.syntax() + .children_with_tokens() + .filter_map(NodeOrToken::into_token) + .find(|token| token.kind() == TYPE) + } +} + +pub trait HasDelims: AstNode<Language = Lang> { + fn left_delim_token(&self) -> Option<SyntaxToken> { + self.syntax() + .children_with_tokens() + .filter_map(NodeOrToken::into_token) + .find(|token| token.kind() == L_DELIM) + } + + fn right_delim_token(&self) -> Option<SyntaxToken> { + self.syntax() + .children_with_tokens() + .filter_map(NodeOrToken::into_token) + .find(|token| token.kind() == R_DELIM) + } +} + +pub trait HasName: AstNode<Language = Lang> { + fn name_token(&self) -> Option<SyntaxToken> { + self.syntax() + .children_with_tokens() + .filter_map(NodeOrToken::into_token) + .find(|token| token.kind() == NAME) + } +} + +pub trait HasEq: AstNode<Language = Lang> { + fn eq_token(&self) -> Option<SyntaxToken> { + self.syntax() + .children_with_tokens() + .filter_map(NodeOrToken::into_token) + .find(|token| token.kind() == NAME) + } +} + +pub trait HasComma: AstNode<Language = Lang> { + fn comma_token(&self) -> Option<SyntaxToken> { + self.syntax() + .children_with_tokens() + .filter_map(NodeOrToken::into_token) + .find(|token| token.kind() == COMMA) + } +} + +pub trait HasPound: AstNode<Language = Lang> { + fn pound_token(&self) -> Option<SyntaxToken> { + self.syntax() + .children_with_tokens() + .filter_map(NodeOrToken::into_token) + .find(|token| token.kind() == POUND) + } +} + +pub trait HasInteger: AstNode<Language = Lang> { + fn integer_token(&self) -> Option<SyntaxToken> { + self.syntax() + .children_with_tokens() + .filter_map(NodeOrToken::into_token) + .find(|token| token.kind() == INTEGER) + } +} + +pub trait HasCommandName: AstNode<Language = Lang> { + fn command_name_token(&self) -> Option<SyntaxToken> { + self.syntax() + .children_with_tokens() + .filter_map(NodeOrToken::into_token) + .find(|token| token.kind() == COMMAND_NAME) + } +} + +pub trait HasAccentName: AstNode<Language = Lang> { + fn accent_name_token(&self) -> Option<SyntaxToken> { + self.syntax() + .children_with_tokens() + .filter_map(NodeOrToken::into_token) + .find(|token| token.kind() == ACCENT_NAME) + } +} + +pub trait HasWord: AstNode<Language = Lang> { + fn word_token(&self) -> Option<SyntaxToken> { + self.syntax() + .children_with_tokens() + .filter_map(NodeOrToken::into_token) + .find(|token| token.kind() == WORD) + } +} + +pub trait HasValue: AstNode<Language = Lang> { + fn value(&self) -> Option<Value> { + self.syntax().children().find_map(Value::cast) + } +} + +ast_node!(name: Root, kinds: [ROOT], traits: []); + +impl Root { + pub fn strings(&self) -> impl Iterator<Item = StringDef> { + self.syntax().children().filter_map(StringDef::cast) + } + + pub fn entries(&self) -> impl Iterator<Item = Entry> { + self.syntax().children().filter_map(Entry::cast) + } + + pub fn find_entry(&self, name: &str) -> Option<Entry> { + self.entries().find(|entry| { + entry + .name_token() + .map_or(false, |token| token.text() == name) + }) + } +} + +ast_node!(name: Preamble, kinds: [PREAMBLE], traits: [HasType, HasDelims, HasValue]); + +ast_node!(name: StringDef, kinds: [STRING], traits: [HasType, HasDelims, HasName, HasEq, HasValue]); + +ast_node!(name: Entry, kinds: [ENTRY], traits: [HasType, HasDelims, HasName, HasComma]); + +impl Entry { + pub fn fields(&self) -> impl Iterator<Item = Field> { + self.syntax().children().filter_map(Field::cast) + } +} + +ast_node!(name: Field, kinds: [FIELD], traits: [HasName, HasEq, HasValue, HasComma]); + +ast_node_enum!(name: Value, variants: [Literal, CurlyGroup, QuoteGroup, Join, Accent, Command]); + +ast_node!(name: Literal, kinds: [LITERAL], traits: [HasName, HasInteger]); + +ast_node!(name: CurlyGroup, kinds: [CURLY_GROUP], traits: []); + +ast_node!(name: QuoteGroup, kinds: [QUOTE_GROUP], traits: []); + +ast_node!(name: Join, kinds: [JOIN], traits: [HasPound]); + +impl Join { + pub fn left_value(&self) -> Option<Value> { + self.syntax().children().find_map(Value::cast) + } + + pub fn right_value(&self) -> Option<Value> { + self.syntax().children().filter_map(Value::cast).nth(1) + } +} + +ast_node!(name: Accent, kinds: [ACCENT], traits: [HasAccentName, HasWord]); + +ast_node!(name: Command, kinds: [COMMAND], traits: [HasCommandName]); diff --git a/support/texlab/src/syntax/bibtex/ast.rs b/support/texlab/src/syntax/bibtex/ast.rs deleted file mode 100644 index 10ac571dd2..0000000000 --- a/support/texlab/src/syntax/bibtex/ast.rs +++ /dev/null @@ -1,244 +0,0 @@ -use rowan::{ast::AstNode, NodeOrToken}; - -use super::{ - Lang, - SyntaxKind::{self, *}, - SyntaxNode, SyntaxToken, -}; - -macro_rules! ast_node { - (name: $name:ident, kinds: [$($kind:pat),+], traits: [$($trait: ident),*]) => { - #[derive(Clone)] - pub struct $name { - node: SyntaxNode, - } - - impl AstNode for $name { - type Language = Lang; - - fn can_cast(kind: SyntaxKind) -> bool { - match kind { - $($kind => true,)+ - _ => false, - } - } - - fn cast(node: SyntaxNode) -> Option<Self> - where - Self: Sized, - { - match node.kind() { - $($kind => Some(Self { node}),)+ - _ => None, - } - } - - fn syntax(&self) -> &SyntaxNode { - &self.node - } - } - - $( - impl $trait for $name { } - )* - }; -} - -macro_rules! ast_node_enum { - (name: $name:ident, variants: [$($variant:ident),+]) => { - #[derive(Clone)] - pub enum $name { - $($variant($variant),)* - } - - impl AstNode for $name { - type Language = Lang; - - fn can_cast(kind: SyntaxKind) -> bool { - false $(|| $variant::can_cast(kind))+ - } - - fn cast(node: SyntaxNode) -> Option<Self> - where - Self: Sized, - { - None $(.or_else(|| $variant::cast(node.clone()).map(Self::$variant)))* - } - - fn syntax(&self) -> &SyntaxNode { - match self { - $(Self::$variant(node) => node.syntax(),)* - } - } - } - - $( - impl From<$variant> for $name { - fn from(node: $variant) -> Self { - Self::$variant(node) - } - } - )* - }; -} - -pub trait HasType: AstNode<Language = Lang> { - fn type_token(&self) -> Option<SyntaxToken> { - self.syntax() - .children_with_tokens() - .filter_map(NodeOrToken::into_token) - .find(|token| token.kind() == TYPE) - } -} - -pub trait HasDelims: AstNode<Language = Lang> { - fn left_delim_token(&self) -> Option<SyntaxToken> { - self.syntax() - .children_with_tokens() - .filter_map(NodeOrToken::into_token) - .find(|token| token.kind() == L_DELIM) - } - - fn right_delim_token(&self) -> Option<SyntaxToken> { - self.syntax() - .children_with_tokens() - .filter_map(NodeOrToken::into_token) - .find(|token| token.kind() == R_DELIM) - } -} - -pub trait HasName: AstNode<Language = Lang> { - fn name_token(&self) -> Option<SyntaxToken> { - self.syntax() - .children_with_tokens() - .filter_map(NodeOrToken::into_token) - .find(|token| token.kind() == NAME) - } -} - -pub trait HasEq: AstNode<Language = Lang> { - fn eq_token(&self) -> Option<SyntaxToken> { - self.syntax() - .children_with_tokens() - .filter_map(NodeOrToken::into_token) - .find(|token| token.kind() == NAME) - } -} - -pub trait HasComma: AstNode<Language = Lang> { - fn comma_token(&self) -> Option<SyntaxToken> { - self.syntax() - .children_with_tokens() - .filter_map(NodeOrToken::into_token) - .find(|token| token.kind() == COMMA) - } -} - -pub trait HasPound: AstNode<Language = Lang> { - fn pound_token(&self) -> Option<SyntaxToken> { - self.syntax() - .children_with_tokens() - .filter_map(NodeOrToken::into_token) - .find(|token| token.kind() == POUND) - } -} - -pub trait HasInteger: AstNode<Language = Lang> { - fn integer_token(&self) -> Option<SyntaxToken> { - self.syntax() - .children_with_tokens() - .filter_map(NodeOrToken::into_token) - .find(|token| token.kind() == INTEGER) - } -} - -pub trait HasCommandName: AstNode<Language = Lang> { - fn command_name_token(&self) -> Option<SyntaxToken> { - self.syntax() - .children_with_tokens() - .filter_map(NodeOrToken::into_token) - .find(|token| token.kind() == COMMAND_NAME) - } -} - -pub trait HasAccentName: AstNode<Language = Lang> { - fn accent_name_token(&self) -> Option<SyntaxToken> { - self.syntax() - .children_with_tokens() - .filter_map(NodeOrToken::into_token) - .find(|token| token.kind() == ACCENT_NAME) - } -} - -pub trait HasWord: AstNode<Language = Lang> { - fn word_token(&self) -> Option<SyntaxToken> { - self.syntax() - .children_with_tokens() - .filter_map(NodeOrToken::into_token) - .find(|token| token.kind() == WORD) - } -} - -pub trait HasValue: AstNode<Language = Lang> { - fn value(&self) -> Option<Value> { - self.syntax().children().find_map(Value::cast) - } -} - -ast_node!(name: Root, kinds: [ROOT], traits: []); - -impl Root { - pub fn strings(&self) -> impl Iterator<Item = StringDef> { - self.syntax().children().filter_map(StringDef::cast) - } - - pub fn entries(&self) -> impl Iterator<Item = Entry> { - self.syntax().children().filter_map(Entry::cast) - } - - pub fn find_entry(&self, name: &str) -> Option<Entry> { - self.entries().find(|entry| { - entry - .name_token() - .map_or(false, |token| token.text() == name) - }) - } -} - -ast_node!(name: Preamble, kinds: [PREAMBLE], traits: [HasType, HasDelims, HasValue]); - -ast_node!(name: StringDef, kinds: [STRING], traits: [HasType, HasDelims, HasName, HasEq, HasValue]); - -ast_node!(name: Entry, kinds: [ENTRY], traits: [HasType, HasDelims, HasName, HasComma]); - -impl Entry { - pub fn fields(&self) -> impl Iterator<Item = Field> { - self.syntax().children().filter_map(Field::cast) - } -} - -ast_node!(name: Field, kinds: [FIELD], traits: [HasName, HasEq, HasValue, HasComma]); - -ast_node_enum!(name: Value, variants: [Literal, CurlyGroup, QuoteGroup, Join, Accent, Command]); - -ast_node!(name: Literal, kinds: [LITERAL], traits: [HasName, HasInteger]); - -ast_node!(name: CurlyGroup, kinds: [CURLY_GROUP], traits: []); - -ast_node!(name: QuoteGroup, kinds: [QUOTE_GROUP], traits: []); - -ast_node!(name: Join, kinds: [JOIN], traits: [HasPound]); - -impl Join { - pub fn left_value(&self) -> Option<Value> { - self.syntax().children().find_map(Value::cast) - } - - pub fn right_value(&self) -> Option<Value> { - self.syntax().children().filter_map(Value::cast).nth(1) - } -} - -ast_node!(name: Accent, kinds: [ACCENT], traits: [HasAccentName, HasWord]); - -ast_node!(name: Command, kinds: [COMMAND], traits: [HasCommandName]); diff --git a/support/texlab/src/syntax/bibtex/lexer.rs b/support/texlab/src/syntax/bibtex/lexer.rs deleted file mode 100644 index 3ea8e9f8d2..0000000000 --- a/support/texlab/src/syntax/bibtex/lexer.rs +++ /dev/null @@ -1,180 +0,0 @@ -use logos::Logos; - -use super::SyntaxKind::{self, *}; - -#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash, Logos)] -pub enum RootToken { - #[token(r"@preamble", ignore(ascii_case))] - Preamble, - - #[token(r"@string", ignore(ascii_case))] - String, - - #[token(r"@comment", ignore(ascii_case))] - Comment, - - #[regex(r"@[a-zA-Z]*")] - Entry, - - #[regex(r"[^@]+")] - #[error] - Junk, -} - -impl From<RootToken> for SyntaxKind { - fn from(token: RootToken) -> Self { - match token { - RootToken::Preamble | RootToken::String | RootToken::Comment | RootToken::Entry => TYPE, - RootToken::Junk => JUNK, - } - } -} - -#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash, Logos)] -pub enum BodyToken { - #[regex(r"\s+")] - Whitespace, - - #[token("{")] - #[token("(")] - LDelim, - - #[token("}")] - #[token(")")] - RDelim, - - #[token(",")] - Comma, - - #[token("=")] - Eq, - - #[regex(r"[^\s\(\)\{\}@,=]+")] - Name, - - #[error] - Error, -} - -impl From<BodyToken> for SyntaxKind { - fn from(token: BodyToken) -> Self { - match token { - BodyToken::Whitespace => WHITESPACE, - BodyToken::LDelim => L_DELIM, - BodyToken::RDelim => R_DELIM, - BodyToken::Comma => COMMA, - BodyToken::Eq => EQ, - BodyToken::Name => NAME, - BodyToken::Error => unreachable!(), - } - } -} - -#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash, Logos)] -pub enum ValueToken { - #[regex(r"\s+")] - Whitespace, - - #[token("#")] - Pound, - - #[token(",")] - Comma, - - #[token("{")] - LCurly, - - #[token("}")] - RCurly, - - #[token("\"")] - Quote, - - #[regex(r"\d+", priority = 2)] - Integer, - - #[regex(r#"[^\s"\{\},]+"#)] - #[error] - Name, -} - -impl From<ValueToken> for SyntaxKind { - fn from(token: ValueToken) -> Self { - match token { - ValueToken::Whitespace => WHITESPACE, - ValueToken::Pound => POUND, - ValueToken::Comma => COMMA, - ValueToken::LCurly => L_CURLY, - ValueToken::RCurly => R_CURLY, - ValueToken::Quote => QUOTE, - ValueToken::Integer => INTEGER, - ValueToken::Name => NAME, - } - } -} - -#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash, Logos)] -pub enum ContentToken { - #[regex(r"\s+")] - Whitespace, - - #[token(",")] - Comma, - - #[token("{")] - LCurly, - - #[token("}")] - RCurly, - - #[token("\"")] - Quote, - - #[regex(r"\d+", priority = 2)] - Integer, - - #[token(r#"~"#)] - Nbsp, - - #[token(r#"\`"#)] - #[token(r#"\'"#)] - #[token(r#"\^"#)] - #[token(r#"\""#)] - #[token(r#"\H"#)] - #[token(r#"\~"#)] - #[token(r#"\c"#)] - #[token(r#"\k"#)] - #[token(r#"\="#)] - #[token(r#"\b"#)] - #[token(r#"\."#)] - #[token(r#"\d"#)] - #[token(r#"\r"#)] - #[token(r#"\u"#)] - #[token(r#"\v"#)] - #[token(r#"\t"#)] - AccentName, - - #[regex(r"\\([^\r\n]|[@a-zA-Z:_]+\*?)?")] - CommandName, - - #[regex(r#"[^\s"\{\}\\~,]+"#)] - #[error] - Word, -} - -impl From<ContentToken> for SyntaxKind { - fn from(token: ContentToken) -> Self { - match token { - ContentToken::Whitespace => WHITESPACE, - ContentToken::Comma => COMMA, - ContentToken::LCurly => L_CURLY, - ContentToken::RCurly => R_CURLY, - ContentToken::Quote => QUOTE, - ContentToken::Integer => INTEGER, - ContentToken::Nbsp => NBSP, - ContentToken::AccentName => ACCENT_NAME, - ContentToken::CommandName => COMMAND_NAME, - ContentToken::Word => WORD, - } - } -} diff --git a/support/texlab/src/syntax/bibtex/snapshots/texlab__syntax__bibtex__tests__biblatex_examples_001.snap b/support/texlab/src/syntax/bibtex/snapshots/texlab__syntax__bibtex__tests__biblatex_examples_001.snap deleted file mode 100644 index 4fbec161d2..0000000000 --- a/support/texlab/src/syntax/bibtex/snapshots/texlab__syntax__bibtex__tests__biblatex_examples_001.snap +++ /dev/null @@ -1,430 +0,0 @@ ---- -source: src/syntax/bibtex/tests.rs -assertion_line: 47 -expression: "setup(r#\"@incollection{westfahl:space,\n author = {Westfahl, Gary},\n title = {The True Frontier},\n subtitle = {Confronting and Avoiding the Realities of Space in {American}\n Science Fiction Films},\n pages = {55-65},\n crossref = {westfahl:frontier},\n langid = {english},\n langidopts = {variant=american},\n indextitle = {True Frontier, The},\n annotation = {A cross-referenced article from a \\texttt{collection}. This is\n an \\texttt{incollection} entry with a \\texttt{crossref}\n field. Note the \\texttt{subtitle} and \\texttt{indextitle}\n fields},\n}\n\n% booktitle and booksubtitle are only needed for BibTeX's less sophisticated\n% inheritance set-up to make sure westfahl:space shows correctly.\n% With Biber they are not needed.\n@collection{westfahl:frontier,\n editor = {Westfahl, Gary},\n title = {Space and Beyond},\n date = 2000,\n subtitle = {The Frontier Theme in Science Fiction},\n publisher = {Greenwood},\n location = {Westport, Conn. and London},\n langid = {english},\n langidopts = {variant=american},\n booktitle = {Space and Beyond},\n booksubtitle = {The Frontier Theme in Science Fiction},\n annotation = {This is a \\texttt{collection} entry. Note the format of the\n \\texttt{location} field as well as the \\texttt{subtitle}\n field},\n}\"#)" ---- -ROOT@0..1484 - ENTRY@0..678 - TYPE@0..13 "@incollection" - L_DELIM@13..14 "{" - NAME@14..28 "westfahl:space" - COMMA@28..29 "," - WHITESPACE@29..34 "\n " - FIELD@34..66 - NAME@34..40 "author" - WHITESPACE@40..47 " " - EQ@47..48 "=" - WHITESPACE@48..49 " " - CURLY_GROUP@49..65 - L_CURLY@49..50 "{" - WORD@50..58 "Westfahl" - COMMA@58..59 "," - WHITESPACE@59..60 " " - WORD@60..64 "Gary" - R_CURLY@64..65 "}" - COMMA@65..66 "," - WHITESPACE@66..71 "\n " - FIELD@71..106 - NAME@71..76 "title" - WHITESPACE@76..84 " " - EQ@84..85 "=" - WHITESPACE@85..86 " " - CURLY_GROUP@86..105 - L_CURLY@86..87 "{" - WORD@87..90 "The" - WHITESPACE@90..91 " " - WORD@91..95 "True" - WHITESPACE@95..96 " " - WORD@96..104 "Frontier" - R_CURLY@104..105 "}" - COMMA@105..106 "," - WHITESPACE@106..111 "\n " - FIELD@111..232 - NAME@111..119 "subtitle" - WHITESPACE@119..124 " " - EQ@124..125 "=" - WHITESPACE@125..126 " " - CURLY_GROUP@126..231 - L_CURLY@126..127 "{" - WORD@127..138 "Confronting" - WHITESPACE@138..139 " " - WORD@139..142 "and" - WHITESPACE@142..143 " " - WORD@143..151 "Avoiding" - WHITESPACE@151..152 " " - WORD@152..155 "the" - WHITESPACE@155..156 " " - WORD@156..165 "Realities" - WHITESPACE@165..166 " " - WORD@166..168 "of" - WHITESPACE@168..169 " " - WORD@169..174 "Space" - WHITESPACE@174..175 " " - WORD@175..177 "in" - WHITESPACE@177..178 " " - CURLY_GROUP@178..188 - L_CURLY@178..179 "{" - WORD@179..187 "American" - R_CURLY@187..188 "}" - WHITESPACE@188..209 "\n " - WORD@209..216 "Science" - WHITESPACE@216..217 " " - WORD@217..224 "Fiction" - WHITESPACE@224..225 " " - WORD@225..230 "Films" - R_CURLY@230..231 "}" - COMMA@231..232 "," - WHITESPACE@232..237 "\n " - FIELD@237..260 - NAME@237..242 "pages" - WHITESPACE@242..250 " " - EQ@250..251 "=" - WHITESPACE@251..252 " " - CURLY_GROUP@252..259 - L_CURLY@252..253 "{" - WORD@253..258 "55-65" - R_CURLY@258..259 "}" - COMMA@259..260 "," - WHITESPACE@260..265 "\n " - FIELD@265..300 - NAME@265..273 "crossref" - WHITESPACE@273..278 " " - EQ@278..279 "=" - WHITESPACE@279..280 " " - CURLY_GROUP@280..299 - L_CURLY@280..281 "{" - WORD@281..298 "westfahl:frontier" - R_CURLY@298..299 "}" - COMMA@299..300 "," - WHITESPACE@300..305 "\n " - FIELD@305..330 - NAME@305..311 "langid" - WHITESPACE@311..318 " " - EQ@318..319 "=" - WHITESPACE@319..320 " " - CURLY_GROUP@320..329 - L_CURLY@320..321 "{" - WORD@321..328 "english" - R_CURLY@328..329 "}" - COMMA@329..330 "," - WHITESPACE@330..335 "\n " - FIELD@335..369 - NAME@335..345 "langidopts" - WHITESPACE@345..348 " " - EQ@348..349 "=" - WHITESPACE@349..350 " " - CURLY_GROUP@350..368 - L_CURLY@350..351 "{" - WORD@351..367 "variant=american" - R_CURLY@367..368 "}" - COMMA@368..369 "," - WHITESPACE@369..374 "\n " - FIELD@374..410 - NAME@374..384 "indextitle" - WHITESPACE@384..387 " " - EQ@387..388 "=" - WHITESPACE@388..389 " " - CURLY_GROUP@389..409 - L_CURLY@389..390 "{" - WORD@390..394 "True" - WHITESPACE@394..395 " " - WORD@395..403 "Frontier" - COMMA@403..404 "," - WHITESPACE@404..405 " " - WORD@405..408 "The" - R_CURLY@408..409 "}" - COMMA@409..410 "," - WHITESPACE@410..415 "\n " - FIELD@415..676 - NAME@415..425 "annotation" - WHITESPACE@425..428 " " - EQ@428..429 "=" - WHITESPACE@429..430 " " - CURLY_GROUP@430..675 - L_CURLY@430..431 "{" - WORD@431..432 "A" - WHITESPACE@432..433 " " - WORD@433..449 "cross-referenced" - WHITESPACE@449..450 " " - WORD@450..457 "article" - WHITESPACE@457..458 " " - WORD@458..462 "from" - WHITESPACE@462..463 " " - WORD@463..464 "a" - WHITESPACE@464..465 " " - COMMAND@465..472 - COMMAND_NAME@465..472 "\\texttt" - CURLY_GROUP@472..484 - L_CURLY@472..473 "{" - WORD@473..483 "collection" - R_CURLY@483..484 "}" - WORD@484..485 "." - WHITESPACE@485..486 " " - WORD@486..490 "This" - WHITESPACE@490..491 " " - WORD@491..493 "is" - WHITESPACE@493..514 "\n " - WORD@514..516 "an" - WHITESPACE@516..517 " " - COMMAND@517..524 - COMMAND_NAME@517..524 "\\texttt" - CURLY_GROUP@524..538 - L_CURLY@524..525 "{" - WORD@525..537 "incollection" - R_CURLY@537..538 "}" - WHITESPACE@538..539 " " - WORD@539..544 "entry" - WHITESPACE@544..545 " " - WORD@545..549 "with" - WHITESPACE@549..550 " " - WORD@550..551 "a" - WHITESPACE@551..552 " " - COMMAND@552..559 - COMMAND_NAME@552..559 "\\texttt" - CURLY_GROUP@559..569 - L_CURLY@559..560 "{" - WORD@560..568 "crossref" - R_CURLY@568..569 "}" - WHITESPACE@569..590 "\n " - WORD@590..596 "field." - WHITESPACE@596..597 " " - WORD@597..601 "Note" - WHITESPACE@601..602 " " - WORD@602..605 "the" - WHITESPACE@605..606 " " - COMMAND@606..613 - COMMAND_NAME@606..613 "\\texttt" - CURLY_GROUP@613..623 - L_CURLY@613..614 "{" - WORD@614..622 "subtitle" - R_CURLY@622..623 "}" - WHITESPACE@623..624 " " - WORD@624..627 "and" - WHITESPACE@627..628 " " - COMMAND@628..635 - COMMAND_NAME@628..635 "\\texttt" - CURLY_GROUP@635..647 - L_CURLY@635..636 "{" - WORD@636..646 "indextitle" - R_CURLY@646..647 "}" - WHITESPACE@647..668 "\n " - WORD@668..674 "fields" - R_CURLY@674..675 "}" - COMMA@675..676 "," - WHITESPACE@676..677 "\n" - R_DELIM@677..678 "}" - JUNK@678..857 "\n\n% booktitle and boo ..." - ENTRY@857..1484 - TYPE@857..868 "@collection" - L_DELIM@868..869 "{" - NAME@869..886 "westfahl:frontier" - COMMA@886..887 "," - WHITESPACE@887..892 "\n " - FIELD@892..924 - NAME@892..898 "editor" - WHITESPACE@898..905 " " - EQ@905..906 "=" - WHITESPACE@906..907 " " - CURLY_GROUP@907..923 - L_CURLY@907..908 "{" - WORD@908..916 "Westfahl" - COMMA@916..917 "," - WHITESPACE@917..918 " " - WORD@918..922 "Gary" - R_CURLY@922..923 "}" - COMMA@923..924 "," - WHITESPACE@924..929 "\n " - FIELD@929..963 - NAME@929..934 "title" - WHITESPACE@934..942 " " - EQ@942..943 "=" - WHITESPACE@943..944 " " - CURLY_GROUP@944..962 - L_CURLY@944..945 "{" - WORD@945..950 "Space" - WHITESPACE@950..951 " " - WORD@951..954 "and" - WHITESPACE@954..955 " " - WORD@955..961 "Beyond" - R_CURLY@961..962 "}" - COMMA@962..963 "," - WHITESPACE@963..968 "\n " - FIELD@968..988 - NAME@968..972 "date" - WHITESPACE@972..981 " " - EQ@981..982 "=" - WHITESPACE@982..983 " " - LITERAL@983..987 - INTEGER@983..987 "2000" - COMMA@987..988 "," - WHITESPACE@988..993 "\n " - FIELD@993..1048 - NAME@993..1001 "subtitle" - WHITESPACE@1001..1006 " " - EQ@1006..1007 "=" - WHITESPACE@1007..1008 " " - CURLY_GROUP@1008..1047 - L_CURLY@1008..1009 "{" - WORD@1009..1012 "The" - WHITESPACE@1012..1013 " " - WORD@1013..1021 "Frontier" - WHITESPACE@1021..1022 " " - WORD@1022..1027 "Theme" - WHITESPACE@1027..1028 " " - WORD@1028..1030 "in" - WHITESPACE@1030..1031 " " - WORD@1031..1038 "Science" - WHITESPACE@1038..1039 " " - WORD@1039..1046 "Fiction" - R_CURLY@1046..1047 "}" - COMMA@1047..1048 "," - WHITESPACE@1048..1053 "\n " - FIELD@1053..1080 - NAME@1053..1062 "publisher" - WHITESPACE@1062..1066 " " - EQ@1066..1067 "=" - WHITESPACE@1067..1068 " " - CURLY_GROUP@1068..1079 - L_CURLY@1068..1069 "{" - WORD@1069..1078 "Greenwood" - R_CURLY@1078..1079 "}" - COMMA@1079..1080 "," - WHITESPACE@1080..1085 "\n " - FIELD@1085..1129 - NAME@1085..1093 "location" - WHITESPACE@1093..1098 " " - EQ@1098..1099 "=" - WHITESPACE@1099..1100 " " - CURLY_GROUP@1100..1128 - L_CURLY@1100..1101 "{" - WORD@1101..1109 "Westport" - COMMA@1109..1110 "," - WHITESPACE@1110..1111 " " - WORD@1111..1116 "Conn." - WHITESPACE@1116..1117 " " - WORD@1117..1120 "and" - WHITESPACE@1120..1121 " " - WORD@1121..1127 "London" - R_CURLY@1127..1128 "}" - COMMA@1128..1129 "," - WHITESPACE@1129..1134 "\n " - FIELD@1134..1159 - NAME@1134..1140 "langid" - WHITESPACE@1140..1147 " " - EQ@1147..1148 "=" - WHITESPACE@1148..1149 " " - CURLY_GROUP@1149..1158 - L_CURLY@1149..1150 "{" - WORD@1150..1157 "english" - R_CURLY@1157..1158 "}" - COMMA@1158..1159 "," - WHITESPACE@1159..1164 "\n " - FIELD@1164..1198 - NAME@1164..1174 "langidopts" - WHITESPACE@1174..1177 " " - EQ@1177..1178 "=" - WHITESPACE@1178..1179 " " - CURLY_GROUP@1179..1197 - L_CURLY@1179..1180 "{" - WORD@1180..1196 "variant=american" - R_CURLY@1196..1197 "}" - COMMA@1197..1198 "," - WHITESPACE@1198..1203 "\n " - FIELD@1203..1237 - NAME@1203..1212 "booktitle" - WHITESPACE@1212..1216 " " - EQ@1216..1217 "=" - WHITESPACE@1217..1218 " " - CURLY_GROUP@1218..1236 - L_CURLY@1218..1219 "{" - WORD@1219..1224 "Space" - WHITESPACE@1224..1225 " " - WORD@1225..1228 "and" - WHITESPACE@1228..1229 " " - WORD@1229..1235 "Beyond" - R_CURLY@1235..1236 "}" - COMMA@1236..1237 "," - WHITESPACE@1237..1242 "\n " - FIELD@1242..1297 - NAME@1242..1254 "booksubtitle" - WHITESPACE@1254..1255 " " - EQ@1255..1256 "=" - WHITESPACE@1256..1257 " " - CURLY_GROUP@1257..1296 - L_CURLY@1257..1258 "{" - WORD@1258..1261 "The" - WHITESPACE@1261..1262 " " - WORD@1262..1270 "Frontier" - WHITESPACE@1270..1271 " " - WORD@1271..1276 "Theme" - WHITESPACE@1276..1277 " " - WORD@1277..1279 "in" - WHITESPACE@1279..1280 " " - WORD@1280..1287 "Science" - WHITESPACE@1287..1288 " " - WORD@1288..1295 "Fiction" - R_CURLY@1295..1296 "}" - COMMA@1296..1297 "," - WHITESPACE@1297..1302 "\n " - FIELD@1302..1482 - NAME@1302..1312 "annotation" - WHITESPACE@1312..1315 " " - EQ@1315..1316 "=" - WHITESPACE@1316..1317 " " - CURLY_GROUP@1317..1481 - L_CURLY@1317..1318 "{" - WORD@1318..1322 "This" - WHITESPACE@1322..1323 " " - WORD@1323..1325 "is" - WHITESPACE@1325..1326 " " - WORD@1326..1327 "a" - WHITESPACE@1327..1328 " " - COMMAND@1328..1335 - COMMAND_NAME@1328..1335 "\\texttt" - CURLY_GROUP@1335..1347 - L_CURLY@1335..1336 "{" - WORD@1336..1346 "collection" - R_CURLY@1346..1347 "}" - WHITESPACE@1347..1348 " " - WORD@1348..1354 "entry." - WHITESPACE@1354..1355 " " - WORD@1355..1359 "Note" - WHITESPACE@1359..1360 " " - WORD@1360..1363 "the" - WHITESPACE@1363..1364 " " - WORD@1364..1370 "format" - WHITESPACE@1370..1371 " " - WORD@1371..1373 "of" - WHITESPACE@1373..1374 " " - WORD@1374..1377 "the" - WHITESPACE@1377..1398 "\n " - COMMAND@1398..1405 - COMMAND_NAME@1398..1405 "\\texttt" - CURLY_GROUP@1405..1415 - L_CURLY@1405..1406 "{" - WORD@1406..1414 "location" - R_CURLY@1414..1415 "}" - WHITESPACE@1415..1416 " " - WORD@1416..1421 "field" - WHITESPACE@1421..1422 " " - WORD@1422..1424 "as" - WHITESPACE@1424..1425 " " - WORD@1425..1429 "well" - WHITESPACE@1429..1430 " " - WORD@1430..1432 "as" - WHITESPACE@1432..1433 " " - WORD@1433..1436 "the" - WHITESPACE@1436..1437 " " - COMMAND@1437..1444 - COMMAND_NAME@1437..1444 "\\texttt" - CURLY_GROUP@1444..1454 - L_CURLY@1444..1445 "{" - WORD@1445..1453 "subtitle" - R_CURLY@1453..1454 "}" - WHITESPACE@1454..1475 "\n " - WORD@1475..1480 "field" - R_CURLY@1480..1481 "}" - COMMA@1481..1482 "," - WHITESPACE@1482..1483 "\n" - R_DELIM@1483..1484 "}" - diff --git a/support/texlab/src/syntax/bibtex/snapshots/texlab__syntax__bibtex__tests__biblatex_examples_003.snap b/support/texlab/src/syntax/bibtex/snapshots/texlab__syntax__bibtex__tests__biblatex_examples_003.snap deleted file mode 100644 index 360b133a8e..0000000000 --- a/support/texlab/src/syntax/bibtex/snapshots/texlab__syntax__bibtex__tests__biblatex_examples_003.snap +++ /dev/null @@ -1,208 +0,0 @@ ---- -source: src/syntax/bibtex/tests.rs -assertion_line: 109 -expression: "setup(r#\"@article{angenendt,\n author = {Angenendt, Arnold},\n title = {In Honore Salvatoris~-- Vom Sinn und Unsinn der\n Patrozinienkunde},\n journaltitle = {Revue d'Histoire Eccl{\\'e}siastique},\n date = 2002,\n volume = 97,\n pages = {431--456, 791--823},\n langid = {german},\n indextitle = {In Honore Salvatoris},\n shorttitle = {In Honore Salvatoris},\n annotation = {A German article in a French journal. Apart from that, a\n typical \\texttt{article} entry. Note the \\texttt{indextitle}\n field},\n}\"#)" ---- -ROOT@0..616 - ENTRY@0..616 - TYPE@0..8 "@article" - L_DELIM@8..9 "{" - NAME@9..18 "angenendt" - COMMA@18..19 "," - WHITESPACE@19..24 "\n " - FIELD@24..59 - NAME@24..30 "author" - WHITESPACE@30..37 " " - EQ@37..38 "=" - WHITESPACE@38..39 " " - CURLY_GROUP@39..58 - L_CURLY@39..40 "{" - WORD@40..49 "Angenendt" - COMMA@49..50 "," - WHITESPACE@50..51 " " - WORD@51..57 "Arnold" - R_CURLY@57..58 "}" - COMMA@58..59 "," - WHITESPACE@59..64 "\n " - FIELD@64..166 - NAME@64..69 "title" - WHITESPACE@69..77 " " - EQ@77..78 "=" - WHITESPACE@78..79 " " - CURLY_GROUP@79..165 - L_CURLY@79..80 "{" - WORD@80..82 "In" - WHITESPACE@82..83 " " - WORD@83..89 "Honore" - WHITESPACE@89..90 " " - WORD@90..100 "Salvatoris" - NBSP@100..101 "~" - WORD@101..103 "--" - WHITESPACE@103..104 " " - WORD@104..107 "Vom" - WHITESPACE@107..108 " " - WORD@108..112 "Sinn" - WHITESPACE@112..113 " " - WORD@113..116 "und" - WHITESPACE@116..117 " " - WORD@117..123 "Unsinn" - WHITESPACE@123..124 " " - WORD@124..127 "der" - WHITESPACE@127..148 "\n " - WORD@148..164 "Patrozinienkunde" - R_CURLY@164..165 "}" - COMMA@165..166 "," - WHITESPACE@166..171 "\n " - FIELD@171..224 - NAME@171..183 "journaltitle" - WHITESPACE@183..184 " " - EQ@184..185 "=" - WHITESPACE@185..186 " " - CURLY_GROUP@186..223 - L_CURLY@186..187 "{" - WORD@187..192 "Revue" - WHITESPACE@192..193 " " - WORD@193..203 "d'Histoire" - WHITESPACE@203..204 " " - WORD@204..208 "Eccl" - CURLY_GROUP@208..213 - L_CURLY@208..209 "{" - ACCENT@209..212 - ACCENT_NAME@209..211 "\\'" - WORD@211..212 "e" - R_CURLY@212..213 "}" - WORD@213..222 "siastique" - R_CURLY@222..223 "}" - COMMA@223..224 "," - WHITESPACE@224..229 "\n " - FIELD@229..249 - NAME@229..233 "date" - WHITESPACE@233..242 " " - EQ@242..243 "=" - WHITESPACE@243..244 " " - LITERAL@244..248 - INTEGER@244..248 "2002" - COMMA@248..249 "," - WHITESPACE@249..254 "\n " - FIELD@254..272 - NAME@254..260 "volume" - WHITESPACE@260..267 " " - EQ@267..268 "=" - WHITESPACE@268..269 " " - LITERAL@269..271 - INTEGER@269..271 "97" - COMMA@271..272 "," - WHITESPACE@272..277 "\n " - FIELD@277..313 - NAME@277..282 "pages" - WHITESPACE@282..290 " " - EQ@290..291 "=" - WHITESPACE@291..292 " " - CURLY_GROUP@292..312 - L_CURLY@292..293 "{" - WORD@293..301 "431--456" - COMMA@301..302 "," - WHITESPACE@302..303 " " - WORD@303..311 "791--823" - R_CURLY@311..312 "}" - COMMA@312..313 "," - WHITESPACE@313..318 "\n " - FIELD@318..342 - NAME@318..324 "langid" - WHITESPACE@324..331 " " - EQ@331..332 "=" - WHITESPACE@332..333 " " - CURLY_GROUP@333..341 - L_CURLY@333..334 "{" - WORD@334..340 "german" - R_CURLY@340..341 "}" - COMMA@341..342 "," - WHITESPACE@342..347 "\n " - FIELD@347..385 - NAME@347..357 "indextitle" - WHITESPACE@357..360 " " - EQ@360..361 "=" - WHITESPACE@361..362 " " - CURLY_GROUP@362..384 - L_CURLY@362..363 "{" - WORD@363..365 "In" - WHITESPACE@365..366 " " - WORD@366..372 "Honore" - WHITESPACE@372..373 " " - WORD@373..383 "Salvatoris" - R_CURLY@383..384 "}" - COMMA@384..385 "," - WHITESPACE@385..390 "\n " - FIELD@390..428 - NAME@390..400 "shorttitle" - WHITESPACE@400..403 " " - EQ@403..404 "=" - WHITESPACE@404..405 " " - CURLY_GROUP@405..427 - L_CURLY@405..406 "{" - WORD@406..408 "In" - WHITESPACE@408..409 " " - WORD@409..415 "Honore" - WHITESPACE@415..416 " " - WORD@416..426 "Salvatoris" - R_CURLY@426..427 "}" - COMMA@427..428 "," - WHITESPACE@428..433 "\n " - FIELD@433..614 - NAME@433..443 "annotation" - WHITESPACE@443..446 " " - EQ@446..447 "=" - WHITESPACE@447..448 " " - CURLY_GROUP@448..613 - L_CURLY@448..449 "{" - WORD@449..450 "A" - WHITESPACE@450..451 " " - WORD@451..457 "German" - WHITESPACE@457..458 " " - WORD@458..465 "article" - WHITESPACE@465..466 " " - WORD@466..468 "in" - WHITESPACE@468..469 " " - WORD@469..470 "a" - WHITESPACE@470..471 " " - WORD@471..477 "French" - WHITESPACE@477..478 " " - WORD@478..486 "journal." - WHITESPACE@486..487 " " - WORD@487..492 "Apart" - WHITESPACE@492..493 " " - WORD@493..497 "from" - WHITESPACE@497..498 " " - WORD@498..502 "that" - COMMA@502..503 "," - WHITESPACE@503..504 " " - WORD@504..505 "a" - WHITESPACE@505..526 "\n " - WORD@526..533 "typical" - WHITESPACE@533..534 " " - COMMAND@534..541 - COMMAND_NAME@534..541 "\\texttt" - CURLY_GROUP@541..550 - L_CURLY@541..542 "{" - WORD@542..549 "article" - R_CURLY@549..550 "}" - WHITESPACE@550..551 " " - WORD@551..557 "entry." - WHITESPACE@557..558 " " - WORD@558..562 "Note" - WHITESPACE@562..563 " " - WORD@563..566 "the" - WHITESPACE@566..567 " " - COMMAND@567..574 - COMMAND_NAME@567..574 "\\texttt" - CURLY_GROUP@574..586 - L_CURLY@574..575 "{" - WORD@575..585 "indextitle" - R_CURLY@585..586 "}" - WHITESPACE@586..607 "\n " - WORD@607..612 "field" - R_CURLY@612..613 "}" - COMMA@613..614 "," - WHITESPACE@614..615 "\n" - R_DELIM@615..616 "}" - diff --git a/support/texlab/src/syntax/bibtex/snapshots/texlab__syntax__bibtex__tests__comment.snap b/support/texlab/src/syntax/bibtex/snapshots/texlab__syntax__bibtex__tests__comment.snap deleted file mode 100644 index 3267517c49..0000000000 --- a/support/texlab/src/syntax/bibtex/snapshots/texlab__syntax__bibtex__tests__comment.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: src/syntax/bibtex/tests.rs -assertion_line: 16 -expression: "setup(r#\"@comment{aksin,\n author = {Aks{\\i}n, {\\\"O}zge and T{\\\"u}rkmen, Hayati and Artok, Levent\n and {\\c{C}}etinkaya, Bekir and Ni, Chaoying and\n B{\\\"u}y{\\\"u}kg{\\\"u}ng{\\\"o}r, Orhan and {\\\"O}zkal, Erhan},\n title = {Effect of immobilization on catalytic characteristics of\n saturated {Pd-N}-heterocyclic carbenes in {Mizoroki-Heck}\n reactions},\n journaltitle = jomch,\n date = 2006,\n volume = 691,\n number = 13,\n pages = {3027-3036},\n indextitle = {Effect of immobilization on catalytic characteristics},\n}\"#)" ---- -ROOT@0..637 - TYPE@0..8 "@comment" - JUNK@8..637 "{aksin,\n author ..." - diff --git a/support/texlab/src/syntax/bibtex/snapshots/texlab__syntax__bibtex__tests__entry_colon.snap b/support/texlab/src/syntax/bibtex/snapshots/texlab__syntax__bibtex__tests__entry_colon.snap deleted file mode 100644 index bff11a8d5a..0000000000 --- a/support/texlab/src/syntax/bibtex/snapshots/texlab__syntax__bibtex__tests__entry_colon.snap +++ /dev/null @@ -1,51 +0,0 @@ ---- -source: src/syntax/bibtex/tests.rs -assertion_line: 36 -expression: "setup(r#\"@article{foo:2019,\n author = {Foo Bar},\n title = {Baz Qux},\n year = {2019},\n}\"#)" ---- -ROOT@0..86 - ENTRY@0..86 - TYPE@0..8 "@article" - L_DELIM@8..9 "{" - NAME@9..17 "foo:2019" - COMMA@17..18 "," - WHITESPACE@18..23 "\n " - FIELD@23..42 - NAME@23..29 "author" - WHITESPACE@29..30 " " - EQ@30..31 "=" - WHITESPACE@31..32 " " - CURLY_GROUP@32..41 - L_CURLY@32..33 "{" - WORD@33..36 "Foo" - WHITESPACE@36..37 " " - WORD@37..40 "Bar" - R_CURLY@40..41 "}" - COMMA@41..42 "," - WHITESPACE@42..47 "\n " - FIELD@47..65 - NAME@47..52 "title" - WHITESPACE@52..53 " " - EQ@53..54 "=" - WHITESPACE@54..55 " " - CURLY_GROUP@55..64 - L_CURLY@55..56 "{" - WORD@56..59 "Baz" - WHITESPACE@59..60 " " - WORD@60..63 "Qux" - R_CURLY@63..64 "}" - COMMA@64..65 "," - WHITESPACE@65..70 "\n " - FIELD@70..84 - NAME@70..74 "year" - WHITESPACE@74..75 " " - EQ@75..76 "=" - WHITESPACE@76..77 " " - CURLY_GROUP@77..83 - L_CURLY@77..78 "{" - INTEGER@78..82 "2019" - R_CURLY@82..83 "}" - COMMA@83..84 "," - WHITESPACE@84..85 "\n" - R_DELIM@85..86 "}" - diff --git a/support/texlab/src/syntax/bibtex/tests.rs b/support/texlab/src/syntax/bibtex/tests.rs deleted file mode 100644 index 8dce0e2df9..0000000000 --- a/support/texlab/src/syntax/bibtex/tests.rs +++ /dev/null @@ -1,126 +0,0 @@ -use insta::assert_debug_snapshot; - -use super::{parse, SyntaxNode}; - -fn setup(input: &str) -> SyntaxNode { - SyntaxNode::new_root(parse(input)) -} - -#[test] -fn test_preamble() { - assert_debug_snapshot!(setup(r#"@preamble{"Hello World!"}"#)); -} - -#[test] -fn test_comment() { - assert_debug_snapshot!(setup( - r#"@comment{aksin, - author = {Aks{\i}n, {\"O}zge and T{\"u}rkmen, Hayati and Artok, Levent - and {\c{C}}etinkaya, Bekir and Ni, Chaoying and - B{\"u}y{\"u}kg{\"u}ng{\"o}r, Orhan and {\"O}zkal, Erhan}, - title = {Effect of immobilization on catalytic characteristics of - saturated {Pd-N}-heterocyclic carbenes in {Mizoroki-Heck} - reactions}, - journaltitle = jomch, - date = 2006, - volume = 691, - number = 13, - pages = {3027-3036}, - indextitle = {Effect of immobilization on catalytic characteristics}, -}"# - )); -} - -#[test] -fn test_entry_colon() { - assert_debug_snapshot!(setup( - r#"@article{foo:2019, - author = {Foo Bar}, - title = {Baz Qux}, - year = {2019}, -}"# - )); -} - -#[test] -fn test_biblatex_examples_001() { - assert_debug_snapshot!(setup( - r#"@incollection{westfahl:space, - author = {Westfahl, Gary}, - title = {The True Frontier}, - subtitle = {Confronting and Avoiding the Realities of Space in {American} - Science Fiction Films}, - pages = {55-65}, - crossref = {westfahl:frontier}, - langid = {english}, - langidopts = {variant=american}, - indextitle = {True Frontier, The}, - annotation = {A cross-referenced article from a \texttt{collection}. This is - an \texttt{incollection} entry with a \texttt{crossref} - field. Note the \texttt{subtitle} and \texttt{indextitle} - fields}, -} - -% booktitle and booksubtitle are only needed for BibTeX's less sophisticated -% inheritance set-up to make sure westfahl:space shows correctly. -% With Biber they are not needed. -@collection{westfahl:frontier, - editor = {Westfahl, Gary}, - title = {Space and Beyond}, - date = 2000, - subtitle = {The Frontier Theme in Science Fiction}, - publisher = {Greenwood}, - location = {Westport, Conn. and London}, - langid = {english}, - langidopts = {variant=american}, - booktitle = {Space and Beyond}, - booksubtitle = {The Frontier Theme in Science Fiction}, - annotation = {This is a \texttt{collection} entry. Note the format of the - \texttt{location} field as well as the \texttt{subtitle} - field}, -}"# - )); -} - -#[test] -fn test_biblatex_examples_002() { - assert_debug_snapshot!(setup( - r#"@string{jomch = {J.~Organomet. Chem.}} - -@article{aksin, - author = {Aks{\i}n, {\"O}zge and T{\"u}rkmen, Hayati and Artok, Levent - and {\c{C}}etinkaya, Bekir and Ni, Chaoying and - B{\"u}y{\"u}kg{\"u}ng{\"o}r, Orhan and {\"O}zkal, Erhan}, - title = {Effect of immobilization on catalytic characteristics of - saturated {Pd-N}-heterocyclic carbenes in {Mizoroki-Heck} - reactions}, - journaltitle = jomch, - date = 2006, - volume = 691, - number = 13, - pages = {3027-3036}, - indextitle = {Effect of immobilization on catalytic characteristics}, -}"# - )); -} - -#[test] -fn test_biblatex_examples_003() { - assert_debug_snapshot!(setup( - r#"@article{angenendt, - author = {Angenendt, Arnold}, - title = {In Honore Salvatoris~-- Vom Sinn und Unsinn der - Patrozinienkunde}, - journaltitle = {Revue d'Histoire Eccl{\'e}siastique}, - date = 2002, - volume = 97, - pages = {431--456, 791--823}, - langid = {german}, - indextitle = {In Honore Salvatoris}, - shorttitle = {In Honore Salvatoris}, - annotation = {A German article in a French journal. Apart from that, a - typical \texttt{article} entry. Note the \texttt{indextitle} - field}, -}"# - )); -} diff --git a/support/texlab/src/syntax/build_log.rs b/support/texlab/src/syntax/build_log.rs deleted file mode 100644 index af03e51d11..0000000000 --- a/support/texlab/src/syntax/build_log.rs +++ /dev/null @@ -1,1332 +0,0 @@ -use std::{cmp::Ordering, path::PathBuf}; - -use once_cell::sync::Lazy; -use regex::{Match, Regex}; - -#[derive(Debug, PartialEq, Eq, Clone, Copy, PartialOrd, Ord, Hash)] -pub enum BuildErrorLevel { - Error, - Warning, -} - -#[derive(Debug, PartialEq, Eq, Clone, Hash)] -pub struct BuildError { - pub relative_path: PathBuf, - pub level: BuildErrorLevel, - pub message: String, - pub line: Option<u32>, -} - -const MAX_LINE_LENGTH: usize = 79; - -pub static PACKAGE_MESSAGE_REGEX: Lazy<Regex> = - Lazy::new(|| Regex::new("^\\([a-zA-Z_\\-]+\\)\\s*(?P<msg>.*)$").unwrap()); - -pub static FILE_REGEX: Lazy<Regex> = - Lazy::new(|| Regex::new("\\((?P<file>[^\r\n()]+\\.(tex|sty|cls))").unwrap()); - -pub static TEX_ERROR_REGEX: Lazy<Regex> = Lazy::new(|| { - Regex::new("(?m)^! ((?P<msg1>(.|\r|\n)*?)\r?\nl\\.(?P<line>\\d+)|(?P<msg2>[^\r\n]*))").unwrap() -}); - -pub static WARNING_REGEX: Lazy<Regex> = - Lazy::new(|| Regex::new("(LaTeX|Package [a-zA-Z_\\-]+) Warning: (?P<msg>[^\r\n]*)").unwrap()); - -pub static BAD_BOX_REGEX: Lazy<Regex> = Lazy::new(|| { - Regex::new("(?P<msg>(Ov|Und)erfull \\\\[hv]box[^\r\n]*lines? (?P<line>\\d+)[^\r\n]*)").unwrap() -}); - -#[derive(Debug, PartialEq, Eq, Clone, Hash)] -pub struct Parse { - pub errors: Vec<BuildError>, -} - -pub fn parse(log: &str) -> Parse { - let log = prepare_log(log); - let mut ranges: Vec<FileRange> = FILE_REGEX - .find_iter(&log) - .map(|result| FileRange::create(&log, result)) - .collect(); - ranges.sort(); - - let tex_errors = extract_matches(&log, &ranges, &TEX_ERROR_REGEX, BuildErrorLevel::Error); - let warnings = extract_matches(&log, &ranges, &WARNING_REGEX, BuildErrorLevel::Warning); - let bad_boxes = extract_matches(&log, &ranges, &BAD_BOX_REGEX, BuildErrorLevel::Warning); - - Parse { - errors: vec![tex_errors, warnings, bad_boxes].concat(), - } -} - -fn extract_matches( - log: &str, - ranges: &[FileRange], - regex: &Regex, - level: BuildErrorLevel, -) -> Vec<BuildError> { - let mut errors = Vec::new(); - for result in regex.find_iter(log) { - let captures = regex.captures(&log[result.start()..result.end()]).unwrap(); - let message = captures - .name("msg") - .or_else(|| captures.name("msg1")) - .or_else(|| captures.name("msg2")) - .unwrap() - .as_str() - .lines() - .next() - .unwrap_or_default() - .to_owned(); - - if let Some(range) = ranges.iter().find(|range| range.contains(result.start())) { - let line = captures - .name("line") - .map(|result| result.as_str().parse::<u32>().unwrap() - 1); - - errors.push(BuildError { - relative_path: range.path.clone(), - level, - message, - line, - }); - } - } - errors -} - -fn prepare_log(log: &str) -> String { - let mut old_lines = log.lines(); - let mut new_lines: Vec<String> = Vec::new(); - while let Some(line) = old_lines.next() { - if PACKAGE_MESSAGE_REGEX.is_match(line) { - let captures = PACKAGE_MESSAGE_REGEX.captures(line).unwrap(); - if let Some(last_line) = new_lines.last_mut() { - last_line.push(' '); - last_line.push_str(captures.name("msg").unwrap().as_str()); - } - } else if line.ends_with("...") { - let mut new_line = line[line.len() - 3..].to_owned(); - if let Some(old_line) = old_lines.next() { - new_line.push_str(old_line); - } - new_lines.push(new_line); - } else if line.chars().count() == MAX_LINE_LENGTH { - let mut new_line = String::new(); - new_line.push_str(line); - if let Some(old_line) = old_lines.next() { - new_line.push_str(old_line); - } - new_lines.push(new_line); - } else { - new_lines.push(line.to_owned()); - } - } - new_lines.join("\n") -} - -#[derive(Debug, PartialEq, Eq, Clone)] -struct FileRange { - pub path: PathBuf, - pub start: usize, - pub end: usize, -} - -impl FileRange { - fn create(log: &str, result: Match) -> Self { - let mut balance = 1; - let mut end = result.start() + 1; - let chars = (&log[result.start() + 1..]).chars(); - for c in chars { - if balance <= 0 { - break; - } - - if c == '(' { - balance += 1; - } else if c == ')' { - balance -= 1; - } - end += c.len_utf8(); - } - - let captures = FILE_REGEX.captures(result.as_str()).unwrap(); - let path = PathBuf::from(captures.name("file").unwrap().as_str()); - Self { - path, - start: result.start(), - end, - } - } - - fn len(&self) -> usize { - self.end - self.start + 1 - } - - fn contains(&self, index: usize) -> bool { - index >= self.start && index <= self.end - } -} - -impl Ord for FileRange { - fn cmp(&self, other: &Self) -> Ordering { - self.len().cmp(&other.len()) - } -} - -impl PartialOrd for FileRange { - fn partial_cmp(&self, other: &Self) -> Option<Ordering> { - Some(self.cmp(other)) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use insta::assert_debug_snapshot; - - #[test] - fn parse_001() { - let log = r#" -This is pdfTeX, Version 3.14159265-2.6-1.40.18 (TeX Live 2017/W32TeX) (preloaded format=pdflatex 2018.3.30) 26 DEC 2018 16:50 -entering extended mode -restricted \write18 enabled. -%&-line parsing enabled. -**./parent.tex -(./parent.tex -LaTeX2e <2017-04-15> -Babel <3.10> and hyphenation patterns for 84 language(s) loaded. -(/TexLive/texmf-dist/tex/latex/base/article.cls -Document Class: article 2014/09/29 v1.4h Standard LaTeX document class -(/TexLive/texmf-dist/tex/latex/base/size10.clo -File: size10.clo 2014/09/29 v1.4h Standard LaTeX file (size option) -) -\c@part=\count79 -\c@section=\count80 -\c@subsection=\count81 -\c@subsubsection=\count82 -\c@paragraph=\count83 -\c@subparagraph=\count84 -\c@figure=\count85 -\c@table=\count86 -\abovecaptionskip=\skip41 -\belowcaptionskip=\skip42 -\bibindent=\dimen102 -) -(/TexLive/texmf-dist/tex/latex/multirow/bigstrut.sty -Package: bigstrut 2016/11/25 v2.2 Provide larger struts in tabulars -\bigstrutjot=\dimen103 -) -(/TexLive/texmf-dist/tex/latex/multirow/multirow.sty -Package: multirow 2016/11/25 v2.2 Span multiple rows of a table -\multirow@colwidth=\skip43 -\multirow@cntb=\count87 -\multirow@dima=\skip44 -) (./parent.aux) -\openout1 = `parent.aux'. - -LaTeX Font Info: Checking defaults for OML/cmm/m/it on input line 6. -LaTeX Font Info: ... okay on input line 6. -LaTeX Font Info: Checking defaults for T1/cmr/m/n on input line 6. -LaTeX Font Info: ... okay on input line 6. -LaTeX Font Info: Checking defaults for OT1/cmr/m/n on input line 6. -LaTeX Font Info: ... okay on input line 6. -LaTeX Font Info: Checking defaults for OMS/cmsy/m/n on input line 6. -LaTeX Font Info: ... okay on input line 6. -LaTeX Font Info: Checking defaults for OMX/cmex/m/n on input line 6. -LaTeX Font Info: ... okay on input line 6. -LaTeX Font Info: Checking defaults for U/cmr/m/n on input line 6. -LaTeX Font Info: ... okay on input line 6. - -Overfull \hbox (200.00162pt too wide) in paragraph at lines 8--9 -[]\OT1/cmr/m/n/10 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -[] - -LaTeX Font Info: External font `cmex10' loaded for size -(Font) <7> on input line 11. -LaTeX Font Info: External font `cmex10' loaded for size -(Font) <5> on input line 11. - -Overfull \vbox (3.19998pt too high) detected at line 23 -[] - -[1 - -{/TexLive/texmf-var/fonts/map/pdftex/updmap/pdftex.map}] (./parent.aux) ) -Here is how much of TeX's memory you used: -265 strings out of 492995 -3121 string characters out of 6138727 -55074 words of memory out of 5000000 -3896 multiletter control sequences out of 15000+600000 -3640 words of font info for 14 fonts, out of 8000000 for 9000 -1141 hyphenation exceptions out of 8191 -23i,20n,20p,124b,282s stack positions out of 5000i,500n,10000p,200000b,80000s -</ -TexLive/texmf-dist/fonts/type1/public/amsfonts/cm/cmr10.pfb></TexLive/texmf-d -ist/fonts/type1/public/amsfonts/cm/cmr7.pfb> -Output written on parent.pdf (1 page, 17505 bytes). -PDF statistics: -16 PDF objects out of 1000 (max. 8388607) -10 compressed objects within 1 object stream -0 named destinations out of 1000 (max. 500000) -1 words of extra memory for PDF output out of 10000 (max. 10000000)"#; - - assert_eq!( - parse(log).errors, - vec![ - BuildError { - relative_path: "./parent.tex".into(), - level: BuildErrorLevel::Warning, - message: "Overfull \\hbox (200.00162pt too wide) in paragraph at lines 8--9" - .into(), - line: Some(7), - }, - BuildError { - relative_path: "./parent.tex".into(), - level: BuildErrorLevel::Warning, - message: "Overfull \\vbox (3.19998pt too high) detected at line 23".into(), - line: Some(22), - } - ] - ); - } - - #[test] - fn parse_002() { - let log = r#" -This is pdfTeX, Version 3.14159265-2.6-1.40.18 (TeX Live 2017/W32TeX) (preloaded format=pdflatex 2018.3.30) 26 DEC 2018 16:52 -entering extended mode -restricted \write18 enabled. -%&-line parsing enabled. -**./parent.tex -(./parent.tex -LaTeX2e <2017-04-15> -Babel <3.10> and hyphenation patterns for 84 language(s) loaded. -(/TexLive/texmf-dist/tex/latex/base/article.cls -Document Class: article 2014/09/29 v1.4h Standard LaTeX document class -(/TexLive/texmf-dist/tex/latex/base/size10.clo -File: size10.clo 2014/09/29 v1.4h Standard LaTeX file (size option) -) -\c@part=\count79 -\c@section=\count80 -\c@subsection=\count81 -\c@subsubsection=\count82 -\c@paragraph=\count83 -\c@subparagraph=\count84 -\c@figure=\count85 -\c@table=\count86 -\abovecaptionskip=\skip41 -\belowcaptionskip=\skip42 -\bibindent=\dimen102 -) (./parent.aux (./child.aux)) -\openout1 = `parent.aux'. - -LaTeX Font Info: Checking defaults for OML/cmm/m/it on input line 4. -LaTeX Font Info: ... okay on input line 4. -LaTeX Font Info: Checking defaults for T1/cmr/m/n on input line 4. -LaTeX Font Info: ... okay on input line 4. -LaTeX Font Info: Checking defaults for OT1/cmr/m/n on input line 4. -LaTeX Font Info: ... okay on input line 4. -LaTeX Font Info: Checking defaults for OMS/cmsy/m/n on input line 4. -LaTeX Font Info: ... okay on input line 4. -LaTeX Font Info: Checking defaults for OMX/cmex/m/n on input line 4. -LaTeX Font Info: ... okay on input line 4. -LaTeX Font Info: Checking defaults for U/cmr/m/n on input line 4. -LaTeX Font Info: ... okay on input line 4. -(./child.tex -! Undefined control sequence. -l.1 \foo - -The control sequence at the end of the top line -of your error message was never \def'ed. If you have -misspelled it (e.g., `\hobx'), type `I' and the correct -spelling (e.g., `I\hbox'). Otherwise just continue, -and I'll forget about whatever was undefined. - -) (./parent.aux) ) -Here is how much of TeX's memory you used: -205 strings out of 492995 -2149 string characters out of 6138727 -54074 words of memory out of 5000000 -3841 multiletter control sequences out of 15000+600000 -3640 words of font info for 14 fonts, out of 8000000 for 9000 -1141 hyphenation exceptions out of 8191 -23i,1n,17p,116b,36s stack positions out of 5000i,500n,10000p,200000b,80000s - -No pages of output. -PDF statistics: -0 PDF objects out of 1000 (max. 8388607) -0 named destinations out of 1000 (max. 500000) -1 words of extra memory for PDF output out of 10000 (max. 10000000)"#; - - assert_eq!( - parse(log).errors, - vec![BuildError { - relative_path: "./child.tex".into(), - level: BuildErrorLevel::Error, - message: "Undefined control sequence.".into(), - line: Some(0) - }] - ); - } - - #[test] - fn parse_003() { - let log = r#" -This is pdfTeX, Version 3.14159265-2.6-1.40.18 (TeX Live 2017/W32TeX) (preloaded format=pdflatex 2018.3.30) 26 DEC 2018 16:51 -entering extended mode -restricted \write18 enabled. -%&-line parsing enabled. -**./parent.tex -(./parent.tex -LaTeX2e <2017-04-15> -Babel <3.10> and hyphenation patterns for 84 language(s) loaded. -(/TexLive/texmf-dist/tex/latex/base/article.cls -Document Class: article 2014/09/29 v1.4h Standard LaTeX document class -(/TexLive/texmf-dist/tex/latex/base/size10.clo -File: size10.clo 2014/09/29 v1.4h Standard LaTeX file (size option) -) -\c@part=\count79 -\c@section=\count80 -\c@subsection=\count81 -\c@subsubsection=\count82 -\c@paragraph=\count83 -\c@subparagraph=\count84 -\c@figure=\count85 -\c@table=\count86 -\abovecaptionskip=\skip41 -\belowcaptionskip=\skip42 -\bibindent=\dimen102 -) (./parent.aux) -\openout1 = `parent.aux'. - -LaTeX Font Info: Checking defaults for OML/cmm/m/it on input line 4. -LaTeX Font Info: ... okay on input line 4. -LaTeX Font Info: Checking defaults for T1/cmr/m/n on input line 4. -LaTeX Font Info: ... okay on input line 4. -LaTeX Font Info: Checking defaults for OT1/cmr/m/n on input line 4. -LaTeX Font Info: ... okay on input line 4. -LaTeX Font Info: Checking defaults for OMS/cmsy/m/n on input line 4. -LaTeX Font Info: ... okay on input line 4. -LaTeX Font Info: Checking defaults for OMX/cmex/m/n on input line 4. -LaTeX Font Info: ... okay on input line 4. -LaTeX Font Info: Checking defaults for U/cmr/m/n on input line 4. -LaTeX Font Info: ... okay on input line 4. - -LaTeX Warning: Citation `foo' on page 1 undefined on input line 6. - -[1 - -{/TexLive/texmf-var/fonts/map/pdftex/updmap/pdftex.map}] (./parent.aux) - -LaTeX Warning: There were undefined references. - -) -Here is how much of TeX's memory you used: -204 strings out of 492995 -2142 string characters out of 6138727 -54074 words of memory out of 5000000 -3842 multiletter control sequences out of 15000+600000 -3948 words of font info for 15 fonts, out of 8000000 for 9000 -1141 hyphenation exceptions out of 8191 -23i,4n,21p,116b,107s stack positions out of 5000i,500n,10000p,200000b,80000s -</TexLive/texmf-dist/fonts/type1/public/amsfonts/cm/cmbx10.pfb></TexLive/ -texmf-dist/fonts/type1/public/amsfonts/cm/cmr10.pfb> -Output written on parent.pdf (1 page, 17339 bytes). -PDF statistics: -16 PDF objects out of 1000 (max. 8388607) -10 compressed objects within 1 object stream -0 named destinations out of 1000 (max. 500000) -1 words of extra memory for PDF output out of 10000 (max. 10000000)"#; - - assert_eq!( - parse(log).errors, - vec![ - BuildError { - relative_path: "./parent.tex".into(), - level: BuildErrorLevel::Warning, - message: "Citation `foo' on page 1 undefined on input line 6.".into(), - line: None - }, - BuildError { - relative_path: "./parent.tex".into(), - level: BuildErrorLevel::Warning, - message: "There were undefined references.".into(), - line: None, - } - ] - ); - } - - #[test] - fn parse_004() { - let log = r#" -This is pdfTeX, Version 3.14159265-2.6-1.40.18 (TeX Live 2017/W32TeX) (preloaded format=pdflatex 2018.3.30) 26 DEC 2018 16:40 -entering extended mode -restricted \write18 enabled. -%&-line parsing enabled. -**./parent.tex -(./parent.tex -LaTeX2e <2017-04-15> -Babel <3.10> and hyphenation patterns for 84 language(s) loaded. -(/TexLive/texmf-dist/tex/latex/base/article.cls -Document Class: article 2014/09/29 v1.4h Standard LaTeX document class -(/TexLive/texmf-dist/tex/latex/base/size10.clo -File: size10.clo 2014/09/29 v1.4h Standard LaTeX file (size option) -) -\c@part=\count79 -\c@section=\count80 -\c@subsection=\count81 -\c@subsubsection=\count82 -\c@paragraph=\count83 -\c@subparagraph=\count84 -\c@figure=\count85 -\c@table=\count86 -\abovecaptionskip=\skip41 -\belowcaptionskip=\skip42 -\bibindent=\dimen102 -) -(/TexLive/texmf-dist/tex/generic/babel/babel.sty -Package: babel 2017/05/19 3.10 The Babel package - -! Package babel Error: Unknown option `foo'. Either you misspelled it -(babel) or the language definition file foo.ldf was not found. - -See the babel package documentation for explanation. -Type H <return> for immediate help. -... - -l.393 \ProcessOptions* - -Valid options are: shorthands=, KeepShorthandsActive, -activeacute, activegrave, noconfigs, safe=, main=, math= -headfoot=, strings=, config=, hyphenmap=, or a language name. - -! Package babel Error: You haven't specified a language option. - -See the babel package documentation for explanation. -Type H <return> for immediate help. -... - -l.426 ...ry to proceed from here, type x to quit.} - -You need to specify a language, either as a global option -or as an optional argument to the \usepackage command; -You shouldn't try to proceed from here, type x to quit. - -) (./parent.aux) -\openout1 = `parent.aux'. - -LaTeX Font Info: Checking defaults for OML/cmm/m/it on input line 5. -LaTeX Font Info: ... okay on input line 5. -LaTeX Font Info: Checking defaults for T1/cmr/m/n on input line 5. -LaTeX Font Info: ... okay on input line 5. -LaTeX Font Info: Checking defaults for OT1/cmr/m/n on input line 5. -LaTeX Font Info: ... okay on input line 5. -LaTeX Font Info: Checking defaults for OMS/cmsy/m/n on input line 5. -LaTeX Font Info: ... okay on input line 5. -LaTeX Font Info: Checking defaults for OMX/cmex/m/n on input line 5. -LaTeX Font Info: ... okay on input line 5. -LaTeX Font Info: Checking defaults for U/cmr/m/n on input line 5. -LaTeX Font Info: ... okay on input line 5. -(./parent.aux) ) -Here is how much of TeX's memory you used: -304 strings out of 492995 -3421 string characters out of 6138727 -56035 words of memory out of 5000000 -3938 multiletter control sequences out of 15000+600000 -3640 words of font info for 14 fonts, out of 8000000 for 9000 -1141 hyphenation exceptions out of 8191 -23i,1n,17p,116b,36s stack positions out of 5000i,500n,10000p,200000b,80000s - -No pages of output. -PDF statistics: -0 PDF objects out of 1000 (max. 8388607) -0 named destinations out of 1000 (max. 500000) -1 words of extra memory for PDF output out of 10000 (max. 10000000)"#; - - assert_eq!( - parse(log).errors, - vec![ - BuildError { - relative_path: "/TexLive/texmf-dist/tex/generic/babel/babel.sty".into(), - level: BuildErrorLevel::Error, - message: "Package babel Error: Unknown option `foo'. Either you misspelled it or the language definition file foo.ldf was not found.".into(), - line: Some(392) - }, - BuildError { - relative_path: "/TexLive/texmf-dist/tex/generic/babel/babel.sty".into(), - level: BuildErrorLevel::Error, - message: "Package babel Error: You haven't specified a language option.".into(), - line: Some(425) - } - ] - ); - } - - #[test] - fn parse_005() { - let log = r#" -This is pdfTeX, Version 3.14159265-2.6-1.40.18 (TeX Live 2017/W32TeX) (preloaded format=pdflatex 2018.3.30) 26 DEC 2018 16:45 -entering extended mode -restricted \write18 enabled. -%&-line parsing enabled. -**./parent.tex -(./parent.tex -LaTeX2e <2017-04-15> -Babel <3.10> and hyphenation patterns for 84 language(s) loaded. -(/TexLive/texmf-dist/tex/latex/base/article.cls -Document Class: article 2014/09/29 v1.4h Standard LaTeX document class -(/TexLive/texmf-dist/tex/latex/base/size10.clo -File: size10.clo 2014/09/29 v1.4h Standard LaTeX file (size option) -) -\c@part=\count79 -\c@section=\count80 -\c@subsection=\count81 -\c@subsubsection=\count82 -\c@paragraph=\count83 -\c@subparagraph=\count84 -\c@figure=\count85 -\c@table=\count86 -\abovecaptionskip=\skip41 -\belowcaptionskip=\skip42 -\bibindent=\dimen102 -) -(/TexLive/texmf-dist/tex/generic/babel/babel.sty -Package: babel 2017/05/19 3.10 The Babel package - -(/TexLive/texmf-dist/tex/generic/babel-spanish/spanish.ldf -Language: spanish.ldf 2016/03/03 v5.0p Spanish support from the babel system - -(/TexLive/texmf-dist/tex/generic/babel/babel.def -File: babel.def 2017/05/19 3.10 Babel common definitions -\babel@savecnt=\count87 -\U@D=\dimen103 -) -\es@quottoks=\toks14 -\es@quotdepth=\count88 -Package babel Info: Making " an active character on input line 561. -Package babel Info: Making . an active character on input line 662. -Package babel Info: Making < an active character on input line 707. -Package babel Info: Making > an active character on input line 707. -)) -(/TexLive/texmf-dist/tex/latex/biblatex/biblatex.sty -Package: biblatex 2016/12/05 v3.7 programmable bibliographies (PK/JW/AB) - -(/TexLive/texmf-dist/tex/generic/oberdiek/pdftexcmds.sty -Package: pdftexcmds 2017/03/19 v0.25 Utility functions of pdfTeX for LuaTeX (HO -) - -(/TexLive/texmf-dist/tex/generic/oberdiek/infwarerr.sty -Package: infwarerr 2016/05/16 v1.4 Providing info/warning/error messages (HO) -) -(/TexLive/texmf-dist/tex/generic/oberdiek/ifluatex.sty -Package: ifluatex 2016/05/16 v1.4 Provides the ifluatex switch (HO) -Package ifluatex Info: LuaTeX not detected. -) -(/TexLive/texmf-dist/tex/generic/oberdiek/ltxcmds.sty -Package: ltxcmds 2016/05/16 v1.23 LaTeX kernel commands for general use (HO) -) -(/TexLive/texmf-dist/tex/generic/oberdiek/ifpdf.sty -Package: ifpdf 2017/03/15 v3.2 Provides the ifpdf switch -) -Package pdftexcmds Info: LuaTeX not detected. -Package pdftexcmds Info: \pdf@primitive is available. -Package pdftexcmds Info: \pdf@ifprimitive is available. -Package pdftexcmds Info: \pdfdraftmode found. -) -(/TexLive/texmf-dist/tex/latex/etoolbox/etoolbox.sty -Package: etoolbox 2017/01/02 v2.4 e-TeX tools for LaTeX (JAW) -\etb@tempcnta=\count89 -) -(/TexLive/texmf-dist/tex/latex/graphics/keyval.sty -Package: keyval 2014/10/28 v1.15 key=value parser (DPC) -\KV@toks@=\toks15 -) -(/TexLive/texmf-dist/tex/latex/oberdiek/kvoptions.sty -Package: kvoptions 2016/05/16 v3.12 Key value format for package options (HO) - -(/TexLive/texmf-dist/tex/generic/oberdiek/kvsetkeys.sty -Package: kvsetkeys 2016/05/16 v1.17 Key value parser (HO) - -(/TexLive/texmf-dist/tex/generic/oberdiek/etexcmds.sty -Package: etexcmds 2016/05/16 v1.6 Avoid name clashes with e-TeX commands (HO) -Package etexcmds Info: Could not find \expanded. -(etexcmds) That can mean that you are not using pdfTeX 1.50 or -(etexcmds) that some package has redefined \expanded. -(etexcmds) In the latter case, load this package earlier. -))) -(/TexLive/texmf-dist/tex/latex/logreq/logreq.sty -Package: logreq 2010/08/04 v1.0 xml request logger -\lrq@indent=\count90 - -(/TexLive/texmf-dist/tex/latex/logreq/logreq.def -File: logreq.def 2010/08/04 v1.0 logreq spec v1.0 -)) -(/TexLive/texmf-dist/tex/latex/base/ifthen.sty -Package: ifthen 2014/09/29 v1.1c Standard LaTeX ifthen package (DPC) -) -(/TexLive/texmf-dist/tex/latex/url/url.sty -\Urlmuskip=\muskip10 -Package: url 2013/09/16 ver 3.4 Verb mode for urls, etc. -) -(/TexLive/texmf-dist/tex/generic/xstring/xstring.sty -(/TexLive/texmf-dist/tex/generic/xstring/xstring.tex -\@xs@message=\write3 -\integerpart=\count91 -\decimalpart=\count92 -) -Package: xstring 2013/10/13 v1.7c String manipulations (C Tellechea) -) -\c@tabx@nest=\count93 -\c@listtotal=\count94 -\c@listcount=\count95 -\c@liststart=\count96 -\c@liststop=\count97 -\c@citecount=\count98 -\c@citetotal=\count99 -\c@multicitecount=\count100 -\c@multicitetotal=\count101 -\c@instcount=\count102 -\c@maxnames=\count103 -\c@minnames=\count104 -\c@maxitems=\count105 -\c@minitems=\count106 -\c@citecounter=\count107 -\c@savedcitecounter=\count108 -\c@uniquelist=\count109 -\c@uniquename=\count110 -\c@refsection=\count111 -\c@refsegment=\count112 -\c@maxextratitle=\count113 -\c@maxextratitleyear=\count114 -\c@maxextrayear=\count115 -\c@maxextraalpha=\count116 -\c@abbrvpenalty=\count117 -\c@highnamepenalty=\count118 -\c@lownamepenalty=\count119 -\c@maxparens=\count120 -\c@parenlevel=\count121 -\blx@tempcnta=\count122 -\blx@tempcntb=\count123 -\blx@tempcntc=\count124 -\blx@maxsection=\count125 -\blx@maxsegment@0=\count126 -\blx@notetype=\count127 -\blx@parenlevel@text=\count128 -\blx@parenlevel@foot=\count129 -\blx@sectionciteorder@0=\count130 -\labelnumberwidth=\skip43 -\labelalphawidth=\skip44 -\biblabelsep=\skip45 -\bibitemsep=\skip46 -\bibnamesep=\skip47 -\bibinitsep=\skip48 -\bibparsep=\skip49 -\bibhang=\skip50 -\blx@bcfin=\read1 -\blx@bcfout=\write4 -\c@mincomprange=\count131 -\c@maxcomprange=\count132 -\c@mincompwidth=\count133 -Package biblatex Info: Trying to load biblatex default data model... -Package biblatex Info: ... file 'blx-dm.def' found. - -(/TexLive/texmf-dist/tex/latex/biblatex/blx-dm.def) -Package biblatex Info: Trying to load biblatex style data model... -Package biblatex Info: ... file 'ieee.dbx' not found. -Package biblatex Info: Trying to load biblatex custom data model... -Package biblatex Info: ... file 'biblatex-dm.cfg' not found. -\c@afterword=\count134 -\c@savedafterword=\count135 -\c@annotator=\count136 -\c@savedannotator=\count137 -\c@author=\count138 -\c@savedauthor=\count139 -\c@bookauthor=\count140 -\c@savedbookauthor=\count141 -\c@commentator=\count142 -\c@savedcommentator=\count143 -\c@editor=\count144 -\c@savededitor=\count145 -\c@editora=\count146 -\c@savededitora=\count147 -\c@editorb=\count148 -\c@savededitorb=\count149 -\c@editorc=\count150 -\c@savededitorc=\count151 -\c@foreword=\count152 -\c@savedforeword=\count153 -\c@holder=\count154 -\c@savedholder=\count155 -\c@introduction=\count156 -\c@savedintroduction=\count157 -\c@namea=\count158 -\c@savednamea=\count159 -\c@nameb=\count160 -\c@savednameb=\count161 -\c@namec=\count162 -\c@savednamec=\count163 -\c@translator=\count164 -\c@savedtranslator=\count165 -\c@shortauthor=\count166 -\c@savedshortauthor=\count167 -\c@shorteditor=\count168 -\c@savedshorteditor=\count169 -\c@labelname=\count170 -\c@savedlabelname=\count171 -\c@institution=\count172 -\c@savedinstitution=\count173 -\c@lista=\count174 -\c@savedlista=\count175 -\c@listb=\count176 -\c@savedlistb=\count177 -\c@listc=\count178 -\c@savedlistc=\count179 -\c@listd=\count180 -\c@savedlistd=\count181 -\c@liste=\count182 -\c@savedliste=\count183 -\c@listf=\count184 -\c@savedlistf=\count185 -\c@location=\count186 -\c@savedlocation=\count187 -\c@organization=\count188 -\c@savedorganization=\count189 -\c@origlocation=\count190 -\c@savedoriglocation=\count191 -\c@origpublisher=\count192 -\c@savedorigpublisher=\count193 -\c@publisher=\count194 -\c@savedpublisher=\count195 -\c@language=\count196 -\c@savedlanguage=\count197 -\c@pageref=\count198 -\c@savedpageref=\count199 -\shorthandwidth=\skip51 -\shortjournalwidth=\skip52 -\shortserieswidth=\skip53 -\shorttitlewidth=\skip54 -\shortauthorwidth=\skip55 -\shorteditorwidth=\skip56 -Package biblatex Info: Trying to load compatibility code... -Package biblatex Info: ... file 'blx-compat.def' found. - -(/TexLive/texmf-dist/tex/latex/biblatex/blx-compat.def -File: blx-compat.def 2016/12/05 v3.7 biblatex compatibility (PK/JW/AB) -) -Package biblatex Info: Trying to load generic definitions... -Package biblatex Info: ... file 'biblatex.def' found. - -(/TexLive/texmf-dist/tex/latex/biblatex/biblatex.def -File: biblatex.def 2016/12/05 v3.7 biblatex compatibility (PK/JW/AB) -\c@textcitecount=\count266 -\c@textcitetotal=\count267 -\c@textcitemaxnames=\count268 -\c@biburlnumpenalty=\count269 -\c@biburlucpenalty=\count270 -\c@biburllcpenalty=\count271 -\c@smartand=\count272 -) -Package biblatex Info: Trying to load bibliography style 'ieee'... -Package biblatex Info: ... file 'ieee.bbx' found. - -(/TexLive/texmf-dist/tex/latex/biblatex-ieee/ieee.bbx -File: ieee.bbx 2017/03/27 v1.2d biblatex bibliography style -Package biblatex Info: Trying to load bibliography style 'numeric-comp'... -Package biblatex Info: ... file 'numeric-comp.bbx' found. - -(/TexLive/texmf-dist/tex/latex/biblatex/bbx/numeric-comp.bbx -File: numeric-comp.bbx 2016/12/05 v3.7 biblatex bibliography style (PK/JW/AB) -Package biblatex Info: Trying to load bibliography style 'numeric'... -Package biblatex Info: ... file 'numeric.bbx' found. - -(/TexLive/texmf-dist/tex/latex/biblatex/bbx/numeric.bbx -File: numeric.bbx 2016/12/05 v3.7 biblatex bibliography style (PK/JW/AB) -Package biblatex Info: Trying to load bibliography style 'standard'... -Package biblatex Info: ... file 'standard.bbx' found. - -(/TexLive/texmf-dist/tex/latex/biblatex/bbx/standard.bbx -File: standard.bbx 2016/12/05 v3.7 biblatex bibliography style (PK/JW/AB) -\c@bbx:relatedcount=\count273 -\c@bbx:relatedtotal=\count274 -)))) -Package biblatex Info: Trying to load citation style 'ieee'... -Package biblatex Info: ... file 'ieee.cbx' found. - -(/TexLive/texmf-dist/tex/latex/biblatex-ieee/ieee.cbx -File: ieee.cbx 2017/03/27 v1.2d biblatex citation style -Package biblatex Info: Trying to load citation style 'numeric-comp'... -Package biblatex Info: ... file 'numeric-comp.cbx' found. - -(/TexLive/texmf-dist/tex/latex/biblatex/cbx/numeric-comp.cbx -File: numeric-comp.cbx 2016/12/05 v3.7 biblatex citation style (PK/JW/AB) -\c@cbx@tempcnta=\count275 -\c@cbx@tempcntb=\count276 -Package biblatex Info: Redefining '\cite'. -Package biblatex Info: Redefining '\parencite'. -Package biblatex Info: Redefining '\footcite'. -Package biblatex Info: Redefining '\footcitetext'. -Package biblatex Info: Redefining '\smartcite'. -Package biblatex Info: Redefining '\supercite'. -Package biblatex Info: Redefining '\textcite'. -Package biblatex Info: Redefining '\textcites'. -Package biblatex Info: Redefining '\cites'. -Package biblatex Info: Redefining '\parencites'. -Package biblatex Info: Redefining '\smartcites'. -) -Package biblatex Info: Redefining '\cite'. -Package biblatex Info: Redefining '\cites'. -) -Package biblatex Info: Trying to load configuration file... -Package biblatex Info: ... file 'biblatex.cfg' found. - -(/TexLive/texmf-dist/tex/latex/biblatex/biblatex.cfg -File: biblatex.cfg -)) -Package biblatex Info: Trying to load language 'spanish'... -Package biblatex Info: ... file 'spanish.lbx' found. - -(/TexLive/texmf-dist/tex/latex/biblatex/lbx/spanish.lbx -File: spanish.lbx 2016/12/05 v3.7 biblatex localization (PK/JW/AB) -) - -Package biblatex Warning: 'babel/polyglossia' detected but 'csquotes' missing. -(biblatex) Loading 'csquotes' recommended. - -\@quotelevel=\count277 -\@quotereset=\count278 -(./parent.aux) -\openout1 = `parent.aux'. - -LaTeX Font Info: Checking defaults for OML/cmm/m/it on input line 6. -LaTeX Font Info: ... okay on input line 6. -LaTeX Font Info: Checking defaults for T1/cmr/m/n on input line 6. -LaTeX Font Info: ... okay on input line 6. -LaTeX Font Info: Checking defaults for OT1/cmr/m/n on input line 6. -LaTeX Font Info: ... okay on input line 6. -LaTeX Font Info: Checking defaults for OMS/cmsy/m/n on input line 6. -LaTeX Font Info: ... okay on input line 6. -LaTeX Font Info: Checking defaults for OMX/cmex/m/n on input line 6. -LaTeX Font Info: ... okay on input line 6. -LaTeX Font Info: Checking defaults for U/cmr/m/n on input line 6. -LaTeX Font Info: ... okay on input line 6. -LaTeX Info: Redefining \sptext on input line 6. -LaTeX Info: Redefining \. on input line 6. -LaTeX Info: Redefining \% on input line 6. -Package biblatex Info: No input encoding detected. -(biblatex) Assuming 'ascii'. -Package biblatex Info: Automatic encoding selection. -(biblatex) Assuming data encoding 'ascii'. -\openout4 = `parent.bcf'. - -Package biblatex Info: Trying to load bibliographic data... -Package biblatex Info: ... file 'parent.bbl' not found. - -No file parent.bbl. -Package biblatex Info: Reference section=0 on input line 6. -Package biblatex Info: Reference segment=0 on input line 6. -(./parent.aux) - -LaTeX Warning: There were undefined references. - -Package biblatex Warning: Please (re)run Biber on the file: -(biblatex) parent -(biblatex) and rerun LaTeX afterwards. - -Package logreq Info: Writing requests to 'parent.run.xml'. -\openout1 = `parent.run.xml'. - -) -Here is how much of TeX's memory you used: -7717 strings out of 492995 -133301 string characters out of 6138727 -557258 words of memory out of 5000000 -11248 multiletter control sequences out of 15000+600000 -3640 words of font info for 14 fonts, out of 8000000 for 9000 -1141 hyphenation exceptions out of 8191 -35i,1n,30p,856b,700s stack positions out of 5000i,500n,10000p,200000b,80000s - -No pages of output. -PDF statistics: -0 PDF objects out of 1000 (max. 8388607) -0 named destinations out of 1000 (max. 500000) -1 words of extra memory for PDF output out of 10000 (max. 10000000)"#; - - assert_eq!( - parse(log).errors, - vec![ - BuildError { - relative_path: "./parent.tex".into(), - level: BuildErrorLevel::Warning, - message: "'babel/polyglossia' detected but 'csquotes' missing. Loading 'csquotes' recommended.".into(), - line: None - }, - BuildError { - relative_path: "./parent.tex".into(), - level: BuildErrorLevel::Warning, - message: "There were undefined references.".into(), - line: None, - }, - BuildError { - relative_path: "./parent.tex".into(), - level: BuildErrorLevel::Warning, - message: "Please (re)run Biber on the file: parent and rerun LaTeX afterwards.".into(), - line: None - } - ] - ); - } - - #[test] - fn parse_006() { - let log = r#" -This is pdfTeX, Version 3.14159265-2.6-1.40.18 (TeX Live 2017/W32TeX) (preloaded format=pdflatex 2018.3.30) 26 DEC 2018 16:33 -entering extended mode -restricted \write18 enabled. -%&-line parsing enabled. -**./parent.tex -(./parent.tex -LaTeX2e <2017-04-15> -Babel <3.10> and hyphenation patterns for 84 language(s) loaded. -(/TexLive/texmf-dist/tex/latex/base/article.cls -Document Class: article 2014/09/29 v1.4h Standard LaTeX document class -(/TexLive/texmf-dist/tex/latex/base/size10.clo -File: size10.clo 2014/09/29 v1.4h Standard LaTeX file (size option) -) -\c@part=\count79 -\c@section=\count80 -\c@subsection=\count81 -\c@subsubsection=\count82 -\c@paragraph=\count83 -\c@subparagraph=\count84 -\c@figure=\count85 -\c@table=\count86 -\abovecaptionskip=\skip41 -\belowcaptionskip=\skip42 -\bibindent=\dimen102 -) (./parent.aux -(./child.tex.aux)) -\openout1 = `parent.aux'. - -LaTeX Font Info: Checking defaults for OML/cmm/m/it on input line 3. -LaTeX Font Info: ... okay on input line 3. -LaTeX Font Info: Checking defaults for T1/cmr/m/n on input line 3. -LaTeX Font Info: ... okay on input line 3. -LaTeX Font Info: Checking defaults for OT1/cmr/m/n on input line 3. -LaTeX Font Info: ... okay on input line 3. -LaTeX Font Info: Checking defaults for OMS/cmsy/m/n on input line 3. -LaTeX Font Info: ... okay on input line 3. -LaTeX Font Info: Checking defaults for OMX/cmex/m/n on input line 3. -LaTeX Font Info: ... okay on input line 3. -LaTeX Font Info: Checking defaults for U/cmr/m/n on input line 3. -LaTeX Font Info: ... okay on input line 3. -\openout2 = `child.aux'. - -(./child.tex) -! Undefined control sequence. -l.7 \foo - -The control sequence at the end of the top line -of your error message was never \def'ed. If you have -misspelled it (e.g., `\hobx'), type `I' and the correct -spelling (e.g., `I\hbox'). Otherwise just continue, -and I'll forget about whatever was undefined. - -! Missing $ inserted. -<inserted text> - $ -l.8 \bar - -I've inserted a begin-math/end-math symbol since I think -you left one out. Proceed, with fingers crossed. - -LaTeX Font Info: External font `cmex10' loaded for size -(Font) <7> on input line 8. -LaTeX Font Info: External font `cmex10' loaded for size -(Font) <5> on input line 8. -! Undefined control sequence. -l.9 \baz - -The control sequence at the end of the top line -of your error message was never \def'ed. If you have -misspelled it (e.g., `\hobx'), type `I' and the correct -spelling (e.g., `I\hbox'). Otherwise just continue, -and I'll forget about whatever was undefined. - -! Missing { inserted. -<to be read again> - \par -l.10 - -A left brace was mandatory here, so I've put one in. -You might want to delete and/or insert some corrections -so that I will find a matching right brace soon. -(If you're confused by all this, try typing `I}' now.) - -! Missing $ inserted. -<inserted text> - $ -l.10 - -I've inserted a begin-math/end-math symbol since I think -you left one out. Proceed, with fingers crossed. - -! Missing } inserted. -<inserted text> - } -l.10 - -I've inserted something that you may have forgotten. -(See the <inserted text> above.) -With luck, this will get me unwedged. But if you -really didn't forget anything, try typing `2' now; then -my insertion and my current dilemma will both disappear. - -[1 - -{/TexLive/texmf-var/fonts/map/pdftex/updmap/pdftex.map}] (./parent.aux -(./child.aux)) ) -Here is how much of TeX's memory you used: -212 strings out of 492995 -2238 string characters out of 6138727 -54074 words of memory out of 5000000 -3843 multiletter control sequences out of 15000+600000 -3640 words of font info for 14 fonts, out of 8000000 for 9000 -1141 hyphenation exceptions out of 8191 -23i,4n,17p,116b,107s stack positions out of 5000i,500n,10000p,200000b,80000s -</TexLive/texmf-dist/fonts/type1/public/amsfonts/cm/cmr10.pfb -> -Output written on parent.pdf (1 page, 8329 bytes). -PDF statistics: -12 PDF objects out of 1000 (max. 8388607) -7 compressed objects within 1 object stream -0 named destinations out of 1000 (max. 500000) -1 words of extra memory for PDF output out of 10000 (max. 10000000)"#; - - assert_eq!( - parse(log).errors, - vec![ - BuildError { - relative_path: "./parent.tex".into(), - level: BuildErrorLevel::Error, - message: "Undefined control sequence.".into(), - line: Some(6) - }, - BuildError { - relative_path: "./parent.tex".into(), - level: BuildErrorLevel::Error, - message: "Missing $ inserted.".into(), - line: Some(7) - }, - BuildError { - relative_path: "./parent.tex".into(), - level: BuildErrorLevel::Error, - message: "Undefined control sequence.".into(), - line: Some(8) - }, - BuildError { - relative_path: "./parent.tex".into(), - level: BuildErrorLevel::Error, - message: "Missing { inserted.".into(), - line: Some(9) - }, - BuildError { - relative_path: "./parent.tex".into(), - level: BuildErrorLevel::Error, - message: "Missing $ inserted.".into(), - line: Some(9) - }, - BuildError { - relative_path: "./parent.tex".into(), - level: BuildErrorLevel::Error, - message: "Missing } inserted.".into(), - line: Some(9) - }, - ] - ); - } - - #[test] - fn parse_007() { - let log = r#" -This is pdfTeX, Version 3.141592653-2.6-1.40.22 (TeX Live 2021/W32TeX) (preloaded format=pdflatex 2021.6.19) 5 NOV 2021 19:10 -entering extended mode -restricted \write18 enabled. -%&-line parsing enabled. -**/some/folder/a.tex -(/some/folder/a.tex -LaTeX2e <2021-06-01> patch level 1 -L3 programming layer <2021-06-18> -(/texlive/2021/texmf-dist/tex/latex/koma-script/scrartcl.cls -Document Class: scrartcl 2021/03/17 v3.33 KOMA-Script document class (article) -(/texlive/2021/texmf-dist/tex/latex/koma-script/scrkbase.sty -Package: scrkbase 2021/03/17 v3.33 KOMA-Script package (KOMA-Script-dependent b -asics and keyval usage) - -(/texlive/2021/texmf-dist/tex/latex/koma-script/scrbase.sty -Package: scrbase 2021/03/17 v3.33 KOMA-Script package (KOMA-Script-independent -basics and keyval usage) - -(/texlive/2021/texmf-dist/tex/latex/koma-script/scrlfile.sty -Package: scrlfile 2021/03/17 v3.33 KOMA-Script package (file load hooks) - -(/texlive/2021/texmf-dist/tex/latex/koma-script/scrlfile-hook.sty -Package: scrlfile-hook 2021/03/17 v3.33 KOMA-Script package (using LaTeX hooks) - - -(/texlive/2021/texmf-dist/tex/latex/koma-script/scrlogo.sty -Package: scrlogo 2021/03/17 v3.33 KOMA-Script package (logo) -))) -(/texlive/2021/texmf-dist/tex/latex/graphics/keyval.sty -Package: keyval 2014/10/28 v1.15 key=value parser (DPC) -\KV@toks@=\toks16 -) -Applying: [2021/05/01] Usage of raw option list on input line 252. -Already applied: [0000/00/00] compatibility for LaTeX before 2021/05/01 on inpu -t line 337. -)) -==> First Aid for scrkbase.sty no longer applied! -(/texlive/2021/texmf-dist/tex/latex/koma-script/tocbasic.sty -Package: tocbasic 2021/03/17 v3.33 KOMA-Script package (handling toc-files) -\scr@dte@tocline@numberwidth=\skip47 -\scr@dte@tocline@numbox=\box50 -) -Package tocbasic Info: babel extension for `toc' omitted -(tocbasic) because of missing \bbl@set@language on input line 135. -Class scrartcl Info: File `scrsize11pt.clo' used instead of -(scrartcl) file `scrsize11.clo' to setup font sizes on input line 223 -9. - -(/texlive/2021/texmf-dist/tex/latex/koma-script/scrsize11pt.clo -File: scrsize11pt.clo 2021/03/17 v3.33 KOMA-Script font size class option (11pt -) -) -(/texlive/2021/texmf-dist/tex/latex/koma-script/typearea.sty -Package: typearea 2021/03/17 v3.33 KOMA-Script package (type area) -\ta@bcor=\skip48 -\ta@div=\count182 -\ta@hblk=\skip49 -\ta@vblk=\skip50 -\ta@temp=\skip51 -\footheight=\skip52 -Package typearea Info: These are the values describing the layout: -(typearea) DIV = 10 -(typearea) BCOR = 0.0pt -(typearea) \paperwidth = 597.50793pt -(typearea) \textwidth = 418.25555pt -(typearea) DIV departure = -6% -(typearea) \evensidemargin = 17.3562pt -(typearea) \oddsidemargin = 17.3562pt -(typearea) \paperheight = 845.04694pt -(typearea) \textheight = 595.80026pt -(typearea) \topmargin = -25.16531pt -(typearea) \headheight = 17.0pt -(typearea) \headsep = 20.40001pt -(typearea) \topskip = 11.0pt -(typearea) \footskip = 47.6pt -(typearea) \baselineskip = 13.6pt -(typearea) on input line 1741. -) -\c@part=\count183 -\c@section=\count184 -\c@subsection=\count185 -\c@subsubsection=\count186 -\c@paragraph=\count187 -\c@subparagraph=\count188 -\scr@dte@section@maxnumwidth=\skip53 -Class scrartcl Info: using compatibility default `runin=bysign' -(scrartcl) for `\section on input line 4846. -Class scrartcl Info: using compatibility default `afterindent=bysign' -(scrartcl) for `\section on input line 4846. -\scr@dte@part@maxnumwidth=\skip54 -Class scrartcl Info: using compatibility default `afterindent=false' -(scrartcl) for `\part on input line 4854. -\scr@dte@subsection@maxnumwidth=\skip55 -Class scrartcl Info: using compatibility default `runin=bysign' -(scrartcl) for `\subsection on input line 4864. -Class scrartcl Info: using compatibility default `afterindent=bysign' -(scrartcl) for `\subsection on input line 4864. -\scr@dte@subsubsection@maxnumwidth=\skip56 -Class scrartcl Info: using compatibility default `runin=bysign' -(scrartcl) for `\subsubsection on input line 4874. -Class scrartcl Info: using compatibility default `afterindent=bysign' -(scrartcl) for `\subsubsection on input line 4874. -\scr@dte@paragraph@maxnumwidth=\skip57 -Class scrartcl Info: using compatibility default `runin=bysign' -(scrartcl) for `\paragraph on input line 4885. -Class scrartcl Info: using compatibility default `afterindent=bysign' -(scrartcl) for `\paragraph on input line 4885. -\scr@dte@subparagraph@maxnumwidth=\skip58 -Class scrartcl Info: using compatibility default `runin=bysign' -(scrartcl) for `\subparagraph on input line 4895. -Class scrartcl Info: using compatibility default `afterindent=bysign' -(scrartcl) for `\subparagraph on input line 4895. -\abovecaptionskip=\skip59 -\belowcaptionskip=\skip60 -\c@pti@nb@sid@b@x=\box51 -Package tocbasic Info: babel extension for `lof' omitted -(tocbasic) because of missing \bbl@set@language on input line 6127. - -\scr@dte@figure@maxnumwidth=\skip61 -\c@figure=\count189 -Package tocbasic Info: babel extension for `lot' omitted -(tocbasic) because of missing \bbl@set@language on input line 6139. - -\scr@dte@table@maxnumwidth=\skip62 -\c@table=\count190 -Class scrartcl Info: Redefining `\numberline' on input line 6303. -\bibindent=\dimen138 -) -(/texlive/2021/texmf-dist/tex/latex/l3backend/l3backend-pdftex.def -File: l3backend-pdftex.def 2021-05-07 L3 backend support: PDF output (pdfTeX) -\l__color_backend_stack_int=\count191 -\l__pdf_internal_box=\box52 -) (./a.aux) -\openout1 = `a.aux'. - -LaTeX Font Info: Checking defaults for OML/cmm/m/it on input line 3. -LaTeX Font Info: ... okay on input line 3. -LaTeX Font Info: Checking defaults for OMS/cmsy/m/n on input line 3. -LaTeX Font Info: ... okay on input line 3. -LaTeX Font Info: Checking defaults for OT1/cmr/m/n on input line 3. -LaTeX Font Info: ... okay on input line 3. -LaTeX Font Info: Checking defaults for T1/cmr/m/n on input line 3. -LaTeX Font Info: ... okay on input line 3. -LaTeX Font Info: Checking defaults for TS1/cmr/m/n on input line 3. -LaTeX Font Info: ... okay on input line 3. -LaTeX Font Info: Checking defaults for OMX/cmex/m/n on input line 3. -LaTeX Font Info: ... okay on input line 3. -LaTeX Font Info: Checking defaults for U/cmr/m/n on input line 3. -LaTeX Font Info: ... okay on input line 3. -Package scrbase Info: activating english \contentsname on input line 3. -Package scrbase Info: activating english \listfigurename on input line 3. -Package scrbase Info: activating english \listtablename on input line 3. -! Undefined control sequence. -l.4 \lsdkfjlskdfj - -The control sequence at the end of the top line -of your error message was never \def'ed. If you have -misspelled it (e.g., `\hobx'), type `I' and the correct -spelling (e.g., `I\hbox'). Otherwise just continue, -and I'll forget about whatever was undefined. - -(./a.aux) ) -Here is how much of TeX's memory you used: -3199 strings out of 478510 -74549 string characters out of 5853586 -510929 words of memory out of 5000000 -21227 multiletter control sequences out of 15000+600000 -403730 words of font info for 28 fonts, out of 8000000 for 9000 -1141 hyphenation exceptions out of 8191 -108i,1n,108p,10625b,270s stack positions out of 5000i,500n,10000p,200000b,80000s - -No pages of output. -PDF statistics: -0 PDF objects out of 1000 (max. 8388607) -0 named destinations out of 1000 (max. 500000) -1 words of extra memory for PDF output out of 10000 (max. 10000000)"#; - - assert_debug_snapshot!(parse(log).errors); - } -} diff --git a/support/texlab/src/syntax/latex.rs b/support/texlab/src/syntax/latex.rs index 2d8918e49e..ce1ca125fd 100644 --- a/support/texlab/src/syntax/latex.rs +++ b/support/texlab/src/syntax/latex.rs @@ -1,14 +1,9 @@ -mod analysis; mod cst; mod kind; -mod lexer; -mod parser; pub use self::{ - analysis::*, cst::*, kind::SyntaxKind::{self, *}, - parser::{parse, Parse}, }; #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] diff --git a/support/texlab/src/syntax/latex/analysis.rs b/support/texlab/src/syntax/latex/analysis.rs deleted file mode 100644 index 02d9b315ba..0000000000 --- a/support/texlab/src/syntax/latex/analysis.rs +++ /dev/null @@ -1,40 +0,0 @@ -mod command; -mod distro_file; -mod environment; -mod explicit_link; -mod graphics_path; -mod implicit_link; -mod label_name; -mod label_number; -mod theorem; -mod types; - -use crate::syntax::latex; - -pub use self::types::*; -use self::{ - command::{analyze_command, analyze_command_definition}, - environment::analyze_begin, - explicit_link::{analyze_import, analyze_include}, - graphics_path::analyze_graphics_path, - implicit_link::analyze_implicit_links, - label_name::analyze_label_name, - label_number::analyze_label_number, - theorem::analyze_theorem_definition, -}; - -pub fn analyze(context: &mut LatexAnalyzerContext, root: &latex::SyntaxNode) { - analyze_implicit_links(context); - for node in root.descendants() { - analyze_command(context, node.clone()) - .or_else(|| analyze_command_definition(context, node.clone())) - .or_else(|| analyze_begin(context, node.clone())) - .or_else(|| analyze_include(context, node.clone())) - .or_else(|| analyze_import(context, node.clone())) - .or_else(|| analyze_label_name(context, node.clone())) - .or_else(|| analyze_label_number(context, node.clone())) - .or_else(|| analyze_theorem_definition(context, node.clone())) - .or_else(|| analyze_graphics_path(context, node)); - } - context.extras.has_document_environment = context.extras.environment_names.contains("document"); -} diff --git a/support/texlab/src/syntax/latex/analysis/command.rs b/support/texlab/src/syntax/latex/analysis/command.rs deleted file mode 100644 index 60aceef725..0000000000 --- a/support/texlab/src/syntax/latex/analysis/command.rs +++ /dev/null @@ -1,26 +0,0 @@ -use rowan::ast::AstNode; - -use crate::syntax::latex; - -use super::LatexAnalyzerContext; - -pub fn analyze_command(context: &mut LatexAnalyzerContext, node: latex::SyntaxNode) -> Option<()> { - let command = latex::GenericCommand::cast(node)?; - context - .extras - .command_names - .insert(command.name()?.text().into()); - Some(()) -} - -pub fn analyze_command_definition( - context: &mut LatexAnalyzerContext, - node: latex::SyntaxNode, -) -> Option<()> { - let definition = latex::CommandDefinition::cast(node)?; - context - .extras - .command_names - .insert(definition.name()?.command()?.text().into()); - Some(()) -} diff --git a/support/texlab/src/syntax/latex/analysis/distro_file.rs b/support/texlab/src/syntax/latex/analysis/distro_file.rs deleted file mode 100644 index f278c33627..0000000000 --- a/support/texlab/src/syntax/latex/analysis/distro_file.rs +++ /dev/null @@ -1,73 +0,0 @@ -use lsp_types::Url; - -use crate::distro::Resolver; - -pub fn resolve_distro_file(resolver: &Resolver, stem: &str, extensions: &[&str]) -> Option<Url> { - let mut document = resolver.files_by_name.get(stem); - for extension in extensions { - document = document.or_else(|| { - let full_name = format!("{}.{}", stem, extension); - resolver.files_by_name.get(full_name.as_str()) - }); - } - document.and_then(|path| Url::from_file_path(path).ok()) -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - #[cfg(windows)] - fn test() { - let mut resolver = Resolver::default(); - resolver - .files_by_name - .insert("foo.tex".into(), "C:/distro/foo.tex".into()); - resolver - .files_by_name - .insert("foo.sty".into(), "C:/distro/foo.sty".into()); - resolver - .files_by_name - .insert("bar.tex".into(), "C:/distro/bar.tex".into()); - - assert_eq!( - resolve_distro_file(&resolver, "foo", &["tex"]), - Some(Url::from_file_path("C:/distro/foo.tex").unwrap()) - ); - - assert_eq!( - resolve_distro_file(&resolver, "foo", &["sty"]), - Some(Url::from_file_path("C:/distro/foo.sty").unwrap()) - ); - - assert_eq!(resolve_distro_file(&resolver, "foo", &["cls"]), None); - } - - #[test] - #[cfg(unix)] - fn test() { - let mut resolver = Resolver::default(); - resolver - .files_by_name - .insert("foo.tex".into(), "/distro/foo.tex".into()); - resolver - .files_by_name - .insert("foo.sty".into(), "/distro/foo.sty".into()); - resolver - .files_by_name - .insert("bar.tex".into(), "/distro/bar.tex".into()); - - assert_eq!( - resolve_distro_file(&resolver, "foo", &["tex"]), - Some(Url::from_file_path("/distro/foo.tex").unwrap()) - ); - - assert_eq!( - resolve_distro_file(&resolver, "foo", &["sty"]), - Some(Url::from_file_path("/distro/foo.sty").unwrap()) - ); - - assert_eq!(resolve_distro_file(&resolver, "foo", &["cls"]), None); - } -} diff --git a/support/texlab/src/syntax/latex/analysis/environment.rs b/support/texlab/src/syntax/latex/analysis/environment.rs deleted file mode 100644 index e99483f706..0000000000 --- a/support/texlab/src/syntax/latex/analysis/environment.rs +++ /dev/null @@ -1,13 +0,0 @@ -use rowan::ast::AstNode; - -use crate::syntax::latex; - -use super::LatexAnalyzerContext; - -pub fn analyze_begin(context: &mut LatexAnalyzerContext, node: latex::SyntaxNode) -> Option<()> { - let begin = latex::Begin::cast(node)?; - let name = begin.name()?.key()?.to_string(); - let extras = &mut context.extras; - extras.environment_names.insert(name); - Some(()) -} diff --git a/support/texlab/src/syntax/latex/analysis/explicit_link.rs b/support/texlab/src/syntax/latex/analysis/explicit_link.rs deleted file mode 100644 index 77e2cfb696..0000000000 --- a/support/texlab/src/syntax/latex/analysis/explicit_link.rs +++ /dev/null @@ -1,72 +0,0 @@ -use std::sync::Arc; - -use rowan::ast::AstNode; - -use crate::syntax::latex; - -use super::{ - distro_file::resolve_distro_file, ExplicitLink, ExplicitLinkKind, LatexAnalyzerContext, -}; - -pub fn analyze_include(context: &mut LatexAnalyzerContext, node: latex::SyntaxNode) -> Option<()> { - let include = latex::Include::cast(node)?; - let kind = match include.syntax().kind() { - latex::LATEX_INCLUDE => ExplicitLinkKind::Latex, - latex::BIBLATEX_INCLUDE | latex::BIBTEX_INCLUDE => ExplicitLinkKind::Bibtex, - latex::PACKAGE_INCLUDE => ExplicitLinkKind::Package, - latex::CLASS_INCLUDE => ExplicitLinkKind::Class, - _ => return None, - }; - - let extensions = match kind { - ExplicitLinkKind::Latex => &["tex"], - ExplicitLinkKind::Bibtex => &["bib"], - ExplicitLinkKind::Package => &["sty"], - ExplicitLinkKind::Class => &["cls"], - }; - - for path in include.path_list()?.keys() { - let stem = path.to_string(); - let mut targets = vec![Arc::new(context.base_uri.join(&stem).ok()?)]; - for extension in extensions { - let path = format!("{}.{}", stem, extension); - targets.push(Arc::new(context.base_uri.join(&path).ok()?)); - } - - resolve_distro_file(&context.environment.resolver, &stem, extensions) - .into_iter() - .for_each(|target| targets.push(Arc::new(target))); - - context.extras.explicit_links.push(ExplicitLink { - kind, - stem: stem.into(), - stem_range: latex::small_range(&path), - targets, - }); - } - - Some(()) -} - -pub fn analyze_import(context: &mut LatexAnalyzerContext, node: latex::SyntaxNode) -> Option<()> { - let import = latex::Import::cast(node)?; - - let mut targets = Vec::new(); - let directory = match import.directory().and_then(|dir| dir.key()) { - Some(dir) => Arc::new(context.base_uri.join(&dir.to_string()).ok()?), - None => Arc::clone(&context.base_uri), - }; - - let file = import.file()?.key()?; - let stem = file.to_string(); - targets.push(Arc::new(directory.join(&stem).ok()?)); - targets.push(Arc::new(directory.join(&format!("{}.tex", stem)).ok()?)); - - context.extras.explicit_links.push(ExplicitLink { - stem: stem.into(), - stem_range: latex::small_range(&file), - targets, - kind: ExplicitLinkKind::Latex, - }); - Some(()) -} diff --git a/support/texlab/src/syntax/latex/analysis/graphics_path.rs b/support/texlab/src/syntax/latex/analysis/graphics_path.rs deleted file mode 100644 index 477094b841..0000000000 --- a/support/texlab/src/syntax/latex/analysis/graphics_path.rs +++ /dev/null @@ -1,21 +0,0 @@ -use rowan::ast::AstNode; - -use crate::syntax::latex; - -use super::LatexAnalyzerContext; - -pub fn analyze_graphics_path( - context: &mut LatexAnalyzerContext, - node: latex::SyntaxNode, -) -> Option<()> { - let definition = latex::GraphicsPath::cast(node)?; - for path in definition - .path_list() - .filter_map(|group| group.key()) - .map(|path| path.to_string()) - { - context.extras.graphics_paths.insert(path); - } - - Some(()) -} diff --git a/support/texlab/src/syntax/latex/analysis/implicit_link.rs b/support/texlab/src/syntax/latex/analysis/implicit_link.rs deleted file mode 100644 index 60524c623e..0000000000 --- a/support/texlab/src/syntax/latex/analysis/implicit_link.rs +++ /dev/null @@ -1,64 +0,0 @@ -use std::{path::Path, sync::Arc}; - -use lsp_types::Url; - -use super::LatexAnalyzerContext; - -pub fn analyze_implicit_links(context: &mut LatexAnalyzerContext) { - context.extras.implicit_links.aux = find_by_extension(context, "aux").unwrap_or_default(); - context.extras.implicit_links.log = find_by_extension(context, "log").unwrap_or_default(); - context.extras.implicit_links.pdf = find_by_extension(context, "pdf").unwrap_or_default(); -} - -fn find_by_extension(context: &LatexAnalyzerContext, extension: &str) -> Option<Vec<Arc<Url>>> { - let mut targets = vec![Arc::new(with_extension(&context.document_uri, extension)?)]; - if context.document_uri.scheme() == "file" { - let file_path = context.document_uri.to_file_path().ok()?; - let file_stem = file_path.file_stem()?; - let aux_name = format!("{}.{}", file_stem.to_str()?, extension); - - let options = &context.environment.options; - if let Some(root_dir) = options.root_directory.as_ref() { - find_inside_directory(context, root_dir, &aux_name, &mut targets)?; - } - - if let Some(build_dir) = options.aux_directory.as_ref() { - find_inside_directory(context, build_dir, &aux_name, &mut targets)?; - } - } - Some(targets) -} - -fn find_inside_directory( - context: &LatexAnalyzerContext, - dir: &Path, - aux_name: &str, - targets: &mut Vec<Arc<Url>>, -) -> Option<()> { - let path = context - .environment - .current_directory - .join(dir) - .join(aux_name); - - targets.push(Arc::new(Url::from_file_path(path).ok()?)); - - targets.push(Arc::new( - context - .base_uri - .join(&dir.join(aux_name).to_string_lossy()) - .ok()?, - )); - - Some(()) -} - -fn with_extension(uri: &Url, extension: &str) -> Option<Url> { - let file_name = uri.path_segments()?.last()?; - let file_stem = file_name - .rfind('.') - .map(|i| &file_name[..i]) - .unwrap_or(file_name); - - uri.join(&format!("{}.{}", file_stem, extension)).ok() -} diff --git a/support/texlab/src/syntax/latex/analysis/label_name.rs b/support/texlab/src/syntax/latex/analysis/label_name.rs deleted file mode 100644 index 1e3339db5e..0000000000 --- a/support/texlab/src/syntax/latex/analysis/label_name.rs +++ /dev/null @@ -1,67 +0,0 @@ -use latex::LabelReferenceRange; -use rowan::ast::AstNode; - -use crate::syntax::latex; - -use super::{LabelName, LatexAnalyzerContext}; - -pub fn analyze_label_name( - context: &mut LatexAnalyzerContext, - node: latex::SyntaxNode, -) -> Option<()> { - analyze_label_definition_name(context, node.clone()) - .or_else(|| analyze_label_reference_name(context, node.clone())) - .or_else(|| analyze_label_reference_range_name(context, node)) -} - -fn analyze_label_definition_name( - context: &mut LatexAnalyzerContext, - node: latex::SyntaxNode, -) -> Option<()> { - let label = latex::LabelDefinition::cast(node)?; - let name = label.name()?.key()?; - context.extras.label_names.push(LabelName { - text: name.to_string().into(), - range: latex::small_range(&name), - is_definition: true, - }); - Some(()) -} - -fn analyze_label_reference_name( - context: &mut LatexAnalyzerContext, - node: latex::SyntaxNode, -) -> Option<()> { - let label = latex::LabelReference::cast(node)?; - for name in label.name_list()?.keys() { - context.extras.label_names.push(LabelName { - text: name.to_string().into(), - range: latex::small_range(&name), - is_definition: false, - }); - } - Some(()) -} - -fn analyze_label_reference_range_name( - context: &mut LatexAnalyzerContext, - node: latex::SyntaxNode, -) -> Option<()> { - let label = LabelReferenceRange::cast(node)?; - if let Some(name1) = label.from().and_then(|name| name.key()) { - context.extras.label_names.push(LabelName { - text: name1.to_string().into(), - range: latex::small_range(&name1), - is_definition: false, - }); - } - - if let Some(name2) = label.to().and_then(|name| name.key()) { - context.extras.label_names.push(LabelName { - text: name2.to_string().into(), - range: latex::small_range(&name2), - is_definition: false, - }); - } - Some(()) -} diff --git a/support/texlab/src/syntax/latex/analysis/label_number.rs b/support/texlab/src/syntax/latex/analysis/label_number.rs deleted file mode 100644 index 61ad348680..0000000000 --- a/support/texlab/src/syntax/latex/analysis/label_number.rs +++ /dev/null @@ -1,24 +0,0 @@ -use rowan::ast::AstNode; - -use crate::syntax::latex; - -use super::LatexAnalyzerContext; - -pub fn analyze_label_number( - context: &mut LatexAnalyzerContext, - node: latex::SyntaxNode, -) -> Option<()> { - let number = latex::LabelNumber::cast(node)?; - let name = number.name()?.key()?.to_string(); - let text = number - .text()? - .syntax() - .descendants_with_tokens() - .filter_map(|element| element.into_node()) - .find(|node| node.kind() == latex::TEXT || node.kind() == latex::MIXED_GROUP)? - .text() - .to_string(); - - context.extras.label_numbers_by_name.insert(name, text); - Some(()) -} diff --git a/support/texlab/src/syntax/latex/analysis/theorem.rs b/support/texlab/src/syntax/latex/analysis/theorem.rs deleted file mode 100644 index 70047362d1..0000000000 --- a/support/texlab/src/syntax/latex/analysis/theorem.rs +++ /dev/null @@ -1,22 +0,0 @@ -use rowan::ast::AstNode; - -use crate::syntax::latex::{self, HasCurly}; - -use super::{LatexAnalyzerContext, TheoremEnvironment}; - -pub fn analyze_theorem_definition( - context: &mut LatexAnalyzerContext, - node: latex::SyntaxNode, -) -> Option<()> { - let theorem = latex::TheoremDefinition::cast(node)?; - let name = theorem.name()?.key()?.to_string(); - let description = theorem.description()?; - let description = description.content_text()?; - - context - .extras - .theorem_environments - .push(TheoremEnvironment { name, description }); - - Some(()) -} diff --git a/support/texlab/src/syntax/latex/analysis/types.rs b/support/texlab/src/syntax/latex/analysis/types.rs deleted file mode 100644 index 7fb938e3d2..0000000000 --- a/support/texlab/src/syntax/latex/analysis/types.rs +++ /dev/null @@ -1,75 +0,0 @@ -use std::sync::Arc; - -use lsp_types::Url; -use rowan::TextRange; -use rustc_hash::{FxHashMap, FxHashSet}; -use smol_str::SmolStr; - -use crate::Environment; - -#[derive(Debug)] -pub struct LatexAnalyzerContext<'a> { - pub environment: &'a Environment, - pub document_uri: Arc<Url>, - pub base_uri: Arc<Url>, - pub extras: Extras, -} - -#[derive(Debug, Clone, Default)] -pub struct Extras { - pub implicit_links: ImplicitLinks, - pub explicit_links: Vec<ExplicitLink>, - pub has_document_environment: bool, - pub command_names: FxHashSet<SmolStr>, - pub environment_names: FxHashSet<String>, - pub label_names: Vec<LabelName>, - pub label_numbers_by_name: FxHashMap<String, String>, - pub theorem_environments: Vec<TheoremEnvironment>, - pub graphics_paths: FxHashSet<String>, -} - -#[derive(Debug, PartialEq, Eq, Clone, Default, Hash)] -pub struct ImplicitLinks { - pub aux: Vec<Arc<Url>>, - pub log: Vec<Arc<Url>>, - pub pdf: Vec<Arc<Url>>, -} - -#[derive(Debug, PartialEq, Eq, Clone, Copy, PartialOrd, Ord, Hash)] -pub enum ExplicitLinkKind { - Package, - Class, - Latex, - Bibtex, -} - -#[derive(Debug, Clone)] -pub struct ExplicitLink { - pub stem: SmolStr, - pub stem_range: TextRange, - pub targets: Vec<Arc<Url>>, - pub kind: ExplicitLinkKind, -} - -impl ExplicitLink { - pub fn as_component_name(&self) -> Option<String> { - match self.kind { - ExplicitLinkKind::Package => Some(format!("{}.sty", self.stem)), - ExplicitLinkKind::Class => Some(format!("{}.cls", self.stem)), - ExplicitLinkKind::Latex | ExplicitLinkKind::Bibtex => None, - } - } -} - -#[derive(Debug, PartialEq, Eq, Clone, Default, Hash)] -pub struct TheoremEnvironment { - pub name: String, - pub description: String, -} - -#[derive(Debug, PartialEq, Eq, Clone, Default, Hash)] -pub struct LabelName { - pub text: SmolStr, - pub range: TextRange, - pub is_definition: bool, -} diff --git a/support/texlab/src/syntax/latex/cst.rs b/support/texlab/src/syntax/latex/cst.rs index a83246571d..d7c9ec9bc7 100644 --- a/support/texlab/src/syntax/latex/cst.rs +++ b/support/texlab/src/syntax/latex/cst.rs @@ -683,6 +683,6 @@ impl GraphicsPath { } pub fn path_list(&self) -> impl Iterator<Item = CurlyGroupWord> { - self.syntax().children().filter_map(CurlyGroupWord::cast) + self.syntax().descendants().filter_map(CurlyGroupWord::cast) } } diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__lexer__tests__asymptote.snap b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__lexer__tests__asymptote.snap deleted file mode 100644 index 12f0f3ca63..0000000000 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__lexer__tests__asymptote.snap +++ /dev/null @@ -1,43 +0,0 @@ ---- -source: src/syntax/latex/lexer.rs -assertion_line: 664 -expression: "verify(r#\"\\begin{asy}\n printf(\"Hello World\\n\");\n\\end{asy}\"#)" ---- -[ - ( - BEGIN_ENVIRONMENT_NAME, - "\\begin", - ), - ( - L_CURLY, - "{", - ), - ( - WORD, - "asy", - ), - ( - R_CURLY, - "}", - ), - ( - VERBATIM, - "\n printf(\"Hello World\\n\");\n", - ), - ( - END_ENVIRONMENT_NAME, - "\\end", - ), - ( - L_CURLY, - "{", - ), - ( - WORD, - "asy", - ), - ( - R_CURLY, - "}", - ), -] diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__lexer__tests__block_comment.snap b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__lexer__tests__block_comment.snap deleted file mode 100644 index 5ced043aaf..0000000000 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__lexer__tests__block_comment.snap +++ /dev/null @@ -1,27 +0,0 @@ ---- -source: src/syntax/latex/lexer.rs -assertion_line: 601 -expression: "verify(\"Foo\\\\iffalse\\n\\\\Bar{Baz}\\n\\\\fi\\\\Qux\")" ---- -[ - ( - WORD, - "Foo", - ), - ( - BEGIN_BLOCK_COMMENT_NAME, - "\\iffalse", - ), - ( - VERBATIM, - "\n\\Bar{Baz}\n", - ), - ( - END_BLOCK_COMMENT_NAME, - "\\fi", - ), - ( - GENERIC_COMMAND_NAME, - "\\Qux", - ), -] diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__lexer__tests__command_with_parameter.snap b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__lexer__tests__command_with_parameter.snap deleted file mode 100644 index a9a0e11ad7..0000000000 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__lexer__tests__command_with_parameter.snap +++ /dev/null @@ -1,47 +0,0 @@ ---- -source: src/syntax/latex/lexer.rs -expression: "verify(r#\"\\newcommand{\\id}[1]{#1}\"#)" - ---- -[ - ( - COMMAND_DEFINITION_NAME, - "\\newcommand", - ), - ( - L_CURLY, - "{", - ), - ( - GENERIC_COMMAND_NAME, - "\\id", - ), - ( - R_CURLY, - "}", - ), - ( - L_BRACK, - "[", - ), - ( - WORD, - "1", - ), - ( - R_BRACK, - "]", - ), - ( - L_CURLY, - "{", - ), - ( - WORD, - "#1", - ), - ( - R_CURLY, - "}", - ), -] diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__lexer__tests__command_with_star.snap b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__lexer__tests__command_with_star.snap deleted file mode 100644 index 41310edaa1..0000000000 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__lexer__tests__command_with_star.snap +++ /dev/null @@ -1,23 +0,0 @@ ---- -source: src/syntax/latex/lexer.rs -expression: "verify(r#\"\\section*{Foo}\"#)" - ---- -[ - ( - SECTION_NAME, - "\\section*", - ), - ( - L_CURLY, - "{", - ), - ( - WORD, - "Foo", - ), - ( - R_CURLY, - "}", - ), -] diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__lexer__tests__comment.snap b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__lexer__tests__comment.snap deleted file mode 100644 index 19db458200..0000000000 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__lexer__tests__comment.snap +++ /dev/null @@ -1,36 +0,0 @@ ---- -source: src/syntax/latex/lexer.rs -assertion_line: 248 -expression: "verify(\"hello %world\\r\\ntest %test\")" - ---- -[ - ( - WORD, - "hello", - ), - ( - WHITESPACE, - " ", - ), - ( - COMMENT, - "%world", - ), - ( - LINE_BREAK, - "\r\n", - ), - ( - WORD, - "test", - ), - ( - WHITESPACE, - " ", - ), - ( - COMMENT, - "%test", - ), -] diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__lexer__tests__delimiters.snap b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__lexer__tests__delimiters.snap deleted file mode 100644 index 36bec0a276..0000000000 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__lexer__tests__delimiters.snap +++ /dev/null @@ -1,79 +0,0 @@ ---- -source: src/syntax/latex/lexer.rs -expression: "verify(r#\"{foo} (bar) [baz, qux = foo-bar]\"#)" - ---- -[ - ( - L_CURLY, - "{", - ), - ( - WORD, - "foo", - ), - ( - R_CURLY, - "}", - ), - ( - WHITESPACE, - " ", - ), - ( - L_PAREN, - "(", - ), - ( - WORD, - "bar", - ), - ( - R_PAREN, - ")", - ), - ( - WHITESPACE, - " ", - ), - ( - L_BRACK, - "[", - ), - ( - WORD, - "baz", - ), - ( - COMMA, - ",", - ), - ( - WHITESPACE, - " ", - ), - ( - WORD, - "qux", - ), - ( - WHITESPACE, - " ", - ), - ( - EQUALITY_SIGN, - "=", - ), - ( - WHITESPACE, - " ", - ), - ( - WORD, - "foo-bar", - ), - ( - R_BRACK, - "]", - ), -] diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__lexer__tests__empty.snap b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__lexer__tests__empty.snap deleted file mode 100644 index 61735b5087..0000000000 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__lexer__tests__empty.snap +++ /dev/null @@ -1,6 +0,0 @@ ---- -source: src/syntax/latex/lexer.rs -expression: "verify(r#\"\"#)" - ---- -[] diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__lexer__tests__escape_sequence.snap b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__lexer__tests__escape_sequence.snap deleted file mode 100644 index 4dbc1bb8f5..0000000000 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__lexer__tests__escape_sequence.snap +++ /dev/null @@ -1,19 +0,0 @@ ---- -source: src/syntax/latex/lexer.rs -expression: "verify(r#\"\\% hello\"#)" - ---- -[ - ( - GENERIC_COMMAND_NAME, - "\\%", - ), - ( - WHITESPACE, - " ", - ), - ( - WORD, - "hello", - ), -] diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__lexer__tests__formula.snap b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__lexer__tests__formula.snap deleted file mode 100644 index 3fb7079384..0000000000 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__lexer__tests__formula.snap +++ /dev/null @@ -1,55 +0,0 @@ ---- -source: src/syntax/latex/lexer.rs -expression: "verify(r#\"$ f(x) = y $$\"#)" - ---- -[ - ( - DOLLAR, - "$", - ), - ( - WHITESPACE, - " ", - ), - ( - WORD, - "f", - ), - ( - L_PAREN, - "(", - ), - ( - WORD, - "x", - ), - ( - R_PAREN, - ")", - ), - ( - WHITESPACE, - " ", - ), - ( - EQUALITY_SIGN, - "=", - ), - ( - WHITESPACE, - " ", - ), - ( - WORD, - "y", - ), - ( - WHITESPACE, - " ", - ), - ( - DOLLAR, - "$$", - ), -] diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__lexer__tests__invalid_parameter.snap b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__lexer__tests__invalid_parameter.snap deleted file mode 100644 index e947ec3fb6..0000000000 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__lexer__tests__invalid_parameter.snap +++ /dev/null @@ -1,11 +0,0 @@ ---- -source: src/syntax/latex/lexer.rs -expression: "verify(r#\"#\"#)" - ---- -[ - ( - WORD, - "#", - ), -] diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__lexer__tests__line_break.snap b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__lexer__tests__line_break.snap deleted file mode 100644 index a8a392370e..0000000000 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__lexer__tests__line_break.snap +++ /dev/null @@ -1,20 +0,0 @@ ---- -source: src/syntax/latex/lexer.rs -assertion_line: 258 -expression: "verify(\"hello\\nworld\")" - ---- -[ - ( - WORD, - "hello", - ), - ( - LINE_BREAK, - "\n", - ), - ( - WORD, - "world", - ), -] diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__empty.snap b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__empty.snap deleted file mode 100644 index f01f7f9092..0000000000 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__empty.snap +++ /dev/null @@ -1,8 +0,0 @@ ---- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"\"#)" - ---- -ROOT@0..0 - PREAMBLE@0..0 - diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__generic_command_empty.snap b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__generic_command_empty.snap deleted file mode 100644 index 84e62ea81d..0000000000 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__generic_command_empty.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"\\foo\"#)" - ---- -ROOT@0..4 - PREAMBLE@0..4 - GENERIC_COMMAND@0..4 - GENERIC_COMMAND_NAME@0..4 "\\foo" - diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__generic_command_escape.snap b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__generic_command_escape.snap deleted file mode 100644 index a0d5d2e29b..0000000000 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__generic_command_escape.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"\\#\"#)" - ---- -ROOT@0..2 - PREAMBLE@0..2 - GENERIC_COMMAND@0..2 - GENERIC_COMMAND_NAME@0..2 "\\#" - diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__graphics_path.snap b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__graphics_path.snap deleted file mode 100644 index 622a0fc869..0000000000 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__graphics_path.snap +++ /dev/null @@ -1,17 +0,0 @@ ---- -source: src/syntax/latex/parser.rs -assertion_line: 1871 -expression: "setup(r#\"\\graphicspath{{../figures/}}\"#)" ---- -ROOT@0..28 - PREAMBLE@0..28 - GRAPHICS_PATH@0..28 - GRAPHICS_PATH_NAME@0..13 "\\graphicspath" - L_CURLY@13..14 "{" - CURLY_GROUP_WORD@14..27 - L_CURLY@14..15 "{" - KEY@15..26 - WORD@15..26 "../figures/" - R_CURLY@26..27 "}" - R_CURLY@27..28 "}" - diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__latex_input_simple.snap b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__latex_input_simple.snap deleted file mode 100644 index efa0d9b675..0000000000 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__latex_input_simple.snap +++ /dev/null @@ -1,15 +0,0 @@ ---- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"\\input{foo/bar.tex}\"#)" - ---- -ROOT@0..19 - PREAMBLE@0..19 - LATEX_INCLUDE@0..19 - LATEX_INCLUDE_NAME@0..6 "\\input" - CURLY_GROUP_WORD_LIST@6..19 - L_CURLY@6..7 "{" - KEY@7..18 - WORD@7..18 "foo/bar.tex" - R_CURLY@18..19 "}" - diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__parameter.snap b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__parameter.snap deleted file mode 100644 index 4888672c31..0000000000 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__parameter.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"#1\"#)" - ---- -ROOT@0..2 - PREAMBLE@0..2 - TEXT@0..2 - WORD@0..2 "#1" - diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__parameter_error.snap b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__parameter_error.snap deleted file mode 100644 index 843327ab80..0000000000 --- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__parameter_error.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: src/syntax/latex/parser.rs -expression: "setup(r#\"#\"#)" - ---- -ROOT@0..1 - PREAMBLE@0..1 - TEXT@0..1 - WORD@0..1 "#" - diff --git a/support/texlab/src/syntax/snapshots/texlab__syntax__build_log__tests__parse_007.snap b/support/texlab/src/syntax/snapshots/texlab__syntax__build_log__tests__parse_007.snap deleted file mode 100644 index 09d99c4f21..0000000000 --- a/support/texlab/src/syntax/snapshots/texlab__syntax__build_log__tests__parse_007.snap +++ /dev/null @@ -1,15 +0,0 @@ ---- -source: src/syntax/build_log.rs -expression: parse(&log).errors - ---- -[ - BuildError { - relative_path: "/some/folder/a.tex", - level: Error, - message: "Undefined control sequence.", - line: Some( - 3, - ), - }, -] diff --git a/support/texlab/tests/integration/lsp.rs b/support/texlab/src/tests.rs index 9ef1a4f2b4..c6afcfc20c 100644 --- a/support/texlab/tests/integration/lsp.rs +++ b/support/texlab/src/tests.rs @@ -1,4 +1,5 @@ mod client; mod fixture; +mod issues; mod text_document; mod workspace; diff --git a/support/texlab/tests/integration/lsp/client.rs b/support/texlab/src/tests/client.rs index 004422813a..ff6b23469b 100644 --- a/support/texlab/tests/integration/lsp/client.rs +++ b/support/texlab/src/tests/client.rs @@ -1,3 +1,5 @@ +use std::sync::Once; + use anyhow::{bail, Result}; use crossbeam_channel::{Receiver, Sender}; use lsp_server::{Connection, Message, Notification, Request, Response}; @@ -5,10 +7,13 @@ use lsp_types::{ notification::{Exit, Initialized}, request::{Initialize, Shutdown}, ClientCapabilities, ClientInfo, DidOpenTextDocumentParams, InitializeParams, InitializeResult, - InitializedParams, Url, + InitializedParams, Url, WorkspaceFolder, }; use tempfile::{tempdir, TempDir}; -use texlab::Server; + +use crate::Server; + +static INIT_LOGGER: Once = Once::new(); pub struct IncomingHandler { _handle: jod_thread::JoinHandle<Result<()>>, @@ -18,7 +23,7 @@ pub struct IncomingHandler { } impl IncomingHandler { - pub fn spawn(receiver: Receiver<Message>) -> Result<Self> { + pub fn spawn(receiver: Receiver<Message>) -> Self { let (req_sender, req_receiver) = crossbeam_channel::unbounded(); let (not_sender, not_receiver) = crossbeam_channel::unbounded(); let (res_sender, res_receiver) = crossbeam_channel::unbounded(); @@ -35,12 +40,12 @@ impl IncomingHandler { Ok(()) }); - Ok(Self { + Self { _handle, requests: req_receiver, notifications: not_receiver, responses: res_receiver, - }) + } } } @@ -58,45 +63,47 @@ pub struct Client { } impl Client { - pub fn spawn() -> Result<Self> { - let directory = tempdir()?; + pub fn spawn() -> Self { + INIT_LOGGER.call_once(|| env_logger::init()); + + let directory = tempdir().unwrap(); let (client, server) = Connection::memory(); - let incoming = IncomingHandler::spawn(client.receiver)?; + let incoming = IncomingHandler::spawn(client.receiver); let outgoing = client.sender; - let server = Server::with_connection(server, directory.path().to_path_buf(), false); + let server = Server::new(server); let _handle = jod_thread::spawn(move || { server.run().expect("server failed to run"); }); - Ok(Self { + Self { outgoing, incoming, directory, request_id: 0, _handle, - }) + } } - #[allow(deprecated)] pub fn initialize( &mut self, client_capabilities: ClientCapabilities, client_info: Option<ClientInfo>, - ) -> Result<InitializeResult> { - let result = self.request::<Initialize>(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, - })?; - - self.notify::<Initialized>(InitializedParams {})?; - Ok(result) + ) -> InitializeResult { + let result = self + .request::<Initialize>(InitializeParams { + initialization_options: Some(serde_json::json!({ "skipDistro": true })), + capabilities: client_capabilities, + workspace_folders: Some(vec![WorkspaceFolder { + name: "Test".into(), + uri: Url::from_directory_path(self.directory.path()).unwrap(), + }]), + client_info, + ..InitializeParams::default() + }) + .unwrap(); + + self.notify::<Initialized>(InitializedParams {}); + result } pub fn request<R: lsp_types::request::Request>( @@ -106,9 +113,10 @@ impl Client { self.request_id += 1; self.outgoing - .send(Request::new(self.request_id.into(), R::METHOD.into(), params).into())?; + .send(Request::new(self.request_id.into(), R::METHOD.into(), params).into()) + .unwrap(); - let response = self.incoming.responses.recv()?; + let response = self.incoming.responses.recv().unwrap(); assert_eq!(response.id, self.request_id.into()); let result = match response.result { @@ -119,47 +127,33 @@ impl Client { Ok(serde_json::from_value(result)?) } - pub fn notify<N: lsp_types::notification::Notification>( - &mut self, - params: N::Params, - ) -> Result<()> { + pub fn notify<N: lsp_types::notification::Notification>(&mut self, params: N::Params) { self.outgoing - .send(Notification::new(N::METHOD.into(), serde_json::to_value(params)?).into())?; - - Ok(()) + .send(Notification::new(N::METHOD.into(), serde_json::to_value(params).unwrap()).into()) + .unwrap(); } - pub fn open(&mut self, name: &str, language_id: &str, text: String) -> Result<()> { + pub fn open(&mut self, name: &str, language_id: &str, text: String) { self.notify::<lsp_types::notification::DidOpenTextDocument>(DidOpenTextDocumentParams { text_document: lsp_types::TextDocumentItem { - uri: self.uri(name)?, + uri: self.uri(name), language_id: language_id.to_string(), version: 0, text, }, - })?; - - Ok(()) - } - - pub fn store_on_disk(&mut self, name: &str, text: &str) -> Result<()> { - let path = self.directory.path().join(name); - std::fs::create_dir_all(path.parent().unwrap())?; - std::fs::write(path, text)?; - Ok(()) + }); } - pub fn shutdown(mut self) -> Result<ClientResult> { - self.request::<Shutdown>(())?; - self.notify::<Exit>(())?; - Ok(ClientResult { + pub fn shutdown(mut self) -> ClientResult { + self.request::<Shutdown>(()).unwrap(); + self.notify::<Exit>(()); + ClientResult { directory: self.directory, incoming: self.incoming, - }) + } } - pub fn uri(&self, name: &str) -> Result<Url> { - Url::from_file_path(self.directory.path().join(name)) - .map_err(|()| anyhow::anyhow!("failed to create uri")) + pub fn uri(&self, name: &str) -> Url { + Url::from_file_path(self.directory.path().join(name)).unwrap() } } diff --git a/support/texlab/tests/integration/lsp/fixture.rs b/support/texlab/src/tests/fixture.rs index 83d63cce60..b837a9f5b0 100644 --- a/support/texlab/tests/integration/lsp/fixture.rs +++ b/support/texlab/src/tests/fixture.rs @@ -1,10 +1,9 @@ use std::collections::BTreeMap; -use anyhow::Result; use lsp_types::{Position, Range, TextDocumentIdentifier, TextDocumentPositionParams}; use rustc_hash::FxHashMap; -use crate::lsp::client::Client; +use super::client::Client; #[derive(Debug, PartialEq, Eq, Clone, Hash)] enum Line<'a> { @@ -60,12 +59,12 @@ pub struct FileCursor<'a> { } impl<'a> FileCursor<'a> { - pub fn into_params(self, server: &Client) -> Result<TextDocumentPositionParams> { - let text_document = TextDocumentIdentifier::new(server.uri(self.name)?); - Ok(TextDocumentPositionParams { + pub fn into_params(self, server: &Client) -> TextDocumentPositionParams { + let text_document = TextDocumentIdentifier::new(server.uri(self.name)); + TextDocumentPositionParams { text_document, position: self.position, - }) + } } } diff --git a/support/texlab/src/tests/issues.rs b/support/texlab/src/tests/issues.rs new file mode 100644 index 0000000000..8f578f5ada --- /dev/null +++ b/support/texlab/src/tests/issues.rs @@ -0,0 +1,12 @@ +use insta::assert_debug_snapshot; + +use crate::Options; + +#[test] +fn issue_707() { + assert_debug_snapshot!( + serde_json::from_value::<Option<Options>>(serde_json::json!({})) + .unwrap() + .unwrap_or_default() + ); +} diff --git a/support/texlab/src/tests/snapshots/texlab__tests__issues__issue_707.snap b/support/texlab/src/tests/snapshots/texlab__tests__issues__issue_707.snap new file mode 100644 index 0000000000..1397a08fc0 --- /dev/null +++ b/support/texlab/src/tests/snapshots/texlab__tests__issues__issue_707.snap @@ -0,0 +1,45 @@ +--- +source: src/tests/issues.rs +expression: "serde_json::from_value::<Option<Options>>(serde_json::json!({}))?.unwrap_or_default()" +--- +Options { + root_directory: None, + aux_directory: None, + bibtex_formatter: Texlab, + latex_formatter: Latexindent, + formatter_line_length: None, + diagnostics: DiagnosticsOptions { + allowed_patterns: [], + ignored_patterns: [], + }, + diagnostics_delay: DiagnosticsDelay( + 300ms, + ), + build: BuildOptions { + executable: BuildExecutable( + "latexmk", + ), + args: BuildArgs( + [ + "-pdf", + "-interaction=nonstopmode", + "-synctex=1", + "%f", + ], + ), + on_save: false, + forward_search_after: false, + }, + chktex: ChktexOptions { + on_open_and_save: false, + on_edit: false, + }, + latexindent: LatexindentOptions { + local: None, + modify_line_breaks: false, + }, + forward_search: ForwardSearchOptions { + executable: None, + args: None, + }, +} diff --git a/support/texlab/tests/integration/lsp/text_document.rs b/support/texlab/src/tests/text_document.rs index 283132d3c4..aac0553ec4 100644 --- a/support/texlab/tests/integration/lsp/text_document.rs +++ b/support/texlab/src/tests/text_document.rs @@ -1,4 +1,3 @@ -#[cfg(feature = "completion")] mod completion; mod definition; mod did_change_configuration; @@ -8,6 +7,6 @@ mod document_symbol; mod folding_range; mod formatting; mod hover; -mod publish_diagnostics; +mod inlay_hint; mod references; mod rename; diff --git a/support/texlab/tests/integration/lsp/text_document/completion.rs b/support/texlab/src/tests/text_document/completion.rs index 5e160904fe..d4f256cdfb 100644 --- a/support/texlab/tests/integration/lsp/text_document/completion.rs +++ b/support/texlab/src/tests/text_document/completion.rs @@ -1,19 +1,31 @@ -use anyhow::Result; use insta::assert_json_snapshot; use lsp_types::{ request::{Completion, ResolveCompletionItem}, - ClientCapabilities, CompletionItem, CompletionList, CompletionParams, CompletionResponse, - CompletionTextEdit, Range, + CompletionItem, CompletionList, CompletionParams, CompletionResponse, CompletionTextEdit, + Range, }; -use crate::lsp::{client::Client, fixture}; +use crate::tests::{client::Client, fixture}; + +fn complete(fixture: &str) -> Vec<CompletionItem> { + let mut client = Client::spawn(); + client.initialize( + serde_json::from_value(serde_json::json!({ + "textDocument": { + "completion": { + "completionItem": { + "documentationFormat": ["plaintext", "markdown"] + } + } + } + })) + .unwrap(), + None, + ); -fn complete(fixture: &str) -> Result<Vec<CompletionItem>, anyhow::Error> { - let mut client = Client::spawn()?; - client.initialize(ClientCapabilities::default(), None)?; let fixture = fixture::parse(fixture); for file in fixture.files { - client.open(file.name, file.lang, file.text)?; + client.open(file.name, file.lang, file.text); } let range = fixture @@ -31,11 +43,12 @@ fn complete(fixture: &str) -> Result<Vec<CompletionItem>, anyhow::Error> { let actual_list = client .request::<Completion>(CompletionParams { - text_document_position: fixture.cursor.unwrap().into_params(&client)?, + text_document_position: fixture.cursor.unwrap().into_params(&client), partial_result_params: Default::default(), work_done_progress_params: Default::default(), context: None, - })? + }) + .unwrap() .map_or(CompletionList::default(), |actual| match actual { CompletionResponse::List(list) => list, CompletionResponse::Array(_) => unreachable!(), @@ -51,11 +64,11 @@ fn complete(fixture: &str) -> Result<Vec<CompletionItem>, anyhow::Error> { .items .into_iter() .take(5) - .map(|item| client.request::<ResolveCompletionItem>(item)) - .collect::<Result<Vec<_>>>()?; + .map(|item| client.request::<ResolveCompletionItem>(item).unwrap()) + .collect(); - client.shutdown()?; - Ok(actual_items) + client.shutdown(); + actual_items } macro_rules! assert_items { @@ -71,7 +84,7 @@ macro_rules! assert_items { } #[test] -fn acronym_ref_simple() -> Result<()> { +fn acronym_ref_simple() { assert_items!(complete( r#" %TEX main.tex @@ -79,26 +92,22 @@ fn acronym_ref_simple() -> Result<()> { %SRC \acrshort{f} %CUR ^ %1.1 ^"# - )?); - - Ok(()) + )); } #[test] -fn acronym_ref_empty() -> Result<()> { +fn acronym_ref_empty() { assert_items!(complete( r#" %TEX main.tex %SRC \newacronym[longplural={Frames per Second}]{fpsLabel}{FPS}{Frame per Second} %SRC \acrshort{} %CUR ^"# - )?); - - Ok(()) + )); } #[test] -fn acronym_ref_after_group() -> Result<()> { +fn acronym_ref_after_group() { let actual_items = complete( r#" %TEX main.tex @@ -106,14 +115,13 @@ fn acronym_ref_after_group() -> Result<()> { %SRC \acrshort{} %CUR ^ %1.1 ^"#, - )?; + ); assert_eq!(actual_items, Vec::new()); - Ok(()) } #[test] -fn acronym_ref_open_brace() -> Result<()> { +fn acronym_ref_open_brace() { assert_items!(complete( r#" %TEX main.tex @@ -121,13 +129,23 @@ fn acronym_ref_open_brace() -> Result<()> { %SRC \acrshort{f %CUR ^ %1.1 ^"# - )?); + )); +} - Ok(()) +#[test] +fn acronym_package_ref() { + assert_items!(complete( + r#" +%TEX main.tex +%SRC \acrodef{fpsLabel}[FPS]{Frames per Second} +%SRC \ac{f +%CUR ^ +%1.1 ^"# + )); } #[test] -fn glossary_ref_simple() -> Result<()> { +fn glossary_ref_simple() { assert_items!(complete( r#" %TEX main.tex @@ -135,13 +153,11 @@ fn glossary_ref_simple() -> Result<()> { %SRC \gls{f} %CUR ^ %1.1 ^"# - )?); - - Ok(()) + )); } #[test] -fn glossary_ref_open_brace() -> Result<()> { +fn glossary_ref_open_brace() { assert_items!(complete( r#" %TEX main.tex @@ -149,26 +165,22 @@ fn glossary_ref_open_brace() -> Result<()> { %SRC \gls{f %CUR ^ %1.1 ^"# - )?); - - Ok(()) + )); } #[test] -fn argument_empty() -> Result<()> { +fn argument_empty() { assert_items!(complete( r#" %TEX main.tex %SRC \usepackage{amsfonts} %SRC \mathbb{} %CUR ^"# - )?); - - Ok(()) + )); } #[test] -fn argument_word() -> Result<()> { +fn argument_word() { assert_items!(complete( r#" %TEX main.tex @@ -176,13 +188,11 @@ fn argument_word() -> Result<()> { %SRC \mathbb{A} %CUR ^ %1.1 ^"# - )?); - - Ok(()) + )); } #[test] -fn argument_open_brace() -> Result<()> { +fn argument_open_brace() { assert_items!(complete( r#" %TEX main.tex @@ -190,13 +200,11 @@ fn argument_open_brace() -> Result<()> { %SRC \mathbb{ %CUR ^ %SRC Test"# - )?); - - Ok(()) + )); } #[test] -fn argument_open_brace_unrelated() -> Result<()> { +fn argument_open_brace_unrelated() { let actual_items = complete( r#" %TEX main.tex @@ -204,27 +212,24 @@ fn argument_open_brace_unrelated() -> Result<()> { %SRC \mathbb{}{ %CUR ^ %SRC Test"#, - )?; + ); assert_eq!(actual_items, Vec::new()); - Ok(()) } #[test] -fn begin_environment_without_snippet_support() -> Result<()> { +fn begin_environment_without_snippet_support() { assert_items!(complete( r#" %TEX main.tex %SRC \beg %CUR ^ %1.1 ^^^"# - )?); - - Ok(()) + )); } #[test] -fn citation() -> Result<()> { +fn citation() { assert_items!(complete( r#" %TEX main.tex @@ -243,13 +248,11 @@ fn citation() -> Result<()> { %SRC } %SRC %SRC @article{bar:2005,}"# - )?); - - Ok(()) + )); } #[test] -fn citation_open_brace() -> Result<()> { +fn citation_open_brace() { assert_items!(complete( r#" %TEX main.tex @@ -259,13 +262,11 @@ fn citation_open_brace() -> Result<()> { %BIB main.bib %SRC @article{foo,}"# - )?); - - Ok(()) + )); } #[test] -fn citation_open_brace_multiple() -> Result<()> { +fn citation_open_brace_multiple() { assert_items!(complete( r#" %TEX main.tex @@ -276,13 +277,11 @@ fn citation_open_brace_multiple() -> Result<()> { %BIB main.bib %SRC @article{foo,}"# - )?); - - Ok(()) + )); } #[test] -fn citation_acronym() -> Result<()> { +fn citation_acronym() { assert_items!(complete( r#" %TEX main.tex @@ -292,13 +291,11 @@ fn citation_acronym() -> Result<()> { %BIB main.bib %SRC @article{foo,}"# - )?); - - Ok(()) + )); } #[test] -fn citation_after_brace() -> Result<()> { +fn citation_after_brace() { let actual_items = complete( r#" %TEX main.tex @@ -311,124 +308,106 @@ fn citation_after_brace() -> Result<()> { %BIB main.bib %SRC @article{foo,}"#, - )?; + ); assert_eq!(actual_items, Vec::new()); - Ok(()) } #[test] -fn color_model_definition_simple() -> Result<()> { +fn color_model_definition_simple() { assert_items!(complete( r#" %TEX main.tex %SRC \definecolor{foo}{} %CUR ^"# - )?); - - Ok(()) + )); } #[test] -fn color_model_definition_open_brace() -> Result<()> { +fn color_model_definition_open_brace() { assert_items!(complete( r#" %TEX main.tex %SRC \definecolor{foo}{ %CUR ^"# - )?); - - Ok(()) + )); } #[test] -fn color_model_definition_set_simple() -> Result<()> { +fn color_model_definition_set_simple() { assert_items!(complete( r#" %TEX main.tex %SRC \definecolorset{} %CUR ^"# - )?); - - Ok(()) + )); } #[test] -fn color_model_definition_set_open_brace() -> Result<()> { +fn color_model_definition_set_open_brace() { assert_items!(complete( r#" %TEX main.tex %SRC \definecolorset{ %CUR ^"# - )?); - - Ok(()) + )); } #[test] -fn color_simple() -> Result<()> { +fn color_simple() { assert_items!(complete( r#" %TEX main.tex %SRC \color{} %CUR ^"# - )?); - - Ok(()) + )); } #[test] -fn color_word() -> Result<()> { +fn color_word() { assert_items!(complete( r#" %TEX main.tex %SRC \color{re} %CUR ^ %1.1 ^^"# - )?); - - Ok(()) + )); } #[test] -fn color_open_brace() -> Result<()> { +fn color_open_brace() { assert_items!(complete( r#" %TEX main.tex %SRC \color{ %CUR ^"# - )?); - - Ok(()) + )); } #[test] -fn component_command_simple() -> Result<()> { +fn component_command_simple() { assert_items!(complete( r#" %TEX main.tex %SRC \ %CUR ^"# - )?); - - Ok(()) + )); } #[test] -fn component_command_simple_before() -> Result<()> { +fn component_command_simple_before() { let actual_items = complete( r#" %TEX main.tex %SRC \ %CUR ^"#, - )?; + ); assert_eq!(actual_items, Vec::new()); - Ok(()) } #[test] -fn component_command_simple_package() -> Result<()> { +fn component_command_simple_package() { assert_items!(complete( r#" %TEX main.tex @@ -436,13 +415,11 @@ fn component_command_simple_package() -> Result<()> { %SRC \lips %CUR ^ %1.1 ^^^^"# - )?); - - Ok(()) + )); } #[test] -fn component_command_bibtex() -> Result<()> { +fn component_command_bibtex() { assert_items!(complete( r#" %BIB main.bib @@ -451,39 +428,33 @@ fn component_command_bibtex() -> Result<()> { %CUR ^ %1.1 ^^^ %SRC }"# - )?); - - Ok(()) + )); } #[test] -fn component_environment_simple() -> Result<()> { +fn component_environment_simple() { assert_items!(complete( r#" %TEX main.tex %SRC \begin{doc %CUR ^ %1.1 ^^^"# - )?); - - Ok(()) + )); } #[test] -fn component_environment_simple_end() -> Result<()> { +fn component_environment_simple_end() { assert_items!(complete( r#" %TEX main.tex %SRC \begin{document} %SRC \end{ %CUR ^"# - )?); - - Ok(()) + )); } #[test] -fn component_environment_class() -> Result<()> { +fn component_environment_class() { assert_items!(complete( r#" %TEX main.tex @@ -491,231 +462,195 @@ fn component_environment_class() -> Result<()> { %SRC \begin{thein} %CUR ^ %1.1 ^^^^^"# - )?); - - Ok(()) + )); } #[test] -fn component_environment_command_definition() -> Result<()> { +fn component_environment_command_definition() { assert_items!(complete( r#" %TEX main.tex %SRC \newcommand{\foo}{\begin{doc} %CUR ^ %1.1 ^^^"# - )?); - - Ok(()) + )); } #[test] -fn entry_type_at_empty() -> Result<()> { +fn entry_type_at_empty() { assert_items!(complete( r#" %BIB main.bib %SRC @ %CUR ^"# - )?); - - Ok(()) + )); } #[test] -fn entry_type_before_preamble() -> Result<()> { +fn entry_type_before_preamble() { assert_items!(complete( r#" %BIB main.bib %SRC @preamble %CUR ^ %1.1 ^^^^^^^^"# - )?); - - Ok(()) + )); } #[test] -fn entry_type_before_string() -> Result<()> { +fn entry_type_before_string() { assert_items!(complete( r#" %BIB main.bib %SRC @string %CUR ^ %1.1 ^^^^^^"# - )?); - - Ok(()) + )); } #[test] -fn entry_type_before_article() -> Result<()> { +fn entry_type_before_article() { assert_items!(complete( r#" %BIB main.bib %SRC @article %CUR ^ %1.1 ^^^^^^^"# - )?); - - Ok(()) + )); } #[test] -fn entry_type_after_preamble() -> Result<()> { +fn entry_type_after_preamble() { assert_items!(complete( r#" %BIB main.bib %SRC @preamble{ %CUR ^ %1.1 ^^^^^^^^"# - )?); - - Ok(()) + )); } #[test] -fn entry_type_after_string() -> Result<()> { +fn entry_type_after_string() { assert_items!(complete( r#" %BIB main.bib %SRC @string{ %CUR ^ %1.1 ^^^^^^"# - )?); - - Ok(()) + )); } #[test] -fn entry_type_complete_entry() -> Result<()> { +fn entry_type_complete_entry() { assert_items!(complete( r#" %BIB main.bib %SRC @article{foo, author = {foo}} %CUR ^ %1.1 ^^^^^^^"# - )?); - - Ok(()) + )); } #[test] -fn field_empty_entry_open() -> Result<()> { +fn field_empty_entry_open() { assert_items!(complete( r#" %BIB main.bib %SRC @article{foo, %CUR ^"# - )?); - - Ok(()) + )); } #[test] -fn field_empty_entry_closed() -> Result<()> { +fn field_empty_entry_closed() { assert_items!(complete( r#" %BIB main.bib %SRC @article{foo,} %CUR ^"# - )?); - - Ok(()) + )); } #[test] -fn field_entry_field_name() -> Result<()> { +fn field_entry_field_name() { assert_items!(complete( r#" %BIB main.bib %SRC @article{foo, a %CUR ^ %1.1 ^"# - )?); - - Ok(()) + )); } #[test] -fn field_entry_two_fields_name_open() -> Result<()> { +fn field_entry_two_fields_name_open() { assert_items!(complete( r#" %BIB main.bib %SRC @article{foo, author = bar, edit %CUR ^ %1.1 ^^^^"# - )?); - - Ok(()) + )); } #[test] -fn field_entry_two_fields_name_closed() -> Result<()> { +fn field_entry_two_fields_name_closed() { assert_items!(complete( r#" %BIB main.bib %SRC @article{foo, author = bar, edit} %CUR ^ %1.1 ^^^^"# - )?); - - Ok(()) + )); } #[test] -fn import_package_open_brace() -> Result<()> { +fn import_package_open_brace() { assert_items!(complete( r#" %TEX main.tex %SRC \usepackage{lips %CUR ^ %1.1 ^^^^"# - )?); - - Ok(()) + )); } #[test] -fn import_package_closed_brace() -> Result<()> { +fn import_package_closed_brace() { assert_items!(complete( r#" %TEX main.tex %SRC \usepackage{lips} %CUR ^ %1.1 ^^^^"# - )?); - - Ok(()) + )); } #[test] -fn import_class_open_brace() -> Result<()> { +fn import_class_open_brace() { assert_items!(complete( r#" %TEX main.tex %SRC \documentclass{art \foo %CUR ^ %1.1 ^^^"# - )?); - - Ok(()) + )); } #[test] -fn import_class_closed_brace() -> Result<()> { +fn import_class_closed_brace() { assert_items!(complete( r#" %TEX main.tex %SRC \documentclass{art} %CUR ^ %1.1 ^^^"# - )?); - - Ok(()) + )); } #[test] -fn label() -> Result<()> { +fn label() { assert_items!(complete( r#" %TEX foo.tex @@ -775,13 +710,11 @@ fn label() -> Result<()> { %SRC \newlabel{eq:bar}{{2}{1}} %SRC \newlabel{thm:foo}{{1}{1}} %SRC \@input{bar.aux}"# - )?); - - Ok(()) + )); } #[test] -fn theorem_begin() -> Result<()> { +fn theorem_begin() { assert_items!(complete( r#" %TEX main.tex @@ -789,13 +722,11 @@ fn theorem_begin() -> Result<()> { %SRC \begin{lem %CUR ^ %1.1 ^^^"# - )?); - - Ok(()) + )); } #[test] -fn theorem_end() -> Result<()> { +fn theorem_end() { assert_items!(complete( r#" %TEX main.tex @@ -804,37 +735,31 @@ fn theorem_end() -> Result<()> { %SRC \end{lem %CUR ^ %1.1 ^^^"# - )?); - - Ok(()) + )); } #[test] -fn tikz_library_open_brace() -> Result<()> { +fn tikz_library_open_brace() { assert_items!(complete( r#" %TEX main.tex %SRC \usepgflibrary{ %CUR ^"# - )?); - - Ok(()) + )); } #[test] -fn tikz_library_closed_brace() -> Result<()> { +fn tikz_library_closed_brace() { assert_items!(complete( r#" %TEX main.tex %SRC \usepgflibrary{} %CUR ^"# - )?); - - Ok(()) + )); } #[test] -fn test_user_command() -> Result<()> { +fn test_user_command() { assert_items!(complete( r#" %TEX main.tex @@ -846,13 +771,11 @@ fn test_user_command() -> Result<()> { %SRC \end{foo} %SRC \begin{fo} "# - )?); - - Ok(()) + )); } #[test] -fn test_user_environment() -> Result<()> { +fn test_user_environment() { assert_items!(complete( r#" %TEX main.tex @@ -864,7 +787,26 @@ fn test_user_environment() -> Result<()> { %CUR ^ %1.1 ^^ "# - )?); + )); +} + +#[test] +fn test_project_resolution() { + assert_items!(complete( + r#" +%TEX main.tex +%SRC \documentclass{article} +%SRC \import{sub}{sub/sub.tex} +%SRC \lipsu +%CUR ^ +%1.1 ^^^^^ - Ok(()) +%TEX sub/sub.tex +%SRC \input{child.tex} + +%TEX sub/child.tex +%SRC \usepackage{lipsum} + +"# + )); } diff --git a/support/texlab/tests/integration/lsp/text_document/definition.rs b/support/texlab/src/tests/text_document/definition.rs index 203c350464..b1b915c6c9 100644 --- a/support/texlab/tests/integration/lsp/text_document/definition.rs +++ b/support/texlab/src/tests/text_document/definition.rs @@ -1,26 +1,25 @@ -use anyhow::Result; use assert_unordered::assert_eq_unordered; use lsp_types::{ request::GotoDefinition, ClientCapabilities, GotoDefinitionParams, GotoDefinitionResponse, LocationLink, }; -use crate::lsp::{client::Client, fixture}; +use crate::tests::{client::Client, fixture}; -fn check(fixture: &str) -> Result<()> { - let mut client = Client::spawn()?; - client.initialize(ClientCapabilities::default(), None)?; +fn check(fixture: &str) { + let mut client = Client::spawn(); + client.initialize(ClientCapabilities::default(), None); let fixture = fixture::parse(fixture); for file in fixture.files { - client.open(file.name, file.lang, file.text)?; + client.open(file.name, file.lang, file.text); } let mut expected_links = Vec::new(); for ranges in fixture.ranges.values() { expected_links.push(LocationLink { origin_selection_range: Some(ranges[&1].range), - target_uri: client.uri(ranges[&2].name)?, + target_uri: client.uri(ranges[&2].name), target_range: ranges[&2].range, target_selection_range: ranges[&3].range, }); @@ -28,23 +27,22 @@ fn check(fixture: &str) -> Result<()> { let actual_links = client .request::<GotoDefinition>(GotoDefinitionParams { - text_document_position_params: fixture.cursor.unwrap().into_params(&client)?, + text_document_position_params: fixture.cursor.unwrap().into_params(&client), partial_result_params: Default::default(), work_done_progress_params: Default::default(), - })? + }) + .unwrap() .map_or(Vec::new(), |actual| match actual { GotoDefinitionResponse::Link(links) => links, GotoDefinitionResponse::Array(_) | GotoDefinitionResponse::Scalar(_) => unreachable!(), }); - client.shutdown()?; - + client.shutdown(); assert_eq_unordered!(actual_links, expected_links); - Ok(()) } #[test] -fn command_definition() -> Result<()> { +fn command_definition() { check( r#" %TEX main.tex @@ -59,7 +57,7 @@ fn command_definition() -> Result<()> { } #[test] -fn document() -> Result<()> { +fn document() { check( r#" %TEX foo.tex @@ -79,7 +77,7 @@ fn document() -> Result<()> { } #[test] -fn entry() -> Result<()> { +fn entry() { check( r#" %TEX foo.tex @@ -100,7 +98,7 @@ fn entry() -> Result<()> { } #[test] -fn string_simple() -> Result<()> { +fn string_simple() { check( r#" %BIB main.bib @@ -115,7 +113,7 @@ fn string_simple() -> Result<()> { } #[test] -fn string_join() -> Result<()> { +fn string_join() { check( r#" %BIB main.bib @@ -130,7 +128,7 @@ fn string_join() -> Result<()> { } #[test] -fn string_field() -> Result<()> { +fn string_field() { check( r#" %BIB main.bib diff --git a/support/texlab/tests/integration/lsp/text_document/did_change_configuration.rs b/support/texlab/src/tests/text_document/did_change_configuration.rs index c45dca094b..15aae0ee4b 100644 --- a/support/texlab/tests/integration/lsp/text_document/did_change_configuration.rs +++ b/support/texlab/src/tests/text_document/did_change_configuration.rs @@ -1,16 +1,15 @@ -use anyhow::Result; use insta::assert_snapshot; use lsp_types::{ notification::{DidChangeConfiguration, Notification, ShowMessage}, ClientCapabilities, DidChangeConfigurationParams, ShowMessageParams, }; -use crate::lsp::client::Client; +use crate::tests::client::Client; #[test] -fn invalid_configuration() -> Result<()> { - let mut client = Client::spawn()?; - client.initialize(ClientCapabilities::default(), None)?; +fn invalid_configuration() { + let mut client = Client::spawn(); + client.initialize(ClientCapabilities::default(), None); client.notify::<DidChangeConfiguration>(DidChangeConfigurationParams { settings: serde_json::json!({ @@ -18,9 +17,9 @@ fn invalid_configuration() -> Result<()> { "allowedPatterns": ["\\"] } }), - })?; + }); - let result = client.shutdown()?; + let result = client.shutdown(); let message = result .incoming .notifications @@ -35,5 +34,4 @@ fn invalid_configuration() -> Result<()> { .message; assert_snapshot!(message); - Ok(()) } diff --git a/support/texlab/tests/integration/lsp/text_document/document_highlight.rs b/support/texlab/src/tests/text_document/document_highlight.rs index 92102ce0ca..01945ce342 100644 --- a/support/texlab/tests/integration/lsp/text_document/document_highlight.rs +++ b/support/texlab/src/tests/text_document/document_highlight.rs @@ -1,19 +1,18 @@ -use anyhow::Result; use assert_unordered::assert_eq_unordered; use lsp_types::{ request::DocumentHighlightRequest, ClientCapabilities, DocumentHighlight, DocumentHighlightKind, DocumentHighlightParams, }; -use crate::lsp::{client::Client, fixture}; +use crate::tests::{client::Client, fixture}; -fn check(fixture: &str) -> Result<()> { - let mut client = Client::spawn()?; - client.initialize(ClientCapabilities::default(), None)?; +fn check(fixture: &str) { + let mut client = Client::spawn(); + client.initialize(ClientCapabilities::default(), None); let fixture = fixture::parse(fixture); for file in fixture.files { - client.open(file.name, file.lang, file.text)?; + client.open(file.name, file.lang, file.text); } let mut expected_highlights = Vec::new(); @@ -34,20 +33,19 @@ fn check(fixture: &str) -> Result<()> { let actual_highlights = client .request::<DocumentHighlightRequest>(DocumentHighlightParams { - text_document_position_params: fixture.cursor.unwrap().into_params(&client)?, + text_document_position_params: fixture.cursor.unwrap().into_params(&client), partial_result_params: Default::default(), work_done_progress_params: Default::default(), - })? + }) + .unwrap() .unwrap_or_default(); - client.shutdown()?; - + client.shutdown(); assert_eq_unordered!(actual_highlights, expected_highlights); - Ok(()) } #[test] -fn test_label() -> Result<()> { +fn test_label() { check( r#" %TEX main.tex diff --git a/support/texlab/tests/integration/lsp/text_document/document_link.rs b/support/texlab/src/tests/text_document/document_link.rs index 1a773fd478..8b4a30ceeb 100644 --- a/support/texlab/tests/integration/lsp/text_document/document_link.rs +++ b/support/texlab/src/tests/text_document/document_link.rs @@ -1,26 +1,25 @@ -use anyhow::Result; use assert_unordered::assert_eq_unordered; use lsp_types::{ request::DocumentLinkRequest, ClientCapabilities, DocumentLink, DocumentLinkParams, TextDocumentIdentifier, }; -use crate::lsp::{client::Client, fixture}; +use crate::tests::{client::Client, fixture}; -fn check(fixture: &str) -> Result<()> { - let mut client = Client::spawn()?; - client.initialize(ClientCapabilities::default(), None)?; +fn check(fixture: &str) { + let mut client = Client::spawn(); + client.initialize(ClientCapabilities::default(), None); let fixture = fixture::parse(fixture); for file in fixture.files { - client.open(file.name, file.lang, file.text)?; + client.open(file.name, file.lang, file.text); } let mut expected_links = Vec::new(); for ranges in fixture.ranges.values() { expected_links.push(DocumentLink { range: ranges[&1].range, - target: Some(client.uri(ranges[&2].name)?), + target: Some(client.uri(ranges[&2].name)), tooltip: None, data: None, }); @@ -28,20 +27,19 @@ fn check(fixture: &str) -> Result<()> { let actual_links = client .request::<DocumentLinkRequest>(DocumentLinkParams { - text_document: TextDocumentIdentifier::new(client.uri(fixture.cursor.unwrap().name)?), + text_document: TextDocumentIdentifier::new(client.uri(fixture.cursor.unwrap().name)), work_done_progress_params: Default::default(), partial_result_params: Default::default(), - })? + }) + .unwrap() .unwrap_or_default(); - client.shutdown()?; - + client.shutdown(); assert_eq_unordered!(actual_links, expected_links); - Ok(()) } #[test] -fn document_include() -> Result<()> { +fn document_include() { check( r#" %TEX foo.tex @@ -57,12 +55,12 @@ fn document_include() -> Result<()> { } #[test] -fn document_import() -> Result<()> { +fn document_import() { check( r#" %TEX foo.tex -%SRC \import{bar/}{baz} -%1.1 ^^^ +%SRC \import{.}{bar/baz} +%1.1 ^^^^^^^ %CUR ^ %TEX bar/baz.tex diff --git a/support/texlab/tests/integration/lsp/text_document/document_symbol.rs b/support/texlab/src/tests/text_document/document_symbol.rs index 50bb9db3fe..2eab81631e 100644 --- a/support/texlab/tests/integration/lsp/text_document/document_symbol.rs +++ b/support/texlab/src/tests/text_document/document_symbol.rs @@ -1,42 +1,43 @@ -use anyhow::Result; use insta::{assert_json_snapshot, internals::Redaction}; use lsp_types::{ request::DocumentSymbolRequest, DocumentSymbolParams, DocumentSymbolResponse, TextDocumentIdentifier, Url, }; -use crate::lsp::{client::Client, fixture}; +use crate::tests::{client::Client, fixture}; struct SymbolResult { response: Option<DocumentSymbolResponse>, uri_redaction: Redaction, } -fn find_symbols(fixture: &str, client_capabilities: serde_json::Value) -> Result<SymbolResult> { - let mut client = Client::spawn()?; - client.initialize(serde_json::from_value(client_capabilities)?, None)?; +fn find_symbols(fixture: &str, client_capabilities: serde_json::Value) -> SymbolResult { + let mut client = Client::spawn(); + client.initialize(serde_json::from_value(client_capabilities).unwrap(), None); let fixture = fixture::parse(fixture); let file = fixture.files.into_iter().next().unwrap(); - client.open(file.name, file.lang, file.text)?; + client.open(file.name, file.lang, file.text); - let response = client.request::<DocumentSymbolRequest>(DocumentSymbolParams { - text_document: TextDocumentIdentifier::new(client.uri(file.name)?), - work_done_progress_params: Default::default(), - partial_result_params: Default::default(), - })?; + let response = client + .request::<DocumentSymbolRequest>(DocumentSymbolParams { + text_document: TextDocumentIdentifier::new(client.uri(file.name)), + work_done_progress_params: Default::default(), + partial_result_params: Default::default(), + }) + .unwrap(); - let result = client.shutdown()?; + let result = client.shutdown(); let uri = Url::from_directory_path(result.directory.path()).unwrap(); let uri_redaction = insta::dynamic_redaction(move |content, _path| { content.as_str().unwrap().replace(uri.as_str(), "[tmp]/") }); - Ok(SymbolResult { + SymbolResult { response, uri_redaction, - }) + } } macro_rules! assert_symbols { @@ -49,7 +50,7 @@ macro_rules! assert_symbols { } #[test] -fn enumerate_nested() -> Result<()> { +fn enumerate_nested() { assert_symbols!(find_symbols( r#" %TEX main.tex @@ -78,13 +79,11 @@ fn enumerate_nested() -> Result<()> { }, }, }), - )?); - - Ok(()) + )); } #[test] -fn enumerate_flat() -> Result<()> { +fn enumerate_flat() { assert_symbols!(find_symbols( r#" %TEX main.tex @@ -107,13 +106,11 @@ fn enumerate_flat() -> Result<()> { %SRC \newlabel{it:qux}{{2}{1}} "#, serde_json::json!({}), - )?); - - Ok(()) + )); } #[test] -fn equation_nested() -> Result<()> { +fn equation_nested() { assert_symbols!(find_symbols( r#" %TEX main.tex @@ -146,13 +143,11 @@ fn equation_nested() -> Result<()> { }, }, }), - )?); - - Ok(()) + )); } #[test] -fn equation_flat() -> Result<()> { +fn equation_flat() { assert_symbols!(find_symbols( r#" %TEX main.tex @@ -179,13 +174,11 @@ fn equation_flat() -> Result<()> { %SRC \newlabel{eq:foo}{{1}{1}} "#, serde_json::json!({}), - )?); - - Ok(()) + )); } #[test] -fn float_nested() -> Result<()> { +fn float_nested() { assert_symbols!(find_symbols( r#" %TEX main.tex @@ -228,13 +221,11 @@ fn float_nested() -> Result<()> { }, }, }), - )?); - - Ok(()) + )); } #[test] -fn float_flat() -> Result<()> { +fn float_flat() { assert_symbols!(find_symbols( r#" %TEX main.tex @@ -271,13 +262,11 @@ fn float_flat() -> Result<()> { %SRC \@writefile{lof}{\contentsline {figure}{\numberline {3}{\ignorespaces Baz}}{1}\protected@file@percent } "#, serde_json::json!({}), - )?); - - Ok(()) + )); } #[test] -fn section_nested() -> Result<()> { +fn section_nested() { assert_symbols!(find_symbols( r#" %TEX main.tex @@ -306,13 +295,11 @@ fn section_nested() -> Result<()> { }, }, }), - )?); - - Ok(()) + )); } #[test] -fn section_flat() -> Result<()> { +fn section_flat() { assert_symbols!(find_symbols( r#" %TEX main.tex @@ -335,13 +322,11 @@ fn section_flat() -> Result<()> { %SRC \newlabel{sec:bar}{{2}{1}} "#, serde_json::json!({}), - )?); - - Ok(()) + )); } #[test] -fn theorem_nested() -> Result<()> { +fn theorem_nested() { assert_symbols!(find_symbols( r#" %TEX main.tex @@ -381,13 +366,11 @@ fn theorem_nested() -> Result<()> { }, }, }), - )?); - - Ok(()) + )); } #[test] -fn theorem_flat() -> Result<()> { +fn theorem_flat() { assert_symbols!(find_symbols( r#" %TEX main.tex @@ -421,7 +404,5 @@ fn theorem_flat() -> Result<()> { %SRC \newlabel{thm:bar}{{2}{1}} "#, serde_json::json!({}), - )?); - - Ok(()) + )); } diff --git a/support/texlab/tests/integration/lsp/text_document/folding_range.rs b/support/texlab/src/tests/text_document/folding_range.rs index 1d75ba3e0e..4b589222b1 100644 --- a/support/texlab/tests/integration/lsp/text_document/folding_range.rs +++ b/support/texlab/src/tests/text_document/folding_range.rs @@ -1,30 +1,30 @@ -use anyhow::Result; use assert_unordered::assert_eq_unordered; use lsp_types::{ request::FoldingRangeRequest, ClientCapabilities, FoldingRange, FoldingRangeKind, FoldingRangeParams, TextDocumentIdentifier, }; -use crate::lsp::{client::Client, fixture}; +use crate::tests::{client::Client, fixture}; -fn check(fixture: &str, expected_ranges: Vec<(u32, u32, u32, u32)>) -> Result<()> { - let mut client = Client::spawn()?; - client.initialize(ClientCapabilities::default(), None)?; +fn check(fixture: &str, expected_ranges: Vec<(u32, u32, u32, u32)>) { + let mut client = Client::spawn(); + client.initialize(ClientCapabilities::default(), None); let fixture = fixture::parse(fixture); for file in fixture.files { - client.open(file.name, file.lang, file.text)?; + client.open(file.name, file.lang, file.text); } let actual_foldings = client .request::<FoldingRangeRequest>(FoldingRangeParams { - text_document: TextDocumentIdentifier::new(client.uri(fixture.cursor.unwrap().name)?), + text_document: TextDocumentIdentifier::new(client.uri(fixture.cursor.unwrap().name)), work_done_progress_params: Default::default(), partial_result_params: Default::default(), - })? + }) + .unwrap() .unwrap_or_default(); - client.shutdown()?; + client.shutdown(); let expected_foldings = expected_ranges .into_iter() @@ -40,11 +40,10 @@ fn check(fixture: &str, expected_ranges: Vec<(u32, u32, u32, u32)>) -> Result<() .collect(); assert_eq_unordered!(actual_foldings, expected_foldings); - Ok(()) } #[test] -fn latex() -> Result<()> { +fn latex() { check( r#" %TEX main.tex @@ -70,7 +69,7 @@ fn latex() -> Result<()> { } #[test] -fn bibtex() -> Result<()> { +fn bibtex() { check( r#" %BIB main.bib diff --git a/support/texlab/tests/integration/lsp/text_document/formatting.rs b/support/texlab/src/tests/text_document/formatting.rs index a0c02bf4b1..eb6804ca66 100644 --- a/support/texlab/tests/integration/lsp/text_document/formatting.rs +++ b/support/texlab/src/tests/text_document/formatting.rs @@ -1,35 +1,37 @@ -use anyhow::Result; use insta::assert_snapshot; use lsp_types::{ request::Formatting, ClientCapabilities, DocumentFormattingParams, FormattingOptions, TextDocumentIdentifier, }; -use texlab::{LineIndex, LineIndexExt}; -use crate::lsp::{client::Client, fixture}; +use crate::{ + tests::{client::Client, fixture}, + util::{line_index::LineIndex, line_index_ext::LineIndexExt}, +}; -fn format(fixture: &str) -> Result<String> { - let mut client = Client::spawn()?; - client.initialize(ClientCapabilities::default(), None)?; +fn format(fixture: &str) -> String { + let mut client = Client::spawn(); + client.initialize(ClientCapabilities::default(), None); let fixture = fixture::parse(fixture); let file = fixture.files.into_iter().next().unwrap(); let old_text = file.text.clone(); - client.open(file.name, file.lang, file.text)?; + client.open(file.name, file.lang, file.text); let actual_edits = client .request::<Formatting>(DocumentFormattingParams { - text_document: TextDocumentIdentifier::new(client.uri(file.name)?), + text_document: TextDocumentIdentifier::new(client.uri(file.name)), work_done_progress_params: Default::default(), options: FormattingOptions { insert_spaces: true, tab_size: 4, ..Default::default() }, - })? + }) + .unwrap() .unwrap_or_default(); - client.shutdown()?; + client.shutdown(); let line_index = LineIndex::new(&old_text); let mut actual_text = old_text; @@ -38,24 +40,22 @@ fn format(fixture: &str) -> Result<String> { actual_text.replace_range::<std::ops::Range<usize>>(range.into(), &edit.new_text); } - Ok(actual_text) + actual_text } #[test] -fn bibtex_internal_wrap_long_lines() -> Result<()> { +fn bibtex_internal_wrap_long_lines() { assert_snapshot!(format( r#" %BIB main.bib %SRC @article{foo, bar = {Lorem ipsum dolor sit amet, consectetur adipiscing elit. %SRC Lorem ipsum dolor sit amet, %SRC consectetur adipiscing elit. Lorem ipsum dolor sit amet, consectetur adipiscing elit.},}"#, - )?); - - Ok(()) + )); } #[test] -fn bibtex_internal_multiple_entries() -> Result<()> { +fn bibtex_internal_multiple_entries() { assert_snapshot!(format( r#" %BIB main.bib @@ -64,85 +64,69 @@ fn bibtex_internal_multiple_entries() -> Result<()> { %SRC %SRC @article{foo, bar = {Lorem ipsum dolor sit amet, consectetur adipiscing elit. Lorem ipsum dolor sit amet, %SRC consectetur adipiscing elit. Lorem ipsum dolor sit amet, consectetur adipiscing elit.},}""#, - )?); - - Ok(()) + )); } #[test] -fn bibtex_internal_trailing_comma() -> Result<()> { +fn bibtex_internal_trailing_comma() { assert_snapshot!(format( r#" %BIB main.bib %SRC @article{foo, bar = baz}"#, - )?); - - Ok(()) + )); } #[test] -fn bibtex_internal_insert_braces() -> Result<()> { +fn bibtex_internal_insert_braces() { assert_snapshot!(format( r#" %BIB main.bib %SRC @article{foo, bar = baz,"#, - )?); - - Ok(()) + )); } #[test] -fn bibtex_internal_command() -> Result<()> { +fn bibtex_internal_command() { assert_snapshot!(format( r#" %BIB main.bib %SRC @article{foo, bar = "\baz",}"#, - )?); - - Ok(()) + )); } #[test] -fn bibtex_internal_join_strings() -> Result<()> { +fn bibtex_internal_join_strings() { assert_snapshot!(format( r#" %BIB main.bib %SRC @article{foo, bar = "baz" # "qux"}"#, - )?); - - Ok(()) + )); } #[test] -fn bibtex_internal_parens() -> Result<()> { +fn bibtex_internal_parens() { assert_snapshot!(format( r#" %BIB main.bib %SRC @article(foo,)"#, - )?); - - Ok(()) + )); } #[test] -fn bibtex_internal_string() -> Result<()> { +fn bibtex_internal_string() { assert_snapshot!(format( r#" %BIB main.bib %SRC @string{foo="bar"}"#, - )?); - - Ok(()) + )); } #[test] -fn bibtex_internal_preamble() -> Result<()> { +fn bibtex_internal_preamble() { assert_snapshot!(format( r#" %BIB main.bib %SRC @preamble{ %SRC "foo bar baz" }"#, - )?); - - Ok(()) + )); } diff --git a/support/texlab/tests/integration/lsp/text_document/hover.rs b/support/texlab/src/tests/text_document/hover.rs index 2a9e8c271f..302be82ca3 100644 --- a/support/texlab/tests/integration/lsp/text_document/hover.rs +++ b/support/texlab/src/tests/text_document/hover.rs @@ -1,19 +1,20 @@ -use anyhow::Result; use lsp_types::{ request::HoverRequest, ClientCapabilities, Hover, HoverContents, HoverParams, MarkupContent, MarkupKind, }; -use texlab::{component_db::COMPONENT_DATABASE, LANGUAGE_DATA}; -use crate::lsp::{client::Client, fixture}; +use crate::{ + tests::{client::Client, fixture}, + util::{components::COMPONENT_DATABASE, lang_data::LANGUAGE_DATA}, +}; -fn check(fixture: &str, contents: Option<HoverContents>) -> Result<()> { - let mut client = Client::spawn()?; - client.initialize(ClientCapabilities::default(), None)?; +fn check(fixture: &str, contents: Option<HoverContents>) { + let mut client = Client::spawn(); + client.initialize(ClientCapabilities::default(), None); let fixture = fixture::parse(fixture); for file in fixture.files { - client.open(file.name, file.lang, file.text)?; + client.open(file.name, file.lang, file.text); } let range = fixture @@ -23,21 +24,21 @@ fn check(fixture: &str, contents: Option<HoverContents>) -> Result<()> { .and_then(|map| map.values().next()) .map(|file_range| file_range.range); - let actual_hover = client.request::<HoverRequest>(HoverParams { - text_document_position_params: fixture.cursor.unwrap().into_params(&client)?, - work_done_progress_params: Default::default(), - })?; + let actual_hover = client + .request::<HoverRequest>(HoverParams { + text_document_position_params: fixture.cursor.unwrap().into_params(&client), + work_done_progress_params: Default::default(), + }) + .unwrap(); - client.shutdown()?; + client.shutdown(); let expected_hover = contents.map(|contents| Hover { range, contents }); - assert_eq!(actual_hover, expected_hover); - Ok(()) } #[test] -fn empty_latex_document() -> Result<()> { +fn empty_latex_document() { check( r#" %TEX main.tex @@ -49,7 +50,7 @@ fn empty_latex_document() -> Result<()> { } #[test] -fn empty_bibtex_document() -> Result<()> { +fn empty_bibtex_document() { check( r#" %BIB main.bib @@ -61,7 +62,7 @@ fn empty_bibtex_document() -> Result<()> { } #[test] -fn citation_inside_cite() -> Result<()> { +fn citation_inside_cite() { check( r#" %BIB main.bib @@ -81,7 +82,7 @@ fn citation_inside_cite() -> Result<()> { } #[test] -fn citation_inside_entry() -> Result<()> { +fn citation_inside_entry() { check( r#" %BIB main.bib @@ -101,7 +102,7 @@ fn citation_inside_entry() -> Result<()> { } #[test] -fn component_known_package() -> Result<()> { +fn component_known_package() { check( r#" %TEX main.tex @@ -116,7 +117,7 @@ fn component_known_package() -> Result<()> { } #[test] -fn component_unknown_class() -> Result<()> { +fn component_unknown_class() { check( r#" %TEX main.tex @@ -128,7 +129,7 @@ fn component_unknown_class() -> Result<()> { } #[test] -fn entry_type_known_type() -> Result<()> { +fn entry_type_known_type() { check( r#" %BIB main.bib @@ -147,7 +148,7 @@ fn entry_type_known_type() -> Result<()> { } #[test] -fn entry_type_unknown_field() -> Result<()> { +fn entry_type_unknown_field() { check( r#" %BIB main.bib @@ -159,7 +160,7 @@ fn entry_type_unknown_field() -> Result<()> { } #[test] -fn entry_type_key() -> Result<()> { +fn entry_type_key() { check( r#" %BIB main.bib @@ -171,7 +172,7 @@ fn entry_type_key() -> Result<()> { } #[test] -fn field_known() -> Result<()> { +fn field_known() { check( r#" %BIB main.bib @@ -190,7 +191,7 @@ fn field_known() -> Result<()> { } #[test] -fn field_unknown() -> Result<()> { +fn field_unknown() { check( r#" %BIB main.bib @@ -202,7 +203,7 @@ fn field_unknown() -> Result<()> { } #[test] -fn section() -> Result<()> { +fn section() { check( r#" %TEX main.tex @@ -219,7 +220,7 @@ fn section() -> Result<()> { } #[test] -fn string_inside_reference() -> Result<()> { +fn string_inside_reference() { check( r#" %BIB main.bib @@ -237,7 +238,7 @@ fn string_inside_reference() -> Result<()> { } #[test] -fn string_inside_field() -> Result<()> { +fn string_inside_field() { check( r#" %BIB main.bib @@ -251,7 +252,7 @@ fn string_inside_field() -> Result<()> { } #[test] -fn label_theorem_child_file() -> Result<()> { +fn label_theorem_child_file() { check( r#" %TEX main.tex @@ -275,7 +276,7 @@ fn label_theorem_child_file() -> Result<()> { } #[test] -fn label_theorem_child_file_mumber() -> Result<()> { +fn label_theorem_child_file_mumber() { check( r#" %TEX main.tex diff --git a/support/texlab/src/tests/text_document/inlay_hint.rs b/support/texlab/src/tests/text_document/inlay_hint.rs new file mode 100644 index 0000000000..acf5c3e132 --- /dev/null +++ b/support/texlab/src/tests/text_document/inlay_hint.rs @@ -0,0 +1,65 @@ +use insta::assert_json_snapshot; +use lsp_types::{ + request::InlayHintRequest, ClientCapabilities, InlayHint, InlayHintParams, Position, Range, + TextDocumentIdentifier, +}; + +use crate::tests::{client::Client, fixture}; + +fn check(fixture: &str) -> Vec<InlayHint> { + let mut client = Client::spawn(); + client.initialize(ClientCapabilities::default(), None); + + let fixture = fixture::parse(fixture); + let uri = client.uri(fixture.files[0].name); + + for file in fixture.files { + client.open(file.name, file.lang, file.text); + } + + let actual_hints = client + .request::<InlayHintRequest>(InlayHintParams { + text_document: TextDocumentIdentifier::new(uri), + range: Range::new(Position::new(0, 0), Position::new(12, 0)), + work_done_progress_params: Default::default(), + }) + .unwrap() + .unwrap_or_default(); + + client.shutdown(); + actual_hints +} + +#[test] +fn label_definition() { + assert_json_snapshot!(check( + r#" +%TEX main.tex +%SRC \documentclass{article} +%SRC \usepackage{caption} +%SRC \begin{document} +%SRC \section{Foo}\label{sec:foo} +%SRC \section{Bar}\label{sec:bar} +%SRC \subsection{Baz}\label{sec:baz} +%SRC \begin{figure} +%SRC Test +%SRC \label{fig:qux} +%SRC \caption{Qux} +%SRC \end{figure} +%SRC \end{document} + +%TEX main.aux +%SRC \relax +%SRC \providecommand*\caption@xref[2]{\@setref\relax\@undefined{#1}} +%SRC \newlabel{fig:qux}{{\caption@xref {fig:qux}{ on input line 15}}{1}} +%SRC \@writefile{lof}{\contentsline {figure}{\numberline {1}{\ignorespaces Qux\relax }}{1}{}\protected@file@percent } +%SRC \@writefile{toc}{\contentsline {section}{\numberline {1}Foo}{1}{}\protected@file@percent } +%SRC \newlabel{sec:foo}{{1}{1}} +%SRC \@writefile{toc}{\contentsline {section}{\numberline {2}Bar}{1}{}\protected@file@percent } +%SRC \newlabel{sec:bar}{{2}{1}} +%SRC \@writefile{toc}{\contentsline {subsection}{\numberline {2.1}Baz}{1}{}\protected@file@percent } +%SRC \newlabel{sec:baz}{{2.1}{1}} +%SRC \gdef \@abspage@last{1} +"#, + )); +} diff --git a/support/texlab/tests/integration/lsp/text_document/references.rs b/support/texlab/src/tests/text_document/references.rs index ff272673dd..a0ebed1fb4 100644 --- a/support/texlab/tests/integration/lsp/text_document/references.rs +++ b/support/texlab/src/tests/text_document/references.rs @@ -1,45 +1,41 @@ -use anyhow::Result; use assert_unordered::assert_eq_unordered; use lsp_types::{ request::References, ClientCapabilities, Location, ReferenceContext, ReferenceParams, }; -use crate::lsp::{client::Client, fixture}; +use crate::tests::{client::Client, fixture}; -fn check(fixture: &str, context: ReferenceContext) -> Result<()> { - let mut client = Client::spawn()?; - client.initialize(ClientCapabilities::default(), None)?; +fn check(fixture: &str, context: ReferenceContext) { + let mut client = Client::spawn(); + client.initialize(ClientCapabilities::default(), None); let fixture = fixture::parse(fixture); for file in fixture.files { - client.open(file.name, file.lang, file.text)?; + client.open(file.name, file.lang, file.text); } let mut expected_locations = Vec::new(); for ranges in fixture.ranges.values() { - expected_locations.push(Location::new( - client.uri(ranges[&1].name)?, - ranges[&1].range, - )); + expected_locations.push(Location::new(client.uri(ranges[&1].name), ranges[&1].range)); } let actual_locations = client .request::<References>(ReferenceParams { - text_document_position: fixture.cursor.unwrap().into_params(&client)?, + text_document_position: fixture.cursor.unwrap().into_params(&client), context, partial_result_params: Default::default(), work_done_progress_params: Default::default(), - })? + }) + .unwrap() .unwrap_or_default(); - client.shutdown()?; + client.shutdown(); assert_eq_unordered!(actual_locations, expected_locations); - Ok(()) } #[test] -fn entry_definition() -> Result<()> { +fn entry_definition() { check( r#" %BIB foo.bib @@ -58,7 +54,7 @@ fn entry_definition() -> Result<()> { } #[test] -fn entry_definition_include_decl() -> Result<()> { +fn entry_definition_include_decl() { check( r#" %BIB foo.bib @@ -78,7 +74,7 @@ fn entry_definition_include_decl() -> Result<()> { } #[test] -fn entry_reference() -> Result<()> { +fn entry_reference() { check( r#" %BIB foo.bib @@ -97,7 +93,7 @@ fn entry_reference() -> Result<()> { } #[test] -fn entry_reference_include_decl() -> Result<()> { +fn entry_reference_include_decl() { check( r#" %BIB foo.bib @@ -117,7 +113,7 @@ fn entry_reference_include_decl() -> Result<()> { } #[test] -fn label_definition() -> Result<()> { +fn label_definition() { check( r#" %TEX foo.tex @@ -136,7 +132,7 @@ fn label_definition() -> Result<()> { } #[test] -fn label_definition_include_decl() -> Result<()> { +fn label_definition_include_decl() { check( r#" %TEX foo.tex @@ -156,7 +152,7 @@ fn label_definition_include_decl() -> Result<()> { } #[test] -fn label_reference() -> Result<()> { +fn label_reference() { check( r#" %TEX foo.tex @@ -180,7 +176,7 @@ fn label_reference() -> Result<()> { } #[test] -fn label_reference_include_decl() -> Result<()> { +fn label_reference_include_decl() { check( r#" %TEX foo.tex @@ -205,7 +201,7 @@ fn label_reference_include_decl() -> Result<()> { } #[test] -fn string_reference() -> Result<()> { +fn string_reference() { check( r#" %BIB main.bib @@ -222,7 +218,7 @@ fn string_reference() -> Result<()> { } #[test] -fn string_reference_include_decl() -> Result<()> { +fn string_reference_include_decl() { check( r#" %BIB main.bib @@ -240,7 +236,7 @@ fn string_reference_include_decl() -> Result<()> { } #[test] -fn string_definition() -> Result<()> { +fn string_definition() { check( r#" %BIB main.bib @@ -257,7 +253,7 @@ fn string_definition() -> Result<()> { } #[test] -fn string_definition_include_decl() -> Result<()> { +fn string_definition_include_decl() { check( r#" %BIB main.bib diff --git a/support/texlab/tests/integration/lsp/text_document/rename.rs b/support/texlab/src/tests/text_document/rename.rs index 6b5a7e4978..2bbdfb1513 100644 --- a/support/texlab/tests/integration/lsp/text_document/rename.rs +++ b/support/texlab/src/tests/text_document/rename.rs @@ -1,43 +1,42 @@ use std::collections::HashMap; -use anyhow::Result; use lsp_types::{request::Rename, ClientCapabilities, RenameParams, TextEdit, Url, WorkspaceEdit}; -use crate::lsp::{client::Client, fixture}; +use crate::tests::{client::Client, fixture}; -fn check(fixture: &str, new_name: &str) -> Result<()> { - let mut client = Client::spawn()?; - client.initialize(ClientCapabilities::default(), None)?; +fn check(fixture: &str, new_name: &str) { + let mut client = Client::spawn(); + client.initialize(ClientCapabilities::default(), None); let fixture = fixture::parse(fixture); for file in fixture.files { - client.open(file.name, file.lang, file.text)?; + client.open(file.name, file.lang, file.text); } let mut expected_changes: HashMap<Url, Vec<TextEdit>> = HashMap::new(); for ranges in fixture.ranges.values() { expected_changes - .entry(client.uri(ranges[&1].name)?) + .entry(client.uri(ranges[&1].name)) .or_default() .push(TextEdit::new(ranges[&1].range, new_name.to_string())); } let actual_edit = client .request::<Rename>(RenameParams { - text_document_position: fixture.cursor.unwrap().into_params(&client)?, + text_document_position: fixture.cursor.unwrap().into_params(&client), new_name: new_name.to_string(), work_done_progress_params: Default::default(), - })? + }) + .unwrap() .unwrap_or_default(); - client.shutdown()?; + client.shutdown(); assert_eq!(actual_edit, WorkspaceEdit::new(expected_changes)); - Ok(()) } #[test] -fn command() -> Result<()> { +fn command() { check( r#" %TEX foo.tex @@ -55,7 +54,7 @@ fn command() -> Result<()> { } #[test] -fn entry() -> Result<()> { +fn entry() { check( r#" %BIB main.bib @@ -73,7 +72,7 @@ fn entry() -> Result<()> { } #[test] -fn citation() -> Result<()> { +fn citation() { check( r#" %BIB main.bib @@ -91,7 +90,7 @@ fn citation() -> Result<()> { } #[test] -fn label() -> Result<()> { +fn label() { check( r#" %TEX foo.tex diff --git a/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__acronym_package_ref.snap b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__acronym_package_ref.snap new file mode 100644 index 0000000000..88ba06e91c --- /dev/null +++ b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__acronym_package_ref.snap @@ -0,0 +1,16 @@ +--- +source: src/tests/text_document/completion.rs +expression: "complete(r#\"\n%TEX main.tex\n%SRC \\acrodef{fpsLabel}[FPS]{Frames per Second}\n%SRC \\ac{f\n%CUR ^\n%1.1 ^\"#)?" +--- +[ + { + "kind": 1, + "label": "fpsLabel", + "preselect": false, + "sortText": "[sortText]", + "textEdit": { + "range": "[range]", + "newText": "fpsLabel" + } + } +] diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__acronym_ref_empty.snap b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__acronym_ref_empty.snap index 33c5b459e1..65259d44a7 100644 --- a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__acronym_ref_empty.snap +++ b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__acronym_ref_empty.snap @@ -1,11 +1,9 @@ --- -source: tests/integration/lsp/text_document/completion.rs -assertion_line: 89 +source: src/tests/text_document/completion.rs expression: "complete(r#\"\n%TEX main.tex\n%SRC \\newacronym[longplural={Frames per Second}]{fpsLabel}{FPS}{Frame per Second}\n%SRC \\acrshort{}\n%CUR ^\"#)?" --- [ { - "data": "[data]", "kind": 1, "label": "fpsLabel", "preselect": false, diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__acronym_ref_open_brace.snap b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__acronym_ref_open_brace.snap index 41a71b7951..f326640993 100644 --- a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__acronym_ref_open_brace.snap +++ b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__acronym_ref_open_brace.snap @@ -1,11 +1,9 @@ --- -source: tests/integration/lsp/text_document/completion.rs -assertion_line: 117 +source: src/tests/text_document/completion.rs expression: "complete(r#\"\n%TEX main.tex\n%SRC \\newacronym[longplural={Frames per Second}]{fpsLabel}{FPS}{Frame per Second}\n%SRC \\acrshort{f\n%CUR ^\n%1.1 ^\"#)?" --- [ { - "data": "[data]", "kind": 1, "label": "fpsLabel", "preselect": false, diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__acronym_ref_simple.snap b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__acronym_ref_simple.snap index 3d31151a72..db7adf0259 100644 --- a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__acronym_ref_simple.snap +++ b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__acronym_ref_simple.snap @@ -1,11 +1,9 @@ --- -source: tests/integration/lsp/text_document/completion.rs -assertion_line: 75 +source: src/tests/text_document/completion.rs expression: "complete(r#\"\n%TEX main.tex\n%SRC \\newacronym[longplural={Frames per Second}]{fpsLabel}{FPS}{Frame per Second}\n%SRC \\acrshort{f}\n%CUR ^\n%1.1 ^\"#)?" --- [ { - "data": "[data]", "kind": 1, "label": "fpsLabel", "preselect": false, diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__argument_empty.snap b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__argument_empty.snap index 41c438baf6..75a73c5e32 100644 --- a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__argument_empty.snap +++ b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__argument_empty.snap @@ -1,11 +1,9 @@ --- -source: tests/integration/lsp/text_document/completion.rs -assertion_line: 159 +source: src/tests/text_document/completion.rs expression: "complete(r#\"\n%TEX main.tex\n%SRC \\usepackage{amsfonts}\n%SRC \\mathbb{}\n%CUR ^\"#)?" --- [ { - "data": "[data]", "documentation": "[documentation]", "kind": 1, "label": "A", @@ -17,7 +15,6 @@ expression: "complete(r#\"\n%TEX main.tex\n%SRC \\usepackage{amsfonts}\n%SRC \\m } }, { - "data": "[data]", "documentation": "[documentation]", "kind": 1, "label": "B", @@ -29,7 +26,6 @@ expression: "complete(r#\"\n%TEX main.tex\n%SRC \\usepackage{amsfonts}\n%SRC \\m } }, { - "data": "[data]", "documentation": "[documentation]", "kind": 1, "label": "C", @@ -41,7 +37,6 @@ expression: "complete(r#\"\n%TEX main.tex\n%SRC \\usepackage{amsfonts}\n%SRC \\m } }, { - "data": "[data]", "documentation": "[documentation]", "kind": 1, "label": "D", @@ -53,7 +48,6 @@ expression: "complete(r#\"\n%TEX main.tex\n%SRC \\usepackage{amsfonts}\n%SRC \\m } }, { - "data": "[data]", "documentation": "[documentation]", "kind": 1, "label": "E", diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__argument_open_brace.snap b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__argument_open_brace.snap index 7009557720..dd33c0eac3 100644 --- a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__argument_open_brace.snap +++ b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__argument_open_brace.snap @@ -1,11 +1,9 @@ --- -source: tests/integration/lsp/text_document/completion.rs -assertion_line: 186 +source: src/tests/text_document/completion.rs expression: "complete(r#\"\n%TEX main.tex\n%SRC \\usepackage{amsfonts}\n%SRC \\mathbb{\n%CUR ^\n%SRC Test\"#)?" --- [ { - "data": "[data]", "documentation": "[documentation]", "kind": 1, "label": "A", @@ -17,7 +15,6 @@ expression: "complete(r#\"\n%TEX main.tex\n%SRC \\usepackage{amsfonts}\n%SRC \\m } }, { - "data": "[data]", "documentation": "[documentation]", "kind": 1, "label": "B", @@ -29,7 +26,6 @@ expression: "complete(r#\"\n%TEX main.tex\n%SRC \\usepackage{amsfonts}\n%SRC \\m } }, { - "data": "[data]", "documentation": "[documentation]", "kind": 1, "label": "C", @@ -41,7 +37,6 @@ expression: "complete(r#\"\n%TEX main.tex\n%SRC \\usepackage{amsfonts}\n%SRC \\m } }, { - "data": "[data]", "documentation": "[documentation]", "kind": 1, "label": "D", @@ -53,7 +48,6 @@ expression: "complete(r#\"\n%TEX main.tex\n%SRC \\usepackage{amsfonts}\n%SRC \\m } }, { - "data": "[data]", "documentation": "[documentation]", "kind": 1, "label": "E", diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__argument_word.snap b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__argument_word.snap index 2ea7a4649d..cf88ba4b2b 100644 --- a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__argument_word.snap +++ b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__argument_word.snap @@ -1,11 +1,9 @@ --- -source: tests/integration/lsp/text_document/completion.rs -assertion_line: 172 +source: src/tests/text_document/completion.rs expression: "complete(r#\"\n%TEX main.tex\n%SRC \\usepackage{amsfonts}\n%SRC \\mathbb{A}\n%CUR ^\n%1.1 ^\"#)?" --- [ { - "data": "[data]", "documentation": "[documentation]", "kind": 1, "label": "A", diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__begin_environment_without_snippet_support.snap b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__begin_environment_without_snippet_support.snap index 468ea3ea5f..167e764aef 100644 --- a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__begin_environment_without_snippet_support.snap +++ b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__begin_environment_without_snippet_support.snap @@ -1,11 +1,9 @@ --- -source: tests/integration/lsp/text_document/completion.rs -assertion_line: 215 +source: src/tests/text_document/completion.rs expression: "complete(r#\"\n%TEX main.tex\n%SRC \\beg\n%CUR ^\n%1.1 ^^^\"#)?" --- [ { - "data": "[data]", "detail": "built-in", "kind": 1, "label": "begin", @@ -17,7 +15,6 @@ expression: "complete(r#\"\n%TEX main.tex\n%SRC \\beg\n%CUR ^\n%1.1 ^^^\"#) } }, { - "data": "[data]", "detail": "built-in", "kind": 1, "label": "begingroup", @@ -29,7 +26,6 @@ expression: "complete(r#\"\n%TEX main.tex\n%SRC \\beg\n%CUR ^\n%1.1 ^^^\"#) } }, { - "data": "[data]", "detail": "built-in", "kind": 1, "label": "AtBeginDocument", @@ -41,7 +37,6 @@ expression: "complete(r#\"\n%TEX main.tex\n%SRC \\beg\n%CUR ^\n%1.1 ^^^\"#) } }, { - "data": "[data]", "detail": "built-in", "kind": 1, "label": "AtBeginDvi", @@ -53,7 +48,6 @@ expression: "complete(r#\"\n%TEX main.tex\n%SRC \\beg\n%CUR ^\n%1.1 ^^^\"#) } }, { - "data": "[data]", "detail": "â‹€, built-in", "documentation": "[documentation]", "kind": 1, diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__citation.snap b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__citation.snap index 517df0a0df..70453476d5 100644 --- a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__citation.snap +++ b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__citation.snap @@ -1,6 +1,5 @@ --- -source: tests/integration/lsp/text_document/completion.rs -assertion_line: 228 +source: src/tests/text_document/completion.rs expression: "complete(r#\"\n%TEX main.tex\n%SRC \\documentclass{article}\n%SRC \\bibliography{main}\n%SRC \\begin{document}\n%SRC \\cite{\n%CUR ^\n%SRC \\end{document}\n\n%BIB main.bib\n%SRC @article{foo:2019,\n%SRC author = {Foo Bar},\n%SRC title = {Baz Qux},\n%SRC year = {2019},\n%SRC }\n%SRC \n%SRC @article{bar:2005,}\"#)?" --- [ diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__citation_acronym.snap b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__citation_acronym.snap index a679c4c42b..5cf8260317 100644 --- a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__citation_acronym.snap +++ b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__citation_acronym.snap @@ -1,6 +1,5 @@ --- -source: tests/integration/lsp/text_document/completion.rs -assertion_line: 286 +source: src/tests/text_document/completion.rs expression: "complete(r#\"\n%TEX main.tex\n%SRC \\addbibresource{main.bib}\n%SRC \\DeclareAcronym{foo}{cite={}}\n%CUR ^\n\n%BIB main.bib\n%SRC @article{foo,}\"#)?" --- [ diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__citation_open_brace.snap b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__citation_open_brace.snap index cf2056b7e7..3143481442 100644 --- a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__citation_open_brace.snap +++ b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__citation_open_brace.snap @@ -1,6 +1,5 @@ --- -source: tests/integration/lsp/text_document/completion.rs -assertion_line: 253 +source: src/tests/text_document/completion.rs expression: "complete(r#\"\n%TEX main.tex\n%SRC \\addbibresource{main.bib}\n%SRC \\cite{\n%CUR ^\n\n%BIB main.bib\n%SRC @article{foo,}\"#)?" --- [ diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__citation_open_brace_multiple.snap b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__citation_open_brace_multiple.snap index 7619c22002..21faa28ecc 100644 --- a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__citation_open_brace_multiple.snap +++ b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__citation_open_brace_multiple.snap @@ -1,6 +1,5 @@ --- -source: tests/integration/lsp/text_document/completion.rs -assertion_line: 269 +source: src/tests/text_document/completion.rs expression: "complete(r#\"\n%TEX main.tex\n%SRC \\addbibresource{main.bib}\n%SRC \\cite{foo,a\n%CUR ^\n%1.1 ^\n\n%BIB main.bib\n%SRC @article{foo,}\"#)?" --- [ diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__color_model_definition_open_brace.snap b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__color_model_definition_open_brace.snap index 651c6e4f36..825d607885 100644 --- a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__color_model_definition_open_brace.snap +++ b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__color_model_definition_open_brace.snap @@ -1,11 +1,9 @@ --- -source: tests/integration/lsp/text_document/completion.rs -assertion_line: 334 +source: src/tests/text_document/completion.rs expression: "complete(r#\"\n%TEX main.tex\n%SRC \\definecolor{foo}{\n%CUR ^\"#)?" --- [ { - "data": "[data]", "kind": 1, "label": "HTML", "preselect": false, @@ -16,7 +14,6 @@ expression: "complete(r#\"\n%TEX main.tex\n%SRC \\definecolor{foo}{\n%CUR } }, { - "data": "[data]", "kind": 1, "label": "RGB", "preselect": false, @@ -27,7 +24,6 @@ expression: "complete(r#\"\n%TEX main.tex\n%SRC \\definecolor{foo}{\n%CUR } }, { - "data": "[data]", "kind": 1, "label": "cmyk", "preselect": false, @@ -38,7 +34,6 @@ expression: "complete(r#\"\n%TEX main.tex\n%SRC \\definecolor{foo}{\n%CUR } }, { - "data": "[data]", "kind": 1, "label": "gray", "preselect": false, @@ -49,7 +44,6 @@ expression: "complete(r#\"\n%TEX main.tex\n%SRC \\definecolor{foo}{\n%CUR } }, { - "data": "[data]", "kind": 1, "label": "rgb", "preselect": false, diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__color_model_definition_set_open_brace.snap b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__color_model_definition_set_open_brace.snap index 4fb23233c9..27dac7d130 100644 --- a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__color_model_definition_set_open_brace.snap +++ b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__color_model_definition_set_open_brace.snap @@ -1,11 +1,9 @@ --- -source: tests/integration/lsp/text_document/completion.rs -assertion_line: 358 +source: src/tests/text_document/completion.rs expression: "complete(r#\"\n%TEX main.tex\n%SRC \\definecolorset{\n%CUR ^\"#)?" --- [ { - "data": "[data]", "kind": 1, "label": "HTML", "preselect": false, @@ -16,7 +14,6 @@ expression: "complete(r#\"\n%TEX main.tex\n%SRC \\definecolorset{\n%CUR } }, { - "data": "[data]", "kind": 1, "label": "RGB", "preselect": false, @@ -27,7 +24,6 @@ expression: "complete(r#\"\n%TEX main.tex\n%SRC \\definecolorset{\n%CUR } }, { - "data": "[data]", "kind": 1, "label": "cmyk", "preselect": false, @@ -38,7 +34,6 @@ expression: "complete(r#\"\n%TEX main.tex\n%SRC \\definecolorset{\n%CUR } }, { - "data": "[data]", "kind": 1, "label": "gray", "preselect": false, @@ -49,7 +44,6 @@ expression: "complete(r#\"\n%TEX main.tex\n%SRC \\definecolorset{\n%CUR } }, { - "data": "[data]", "kind": 1, "label": "rgb", "preselect": false, diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__color_model_definition_set_simple.snap b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__color_model_definition_set_simple.snap index 4b7f137e4f..c2a2640786 100644 --- a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__color_model_definition_set_simple.snap +++ b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__color_model_definition_set_simple.snap @@ -1,11 +1,9 @@ --- -source: tests/integration/lsp/text_document/completion.rs -assertion_line: 346 +source: src/tests/text_document/completion.rs expression: "complete(r#\"\n%TEX main.tex\n%SRC \\definecolorset{}\n%CUR ^\"#)?" --- [ { - "data": "[data]", "kind": 1, "label": "HTML", "preselect": false, @@ -16,7 +14,6 @@ expression: "complete(r#\"\n%TEX main.tex\n%SRC \\definecolorset{}\n%CUR } }, { - "data": "[data]", "kind": 1, "label": "RGB", "preselect": false, @@ -27,7 +24,6 @@ expression: "complete(r#\"\n%TEX main.tex\n%SRC \\definecolorset{}\n%CUR } }, { - "data": "[data]", "kind": 1, "label": "cmyk", "preselect": false, @@ -38,7 +34,6 @@ expression: "complete(r#\"\n%TEX main.tex\n%SRC \\definecolorset{}\n%CUR } }, { - "data": "[data]", "kind": 1, "label": "gray", "preselect": false, @@ -49,7 +44,6 @@ expression: "complete(r#\"\n%TEX main.tex\n%SRC \\definecolorset{}\n%CUR } }, { - "data": "[data]", "kind": 1, "label": "rgb", "preselect": false, diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__color_model_definition_simple.snap b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__color_model_definition_simple.snap index a160c859c3..da3431986d 100644 --- a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__color_model_definition_simple.snap +++ b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__color_model_definition_simple.snap @@ -1,11 +1,9 @@ --- -source: tests/integration/lsp/text_document/completion.rs -assertion_line: 322 +source: src/tests/text_document/completion.rs expression: "complete(r#\"\n%TEX main.tex\n%SRC \\definecolor{foo}{}\n%CUR ^\"#)?" --- [ { - "data": "[data]", "kind": 1, "label": "HTML", "preselect": false, @@ -16,7 +14,6 @@ expression: "complete(r#\"\n%TEX main.tex\n%SRC \\definecolor{foo}{}\n%CUR } }, { - "data": "[data]", "kind": 1, "label": "RGB", "preselect": false, @@ -27,7 +24,6 @@ expression: "complete(r#\"\n%TEX main.tex\n%SRC \\definecolor{foo}{}\n%CUR } }, { - "data": "[data]", "kind": 1, "label": "cmyk", "preselect": false, @@ -38,7 +34,6 @@ expression: "complete(r#\"\n%TEX main.tex\n%SRC \\definecolor{foo}{}\n%CUR } }, { - "data": "[data]", "kind": 1, "label": "gray", "preselect": false, @@ -49,7 +44,6 @@ expression: "complete(r#\"\n%TEX main.tex\n%SRC \\definecolor{foo}{}\n%CUR } }, { - "data": "[data]", "kind": 1, "label": "rgb", "preselect": false, diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__color_open_brace.snap b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__color_open_brace.snap index df57a6e6ef..f2ae7d8db0 100644 --- a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__color_open_brace.snap +++ b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__color_open_brace.snap @@ -1,11 +1,9 @@ --- -source: tests/integration/lsp/text_document/completion.rs -assertion_line: 395 +source: src/tests/text_document/completion.rs expression: "complete(r#\"\n%TEX main.tex\n%SRC \\color{\n%CUR ^\"#)?" --- [ { - "data": "[data]", "kind": 1, "label": "Apricot", "preselect": false, @@ -16,7 +14,6 @@ expression: "complete(r#\"\n%TEX main.tex\n%SRC \\color{\n%CUR ^\"#)?" } }, { - "data": "[data]", "kind": 1, "label": "Aquamarine", "preselect": false, @@ -27,7 +24,6 @@ expression: "complete(r#\"\n%TEX main.tex\n%SRC \\color{\n%CUR ^\"#)?" } }, { - "data": "[data]", "kind": 1, "label": "Bittersweet", "preselect": false, @@ -38,7 +34,6 @@ expression: "complete(r#\"\n%TEX main.tex\n%SRC \\color{\n%CUR ^\"#)?" } }, { - "data": "[data]", "kind": 1, "label": "Black", "preselect": false, @@ -49,7 +44,6 @@ expression: "complete(r#\"\n%TEX main.tex\n%SRC \\color{\n%CUR ^\"#)?" } }, { - "data": "[data]", "kind": 1, "label": "Blue", "preselect": false, diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__color_simple.snap b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__color_simple.snap index fb4e2bee73..fc3db2911b 100644 --- a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__color_simple.snap +++ b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__color_simple.snap @@ -1,11 +1,9 @@ --- -source: tests/integration/lsp/text_document/completion.rs -assertion_line: 370 +source: src/tests/text_document/completion.rs expression: "complete(r#\"\n%TEX main.tex\n%SRC \\color{}\n%CUR ^\"#)?" --- [ { - "data": "[data]", "kind": 1, "label": "Apricot", "preselect": false, @@ -16,7 +14,6 @@ expression: "complete(r#\"\n%TEX main.tex\n%SRC \\color{}\n%CUR ^\"#)?" } }, { - "data": "[data]", "kind": 1, "label": "Aquamarine", "preselect": false, @@ -27,7 +24,6 @@ expression: "complete(r#\"\n%TEX main.tex\n%SRC \\color{}\n%CUR ^\"#)?" } }, { - "data": "[data]", "kind": 1, "label": "Bittersweet", "preselect": false, @@ -38,7 +34,6 @@ expression: "complete(r#\"\n%TEX main.tex\n%SRC \\color{}\n%CUR ^\"#)?" } }, { - "data": "[data]", "kind": 1, "label": "Black", "preselect": false, @@ -49,7 +44,6 @@ expression: "complete(r#\"\n%TEX main.tex\n%SRC \\color{}\n%CUR ^\"#)?" } }, { - "data": "[data]", "kind": 1, "label": "Blue", "preselect": false, diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__color_word.snap b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__color_word.snap index b730f14a42..cd671de9b9 100644 --- a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__color_word.snap +++ b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__color_word.snap @@ -1,11 +1,9 @@ --- -source: tests/integration/lsp/text_document/completion.rs -assertion_line: 382 +source: src/tests/text_document/completion.rs expression: "complete(r#\"\n%TEX main.tex\n%SRC \\color{re}\n%CUR ^\n%1.1 ^^\"#)?" --- [ { - "data": "[data]", "kind": 1, "label": "red", "preselect": false, @@ -16,7 +14,6 @@ expression: "complete(r#\"\n%TEX main.tex\n%SRC \\color{re}\n%CUR ^\n%1. } }, { - "data": "[data]", "kind": 1, "label": "Red", "preselect": false, @@ -27,7 +24,6 @@ expression: "complete(r#\"\n%TEX main.tex\n%SRC \\color{re}\n%CUR ^\n%1. } }, { - "data": "[data]", "kind": 1, "label": "RedOrange", "preselect": false, @@ -38,7 +34,6 @@ expression: "complete(r#\"\n%TEX main.tex\n%SRC \\color{re}\n%CUR ^\n%1. } }, { - "data": "[data]", "kind": 1, "label": "RedViolet", "preselect": false, @@ -49,7 +44,6 @@ expression: "complete(r#\"\n%TEX main.tex\n%SRC \\color{re}\n%CUR ^\n%1. } }, { - "data": "[data]", "kind": 1, "label": "BrickRed", "preselect": false, diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__component_command_bibtex.snap b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__component_command_bibtex.snap index 545a13af3c..76dd1d07f8 100644 --- a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__component_command_bibtex.snap +++ b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__component_command_bibtex.snap @@ -1,11 +1,9 @@ --- -source: tests/integration/lsp/text_document/completion.rs -assertion_line: 446 +source: src/tests/text_document/completion.rs expression: "complete(r#\"\n%BIB main.bib\n%SRC @article{b, \n%SRC c = {\\LaT }\n%CUR ^\n%1.1 ^^^\n%SRC }\"#)?" --- [ { - "data": "[data]", "detail": "built-in", "kind": 1, "label": "LaTeX", @@ -17,7 +15,6 @@ expression: "complete(r#\"\n%BIB main.bib\n%SRC @article{b, \n%SRC c = {\\La } }, { - "data": "[data]", "detail": "built-in", "kind": 1, "label": "LaTeXe", @@ -29,7 +26,6 @@ expression: "complete(r#\"\n%BIB main.bib\n%SRC @article{b, \n%SRC c = {\\La } }, { - "data": "[data]", "detail": "built-in", "kind": 1, "label": "latexreleaseversion", @@ -41,7 +37,6 @@ expression: "complete(r#\"\n%BIB main.bib\n%SRC @article{b, \n%SRC c = {\\La } }, { - "data": "[data]", "detail": "built-in", "kind": 1, "label": "LastDeclaredEncoding", @@ -53,7 +48,6 @@ expression: "complete(r#\"\n%BIB main.bib\n%SRC @article{b, \n%SRC c = {\\La } }, { - "data": "[data]", "detail": "built-in", "kind": 1, "label": "last", diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__component_command_simple.snap b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__component_command_simple.snap index 8414866ca1..c974de42b7 100644 --- a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__component_command_simple.snap +++ b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__component_command_simple.snap @@ -1,11 +1,9 @@ --- -source: tests/integration/lsp/text_document/completion.rs -assertion_line: 407 +source: src/tests/text_document/completion.rs expression: "complete(r#\"\n%TEX main.tex\n%SRC \\\n%CUR ^\"#)?" --- [ { - "data": "[data]", "detail": "built-in", "kind": 1, "label": "!", @@ -17,7 +15,6 @@ expression: "complete(r#\"\n%TEX main.tex\n%SRC \\\n%CUR ^\"#)?" } }, { - "data": "[data]", "detail": "built-in", "documentation": "[documentation]", "kind": 1, @@ -30,7 +27,6 @@ expression: "complete(r#\"\n%TEX main.tex\n%SRC \\\n%CUR ^\"#)?" } }, { - "data": "[data]", "detail": "built-in", "kind": 1, "label": "#", @@ -42,7 +38,6 @@ expression: "complete(r#\"\n%TEX main.tex\n%SRC \\\n%CUR ^\"#)?" } }, { - "data": "[data]", "detail": "$, built-in", "documentation": "[documentation]", "kind": 1, @@ -55,7 +50,6 @@ expression: "complete(r#\"\n%TEX main.tex\n%SRC \\\n%CUR ^\"#)?" } }, { - "data": "[data]", "detail": "built-in", "kind": 1, "label": "%", diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__component_command_simple_package.snap b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__component_command_simple_package.snap index c08f480f7e..ada70e293a 100644 --- a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__component_command_simple_package.snap +++ b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__component_command_simple_package.snap @@ -1,11 +1,9 @@ --- -source: tests/integration/lsp/text_document/completion.rs -assertion_line: 432 +source: src/tests/text_document/completion.rs expression: "complete(r#\"\n%TEX main.tex\n%SRC \\usepackage{lipsum}\n%SRC \\lips\n%CUR ^\n%1.1 ^^^^\"#)?" --- [ { - "data": "[data]", "detail": "lipsum.sty", "kind": 1, "label": "lipsum", @@ -17,7 +15,6 @@ expression: "complete(r#\"\n%TEX main.tex\n%SRC \\usepackage{lipsum}\n%SRC \\lip } }, { - "data": "[data]", "detail": "lipsum.sty", "kind": 1, "label": "lipsumexp", @@ -29,7 +26,6 @@ expression: "complete(r#\"\n%TEX main.tex\n%SRC \\usepackage{lipsum}\n%SRC \\lip } }, { - "data": "[data]", "detail": "lipsum.sty", "kind": 1, "label": "LipsumPar", @@ -41,7 +37,6 @@ expression: "complete(r#\"\n%TEX main.tex\n%SRC \\usepackage{lipsum}\n%SRC \\lip } }, { - "data": "[data]", "detail": "lipsum.sty", "kind": 1, "label": "LipsumProtect", @@ -53,7 +48,6 @@ expression: "complete(r#\"\n%TEX main.tex\n%SRC \\usepackage{lipsum}\n%SRC \\lip } }, { - "data": "[data]", "detail": "lipsum.sty", "kind": 1, "label": "LipsumRestoreAll", diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__component_environment_class.snap b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__component_environment_class.snap index ff16b8e7b6..bb409a442b 100644 --- a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__component_environment_class.snap +++ b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__component_environment_class.snap @@ -1,11 +1,9 @@ --- -source: tests/integration/lsp/text_document/completion.rs -assertion_line: 487 +source: src/tests/text_document/completion.rs expression: "complete(r#\"\n%TEX main.tex\n%SRC \\documentclass{article}\n%SRC \\begin{thein}\n%CUR ^\n%1.1 ^^^^^\"#)?" --- [ { - "data": "[data]", "detail": "article.cls", "kind": 1, "label": "theindex", diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__component_environment_command_definition.snap b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__component_environment_command_definition.snap index e07204dd14..d319eeb734 100644 --- a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__component_environment_command_definition.snap +++ b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__component_environment_command_definition.snap @@ -1,11 +1,9 @@ --- -source: tests/integration/lsp/text_document/completion.rs -assertion_line: 501 +source: src/tests/text_document/completion.rs expression: "complete(r#\"\n%TEX main.tex\n%SRC \\newcommand{\\foo}{\\begin{doc}\n%CUR ^\n%1.1 ^^^\"#)?" --- [ { - "data": "[data]", "detail": "built-in", "kind": 1, "label": "document", diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__component_environment_simple.snap b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__component_environment_simple.snap index 6c3be2426e..f6b8710db3 100644 --- a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__component_environment_simple.snap +++ b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__component_environment_simple.snap @@ -1,11 +1,9 @@ --- -source: tests/integration/lsp/text_document/completion.rs -assertion_line: 461 +source: src/tests/text_document/completion.rs expression: "complete(r#\"\n%TEX main.tex\n%SRC \\begin{doc\n%CUR ^\n%1.1 ^^^\"#)?" --- [ { - "data": "[data]", "detail": "built-in", "kind": 1, "label": "document", diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__component_environment_simple_end.snap b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__component_environment_simple_end.snap index af0e4ca762..e3ffa551d3 100644 --- a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__component_environment_simple_end.snap +++ b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__component_environment_simple_end.snap @@ -1,11 +1,9 @@ --- -source: tests/integration/lsp/text_document/completion.rs -assertion_line: 474 +source: src/tests/text_document/completion.rs expression: "complete(r#\"\n%TEX main.tex\n%SRC \\begin{document}\n%SRC \\end{\n%CUR ^\"#)?" --- [ { - "data": "[data]", "detail": "built-in", "kind": 1, "label": "document", @@ -17,7 +15,6 @@ expression: "complete(r#\"\n%TEX main.tex\n%SRC \\begin{document}\n%SRC \\end{\n } }, { - "data": "[data]", "detail": "built-in", "kind": 1, "label": "abstract", @@ -29,7 +26,6 @@ expression: "complete(r#\"\n%TEX main.tex\n%SRC \\begin{document}\n%SRC \\end{\n } }, { - "data": "[data]", "detail": "built-in", "kind": 1, "label": "array", @@ -41,7 +37,6 @@ expression: "complete(r#\"\n%TEX main.tex\n%SRC \\begin{document}\n%SRC \\end{\n } }, { - "data": "[data]", "detail": "built-in", "kind": 1, "label": "center", @@ -53,7 +48,6 @@ expression: "complete(r#\"\n%TEX main.tex\n%SRC \\begin{document}\n%SRC \\end{\n } }, { - "data": "[data]", "detail": "built-in", "kind": 1, "label": "csname", diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__entry_type_after_preamble.snap b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__entry_type_after_preamble.snap index 281254f2b8..5f29c307a7 100644 --- a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__entry_type_after_preamble.snap +++ b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__entry_type_after_preamble.snap @@ -1,11 +1,9 @@ --- -source: tests/integration/lsp/text_document/completion.rs -assertion_line: 565 +source: src/tests/text_document/completion.rs expression: "complete(r#\"\n%BIB main.bib\n%SRC @preamble{\n%CUR ^\n%1.1 ^^^^^^^^\"#)?" --- [ { - "data": "[data]", "kind": 1, "label": "preamble", "preselect": false, diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__entry_type_after_string.snap b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__entry_type_after_string.snap index 706bd78d07..5b18f17cfe 100644 --- a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__entry_type_after_string.snap +++ b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__entry_type_after_string.snap @@ -1,11 +1,9 @@ --- -source: tests/integration/lsp/text_document/completion.rs -assertion_line: 578 +source: src/tests/text_document/completion.rs expression: "complete(r#\"\n%BIB main.bib\n%SRC @string{\n%CUR ^\n%1.1 ^^^^^^\"#)?" --- [ { - "data": "[data]", "kind": 1, "label": "string", "preselect": false, diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__entry_type_at_empty.snap b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__entry_type_at_empty.snap index 19d2a451af..7928676b92 100644 --- a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__entry_type_at_empty.snap +++ b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__entry_type_at_empty.snap @@ -1,11 +1,9 @@ --- -source: tests/integration/lsp/text_document/completion.rs -assertion_line: 514 +source: src/tests/text_document/completion.rs expression: "complete(r#\"\n%BIB main.bib\n%SRC @\n%CUR ^\"#)?" --- [ { - "data": "[data]", "documentation": "[documentation]", "kind": 1, "label": "article", @@ -17,7 +15,6 @@ expression: "complete(r#\"\n%BIB main.bib\n%SRC @\n%CUR ^\"#)?" } }, { - "data": "[data]", "documentation": "[documentation]", "kind": 1, "label": "artwork", @@ -29,7 +26,6 @@ expression: "complete(r#\"\n%BIB main.bib\n%SRC @\n%CUR ^\"#)?" } }, { - "data": "[data]", "documentation": "[documentation]", "kind": 1, "label": "audio", @@ -41,7 +37,6 @@ expression: "complete(r#\"\n%BIB main.bib\n%SRC @\n%CUR ^\"#)?" } }, { - "data": "[data]", "documentation": "[documentation]", "kind": 1, "label": "bibnote", @@ -53,7 +48,6 @@ expression: "complete(r#\"\n%BIB main.bib\n%SRC @\n%CUR ^\"#)?" } }, { - "data": "[data]", "documentation": "[documentation]", "kind": 1, "label": "book", diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__entry_type_before_article.snap b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__entry_type_before_article.snap index 654258a594..1522a7594a 100644 --- a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__entry_type_before_article.snap +++ b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__entry_type_before_article.snap @@ -1,11 +1,9 @@ --- -source: tests/integration/lsp/text_document/completion.rs -assertion_line: 552 +source: src/tests/text_document/completion.rs expression: "complete(r#\"\n%BIB main.bib\n%SRC @article\n%CUR ^\n%1.1 ^^^^^^^\"#)?" --- [ { - "data": "[data]", "documentation": "[documentation]", "kind": 1, "label": "article", diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__entry_type_before_preamble.snap b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__entry_type_before_preamble.snap index 6a4a79f14d..50e7a2162d 100644 --- a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__entry_type_before_preamble.snap +++ b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__entry_type_before_preamble.snap @@ -1,11 +1,9 @@ --- -source: tests/integration/lsp/text_document/completion.rs -assertion_line: 526 +source: src/tests/text_document/completion.rs expression: "complete(r#\"\n%BIB main.bib\n%SRC @preamble\n%CUR ^\n%1.1 ^^^^^^^^\"#)?" --- [ { - "data": "[data]", "kind": 1, "label": "preamble", "preselect": false, diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__entry_type_before_string.snap b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__entry_type_before_string.snap index b3b6f2928b..0c00ddd5fc 100644 --- a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__entry_type_before_string.snap +++ b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__entry_type_before_string.snap @@ -1,11 +1,9 @@ --- -source: tests/integration/lsp/text_document/completion.rs -assertion_line: 539 +source: src/tests/text_document/completion.rs expression: "complete(r#\"\n%BIB main.bib\n%SRC @string\n%CUR ^\n%1.1 ^^^^^^\"#)?" --- [ { - "data": "[data]", "kind": 1, "label": "string", "preselect": false, diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__entry_type_complete_entry.snap b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__entry_type_complete_entry.snap index 2a18a34789..6afb028f95 100644 --- a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__entry_type_complete_entry.snap +++ b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__entry_type_complete_entry.snap @@ -1,11 +1,9 @@ --- -source: tests/integration/lsp/text_document/completion.rs -assertion_line: 591 +source: src/tests/text_document/completion.rs expression: "complete(r#\"\n%BIB main.bib\n%SRC @article{foo, author = {foo}}\n%CUR ^\n%1.1 ^^^^^^^\"#)?" --- [ { - "data": "[data]", "documentation": "[documentation]", "kind": 1, "label": "article", diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__field_empty_entry_closed.snap b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__field_empty_entry_closed.snap index 10f3b1d89a..86a6e06c89 100644 --- a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__field_empty_entry_closed.snap +++ b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__field_empty_entry_closed.snap @@ -1,11 +1,9 @@ --- -source: tests/integration/lsp/text_document/completion.rs -assertion_line: 616 +source: src/tests/text_document/completion.rs expression: "complete(r#\"\n%BIB main.bib\n%SRC @article{foo,}\n%CUR ^\"#)?" --- [ { - "data": "[data]", "documentation": "[documentation]", "kind": 1, "label": "abstract", @@ -17,7 +15,6 @@ expression: "complete(r#\"\n%BIB main.bib\n%SRC @article{foo,}\n%CUR } }, { - "data": "[data]", "documentation": "[documentation]", "kind": 1, "label": "addendum", @@ -29,7 +26,6 @@ expression: "complete(r#\"\n%BIB main.bib\n%SRC @article{foo,}\n%CUR } }, { - "data": "[data]", "documentation": "[documentation]", "kind": 1, "label": "address", @@ -41,7 +37,6 @@ expression: "complete(r#\"\n%BIB main.bib\n%SRC @article{foo,}\n%CUR } }, { - "data": "[data]", "documentation": "[documentation]", "kind": 1, "label": "afterword", @@ -53,7 +48,6 @@ expression: "complete(r#\"\n%BIB main.bib\n%SRC @article{foo,}\n%CUR } }, { - "data": "[data]", "documentation": "[documentation]", "kind": 1, "label": "annotation", diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__field_empty_entry_open.snap b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__field_empty_entry_open.snap index bb8b03efda..75a242d25d 100644 --- a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__field_empty_entry_open.snap +++ b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__field_empty_entry_open.snap @@ -1,11 +1,9 @@ --- -source: tests/integration/lsp/text_document/completion.rs -assertion_line: 604 +source: src/tests/text_document/completion.rs expression: "complete(r#\"\n%BIB main.bib\n%SRC @article{foo,\n%CUR ^\"#)?" --- [ { - "data": "[data]", "documentation": "[documentation]", "kind": 1, "label": "abstract", @@ -17,7 +15,6 @@ expression: "complete(r#\"\n%BIB main.bib\n%SRC @article{foo,\n%CUR } }, { - "data": "[data]", "documentation": "[documentation]", "kind": 1, "label": "addendum", @@ -29,7 +26,6 @@ expression: "complete(r#\"\n%BIB main.bib\n%SRC @article{foo,\n%CUR } }, { - "data": "[data]", "documentation": "[documentation]", "kind": 1, "label": "address", @@ -41,7 +37,6 @@ expression: "complete(r#\"\n%BIB main.bib\n%SRC @article{foo,\n%CUR } }, { - "data": "[data]", "documentation": "[documentation]", "kind": 1, "label": "afterword", @@ -53,7 +48,6 @@ expression: "complete(r#\"\n%BIB main.bib\n%SRC @article{foo,\n%CUR } }, { - "data": "[data]", "documentation": "[documentation]", "kind": 1, "label": "annotation", diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__field_entry_field_name.snap b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__field_entry_field_name.snap index 32f1df6369..3178da8d07 100644 --- a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__field_entry_field_name.snap +++ b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__field_entry_field_name.snap @@ -1,11 +1,9 @@ --- -source: tests/integration/lsp/text_document/completion.rs -assertion_line: 628 +source: src/tests/text_document/completion.rs expression: "complete(r#\"\n%BIB main.bib\n%SRC @article{foo, a\n%CUR ^\n%1.1 ^\"#)?" --- [ { - "data": "[data]", "documentation": "[documentation]", "kind": 1, "label": "abstract", @@ -17,7 +15,6 @@ expression: "complete(r#\"\n%BIB main.bib\n%SRC @article{foo, a\n%CUR } }, { - "data": "[data]", "documentation": "[documentation]", "kind": 1, "label": "addendum", @@ -29,7 +26,6 @@ expression: "complete(r#\"\n%BIB main.bib\n%SRC @article{foo, a\n%CUR } }, { - "data": "[data]", "documentation": "[documentation]", "kind": 1, "label": "address", @@ -41,7 +37,6 @@ expression: "complete(r#\"\n%BIB main.bib\n%SRC @article{foo, a\n%CUR } }, { - "data": "[data]", "documentation": "[documentation]", "kind": 1, "label": "afterword", @@ -53,7 +48,6 @@ expression: "complete(r#\"\n%BIB main.bib\n%SRC @article{foo, a\n%CUR } }, { - "data": "[data]", "documentation": "[documentation]", "kind": 1, "label": "annotation", diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__field_entry_two_fields_name_closed.snap b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__field_entry_two_fields_name_closed.snap index e1c61bab4c..80595edf98 100644 --- a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__field_entry_two_fields_name_closed.snap +++ b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__field_entry_two_fields_name_closed.snap @@ -1,11 +1,9 @@ --- -source: tests/integration/lsp/text_document/completion.rs -assertion_line: 654 +source: src/tests/text_document/completion.rs expression: "complete(r#\"\n%BIB main.bib\n%SRC @article{foo, author = bar, edit}\n%CUR ^\n%1.1 ^^^^\"#)?" --- [ { - "data": "[data]", "documentation": "[documentation]", "kind": 1, "label": "edition", @@ -17,7 +15,6 @@ expression: "complete(r#\"\n%BIB main.bib\n%SRC @article{foo, author = bar, edit } }, { - "data": "[data]", "documentation": "[documentation]", "kind": 1, "label": "editor", @@ -29,7 +26,6 @@ expression: "complete(r#\"\n%BIB main.bib\n%SRC @article{foo, author = bar, edit } }, { - "data": "[data]", "documentation": "[documentation]", "kind": 1, "label": "editora", @@ -41,7 +37,6 @@ expression: "complete(r#\"\n%BIB main.bib\n%SRC @article{foo, author = bar, edit } }, { - "data": "[data]", "documentation": "[documentation]", "kind": 1, "label": "editoratype", @@ -53,7 +48,6 @@ expression: "complete(r#\"\n%BIB main.bib\n%SRC @article{foo, author = bar, edit } }, { - "data": "[data]", "documentation": "[documentation]", "kind": 1, "label": "editorb", diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__field_entry_two_fields_name_open.snap b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__field_entry_two_fields_name_open.snap index b86d4e96b0..8de75313e8 100644 --- a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__field_entry_two_fields_name_open.snap +++ b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__field_entry_two_fields_name_open.snap @@ -1,11 +1,9 @@ --- -source: tests/integration/lsp/text_document/completion.rs -assertion_line: 641 +source: src/tests/text_document/completion.rs expression: "complete(r#\"\n%BIB main.bib\n%SRC @article{foo, author = bar, edit\n%CUR ^\n%1.1 ^^^^\"#)?" --- [ { - "data": "[data]", "documentation": "[documentation]", "kind": 1, "label": "edition", @@ -17,7 +15,6 @@ expression: "complete(r#\"\n%BIB main.bib\n%SRC @article{foo, author = bar, edit } }, { - "data": "[data]", "documentation": "[documentation]", "kind": 1, "label": "editor", @@ -29,7 +26,6 @@ expression: "complete(r#\"\n%BIB main.bib\n%SRC @article{foo, author = bar, edit } }, { - "data": "[data]", "documentation": "[documentation]", "kind": 1, "label": "editora", @@ -41,7 +37,6 @@ expression: "complete(r#\"\n%BIB main.bib\n%SRC @article{foo, author = bar, edit } }, { - "data": "[data]", "documentation": "[documentation]", "kind": 1, "label": "editoratype", @@ -53,7 +48,6 @@ expression: "complete(r#\"\n%BIB main.bib\n%SRC @article{foo, author = bar, edit } }, { - "data": "[data]", "documentation": "[documentation]", "kind": 1, "label": "editorb", diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__glossary_ref_open_brace.snap b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__glossary_ref_open_brace.snap index 25c90c0a4e..36a77e92e5 100644 --- a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__glossary_ref_open_brace.snap +++ b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__glossary_ref_open_brace.snap @@ -1,11 +1,9 @@ --- -source: tests/integration/lsp/text_document/completion.rs -assertion_line: 145 +source: src/tests/text_document/completion.rs expression: "complete(r#\"\n%TEX main.tex\n%SRC \\newacronym[longplural={Frames per Second}]{fpsLabel}{FPS}{Frame per Second}\n%SRC \\gls{f\n%CUR ^\n%1.1 ^\"#)?" --- [ { - "data": "[data]", "kind": 1, "label": "fpsLabel", "preselect": false, diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__glossary_ref_simple.snap b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__glossary_ref_simple.snap index a9c8bc5478..7a4d9a584b 100644 --- a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__glossary_ref_simple.snap +++ b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__glossary_ref_simple.snap @@ -1,11 +1,9 @@ --- -source: tests/integration/lsp/text_document/completion.rs -assertion_line: 131 +source: src/tests/text_document/completion.rs expression: "complete(r#\"\n%TEX main.tex\n%SRC \\newacronym[longplural={Frames per Second}]{fpsLabel}{FPS}{Frame per Second}\n%SRC \\gls{f}\n%CUR ^\n%1.1 ^\"#)?" --- [ { - "data": "[data]", "kind": 1, "label": "fpsLabel", "preselect": false, diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__import_class_closed_brace.snap b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__import_class_closed_brace.snap index 1b15dff00b..f346f67f41 100644 --- a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__import_class_closed_brace.snap +++ b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__import_class_closed_brace.snap @@ -1,6 +1,5 @@ --- -source: tests/integration/lsp/text_document/completion.rs -assertion_line: 706 +source: src/tests/text_document/completion.rs expression: "complete(r#\"\n%TEX main.tex\n%SRC \\documentclass{art}\n%CUR ^\n%1.1 ^^^\"#)?" --- [ diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__import_class_open_brace.snap b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__import_class_open_brace.snap index 4118d60707..0d236ae496 100644 --- a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__import_class_open_brace.snap +++ b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__import_class_open_brace.snap @@ -1,6 +1,5 @@ --- -source: tests/integration/lsp/text_document/completion.rs -assertion_line: 693 +source: src/tests/text_document/completion.rs expression: "complete(r#\"\n%TEX main.tex\n%SRC \\documentclass{art \\foo\n%CUR ^\n%1.1 ^^^\"#)?" --- [ diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__import_package_closed_brace.snap b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__import_package_closed_brace.snap index 141441047f..2952c5d401 100644 --- a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__import_package_closed_brace.snap +++ b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__import_package_closed_brace.snap @@ -1,6 +1,5 @@ --- -source: tests/integration/lsp/text_document/completion.rs -assertion_line: 680 +source: src/tests/text_document/completion.rs expression: "complete(r#\"\n%TEX main.tex\n%SRC \\usepackage{lips}\n%CUR ^\n%1.1 ^^^^\"#)?" --- [ diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__import_package_open_brace.snap b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__import_package_open_brace.snap index c188633107..349830d5f2 100644 --- a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__import_package_open_brace.snap +++ b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__import_package_open_brace.snap @@ -1,6 +1,5 @@ --- -source: tests/integration/lsp/text_document/completion.rs -assertion_line: 667 +source: src/tests/text_document/completion.rs expression: "complete(r#\"\n%TEX main.tex\n%SRC \\usepackage{lips\n%CUR ^\n%1.1 ^^^^\"#)?" --- [ diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__label.snap b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__label.snap index e30dd28ab9..a4b26aa41d 100644 --- a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__label.snap +++ b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__label.snap @@ -1,11 +1,9 @@ --- -source: tests/integration/lsp/text_document/completion.rs -assertion_line: 719 +source: src/tests/text_document/completion.rs expression: "complete(r#\"\n%TEX foo.tex\n%SRC \\documentclass{article}\n%SRC \n%SRC \\usepackage{amsmath}\n%SRC \\usepackage{caption}\n%SRC \\usepackage{amsthm}\n%SRC \\newtheorem{lemma}{Lemma}\n%SRC \n%SRC \\begin{document}\n%SRC \n%SRC \\section{Foo}%\n%SRC \\label{sec:foo}\n%SRC \n%SRC \\begin{equation}%\n%SRC \\label{eq:foo}\n%SRC 1 + 1 = 2\n%SRC \\end{equation}\n%SRC \n%SRC \\begin{equation}%\n%SRC \\label{eq:bar}\n%SRC 1 + 1 = 2\n%SRC \\end{equation}\n%SRC \n%SRC \\begin{figure}%\n%SRC \\LaTeX{}\n%SRC \\caption{Baz}%\n%SRC \\label{fig:baz}\n%SRC \\end{figure}\n%SRC \n%SRC \\begin{lemma}%\n%SRC \\label{thm:foo}\n%SRC 1 + 1 = 2\n%SRC \\end{lemma}\n%SRC \n%SRC \\include{bar}\n%SRC \n%SRC \\end{document}\n\n%TEX bar.tex\n%SRC \\section{Bar}%\n%SRC \\label{sec:bar}\n%SRC \n%SRC Lorem ipsum dolor sit amet.\n%SRC \\ref{}\n%CUR ^\n\n%TEX foo.aux\n%SRC \\relax\n%SRC \\@writefile{lof}{\\contentsline {figure}{\\numberline {1}{\\ignorespaces Baz\\relax }}{1}\\protected@file@percent }\n%SRC \\providecommand*\\caption@xref[2]{\\@setref\\relax\\@undefined{#1}}\n%SRC \\newlabel{fig:baz}{{1}{1}}\n%SRC \\@writefile{toc}{\\contentsline {section}{\\numberline {1}Foo}{1}\\protected@file@percent }\n%SRC \\newlabel{sec:foo}{{1}{1}}\n%SRC \\newlabel{eq:foo}{{1}{1}}\n%SRC \\newlabel{eq:bar}{{2}{1}}\n%SRC \\newlabel{thm:foo}{{1}{1}}\n%SRC \\@input{bar.aux}\"#)?" --- [ { - "data": "[data]", "detail": "Equation (2)", "filterText": "eq:bar Equation (2)", "kind": 1, @@ -18,7 +16,6 @@ expression: "complete(r#\"\n%TEX foo.tex\n%SRC \\documentclass{article}\n%SRC \n } }, { - "data": "[data]", "detail": "Equation (1)", "filterText": "eq:foo Equation (1)", "kind": 1, @@ -31,7 +28,6 @@ expression: "complete(r#\"\n%TEX foo.tex\n%SRC \\documentclass{article}\n%SRC \n } }, { - "data": "[data]", "detail": "Figure 1", "documentation": "[documentation]", "filterText": "fig:baz Figure 1: Baz", @@ -45,7 +41,6 @@ expression: "complete(r#\"\n%TEX foo.tex\n%SRC \\documentclass{article}\n%SRC \n } }, { - "data": "[data]", "detail": "Section (Bar)", "filterText": "sec:bar Section (Bar)", "kind": 1, @@ -58,7 +53,6 @@ expression: "complete(r#\"\n%TEX foo.tex\n%SRC \\documentclass{article}\n%SRC \n } }, { - "data": "[data]", "detail": "Section 1 (Foo)", "filterText": "sec:foo Section 1 (Foo)", "kind": 1, diff --git a/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__project_resolution.snap b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__project_resolution.snap new file mode 100644 index 0000000000..5ee9c3c207 --- /dev/null +++ b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__project_resolution.snap @@ -0,0 +1,61 @@ +--- +source: src/tests/text_document/completion.rs +expression: "complete(r#\"\n%TEX main.tex\n%SRC \\documentclass{article}\n%SRC \\import{sub}{sub/sub.tex}\n%SRC \\lipsu\n%CUR ^\n%1.1 ^^^^^\n\n%TEX sub/sub.tex\n%SRC \\input{child.tex}\n\n%TEX sub/child.tex\n%SRC \\usepackage{lipsum}\n\n\"#)" +--- +[ + { + "detail": "lipsum.sty", + "kind": 1, + "label": "lipsum", + "preselect": false, + "sortText": "[sortText]", + "textEdit": { + "range": "[range]", + "newText": "lipsum" + } + }, + { + "detail": "lipsum.sty", + "kind": 1, + "label": "lipsumexp", + "preselect": false, + "sortText": "[sortText]", + "textEdit": { + "range": "[range]", + "newText": "lipsumexp" + } + }, + { + "detail": "lipsum.sty", + "kind": 1, + "label": "LipsumPar", + "preselect": false, + "sortText": "[sortText]", + "textEdit": { + "range": "[range]", + "newText": "LipsumPar" + } + }, + { + "detail": "lipsum.sty", + "kind": 1, + "label": "LipsumProtect", + "preselect": false, + "sortText": "[sortText]", + "textEdit": { + "range": "[range]", + "newText": "LipsumProtect" + } + }, + { + "detail": "lipsum.sty", + "kind": 1, + "label": "LipsumRestoreAll", + "preselect": false, + "sortText": "[sortText]", + "textEdit": { + "range": "[range]", + "newText": "LipsumRestoreAll" + } + } +] diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__theorem_begin.snap b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__theorem_begin.snap index b6964fe89c..a4de708b1b 100644 --- a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__theorem_begin.snap +++ b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__theorem_begin.snap @@ -1,11 +1,9 @@ --- -source: tests/integration/lsp/text_document/completion.rs -assertion_line: 785 +source: src/tests/text_document/completion.rs expression: "complete(r#\"\n%TEX main.tex\n%SRC \\newtheorem{lemma}{Lemma}\n%SRC \\begin{lem \n%CUR ^\n%1.1 ^^^\"#)?" --- [ { - "data": "[data]", "detail": "user-defined", "kind": 1, "label": "lemma", diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__theorem_end.snap b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__theorem_end.snap index 60fdc37edb..0c2c20083e 100644 --- a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__theorem_end.snap +++ b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__theorem_end.snap @@ -1,11 +1,9 @@ --- -source: tests/integration/lsp/text_document/completion.rs -assertion_line: 799 +source: src/tests/text_document/completion.rs expression: "complete(r#\"\n%TEX main.tex\n%SRC \\newtheorem{lemma}{Lemma}\n%SRC \\begin{}\n%SRC \\end{lem\n%CUR ^\n%1.1 ^^^\"#)?" --- [ { - "data": "[data]", "detail": "user-defined", "kind": 1, "label": "lemma", diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__tikz_library_closed_brace.snap b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__tikz_library_closed_brace.snap index a1d7354f8f..f2a00d22bb 100644 --- a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__tikz_library_closed_brace.snap +++ b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__tikz_library_closed_brace.snap @@ -1,11 +1,9 @@ --- -source: tests/integration/lsp/text_document/completion.rs -assertion_line: 826 +source: src/tests/text_document/completion.rs expression: "complete(r#\"\n%TEX main.tex\n%SRC \\usepgflibrary{}\n%CUR ^\"#)?" --- [ { - "data": "[data]", "kind": 1, "label": "arrows", "preselect": false, @@ -16,7 +14,6 @@ expression: "complete(r#\"\n%TEX main.tex\n%SRC \\usepgflibrary{}\n%CUR } }, { - "data": "[data]", "kind": 1, "label": "arrows.meta", "preselect": false, @@ -27,7 +24,6 @@ expression: "complete(r#\"\n%TEX main.tex\n%SRC \\usepgflibrary{}\n%CUR } }, { - "data": "[data]", "kind": 1, "label": "arrows.spaced", "preselect": false, @@ -38,7 +34,6 @@ expression: "complete(r#\"\n%TEX main.tex\n%SRC \\usepgflibrary{}\n%CUR } }, { - "data": "[data]", "kind": 1, "label": "curvilinear", "preselect": false, @@ -49,7 +44,6 @@ expression: "complete(r#\"\n%TEX main.tex\n%SRC \\usepgflibrary{}\n%CUR } }, { - "data": "[data]", "kind": 1, "label": "datavisualization.barcharts", "preselect": false, diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__tikz_library_open_brace.snap b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__tikz_library_open_brace.snap index 3c8a7a4b79..62bb3729b7 100644 --- a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__tikz_library_open_brace.snap +++ b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__tikz_library_open_brace.snap @@ -1,11 +1,9 @@ --- -source: tests/integration/lsp/text_document/completion.rs -assertion_line: 814 +source: src/tests/text_document/completion.rs expression: "complete(r#\"\n%TEX main.tex\n%SRC \\usepgflibrary{\n%CUR ^\"#)?" --- [ { - "data": "[data]", "kind": 1, "label": "arrows", "preselect": false, @@ -16,7 +14,6 @@ expression: "complete(r#\"\n%TEX main.tex\n%SRC \\usepgflibrary{\n%CUR } }, { - "data": "[data]", "kind": 1, "label": "arrows.meta", "preselect": false, @@ -27,7 +24,6 @@ expression: "complete(r#\"\n%TEX main.tex\n%SRC \\usepgflibrary{\n%CUR } }, { - "data": "[data]", "kind": 1, "label": "arrows.spaced", "preselect": false, @@ -38,7 +34,6 @@ expression: "complete(r#\"\n%TEX main.tex\n%SRC \\usepgflibrary{\n%CUR } }, { - "data": "[data]", "kind": 1, "label": "curvilinear", "preselect": false, @@ -49,7 +44,6 @@ expression: "complete(r#\"\n%TEX main.tex\n%SRC \\usepgflibrary{\n%CUR } }, { - "data": "[data]", "kind": 1, "label": "datavisualization.barcharts", "preselect": false, diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__user_command.snap b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__user_command.snap index c5c6b741f3..fe0a397706 100644 --- a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__user_command.snap +++ b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__user_command.snap @@ -1,11 +1,9 @@ --- -source: tests/integration/lsp/text_document/completion.rs -assertion_line: 838 +source: src/tests/text_document/completion.rs expression: "complete(r#\"\n%TEX main.tex\n%SRC \\foobar\n%SRC \\fooba\n%CUR ^\n%1.1 ^^^^^\n%SRC \\begin{foo}\n%SRC \\end{foo}\n%SRC \\begin{fo}\n\"#)?" --- [ { - "data": "[data]", "detail": "user-defined", "kind": 1, "label": "foobar", diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__user_environment.snap b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__user_environment.snap index d760617880..7230e9a951 100644 --- a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__user_environment.snap +++ b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__completion__user_environment.snap @@ -1,11 +1,9 @@ --- -source: tests/integration/lsp/text_document/completion.rs -assertion_line: 856 +source: src/tests/text_document/completion.rs expression: "complete(r#\"\n%TEX main.tex\n%SRC \\foobar\n%SRC \\fooba\n%SRC \\begin{foo}\n%SRC \\end{foo}\n%SRC \\begin{fo}\n%CUR ^\n%1.1 ^^\n\"#)?" --- [ { - "data": "[data]", "detail": "user-defined", "kind": 1, "label": "foo", @@ -17,7 +15,6 @@ expression: "complete(r#\"\n%TEX main.tex\n%SRC \\foobar\n%SRC \\fooba\n%SRC \\b } }, { - "data": "[data]", "detail": "built-in", "kind": 1, "label": "filecontents", diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__did_change_configuration__invalid_configuration.snap b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__did_change_configuration__invalid_configuration.snap index 4f41cfbeb2..1400d80167 100644 --- a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__did_change_configuration__invalid_configuration.snap +++ b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__did_change_configuration__invalid_configuration.snap @@ -1,6 +1,5 @@ --- -source: tests/integration/lsp/text_document/did_change_configuration.rs -assertion_line: 37 +source: src/tests/text_document/did_change_configuration.rs expression: message --- The texlab configuration is invalid; using the default settings instead. diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__document_symbol__enumerate_flat.snap b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__document_symbol__enumerate_flat.snap index 3293d55600..4c5a17fb98 100644 --- a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__document_symbol__enumerate_flat.snap +++ b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__document_symbol__enumerate_flat.snap @@ -1,6 +1,5 @@ --- -source: tests/integration/lsp/text_document/document_symbol.rs -assertion_line: 88 +source: src/tests/text_document/document_symbol.rs expression: result.response --- [ diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__document_symbol__enumerate_nested.snap b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__document_symbol__enumerate_nested.snap index b2753ba69f..630311f32e 100644 --- a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__document_symbol__enumerate_nested.snap +++ b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__document_symbol__enumerate_nested.snap @@ -1,6 +1,5 @@ --- -source: tests/integration/lsp/text_document/document_symbol.rs -assertion_line: 53 +source: src/tests/text_document/document_symbol.rs expression: result.response --- [ diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__document_symbol__equation_flat.snap b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__document_symbol__equation_flat.snap index b1a4630dab..24ab44c772 100644 --- a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__document_symbol__equation_flat.snap +++ b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__document_symbol__equation_flat.snap @@ -1,6 +1,5 @@ --- -source: tests/integration/lsp/text_document/document_symbol.rs -assertion_line: 156 +source: src/tests/text_document/document_symbol.rs expression: result.response --- [ diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__document_symbol__equation_nested.snap b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__document_symbol__equation_nested.snap index fc707bd031..2efe7a4796 100644 --- a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__document_symbol__equation_nested.snap +++ b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__document_symbol__equation_nested.snap @@ -1,6 +1,5 @@ --- -source: tests/integration/lsp/text_document/document_symbol.rs -assertion_line: 117 +source: src/tests/text_document/document_symbol.rs expression: result.response --- [ diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__document_symbol__float_flat.snap b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__document_symbol__float_flat.snap index da456f914e..3d2537d85b 100644 --- a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__document_symbol__float_flat.snap +++ b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__document_symbol__float_flat.snap @@ -1,6 +1,5 @@ --- -source: tests/integration/lsp/text_document/document_symbol.rs -assertion_line: 238 +source: src/tests/text_document/document_symbol.rs expression: result.response --- [ diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__document_symbol__float_nested.snap b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__document_symbol__float_nested.snap index 4f60c21c92..18c5f3ca93 100644 --- a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__document_symbol__float_nested.snap +++ b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__document_symbol__float_nested.snap @@ -1,6 +1,5 @@ --- -source: tests/integration/lsp/text_document/document_symbol.rs -assertion_line: 189 +source: src/tests/text_document/document_symbol.rs expression: result.response --- [ diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__document_symbol__section_flat.snap b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__document_symbol__section_flat.snap index 85e72e90e1..87ff442db1 100644 --- a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__document_symbol__section_flat.snap +++ b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__document_symbol__section_flat.snap @@ -1,6 +1,5 @@ --- -source: tests/integration/lsp/text_document/document_symbol.rs -assertion_line: 316 +source: src/tests/text_document/document_symbol.rs expression: result.response --- [ diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__document_symbol__section_nested.snap b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__document_symbol__section_nested.snap index 97ae75eac4..bf4fea547e 100644 --- a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__document_symbol__section_nested.snap +++ b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__document_symbol__section_nested.snap @@ -1,6 +1,5 @@ --- -source: tests/integration/lsp/text_document/document_symbol.rs -assertion_line: 281 +source: src/tests/text_document/document_symbol.rs expression: result.response --- [ diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__document_symbol__theorem_flat.snap b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__document_symbol__theorem_flat.snap index 9af601da0d..d033c3ca62 100644 --- a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__document_symbol__theorem_flat.snap +++ b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__document_symbol__theorem_flat.snap @@ -1,6 +1,5 @@ --- -source: tests/integration/lsp/text_document/document_symbol.rs -assertion_line: 391 +source: src/tests/text_document/document_symbol.rs expression: result.response --- [ diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__document_symbol__theorem_nested.snap b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__document_symbol__theorem_nested.snap index 6a81f96fa6..22844dd700 100644 --- a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__document_symbol__theorem_nested.snap +++ b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__document_symbol__theorem_nested.snap @@ -1,6 +1,5 @@ --- -source: tests/integration/lsp/text_document/document_symbol.rs -assertion_line: 345 +source: src/tests/text_document/document_symbol.rs expression: result.response --- [ diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__formatting__bibtex_internal_command.snap b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__formatting__bibtex_internal_command.snap index 1add9efc6a..c7d1491245 100644 --- a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__formatting__bibtex_internal_command.snap +++ b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__formatting__bibtex_internal_command.snap @@ -1,6 +1,5 @@ --- -source: tests/integration/lsp/text_document/formatting.rs -assertion_line: 96 +source: src/tests/text_document/formatting.rs expression: "format(r#\"\n%BIB main.bib\n%SRC @article{foo, bar = \"\\baz\",}\"#)?" --- @article{foo, diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__formatting__bibtex_internal_insert_braces.snap b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__formatting__bibtex_internal_insert_braces.snap index ee9be8c822..d05b077188 100644 --- a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__formatting__bibtex_internal_insert_braces.snap +++ b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__formatting__bibtex_internal_insert_braces.snap @@ -1,6 +1,5 @@ --- -source: tests/integration/lsp/text_document/formatting.rs -assertion_line: 85 +source: src/tests/text_document/formatting.rs expression: "format(r#\"\n%BIB main.bib\n%SRC @article{foo, bar = baz,\"#)?" --- @article{foo, diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__formatting__bibtex_internal_join_strings.snap b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__formatting__bibtex_internal_join_strings.snap index 8c2a21f579..8fb3765129 100644 --- a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__formatting__bibtex_internal_join_strings.snap +++ b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__formatting__bibtex_internal_join_strings.snap @@ -1,6 +1,5 @@ --- -source: tests/integration/lsp/text_document/formatting.rs -assertion_line: 107 +source: src/tests/text_document/formatting.rs expression: "format(r#\"\n%BIB main.bib\n%SRC @article{foo, bar = \"baz\" # \"qux\"}\"#)?" --- @article{foo, diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__formatting__bibtex_internal_multiple_entries.snap b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__formatting__bibtex_internal_multiple_entries.snap index cf228db867..2496f9b5e5 100644 --- a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__formatting__bibtex_internal_multiple_entries.snap +++ b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__formatting__bibtex_internal_multiple_entries.snap @@ -1,6 +1,5 @@ --- -source: tests/integration/lsp/text_document/formatting.rs -assertion_line: 59 +source: src/tests/text_document/formatting.rs expression: "format(r#\"\n%BIB main.bib\n%SRC @article{foo, bar = {Lorem ipsum dolor sit amet, consectetur adipiscing elit. Lorem ipsum dolor sit amet, \n%SRC consectetur adipiscing elit. Lorem ipsum dolor sit amet, consectetur adipiscing elit.},}\n%SRC \n%SRC @article{foo, bar = {Lorem ipsum dolor sit amet, consectetur adipiscing elit. Lorem ipsum dolor sit amet, \n%SRC consectetur adipiscing elit. Lorem ipsum dolor sit amet, consectetur adipiscing elit.},}\"\"#)?" --- @article{foo, diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__formatting__bibtex_internal_parens.snap b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__formatting__bibtex_internal_parens.snap index 58e98f7ba5..883b97b375 100644 --- a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__formatting__bibtex_internal_parens.snap +++ b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__formatting__bibtex_internal_parens.snap @@ -1,6 +1,5 @@ --- -source: tests/integration/lsp/text_document/formatting.rs -assertion_line: 118 +source: src/tests/text_document/formatting.rs expression: "format(r#\"\n%BIB main.bib\n%SRC @article(foo,)\"#)?" --- @article{foo, diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__formatting__bibtex_internal_preamble.snap b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__formatting__bibtex_internal_preamble.snap index a82706dbf6..fdac219c35 100644 --- a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__formatting__bibtex_internal_preamble.snap +++ b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__formatting__bibtex_internal_preamble.snap @@ -1,6 +1,5 @@ --- -source: tests/integration/lsp/text_document/formatting.rs -assertion_line: 140 +source: src/tests/text_document/formatting.rs expression: "format(r#\"\n%BIB main.bib\n%SRC @preamble{\n%SRC \"foo bar baz\" }\"#)?" --- @preamble{"foo bar baz"} diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__formatting__bibtex_internal_string.snap b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__formatting__bibtex_internal_string.snap index 3234fca52c..8f9589773e 100644 --- a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__formatting__bibtex_internal_string.snap +++ b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__formatting__bibtex_internal_string.snap @@ -1,6 +1,5 @@ --- -source: tests/integration/lsp/text_document/formatting.rs -assertion_line: 129 +source: src/tests/text_document/formatting.rs expression: "format(r#\"\n%BIB main.bib\n%SRC @string{foo=\"bar\"}\"#)?" --- @string{foo = "bar"} diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__formatting__bibtex_internal_trailing_comma.snap b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__formatting__bibtex_internal_trailing_comma.snap index 1231f1795f..1051e00cf3 100644 --- a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__formatting__bibtex_internal_trailing_comma.snap +++ b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__formatting__bibtex_internal_trailing_comma.snap @@ -1,6 +1,5 @@ --- -source: tests/integration/lsp/text_document/formatting.rs -assertion_line: 74 +source: src/tests/text_document/formatting.rs expression: "format(r#\"\n%BIB main.bib\n%SRC @article{foo, bar = baz}\"#)?" --- @article{foo, diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__formatting__bibtex_internal_wrap_long_lines.snap b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__formatting__bibtex_internal_wrap_long_lines.snap index fd9355025c..e7e1f39386 100644 --- a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__formatting__bibtex_internal_wrap_long_lines.snap +++ b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__formatting__bibtex_internal_wrap_long_lines.snap @@ -1,6 +1,5 @@ --- -source: tests/integration/lsp/text_document/formatting.rs -assertion_line: 46 +source: src/tests/text_document/formatting.rs expression: "format(r#\"\n%BIB main.bib\n%SRC @article{foo, bar = {Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n%SRC Lorem ipsum dolor sit amet,\n%SRC consectetur adipiscing elit. Lorem ipsum dolor sit amet, consectetur adipiscing elit.},}\"#)?" --- @article{foo, diff --git a/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__inlay_hint__label_definition.snap b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__inlay_hint__label_definition.snap new file mode 100644 index 0000000000..ff04d65efb --- /dev/null +++ b/support/texlab/src/tests/text_document/snapshots/texlab__tests__text_document__inlay_hint__label_definition.snap @@ -0,0 +1,38 @@ +--- +source: src/tests/text_document/inlay_hint.rs +expression: "check(r#\"\n%TEX main.tex\n%SRC \\documentclass{article}\n%SRC \\usepackage{caption}\n%SRC \\begin{document}\n%SRC \\section{Foo}\\label{sec:foo}\n%SRC \\section{Bar}\\label{sec:bar}\n%SRC \\subsection{Baz}\\label{sec:baz}\n%SRC \\begin{figure}\n%SRC Test\n%SRC \\label{fig:qux}\n%SRC \\caption{Qux}\n%SRC \\end{figure}\n%SRC \\end{document}\n\n%TEX main.aux\n%SRC \\relax \n%SRC \\providecommand*\\caption@xref[2]{\\@setref\\relax\\@undefined{#1}}\n%SRC \\newlabel{fig:qux}{{\\caption@xref {fig:qux}{ on input line 15}}{1}}\n%SRC \\@writefile{lof}{\\contentsline {figure}{\\numberline {1}{\\ignorespaces Qux\\relax }}{1}{}\\protected@file@percent }\n%SRC \\@writefile{toc}{\\contentsline {section}{\\numberline {1}Foo}{1}{}\\protected@file@percent }\n%SRC \\newlabel{sec:foo}{{1}{1}}\n%SRC \\@writefile{toc}{\\contentsline {section}{\\numberline {2}Bar}{1}{}\\protected@file@percent }\n%SRC \\newlabel{sec:bar}{{2}{1}}\n%SRC \\@writefile{toc}{\\contentsline {subsection}{\\numberline {2.1}Baz}{1}{}\\protected@file@percent }\n%SRC \\newlabel{sec:baz}{{2.1}{1}}\n%SRC \\gdef \\@abspage@last{1}\n\"#)?" +--- +[ + { + "position": { + "line": 3, + "character": 27 + }, + "label": "Section 1 (Foo)", + "paddingLeft": true + }, + { + "position": { + "line": 4, + "character": 27 + }, + "label": "Section 2 (Bar)", + "paddingLeft": true + }, + { + "position": { + "line": 5, + "character": 30 + }, + "label": "Subsection 2.1 (Baz)", + "paddingLeft": true + }, + { + "position": { + "line": 8, + "character": 18 + }, + "label": "Figure fig:qux: Qux", + "paddingLeft": true + } +] diff --git a/support/texlab/tests/integration/lsp/workspace.rs b/support/texlab/src/tests/workspace.rs index 15e0679dea..15e0679dea 100644 --- a/support/texlab/tests/integration/lsp/workspace.rs +++ b/support/texlab/src/tests/workspace.rs diff --git a/support/texlab/tests/integration/lsp/workspace/snapshots/integration__lsp__workspace__symbol__filter_bibtex.snap b/support/texlab/src/tests/workspace/snapshots/texlab__tests__workspace__symbol__filter_bibtex.snap index 8b71b0519e..16963641bf 100644 --- a/support/texlab/tests/integration/lsp/workspace/snapshots/integration__lsp__workspace__symbol__filter_bibtex.snap +++ b/support/texlab/src/tests/workspace/snapshots/texlab__tests__workspace__symbol__filter_bibtex.snap @@ -1,6 +1,5 @@ --- -source: tests/integration/lsp/workspace/symbol.rs -assertion_line: 145 +source: src/tests/workspace/symbol.rs expression: result.actual_symbols --- [ diff --git a/support/texlab/tests/integration/lsp/workspace/snapshots/integration__lsp__workspace__symbol__filter_type_figure.snap b/support/texlab/src/tests/workspace/snapshots/texlab__tests__workspace__symbol__filter_type_figure.snap index a2343d994b..1b1d2371a4 100644 --- a/support/texlab/tests/integration/lsp/workspace/snapshots/integration__lsp__workspace__symbol__filter_type_figure.snap +++ b/support/texlab/src/tests/workspace/snapshots/texlab__tests__workspace__symbol__filter_type_figure.snap @@ -1,6 +1,5 @@ --- -source: tests/integration/lsp/workspace/symbol.rs -assertion_line: 127 +source: src/tests/workspace/symbol.rs expression: result.actual_symbols --- [ diff --git a/support/texlab/tests/integration/lsp/workspace/snapshots/integration__lsp__workspace__symbol__filter_type_item.snap b/support/texlab/src/tests/workspace/snapshots/texlab__tests__workspace__symbol__filter_type_item.snap index 37dad570c9..ed45c13cf1 100644 --- a/support/texlab/tests/integration/lsp/workspace/snapshots/integration__lsp__workspace__symbol__filter_type_item.snap +++ b/support/texlab/src/tests/workspace/snapshots/texlab__tests__workspace__symbol__filter_type_item.snap @@ -1,6 +1,5 @@ --- -source: tests/integration/lsp/workspace/symbol.rs -assertion_line: 133 +source: src/tests/workspace/symbol.rs expression: result.actual_symbols --- [ diff --git a/support/texlab/tests/integration/lsp/workspace/snapshots/integration__lsp__workspace__symbol__filter_type_math.snap b/support/texlab/src/tests/workspace/snapshots/texlab__tests__workspace__symbol__filter_type_math.snap index 8b98b614a3..d4cea99cc5 100644 --- a/support/texlab/tests/integration/lsp/workspace/snapshots/integration__lsp__workspace__symbol__filter_type_math.snap +++ b/support/texlab/src/tests/workspace/snapshots/texlab__tests__workspace__symbol__filter_type_math.snap @@ -1,6 +1,5 @@ --- -source: tests/integration/lsp/workspace/symbol.rs -assertion_line: 139 +source: src/tests/workspace/symbol.rs expression: result.actual_symbols --- [ diff --git a/support/texlab/tests/integration/lsp/workspace/snapshots/integration__lsp__workspace__symbol__filter_type_section.snap b/support/texlab/src/tests/workspace/snapshots/texlab__tests__workspace__symbol__filter_type_section.snap index b4974c9d7f..3a3ef78ab2 100644 --- a/support/texlab/tests/integration/lsp/workspace/snapshots/integration__lsp__workspace__symbol__filter_type_section.snap +++ b/support/texlab/src/tests/workspace/snapshots/texlab__tests__workspace__symbol__filter_type_section.snap @@ -1,6 +1,5 @@ --- -source: tests/integration/lsp/workspace/symbol.rs -assertion_line: 121 +source: src/tests/workspace/symbol.rs expression: result.actual_symbols --- [ diff --git a/support/texlab/tests/integration/lsp/workspace/symbol.rs b/support/texlab/src/tests/workspace/symbol.rs index 0af7534af3..626cce3c0b 100644 --- a/support/texlab/tests/integration/lsp/workspace/symbol.rs +++ b/support/texlab/src/tests/workspace/symbol.rs @@ -1,23 +1,22 @@ -use anyhow::Result; use insta::{assert_json_snapshot, internals::Redaction}; use lsp_types::{ request::WorkspaceSymbol, ClientCapabilities, SymbolInformation, Url, WorkspaceSymbolParams, }; -use crate::lsp::{client::Client, fixture}; +use crate::tests::{client::Client, fixture}; struct SymbolResult { actual_symbols: Vec<SymbolInformation>, uri_redaction: Redaction, } -fn find_symbols(fixture: &str, query: &str) -> Result<SymbolResult> { - let mut client = Client::spawn()?; - client.initialize(ClientCapabilities::default(), None)?; +fn find_symbols(fixture: &str, query: &str) -> SymbolResult { + let mut client = Client::spawn(); + client.initialize(ClientCapabilities::default(), None); let fixture = fixture::parse(fixture); for file in fixture.files { - client.open(file.name, file.lang, file.text)?; + client.open(file.name, file.lang, file.text); } let actual_symbols = client @@ -25,20 +24,21 @@ fn find_symbols(fixture: &str, query: &str) -> Result<SymbolResult> { query: query.to_string(), work_done_progress_params: Default::default(), partial_result_params: Default::default(), - })? + }) + .unwrap() .unwrap_or_default(); - let result = client.shutdown()?; + let result = client.shutdown(); let uri = Url::from_directory_path(result.directory.path()).unwrap(); let uri_redaction = insta::dynamic_redaction(move |content, _path| { content.as_str().unwrap().replace(uri.as_str(), "[tmp]/") }); - Ok(SymbolResult { + SymbolResult { actual_symbols, uri_redaction, - }) + } } macro_rules! assert_symbols { @@ -117,31 +117,26 @@ const FIXTURE: &str = r#" %SRC @string{bar = "bar"}"#; #[test] -fn filter_type_section() -> Result<()> { - assert_symbols!(find_symbols(FIXTURE, "section")?); - Ok(()) +fn filter_type_section() { + assert_symbols!(find_symbols(FIXTURE, "section")); } #[test] -fn filter_type_figure() -> Result<()> { - assert_symbols!(find_symbols(FIXTURE, "figure")?); - Ok(()) +fn filter_type_figure() { + assert_symbols!(find_symbols(FIXTURE, "figure")); } #[test] -fn filter_type_item() -> Result<()> { - assert_symbols!(find_symbols(FIXTURE, "item")?); - Ok(()) +fn filter_type_item() { + assert_symbols!(find_symbols(FIXTURE, "item")); } #[test] -fn filter_type_math() -> Result<()> { - assert_symbols!(find_symbols(FIXTURE, "math")?); - Ok(()) +fn filter_type_math() { + assert_symbols!(find_symbols(FIXTURE, "math")); } #[test] -fn filter_bibtex() -> Result<()> { - assert_symbols!(find_symbols(FIXTURE, "bibtex")?); - Ok(()) +fn filter_bibtex() { + assert_symbols!(find_symbols(FIXTURE, "bibtex")); } diff --git a/support/texlab/src/util.rs b/support/texlab/src/util.rs new file mode 100644 index 0000000000..1c4d55a19d --- /dev/null +++ b/support/texlab/src/util.rs @@ -0,0 +1,15 @@ +pub mod capabilities; +pub mod chktex; +pub mod components; +pub mod cursor; +pub mod label; +pub mod lang_data; +pub mod line_index; +pub mod line_index_ext; +pub mod lsp_enums; + +use std::path::PathBuf; + +use once_cell::sync::Lazy; + +pub static HOME_DIR: Lazy<Option<PathBuf>> = Lazy::new(|| dirs::home_dir()); diff --git a/support/texlab/src/capabilities.rs b/support/texlab/src/util/capabilities.rs index bcb5bbba8b..987c0b48dd 100644 --- a/support/texlab/src/capabilities.rs +++ b/support/texlab/src/util/capabilities.rs @@ -7,6 +7,8 @@ pub trait ClientCapabilitiesExt { fn has_work_done_progress_support(&self) -> bool; + fn has_completion_markdown_support(&self) -> bool; + fn has_hover_markdown_support(&self) -> bool; fn has_pull_configuration_support(&self) -> bool; @@ -14,6 +16,8 @@ pub trait ClientCapabilitiesExt { fn has_push_configuration_support(&self) -> bool; fn has_file_watching_support(&self) -> bool; + + fn has_snippet_support(&self) -> bool; } impl ClientCapabilitiesExt for ClientCapabilities { @@ -37,13 +41,21 @@ impl ClientCapabilitiesExt for ClientCapabilities { self.window.as_ref().and_then(|cap| cap.work_done_progress) == Some(true) } + fn has_completion_markdown_support(&self) -> bool { + self.text_document + .as_ref() + .and_then(|cap| cap.completion.as_ref()) + .and_then(|cap| cap.completion_item.as_ref()) + .and_then(|cap| cap.documentation_format.as_ref()) + .map_or(false, |formats| formats.contains(&MarkupKind::Markdown)) + } + fn has_hover_markdown_support(&self) -> bool { self.text_document .as_ref() .and_then(|cap| cap.hover.as_ref()) .and_then(|cap| cap.content_format.as_ref()) - .filter(|formats| formats.contains(&MarkupKind::Markdown)) - .is_some() + .map_or(false, |formats| formats.contains(&MarkupKind::Markdown)) } fn has_pull_configuration_support(&self) -> bool { @@ -65,6 +77,15 @@ impl ClientCapabilitiesExt for ClientCapabilities { .and_then(|cap| cap.dynamic_registration) == Some(true) } + + fn has_snippet_support(&self) -> bool { + self.text_document + .as_ref() + .and_then(|cap| cap.completion.as_ref()) + .and_then(|cap| cap.completion_item.as_ref()) + .and_then(|cap| cap.snippet_support) + == Some(true) + } } #[cfg(test)] diff --git a/support/texlab/src/util/chktex.rs b/support/texlab/src/util/chktex.rs new file mode 100644 index 0000000000..29a7ac5630 --- /dev/null +++ b/support/texlab/src/util/chktex.rs @@ -0,0 +1,112 @@ +use std::{ + io::{BufRead, BufReader, Write}, + path::PathBuf, + process::Stdio, +}; + +use encoding_rs_io::DecodeReaderBytesBuilder; +use lsp_types::{DiagnosticSeverity, Position, Range}; +use once_cell::sync::Lazy; +use regex::Regex; + +use crate::{ + db::{ + diagnostics::{Diagnostic, DiagnosticCode}, + Document, Workspace, + }, + Db, +}; + +#[derive(Debug)] +pub struct Command { + text: String, + working_dir: PathBuf, +} + +impl Command { + pub fn new(db: &dyn Db, document: Document) -> Option<Self> { + document.parse(db).as_tex()?; + + let workspace = Workspace::get(db); + let parent = workspace + .parents(db, document) + .iter() + .next() + .map_or(document, Clone::clone); + + let working_dir = workspace + .working_dir(db, parent.directory(db)) + .path(db) + .as_deref()? + .to_owned(); + + log::debug!("Calling ChkTeX from directory: {}", working_dir.display()); + + let text = document.contents(db).text(db).clone(); + + Some(Self { text, working_dir }) + } + + pub fn run(self) -> std::io::Result<Vec<Diagnostic>> { + let mut child = std::process::Command::new("chktex") + .args(&["-I0", "-f%l:%c:%d:%k:%n:%m\n"]) + .stdin(Stdio::piped()) + .stdout(Stdio::piped()) + .stderr(Stdio::null()) + .current_dir(self.working_dir) + .spawn()?; + + let stdout = child.stdout.take().unwrap(); + let reader = std::thread::spawn(move || { + let mut diagnostics = Vec::new(); + let reader = BufReader::new( + DecodeReaderBytesBuilder::new() + .encoding(Some(encoding_rs::UTF_8)) + .utf8_passthru(true) + .strip_bom(true) + .build(stdout), + ); + + for line in reader.lines().flatten() { + let captures = LINE_REGEX.captures(&line).unwrap(); + let line = captures[1].parse::<u32>().unwrap() - 1; + let character = captures[2].parse::<u32>().unwrap() - 1; + let digit = captures[3].parse::<u32>().unwrap(); + let kind = &captures[4]; + let code = &captures[5]; + let message = captures[6].into(); + let range = Range::new( + Position::new(line, character), + Position::new(line, character + digit), + ); + + let severity = match kind { + "Message" => DiagnosticSeverity::INFORMATION, + "Warning" => DiagnosticSeverity::WARNING, + _ => DiagnosticSeverity::ERROR, + }; + + diagnostics.push(Diagnostic { + range, + severity, + code: DiagnosticCode::Chktex(code.into()), + message, + }); + } + + diagnostics + }); + + let mut stdin = child.stdin.take().unwrap(); + let bytes = self.text.into_bytes(); + let writer = std::thread::spawn(move || stdin.write_all(&bytes)); + + child.wait()?; + writer.join().unwrap()?; + let diagnostics = reader.join().unwrap(); + Ok(diagnostics) + } +} + +static LINE_REGEX: Lazy<Regex> = + Lazy::new(|| Regex::new("(\\d+):(\\d+):(\\d+):(\\w+):(\\w+):(.*)").unwrap()); diff --git a/support/texlab/src/util/components.rs b/support/texlab/src/util/components.rs new file mode 100644 index 0000000000..022e7efbc8 --- /dev/null +++ b/support/texlab/src/util/components.rs @@ -0,0 +1,120 @@ +use std::io::Read; + +use flate2::read::GzDecoder; +use itertools::Itertools; +use lsp_types::{MarkupContent, MarkupKind}; +use once_cell::sync::Lazy; +use serde::Deserialize; +use smol_str::SmolStr; + +use crate::{ + db::{analysis::TexLinkKind, Document, Workspace}, + Db, +}; + +#[derive(Debug, PartialEq, Eq, Clone, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct ComponentDatabase { + pub components: Vec<Component>, + pub metadata: Vec<ComponentMetadata>, +} + +impl ComponentDatabase { + pub fn find(&self, name: &str) -> Option<&Component> { + self.components.iter().find(|component| { + component + .file_names + .iter() + .any(|file_name| file_name == name) + }) + } + + pub fn linked_components(&self, db: &dyn Db, child: Document) -> Vec<&Component> { + Workspace::get(db) + .related(db, child) + .iter() + .filter_map(|document| document.parse(db).as_tex()) + .flat_map(|data| data.analyze(db).links(db)) + .filter_map(|link| match link.kind(db) { + TexLinkKind::Sty => Some(format!("{}.sty", link.path(db).text(db))), + TexLinkKind::Cls => Some(format!("{}.cls", link.path(db).text(db))), + _ => None, + }) + .filter_map(|name| self.find(&name)) + .chain(std::iter::once(self.kernel())) + .flat_map(|comp| { + comp.references + .iter() + .filter_map(|name| self.find(name)) + .chain(std::iter::once(comp)) + }) + .unique_by(|comp| &comp.file_names) + .collect() + } + + pub fn kernel(&self) -> &Component { + self.components + .iter() + .find(|component| component.file_names.is_empty()) + .unwrap() + } + + pub fn documentation(&self, name: &str) -> Option<MarkupContent> { + let metadata = self + .metadata + .iter() + .find(|metadata| metadata.name == name)?; + + let desc = metadata.description.clone()?; + Some(MarkupContent { + kind: MarkupKind::PlainText, + value: desc, + }) + } +} + +#[derive(Debug, PartialEq, Eq, Clone, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct Component { + pub file_names: Vec<SmolStr>, + pub references: Vec<SmolStr>, + pub commands: Vec<ComponentCommand>, + pub environments: Vec<SmolStr>, +} + +#[derive(Debug, PartialEq, Eq, Clone, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct ComponentCommand { + pub name: SmolStr, + pub image: Option<String>, + pub glyph: Option<SmolStr>, + pub parameters: Vec<ComponentParameter>, +} + +#[derive(Debug, PartialEq, Eq, Clone, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct ComponentParameter(pub Vec<ComponentArgument>); + +#[derive(Debug, PartialEq, Eq, Clone, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct ComponentArgument { + pub name: SmolStr, + pub image: Option<String>, +} + +#[derive(Debug, PartialEq, Eq, Clone, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct ComponentMetadata { + pub name: String, + pub caption: Option<String>, + pub description: Option<String>, +} + +const JSON_GZ: &[u8] = include_bytes!("../../data/components.json.gz"); + +pub static COMPONENT_DATABASE: Lazy<ComponentDatabase> = Lazy::new(|| { + let mut decoder = GzDecoder::new(JSON_GZ); + let mut buf = String::new(); + decoder.read_to_string(&mut buf).unwrap(); + serde_json::from_str(&buf).unwrap() +}); diff --git a/support/texlab/src/features/cursor.rs b/support/texlab/src/util/cursor.rs index 84ee6e98c4..5c3758ef46 100644 --- a/support/texlab/src/features/cursor.rs +++ b/support/texlab/src/util/cursor.rs @@ -1,25 +1,23 @@ -use lsp_types::{ - CompletionParams, DocumentHighlightParams, GotoDefinitionParams, HoverParams, Position, - ReferenceParams, RenameParams, TextDocumentPositionParams, -}; +use lsp_types::{Position, Url}; use rowan::{ast::AstNode, TextRange, TextSize}; use crate::{ + db::{parse::DocumentData, Document, Workspace}, syntax::{bibtex, latex}, - DocumentData, LineIndexExt, + Db, }; -use super::FeatureRequest; +use super::{line_index::LineIndex, line_index_ext::LineIndexExt}; #[derive(Debug)] pub enum Cursor { - Latex(latex::SyntaxToken), - Bibtex(bibtex::SyntaxToken), + Tex(latex::SyntaxToken), + Bib(bibtex::SyntaxToken), Nothing, } impl Cursor { - pub fn new_latex( + pub fn new_tex( left: Option<latex::SyntaxToken>, right: Option<latex::SyntaxToken>, ) -> Option<Self> { @@ -27,35 +25,35 @@ impl Cursor { let right = right?; if left.kind().is_command_name() { - return Some(Self::Latex(left)); + return Some(Self::Tex(left)); } if right.kind() == latex::WORD { - return Some(Self::Latex(right)); + return Some(Self::Tex(right)); } if left.kind() == latex::WORD { - return Some(Self::Latex(left)); + return Some(Self::Tex(left)); } if right.kind().is_command_name() { - return Some(Self::Latex(right)); + return Some(Self::Tex(right)); } if left.kind() == latex::WHITESPACE && left.parent()?.kind() == latex::KEY { - return Some(Self::Latex(left)); + return Some(Self::Tex(left)); } if matches!(right.kind(), latex::WHITESPACE | latex::LINE_BREAK) && right.parent()?.kind() == latex::KEY { - return Some(Self::Latex(right)); + return Some(Self::Tex(right)); } - Some(Self::Latex(right)) + Some(Self::Tex(right)) } - pub fn new_bibtex( + pub fn new_bib( left: Option<bibtex::SyntaxToken>, right: Option<bibtex::SyntaxToken>, ) -> Option<Self> { @@ -63,42 +61,42 @@ impl Cursor { let right = right?; if right.kind() == bibtex::TYPE { - return Some(Self::Bibtex(right)); + return Some(Self::Bib(right)); } if left.kind() == bibtex::TYPE { - return Some(Self::Bibtex(left)); + return Some(Self::Bib(left)); } if matches!(left.kind(), bibtex::COMMAND_NAME | bibtex::ACCENT_NAME) { - return Some(Self::Bibtex(left)); + return Some(Self::Bib(left)); } if matches!(right.kind(), bibtex::WORD | bibtex::NAME) { - return Some(Self::Bibtex(right)); + return Some(Self::Bib(right)); } if matches!(left.kind(), bibtex::WORD | bibtex::NAME) { - return Some(Self::Bibtex(left)); + return Some(Self::Bib(left)); } if matches!(right.kind(), bibtex::COMMAND_NAME | bibtex::ACCENT_NAME) { - return Some(Self::Bibtex(right)); + return Some(Self::Bib(right)); } - Some(Self::Bibtex(right)) + Some(Self::Bib(right)) } - pub fn as_latex(&self) -> Option<&latex::SyntaxToken> { - if let Self::Latex(v) = self { + pub fn as_tex(&self) -> Option<&latex::SyntaxToken> { + if let Self::Tex(v) = self { Some(v) } else { None } } - pub fn as_bibtex(&self) -> Option<&bibtex::SyntaxToken> { - if let Self::Bibtex(v) = self { + pub fn as_bib(&self) -> Option<&bibtex::SyntaxToken> { + if let Self::Bib(v) = self { Some(v) } else { None @@ -106,13 +104,13 @@ impl Cursor { } pub fn command_range(&self, offset: TextSize) -> Option<TextRange> { - self.as_latex() + self.as_tex() .filter(|token| token.kind().is_command_name()) .filter(|token| token.text_range().start() != offset) .map(|token| token.text_range()) .map(|range| TextRange::new(range.start() + TextSize::from(1), range.end())) .or_else(|| { - self.as_bibtex() + self.as_bib() .filter(|token| { matches!(token.kind(), bibtex::COMMAND_NAME | bibtex::ACCENT_NAME) }) @@ -123,40 +121,55 @@ impl Cursor { } } -pub struct CursorContext<P> { - pub request: FeatureRequest<P>, +pub struct CursorContext<'db, T = ()> { + pub db: &'db dyn Db, + pub document: Document, + pub line_index: &'db LineIndex, + pub workspace: Workspace, pub cursor: Cursor, pub offset: TextSize, + pub params: T, } -impl<P: HasPosition> CursorContext<P> { - pub fn new(request: FeatureRequest<P>) -> Self { - let main_document = request.main_document(); - let offset = main_document - .line_index - .offset_lsp(request.params.position()); +impl<'db, T> CursorContext<'db, T> { + pub fn new(db: &'db dyn Db, uri: &Url, position: Position, params: T) -> Option<Self> { + let workspace = Workspace::get(db); + let document = workspace.lookup_uri(db, uri)?; + let line_index = document.contents(db).line_index(db); + let offset = line_index.offset_lsp(position); - let cursor = match &main_document.data { - DocumentData::Latex(data) => { - let root = latex::SyntaxNode::new_root(data.green.clone()); + let cursor = match document.parse(db) { + DocumentData::Tex(data) => { + let root = data.root(db); let left = root.token_at_offset(offset).left_biased(); let right = root.token_at_offset(offset).right_biased(); - Cursor::new_latex(left, right) + Cursor::new_tex(left, right) } - DocumentData::Bibtex(data) => { - let root = bibtex::SyntaxNode::new_root(data.green.clone()); + DocumentData::Bib(data) => { + let root = data.root(db); let left = root.token_at_offset(offset).left_biased(); let right = root.token_at_offset(offset).right_biased(); - Cursor::new_bibtex(left, right) + Cursor::new_bib(left, right) } - DocumentData::BuildLog(_) => None, + DocumentData::Log(_) => None, }; - Self { - request, + Some(Self { + db, + document, + line_index, + workspace, cursor: cursor.unwrap_or(Cursor::Nothing), offset, - } + params, + }) + } + + pub fn related(&self) -> impl Iterator<Item = Document> + '_ { + self.workspace + .related(self.db, self.document) + .iter() + .copied() } pub fn is_inside_latex_curly(&self, group: &impl latex::HasCurly) -> bool { @@ -166,7 +179,7 @@ impl<P: HasPosition> CursorContext<P> { pub fn find_citation_key_word(&self) -> Option<(String, TextRange)> { let word = self .cursor - .as_latex() + .as_tex() .filter(|token| token.kind() == latex::WORD)?; let key = latex::Key::cast(word.parent()?)?; @@ -177,7 +190,7 @@ impl<P: HasPosition> CursorContext<P> { } pub fn find_citation_key_command(&self) -> Option<(String, TextRange)> { - let command = self.cursor.as_latex()?; + let command = self.cursor.as_tex()?; let citation = latex::Citation::cast(command.parent()?)?; let key = citation.key_list()?.keys().next()?; @@ -187,7 +200,7 @@ impl<P: HasPosition> CursorContext<P> { pub fn find_entry_key(&self) -> Option<(String, TextRange)> { let key = self .cursor - .as_bibtex() + .as_bib() .filter(|token| token.kind() == bibtex::NAME)?; bibtex::Entry::cast(key.parent()?)?; @@ -197,7 +210,7 @@ impl<P: HasPosition> CursorContext<P> { pub fn find_label_name_key(&self) -> Option<(String, TextRange)> { let name = self .cursor - .as_latex() + .as_tex() .filter(|token| token.kind() == latex::WORD)?; let key = latex::Key::cast(name.parent()?)?; @@ -213,7 +226,7 @@ impl<P: HasPosition> CursorContext<P> { } pub fn find_label_name_command(&self) -> Option<(String, TextRange)> { - let node = self.cursor.as_latex()?.parent()?; + let node = self.cursor.as_tex()?.parent()?; if let Some(label) = latex::LabelDefinition::cast(node.clone()) { let name = label.name()?.key()?; Some((name.to_string(), latex::small_range(&name))) @@ -239,7 +252,7 @@ impl<P: HasPosition> CursorContext<P> { } pub fn find_curly_group_word(&self) -> Option<(String, TextRange, latex::CurlyGroupWord)> { - let token = self.cursor.as_latex()?; + let token = self.cursor.as_tex()?; let key = latex::Key::cast(token.parent()?); let group = key @@ -257,7 +270,7 @@ impl<P: HasPosition> CursorContext<P> { pub fn find_curly_group_word_list( &self, ) -> Option<(String, TextRange, latex::CurlyGroupWordList)> { - let token = self.cursor.as_latex()?; + let token = self.cursor.as_tex()?; let key = latex::Key::cast(token.parent()?); let group = key @@ -285,49 +298,3 @@ impl<P: HasPosition> CursorContext<P> { .or_else(|| Some((String::new(), TextRange::empty(self.offset), group))) } } - -pub trait HasPosition { - fn position(&self) -> Position; -} - -impl HasPosition for CompletionParams { - fn position(&self) -> Position { - self.text_document_position.position - } -} - -impl HasPosition for TextDocumentPositionParams { - fn position(&self) -> Position { - self.position - } -} - -impl HasPosition for RenameParams { - fn position(&self) -> Position { - self.text_document_position.position - } -} - -impl HasPosition for ReferenceParams { - fn position(&self) -> Position { - self.text_document_position.position - } -} - -impl HasPosition for HoverParams { - fn position(&self) -> Position { - self.text_document_position_params.position - } -} - -impl HasPosition for GotoDefinitionParams { - fn position(&self) -> Position { - self.text_document_position_params.position - } -} - -impl HasPosition for DocumentHighlightParams { - fn position(&self) -> Position { - self.text_document_position_params.position - } -} diff --git a/support/texlab/src/label.rs b/support/texlab/src/util/label.rs index b66db836f2..f0fae34337 100644 --- a/support/texlab/src/label.rs +++ b/support/texlab/src/util/label.rs @@ -1,24 +1,26 @@ use std::str::FromStr; -use lsp_types::{MarkupContent, MarkupKind}; use rowan::{ast::AstNode, TextRange}; use crate::{ + db::{analysis::label, Document, Word, Workspace}, syntax::latex::{self, HasBrack, HasCurly}, - Workspace, LANGUAGE_DATA, + Db, }; -use self::LabelledObject::*; +use self::LabeledObject::*; + +use super::lang_data::LANGUAGE_DATA; #[derive(Debug, PartialEq, Eq, Clone, Copy)] -pub enum LabelledFloatKind { +pub enum LabeledFloatKind { Figure, Table, Listing, Algorithm, } -impl LabelledFloatKind { +impl LabeledFloatKind { pub fn as_str(self) -> &'static str { match self { Self::Figure => "Figure", @@ -29,7 +31,7 @@ impl LabelledFloatKind { } } -impl FromStr for LabelledFloatKind { +impl FromStr for LabeledFloatKind { type Err = (); fn from_str(s: &str) -> Result<Self, Self::Err> { @@ -44,17 +46,17 @@ impl FromStr for LabelledFloatKind { } #[derive(Debug, PartialEq, Eq, Clone)] -pub enum LabelledObject { +pub enum LabeledObject { Section { prefix: &'static str, text: String, }, Float { - kind: LabelledFloatKind, + kind: LabeledFloatKind, caption: String, }, Theorem { - kind: String, + kind: Word, description: Option<String>, }, Equation, @@ -64,27 +66,28 @@ pub enum LabelledObject { #[derive(Debug, PartialEq, Eq, Clone)] pub struct RenderedLabel { pub range: TextRange, - pub number: Option<String>, - pub object: LabelledObject, + pub number: Option<Word>, + pub object: LabeledObject, } impl RenderedLabel { - #[must_use] - pub fn reference(&self) -> String { + pub fn reference(&self, db: &dyn Db) -> String { match &self.number { Some(number) => match &self.object { - Section { prefix, text } => format!("{} {} ({})", prefix, number, text), - Float { kind, caption } => format!("{} {}: {}", kind.as_str(), number, caption), + Section { prefix, text } => format!("{} {} ({})", prefix, number.text(db), text), + Float { kind, caption } => { + format!("{} {}: {}", kind.as_str(), number.text(db), caption) + } Theorem { kind, description: None, - } => format!("{} {}", kind, number), + } => format!("{} {}", kind.text(db), number.text(db)), Theorem { kind, description: Some(description), - } => format!("{} {} ({})", kind, number, description), - Equation => format!("Equation ({})", number), - EnumItem => format!("Item {}", number), + } => format!("{} {} ({})", kind.text(db), number.text(db), description), + Equation => format!("Equation ({})", number.text(db)), + EnumItem => format!("Item {}", number.text(db)), }, None => match &self.object { Section { prefix, text } => format!("{} ({})", prefix, text), @@ -92,117 +95,93 @@ impl RenderedLabel { Theorem { kind, description: None, - } => kind.into(), + } => kind.text(db).into(), Theorem { kind, description: Some(description), - } => format!("{} ({})", kind, description), + } => format!("{} ({})", kind.text(db), description), Equation => "Equation".into(), EnumItem => "Item".into(), }, } } - #[must_use] - pub fn detail(&self) -> Option<String> { + pub fn detail(&self, db: &dyn Db) -> Option<String> { match &self.object { - Section { .. } | Theorem { .. } | Equation | EnumItem => Some(self.reference()), + Section { .. } | Theorem { .. } | Equation | EnumItem => Some(self.reference(db)), Float { kind, .. } => { let result = match &self.number { - Some(number) => format!("{} {}", kind.as_str(), number), + Some(number) => format!("{} {}", kind.as_str(), number.text(db)), None => kind.as_str().to_owned(), }; Some(result) } } } - - #[must_use] - pub fn documentation(&self) -> MarkupContent { - MarkupContent { - kind: MarkupKind::PlainText, - value: self.reference(), - } - } } -pub fn render_label( - workspace: &Workspace, - label_name: &str, - mut label: Option<latex::LabelDefinition>, -) -> Option<RenderedLabel> { - let mut number = find_label_number(workspace, label_name).map(ToString::to_string); +pub fn render(db: &dyn Db, document: Document, label_def: label::Name) -> Option<RenderedLabel> { + let workspace = Workspace::get(db); + let label_num = workspace.number_of_label(db, document, label_def.name(db)); + let root = document.parse(db).as_tex()?.root(db); - for document in workspace.documents_by_uri.values() { - if let Some(data) = document.data.as_latex() { - label = label.or_else(|| { - find_label_definition(&latex::SyntaxNode::new_root(data.green.clone()), label_name) - }); - } - } - - label?.syntax().ancestors().find_map(|parent| { - render_label_float(parent.clone(), &mut number) - .or_else(|| render_label_section(parent.clone(), &mut number)) - .or_else(|| render_label_enum_item(parent.clone(), &mut number)) - .or_else(|| render_label_equation(parent.clone(), &mut number)) - .or_else(|| render_label_theorem(workspace, parent, &mut number)) - }) + label_def + .origin(db) + .as_definition()? + .to_node(&root) + .syntax() + .ancestors() + .find_map(|parent| { + render_label_float(parent.clone(), label_num) + .or_else(|| render_label_section(parent.clone(), label_num)) + .or_else(|| render_label_enum_item(db, parent.clone(), label_num)) + .or_else(|| render_label_equation(parent.clone(), label_num)) + .or_else(|| render_label_theorem(db, document, parent, label_num)) + }) } pub fn find_label_definition( - root: &latex::SyntaxNode, - label_name: &str, -) -> Option<latex::LabelDefinition> { - root.descendants() - .filter_map(latex::LabelDefinition::cast) - .find(|label| { - label - .name() - .and_then(|name| name.key()) - .map(|name| name.to_string()) - .as_deref() - == Some(label_name) - }) -} + db: &dyn Db, + child: Document, + name: Word, +) -> Option<(Document, label::Name)> { + Workspace::get(db) + .related(db, child) + .iter() + .find_map(|document| { + let data = document.parse(db).as_tex()?; + let label = data + .analyze(db) + .labels(db) + .iter() + .filter(|label| label.origin(db).as_definition().is_some()) + .find(|label| label.name(db) == name)?; -pub fn find_label_number<'a>(workspace: &'a Workspace, label_name: &str) -> Option<&'a str> { - workspace.documents_by_uri.values().find_map(|document| { - document - .data - .as_latex() - .and_then(|data| data.extras.label_numbers_by_name.get(label_name)) - .map(|number| number.as_str()) - }) + Some((*document, *label)) + }) } -fn render_label_float( - parent: latex::SyntaxNode, - number: &mut Option<String>, -) -> Option<RenderedLabel> { +fn render_label_float(parent: latex::SyntaxNode, number: Option<Word>) -> Option<RenderedLabel> { let environment = latex::Environment::cast(parent.clone())?; let environment_name = environment.begin()?.name()?.key()?.to_string(); - let kind = LabelledFloatKind::from_str(&environment_name).ok()?; + let kind = LabeledFloatKind::from_str(&environment_name).ok()?; let caption = find_caption_by_parent(&parent)?; Some(RenderedLabel { range: latex::small_range(&environment), - number: number.take(), - object: LabelledObject::Float { caption, kind }, + number, + object: LabeledObject::Float { caption, kind }, }) } -fn render_label_section( - parent: latex::SyntaxNode, - number: &mut Option<String>, -) -> Option<RenderedLabel> { +fn render_label_section(parent: latex::SyntaxNode, number: Option<Word>) -> Option<RenderedLabel> { let section = latex::Section::cast(parent)?; let text_group = section.name()?; let text = text_group.content_text()?; Some(RenderedLabel { range: latex::small_range(§ion), - number: number.take(), - object: LabelledObject::Section { + number, + object: LabeledObject::Section { prefix: match section.syntax().kind() { latex::PART => "Part", latex::CHAPTER => "Chapter", @@ -219,24 +198,23 @@ fn render_label_section( } fn render_label_enum_item( + db: &dyn Db, parent: latex::SyntaxNode, - number: &mut Option<String>, + number: Option<Word>, ) -> Option<RenderedLabel> { let enum_item = latex::EnumItem::cast(parent)?; Some(RenderedLabel { range: latex::small_range(&enum_item), number: enum_item .label() - .and_then(|number| number.content_text()) - .or_else(|| number.take()), - object: LabelledObject::EnumItem, + .and_then(|label| label.content_text()) + .map(|text| Word::new(db, text)) + .or_else(|| number), + object: LabeledObject::EnumItem, }) } -fn render_label_equation( - parent: latex::SyntaxNode, - number: &mut Option<String>, -) -> Option<RenderedLabel> { +fn render_label_equation(parent: latex::SyntaxNode, number: Option<Word>) -> Option<RenderedLabel> { let environment = latex::Environment::cast(parent)?; let environment_name = environment.begin()?.name()?.key()?.to_string(); @@ -250,15 +228,16 @@ fn render_label_equation( Some(RenderedLabel { range: latex::small_range(&environment), - number: number.take(), - object: LabelledObject::Equation, + number, + object: LabeledObject::Equation, }) } fn render_label_theorem( - workspace: &Workspace, + db: &dyn Db, + document: Document, parent: latex::SyntaxNode, - number: &mut Option<String>, + number: Option<Word>, ) -> Option<RenderedLabel> { let environment = latex::Environment::cast(parent)?; let begin = environment.begin()?; @@ -266,22 +245,18 @@ fn render_label_theorem( let environment_name = begin.name()?.key()?.to_string(); - let theorem = workspace.documents_by_uri.values().find_map(|document| { - document.data.as_latex().and_then(|data| { - data.extras - .theorem_environments - .iter() - .find(|theorem| theorem.name.as_str() == environment_name) - }) - })?; + let kind = Workspace::get(db) + .related(db, document) + .iter() + .filter_map(|document| document.parse(db).as_tex()) + .flat_map(|data| data.analyze(db).theorem_environments(db)) + .find(|env| env.name(db).text(db) == &environment_name) + .map(|env| env.description(db))?; Some(RenderedLabel { range: latex::small_range(&environment), - number: number.take(), - object: LabelledObject::Theorem { - kind: theorem.description.clone(), - description, - }, + number, + object: LabeledObject::Theorem { kind, description }, }) } diff --git a/support/texlab/src/lang_data.rs b/support/texlab/src/util/lang_data.rs index 28e6a540e0..f270c3f65e 100644 --- a/support/texlab/src/lang_data.rs +++ b/support/texlab/src/util/lang_data.rs @@ -65,6 +65,6 @@ impl LanguageData { } pub static LANGUAGE_DATA: Lazy<LanguageData> = Lazy::new(|| { - const JSON: &str = include_str!("../data/lang_data.json"); + const JSON: &str = include_str!("../../data/lang_data.json"); serde_json::from_str(JSON).expect("Failed to deserialize language.json") }); diff --git a/support/texlab/src/line_index.rs b/support/texlab/src/util/line_index.rs index 70e8f8128b..70e8f8128b 100644 --- a/support/texlab/src/line_index.rs +++ b/support/texlab/src/util/line_index.rs diff --git a/support/texlab/src/line_index_ext.rs b/support/texlab/src/util/line_index_ext.rs index 9faccf1c86..becbb8bde7 100644 --- a/support/texlab/src/line_index_ext.rs +++ b/support/texlab/src/util/line_index_ext.rs @@ -1,7 +1,7 @@ use lsp_types::{Position, Range}; use rowan::{TextRange, TextSize}; -use crate::{LineColUtf16, LineIndex}; +use super::line_index::{LineColUtf16, LineIndex}; pub trait LineIndexExt { fn offset_lsp(&self, line_col: Position) -> TextSize; diff --git a/support/texlab/src/features/lsp_kinds.rs b/support/texlab/src/util/lsp_enums.rs index 82706b5aee..75b97097c5 100644 --- a/support/texlab/src/features/lsp_kinds.rs +++ b/support/texlab/src/util/lsp_enums.rs @@ -1,6 +1,6 @@ use lsp_types::{CompletionItemKind, SymbolKind}; -use crate::BibtexEntryTypeCategory; +use super::lang_data::BibtexEntryTypeCategory; #[derive(Debug, PartialEq, Eq, Clone, Copy)] pub enum Structure { diff --git a/support/texlab/src/workspace.rs b/support/texlab/src/workspace.rs deleted file mode 100644 index e01a2fede4..0000000000 --- a/support/texlab/src/workspace.rs +++ /dev/null @@ -1,225 +0,0 @@ -use std::{ - fs::{self, FileType}, - path::PathBuf, - sync::Arc, -}; - -use anyhow::Result; -use crossbeam_channel::Sender; -use lsp_types::Url; -use petgraph::{graphmap::UnGraphMap, visit::Dfs}; -use rustc_hash::{FxHashMap, FxHashSet}; - -use crate::{ - component_db::COMPONENT_DATABASE, syntax::latex::ExplicitLink, Document, DocumentLanguage, - Environment, -}; - -#[derive(Debug, Clone)] -pub enum WorkspaceEvent { - Changed(Workspace, Document), -} - -#[derive(Debug, Clone, Default)] -pub struct Workspace { - pub documents_by_uri: FxHashMap<Arc<Url>, Document>, - pub viewport: FxHashSet<Arc<Url>>, - pub listeners: Vec<Sender<WorkspaceEvent>>, - pub environment: Environment, -} - -impl Workspace { - #[must_use] - pub fn new(environment: Environment) -> Self { - Self { - environment, - ..Self::default() - } - } - - pub fn open( - &mut self, - uri: Arc<Url>, - text: Arc<String>, - language: DocumentLanguage, - ) -> Result<Document> { - log::debug!("(Re)Loading document: {}", uri); - let document = Document::parse(&self.environment, Arc::clone(&uri), text, language); - - self.documents_by_uri - .insert(Arc::clone(&uri), document.clone()); - - for listener in &self.listeners { - listener.send(WorkspaceEvent::Changed(self.clone(), document.clone()))?; - } - - self.expand_parent(&document); - self.expand_children(&document); - Ok(document) - } - - pub fn reload(&mut self, path: PathBuf) -> Result<Option<Document>> { - let uri = Arc::new(Url::from_file_path(path.clone()).unwrap()); - - if self.is_open(&uri) && !uri.as_str().ends_with(".log") { - return Ok(self.documents_by_uri.get(&uri).cloned()); - } - - if let Some(language) = DocumentLanguage::by_path(&path) { - let data = fs::read(&path)?; - let text = Arc::new(String::from_utf8_lossy(&data).into_owned()); - Ok(Some(self.open(uri, text, language)?)) - } else { - Ok(None) - } - } - - pub fn load(&mut self, path: PathBuf) -> Result<Option<Document>> { - let uri = Arc::new(Url::from_file_path(path.clone()).unwrap()); - - if let Some(document) = self.documents_by_uri.get(&uri).cloned() { - return Ok(Some(document)); - } - - let data = fs::read(&path)?; - let text = Arc::new(String::from_utf8_lossy(&data).into_owned()); - if let Some(language) = DocumentLanguage::by_path(&path) { - Ok(Some(self.open(uri, text, language)?)) - } else { - Ok(None) - } - } - - pub fn close(&mut self, uri: &Url) { - self.viewport.remove(uri); - } - - pub fn is_open(&self, uri: &Url) -> bool { - self.viewport.contains(uri) - } - - pub fn slice(&self, uri: &Url) -> Self { - let all_uris: Vec<_> = self.documents_by_uri.keys().cloned().collect(); - - all_uris - .iter() - .position(|u| u.as_ref() == uri) - .map(|start| { - let mut edges = Vec::new(); - for (i, uri) in all_uris.iter().enumerate() { - let document = self.documents_by_uri.get(uri); - if let Some(data) = document - .as_ref() - .and_then(|document| document.data.as_latex()) - { - let extras = &data.extras; - let mut all_targets = - vec![&extras.implicit_links.aux, &extras.implicit_links.log]; - for link in &extras.explicit_links { - all_targets.push(&link.targets); - } - - for targets in all_targets { - for target in targets { - if let Some(j) = all_uris.iter().position(|uri| uri == target) { - edges.push((i, j, ())); - break; - } - } - } - } - } - - let mut slice = self.clone(); - slice.documents_by_uri = FxHashMap::default(); - let graph = UnGraphMap::from_edges(edges); - let mut dfs = Dfs::new(&graph, start); - while let Some(i) = dfs.next(&graph) { - let uri = &all_uris[i]; - let doc = self.documents_by_uri[uri].clone(); - slice.documents_by_uri.insert(Arc::clone(uri), doc); - } - - slice - }) - .unwrap_or_default() - } - - #[must_use] - pub fn find_parent(&self, uri: &Url) -> Option<Document> { - self.slice(uri) - .documents_by_uri - .values() - .find(|document| { - document.data.as_latex().map_or(false, |data| { - data.extras.has_document_environment - && !data - .extras - .explicit_links - .iter() - .filter_map(ExplicitLink::as_component_name) - .any(|name| name == "subfiles.cls") - }) - }) - .cloned() - } - - fn expand_parent(&mut self, document: &Document) { - let all_current_paths = self - .documents_by_uri - .values() - .filter_map(|doc| doc.uri.to_file_path().ok()) - .collect::<FxHashSet<_>>(); - - if document.uri.scheme() == "file" { - if let Ok(mut path) = document.uri.to_file_path() { - while path.pop() && self.find_parent(&document.uri).is_none() { - std::fs::read_dir(&path) - .into_iter() - .flatten() - .filter_map(Result::ok) - .filter(|entry| entry.file_type().ok().filter(FileType::is_file).is_some()) - .map(|entry| entry.path()) - .filter(|path| { - matches!( - DocumentLanguage::by_path(path), - Some(DocumentLanguage::Latex) - ) - }) - .filter(|path| !all_current_paths.contains(path)) - .for_each(|path| { - let _ = self.load(path); - }); - } - } - } - } - - fn expand_children(&mut self, document: &Document) { - if let Some(data) = document.data.as_latex() { - let extras = &data.extras; - let mut all_targets = vec![&extras.implicit_links.aux, &extras.implicit_links.log]; - for link in &extras.explicit_links { - if link - .as_component_name() - .and_then(|name| COMPONENT_DATABASE.find(&name)) - .is_none() - { - all_targets.push(&link.targets); - } - } - - for targets in all_targets { - for path in targets - .iter() - .filter(|uri| uri.scheme() == "file" && uri.fragment().is_none()) - .filter_map(|uri| uri.to_file_path().ok()) - { - if self.load(path).is_ok() { - break; - } - } - } - } - } -} diff --git a/support/texlab/tests/integration/lsp/text_document/publish_diagnostics.rs b/support/texlab/tests/integration/lsp/text_document/publish_diagnostics.rs deleted file mode 100644 index 7e406b5319..0000000000 --- a/support/texlab/tests/integration/lsp/text_document/publish_diagnostics.rs +++ /dev/null @@ -1,264 +0,0 @@ -use anyhow::Result; -use insta::{assert_json_snapshot, internals::Redaction}; -use lsp_types::{ - notification::{ - DidChangeConfiguration, DidChangeWatchedFiles, Notification, PublishDiagnostics, - }, - ClientCapabilities, Diagnostic, DidChangeConfigurationParams, DidChangeWatchedFilesParams, - FileChangeType, FileEvent, PublishDiagnosticsParams, Url, -}; -use rustc_hash::FxHashMap; - -use crate::lsp::{client::Client, fixture}; - -struct DiagnosticResult { - all_diagnostics: FxHashMap<Url, Vec<Diagnostic>>, - uri_redaction: Redaction, -} - -fn find_diagnostics(fixture: &str, settings: serde_json::Value) -> Result<DiagnosticResult> { - let mut client = Client::spawn()?; - client.initialize(ClientCapabilities::default(), None)?; - - let mut disk_files = Vec::new(); - let fixture = fixture::parse(fixture); - for file in fixture.files { - if file.lang == "log" { - client.store_on_disk(file.name, &file.text)?; - disk_files.push(client.uri(file.name)?); - } else { - client.open(file.name, file.lang, file.text)?; - } - } - - client.notify::<DidChangeWatchedFiles>(DidChangeWatchedFilesParams { - changes: disk_files - .into_iter() - .map(|uri| FileEvent::new(uri, FileChangeType::CHANGED)) - .collect(), - })?; - - client.notify::<DidChangeConfiguration>(DidChangeConfigurationParams { settings })?; - - let result = client.shutdown()?; - - let uri = Url::from_directory_path(result.directory.path()).unwrap(); - let uri_redaction = insta::dynamic_redaction(move |content, _path| { - content.as_str().unwrap().replace(uri.as_str(), "[tmp]/") - }); - - let all_diagnostics = result - .incoming - .notifications - .into_iter() - .filter_map(|notification| { - notification - .extract::<PublishDiagnosticsParams>(PublishDiagnostics::METHOD) - .ok() - }) - .map(|params| (params.uri, params.diagnostics)) - .collect(); - - Ok(DiagnosticResult { - all_diagnostics, - uri_redaction, - }) -} - -macro_rules! assert_symbols { - ($result:expr) => { - let result = $result; - assert_json_snapshot!(result.all_diagnostics, { - ".$key" => result.uri_redaction - }); - }; -} - -static BUILD_LOG_FIXTURE: &str = r#" -%TEX main.tex -%SRC \documentclass{article} -%SRC -%SRC \usepackage{amsmath} -%SRC -%SRC \begin{document} -%SRC -%SRC \foo{} -%SRC aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -%SRC -%SRC \end{document} - -%LOG main.log -%SRC This is pdfTeX, Version 3.141592653-2.6-1.40.22 (TeX Live 2021/W32TeX) (preloaded format=pdflatex 2022.1.23) 16 JUN 2022 11:04 -%SRC entering extended mode -%SRC restricted \write18 enabled. -%SRC %&-line parsing enabled. -%SRC **main.tex -%SRC (./main.tex -%SRC LaTeX2e <2020-10-01> patch level 4 -%SRC L3 programming layer <2021-02-18> -%SRC (c:/texlive/2021/texmf-dist/tex/latex/base/article.cls -%SRC Document Class: article 2020/04/10 v1.4m Standard LaTeX document class -%SRC (c:/texlive/2021/texmf-dist/tex/latex/base/size10.clo -%SRC File: size10.clo 2020/04/10 v1.4m Standard LaTeX file (size option) -%SRC ) -%SRC \c@part=\count179 -%SRC \c@section=\count180 -%SRC \c@subsection=\count181 -%SRC \c@subsubsection=\count182 -%SRC \c@paragraph=\count183 -%SRC \c@subparagraph=\count184 -%SRC \c@figure=\count185 -%SRC \c@table=\count186 -%SRC \abovecaptionskip=\skip47 -%SRC \belowcaptionskip=\skip48 -%SRC \bibindent=\dimen138 -%SRC ) -%SRC (c:/texlive/2021/texmf-dist/tex/latex/amsmath/amsmath.sty -%SRC Package: amsmath 2020/09/23 v2.17i AMS math features -%SRC \@mathmargin=\skip49 -%SRC -%SRC For additional information on amsmath, use the `?' option. -%SRC (c:/texlive/2021/texmf-dist/tex/latex/amsmath/amstext.sty -%SRC Package: amstext 2000/06/29 v2.01 AMS text -%SRC -%SRC (c:/texlive/2021/texmf-dist/tex/latex/amsmath/amsgen.sty -%SRC File: amsgen.sty 1999/11/30 v2.0 generic functions -%SRC \@emptytoks=\toks15 -%SRC \ex@=\dimen139 -%SRC )) -%SRC (c:/texlive/2021/texmf-dist/tex/latex/amsmath/amsbsy.sty -%SRC Package: amsbsy 1999/11/29 v1.2d Bold Symbols -%SRC \pmbraise@=\dimen140 -%SRC ) -%SRC (c:/texlive/2021/texmf-dist/tex/latex/amsmath/amsopn.sty -%SRC Package: amsopn 2016/03/08 v2.02 operator names -%SRC ) -%SRC \inf@bad=\count187 -%SRC LaTeX Info: Redefining \frac on input line 234. -%SRC \uproot@=\count188 -%SRC \leftroot@=\count189 -%SRC LaTeX Info: Redefining \overline on input line 399. -%SRC \classnum@=\count190 -%SRC \DOTSCASE@=\count191 -%SRC LaTeX Info: Redefining \ldots on input line 496. -%SRC LaTeX Info: Redefining \dots on input line 499. -%SRC LaTeX Info: Redefining \cdots on input line 620. -%SRC \Mathstrutbox@=\box47 -%SRC \strutbox@=\box48 -%SRC \big@size=\dimen141 -%SRC LaTeX Font Info: Redeclaring font encoding OML on input line 743. -%SRC LaTeX Font Info: Redeclaring font encoding OMS on input line 744. -%SRC \macc@depth=\count192 -%SRC \c@MaxMatrixCols=\count193 -%SRC \dotsspace@=\muskip16 -%SRC \c@parentequation=\count194 -%SRC \dspbrk@lvl=\count195 -%SRC \tag@help=\toks16 -%SRC \row@=\count196 -%SRC \column@=\count197 -%SRC \maxfields@=\count198 -%SRC \andhelp@=\toks17 -%SRC \eqnshift@=\dimen142 -%SRC \alignsep@=\dimen143 -%SRC \tagshift@=\dimen144 -%SRC \tagwidth@=\dimen145 -%SRC \totwidth@=\dimen146 -%SRC \lineht@=\dimen147 -%SRC \@envbody=\toks18 -%SRC \multlinegap=\skip50 -%SRC \multlinetaggap=\skip51 -%SRC \mathdisplay@stack=\toks19 -%SRC LaTeX Info: Redefining \[ on input line 2923. -%SRC LaTeX Info: Redefining \] on input line 2924. -%SRC ) -%SRC (c:/texlive/2021/texmf-dist/tex/latex/l3backend/l3backend-pdftex.def -%SRC File: l3backend-pdftex.def 2021-03-18 L3 backend support: PDF output (pdfTeX) -%SRC \l__color_backend_stack_int=\count199 -%SRC \l__pdf_internal_box=\box49 -%SRC ) -%SRC (./main.aux) -%SRC \openout1 = `main.aux'. -%SRC -%SRC LaTeX Font Info: Checking defaults for OML/cmm/m/it on input line 5. -%SRC LaTeX Font Info: ... okay on input line 5. -%SRC LaTeX Font Info: Checking defaults for OMS/cmsy/m/n on input line 5. -%SRC LaTeX Font Info: ... okay on input line 5. -%SRC LaTeX Font Info: Checking defaults for OT1/cmr/m/n on input line 5. -%SRC LaTeX Font Info: ... okay on input line 5. -%SRC LaTeX Font Info: Checking defaults for T1/cmr/m/n on input line 5. -%SRC LaTeX Font Info: ... okay on input line 5. -%SRC LaTeX Font Info: Checking defaults for TS1/cmr/m/n on input line 5. -%SRC LaTeX Font Info: ... okay on input line 5. -%SRC LaTeX Font Info: Checking defaults for OMX/cmex/m/n on input line 5. -%SRC LaTeX Font Info: ... okay on input line 5. -%SRC LaTeX Font Info: Checking defaults for U/cmr/m/n on input line 5. -%SRC LaTeX Font Info: ... okay on input line 5. -%SRC -%SRC ! Undefined control sequence. -%SRC l.7 \foo -%SRC {} -%SRC The control sequence at the end of the top line -%SRC of your error message was never \def'ed. If you have -%SRC misspelled it (e.g., `\hobx'), type `I' and the correct -%SRC spelling (e.g., `I\hbox'). Otherwise just continue, -%SRC and I'll forget about whatever was undefined. -%SRC -%SRC -%SRC Overfull \hbox (80.00125pt too wide) in paragraph at lines 8--9 -%SRC []\OT1/cmr/m/n/10 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -%SRC aaaaaaaaaaaaaaaaaaaaa -%SRC [] -%SRC -%SRC [1 -%SRC -%SRC {c:/texlive/2021/texmf-var/fonts/map/pdftex/updmap/pdftex.map}] (./main.aux) ) -%SRC Here is how much of TeX's memory you used: -%SRC 1014 strings out of 478994 -%SRC 13996 string characters out of 5862207 -%SRC 300924 words of memory out of 5000000 -%SRC 18565 multiletter control sequences out of 15000+600000 -%SRC 403430 words of font info for 27 fonts, out of 8000000 for 9000 -%SRC 1141 hyphenation exceptions out of 8191 -%SRC 67i,4n,74p,200b,104s stack positions out of 5000i,500n,10000p,200000b,80000s -%SRC < -%SRC c:/texlive/2021/texmf-dist/fonts/type1/public/amsfonts/cm/cmr10.pfb> -%SRC Output written on main.pdf (1 page, 9741 bytes). -%SRC PDF statistics: -%SRC 12 PDF objects out of 1000 (max. 8388607) -%SRC 7 compressed objects within 1 object stream -%SRC 0 named destinations out of 1000 (max. 500000) -%SRC 1 words of extra memory for PDF output out of 10000 (max. 10000000)"#; - -#[test] -fn build_log_filter_none() -> Result<()> { - assert_symbols!(find_diagnostics(BUILD_LOG_FIXTURE, serde_json::json!({}))?); - Ok(()) -} - -#[test] -fn build_log_filter_allowed() -> Result<()> { - assert_symbols!(find_diagnostics( - BUILD_LOG_FIXTURE, - serde_json::json!({ - "diagnostics": { - "allowedPatterns": ["Overfull \\\\[hv]box"] - } - }) - )?); - - Ok(()) -} - -#[test] -fn build_log_filter_ignored() -> Result<()> { - assert_symbols!(find_diagnostics( - BUILD_LOG_FIXTURE, - serde_json::json!({ - "diagnostics": { - "ignoredPatterns": ["Overfull \\\\[hv]box"] - } - }) - )?); - - Ok(()) -} diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__publish_diagnostics__build_log_filter_allowed.snap b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__publish_diagnostics__build_log_filter_allowed.snap deleted file mode 100644 index 9fc11d295b..0000000000 --- a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__publish_diagnostics__build_log_filter_allowed.snap +++ /dev/null @@ -1,24 +0,0 @@ ---- -source: tests/integration/lsp/text_document/publish_diagnostics.rs -assertion_line: 240 -expression: result.all_diagnostics ---- -{ - "[tmp]/main.tex": [ - { - "range": { - "start": { - "line": 7, - "character": 0 - }, - "end": { - "line": 7, - "character": 0 - } - }, - "severity": 2, - "source": "latex-build", - "message": "Overfull \\hbox (80.00125pt too wide) in paragraph at lines 8--9" - } - ] -} diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__publish_diagnostics__build_log_filter_ignored.snap b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__publish_diagnostics__build_log_filter_ignored.snap deleted file mode 100644 index 28e0308a72..0000000000 --- a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__publish_diagnostics__build_log_filter_ignored.snap +++ /dev/null @@ -1,24 +0,0 @@ ---- -source: tests/integration/lsp/text_document/publish_diagnostics.rs -assertion_line: 254 -expression: result.all_diagnostics ---- -{ - "[tmp]/main.tex": [ - { - "range": { - "start": { - "line": 6, - "character": 0 - }, - "end": { - "line": 6, - "character": 0 - } - }, - "severity": 1, - "source": "latex-build", - "message": "Undefined control sequence." - } - ] -} diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__publish_diagnostics__build_log_filter_none.snap b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__publish_diagnostics__build_log_filter_none.snap deleted file mode 100644 index b16238381b..0000000000 --- a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__publish_diagnostics__build_log_filter_none.snap +++ /dev/null @@ -1,39 +0,0 @@ ---- -source: tests/integration/lsp/text_document/publish_diagnostics.rs -assertion_line: 234 -expression: result.all_diagnostics ---- -{ - "[tmp]/main.tex": [ - { - "range": { - "start": { - "line": 6, - "character": 0 - }, - "end": { - "line": 6, - "character": 0 - } - }, - "severity": 1, - "source": "latex-build", - "message": "Undefined control sequence." - }, - { - "range": { - "start": { - "line": 7, - "character": 0 - }, - "end": { - "line": 7, - "character": 0 - } - }, - "severity": 2, - "source": "latex-build", - "message": "Overfull \\hbox (80.00125pt too wide) in paragraph at lines 8--9" - } - ] -} diff --git a/support/texlab/tests/integration/main.rs b/support/texlab/tests/integration/main.rs deleted file mode 100644 index 44e0d3635a..0000000000 --- a/support/texlab/tests/integration/main.rs +++ /dev/null @@ -1 +0,0 @@ -mod lsp; diff --git a/support/texlab/texlab.1 b/support/texlab/texlab.1 index 8dd6b664a4..25dd817248 100644 --- a/support/texlab/texlab.1 +++ b/support/texlab/texlab.1 @@ -1,26 +1,25 @@ -.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.15. -.TH TEXLAB "1" "May 2020" "texlab " "User Commands" +.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.13. +.TH TEXLAB "1" "December 2022" "texlab 5.0.0" "User Commands" .SH NAME -texlab \- manual page for texlab +texlab \- manual page for texlab 5.0.0 +.SH SYNOPSIS +.B texlab +[\fI\,OPTIONS\/\fR] .SH DESCRIPTION An implementation of the Language Server Protocol for LaTeX -.SS "USAGE:" -.IP -texlab [FLAGS] [OPTIONS] -.SS "FLAGS:" +.SH OPTIONS .TP -\fB\-h\fR, \fB\-\-help\fR -Prints help information +\fB\-v\fR, \fB\-\-verbosity\fR... +Increase message verbosity (\fB\-vvvv\fR for max verbosity) .TP \fB\-q\fR, \fB\-\-quiet\fR No output printed to stderr .TP -\fB\-V\fR, \fB\-\-version\fR -Prints version information -.TP -\fB\-v\fR, \fB\-\-verbosity\fR -Increase message verbosity (\fB\-vvvv\fR for max verbosity) -.SS "OPTIONS:" -.TP \fB\-\-log\-file\fR <FILE> Write the logging output to FILE +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help information +.TP +\fB\-V\fR, \fB\-\-version\fR +Print version information diff --git a/support/texlab/texlab.pdf b/support/texlab/texlab.pdf Binary files differindex 68e68c312d..b4749920ec 100644 --- a/support/texlab/texlab.pdf +++ b/support/texlab/texlab.pdf |