summaryrefslogtreecommitdiff
path: root/support
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2022-06-13 03:03:42 +0000
committerNorbert Preining <norbert@preining.info>2022-06-13 03:03:42 +0000
commitef6d63ded56fb892decaa8ab41d7deebbe670473 (patch)
tree9c8eccf2e633fcfe0ad512e5428222ce0707971e /support
parent86d0c4c6729cfb43e13fb29790810c3cc2521806 (diff)
CTAN sync 202206130303
Diffstat (limited to 'support')
-rw-r--r--support/texlab/CHANGELOG.md16
-rw-r--r--support/texlab/Cargo.lock217
-rw-r--r--support/texlab/Cargo.toml26
-rw-r--r--support/texlab/README.md17
-rw-r--r--support/texlab/docs/custom_commands.md21
-rw-r--r--support/texlab/src/citation.rs3
-rw-r--r--support/texlab/src/citation/driver.rs18
-rw-r--r--support/texlab/src/citation/entry.rs35
-rw-r--r--support/texlab/src/citation/field/author.rs11
-rw-r--r--support/texlab/src/citation/field/date.rs6
-rw-r--r--support/texlab/src/citation/field/number.rs6
-rw-r--r--support/texlab/src/citation/field/text.rs16
-rw-r--r--support/texlab/src/citation/output.rs31
-rw-r--r--support/texlab/src/component_db.rs15
-rw-r--r--support/texlab/src/diagnostics.rs11
-rw-r--r--support/texlab/src/diagnostics/build_log.rs3
-rw-r--r--support/texlab/src/diagnostics/chktex.rs4
-rw-r--r--support/texlab/src/diagnostics/debouncer.rs2
-rw-r--r--support/texlab/src/diagnostics/latex.rs8
-rw-r--r--support/texlab/src/distro.rs1
-rw-r--r--support/texlab/src/distro/kpsewhich.rs1
-rw-r--r--support/texlab/src/distro/miktex.rs14
-rw-r--r--support/texlab/src/distro/texlive.rs9
-rw-r--r--support/texlab/src/document.rs8
-rw-r--r--support/texlab/src/environment.rs1
-rw-r--r--support/texlab/src/features.rs213
-rw-r--r--support/texlab/src/features/build.rs4
-rw-r--r--support/texlab/src/features/completion.rs5
-rw-r--r--support/texlab/src/features/completion/acronym_ref.rs120
-rw-r--r--support/texlab/src/features/completion/argument.rs120
-rw-r--r--support/texlab/src/features/completion/begin_command.rs63
-rw-r--r--support/texlab/src/features/completion/citation.rs209
-rw-r--r--support/texlab/src/features/completion/color.rs83
-rw-r--r--support/texlab/src/features/completion/color_model.rs123
-rw-r--r--support/texlab/src/features/completion/component_command.rs144
-rw-r--r--support/texlab/src/features/completion/component_environment.rs147
-rw-r--r--support/texlab/src/features/completion/entry_type.rs200
-rw-r--r--support/texlab/src/features/completion/field.rs158
-rw-r--r--support/texlab/src/features/completion/glossary_ref.rs83
-rw-r--r--support/texlab/src/features/completion/import.rs129
-rw-r--r--support/texlab/src/features/completion/include.rs75
-rw-r--r--support/texlab/src/features/completion/label.rs103
-rw-r--r--support/texlab/src/features/completion/theorem.rs106
-rw-r--r--support/texlab/src/features/completion/tikz_library.rs123
-rw-r--r--support/texlab/src/features/completion/user_command.rs63
-rw-r--r--support/texlab/src/features/completion/user_environment.rs66
-rw-r--r--support/texlab/src/features/definition.rs47
-rw-r--r--support/texlab/src/features/definition/command.rs128
-rw-r--r--support/texlab/src/features/definition/document.rs132
-rw-r--r--support/texlab/src/features/definition/entry.rs109
-rw-r--r--support/texlab/src/features/definition/label.rs77
-rw-r--r--support/texlab/src/features/definition/string.rs159
-rw-r--r--support/texlab/src/features/execute_command.rs103
-rw-r--r--support/texlab/src/features/folding.rs172
-rw-r--r--support/texlab/src/features/formatting/bibtex_internal.rs134
-rw-r--r--support/texlab/src/features/formatting/snapshots/texlab__features__formatting__bibtex_internal__tests__command.snap8
-rw-r--r--support/texlab/src/features/formatting/snapshots/texlab__features__formatting__bibtex_internal__tests__concatenation.snap8
-rw-r--r--support/texlab/src/features/formatting/snapshots/texlab__features__formatting__bibtex_internal__tests__insert_braces.snap8
-rw-r--r--support/texlab/src/features/formatting/snapshots/texlab__features__formatting__bibtex_internal__tests__multiple_entries.snap9
-rw-r--r--support/texlab/src/features/formatting/snapshots/texlab__features__formatting__bibtex_internal__tests__parens.snap7
-rw-r--r--support/texlab/src/features/formatting/snapshots/texlab__features__formatting__bibtex_internal__tests__preamble.snap6
-rw-r--r--support/texlab/src/features/formatting/snapshots/texlab__features__formatting__bibtex_internal__tests__string.snap6
-rw-r--r--support/texlab/src/features/formatting/snapshots/texlab__features__formatting__bibtex_internal__tests__trailing_comma.snap8
-rw-r--r--support/texlab/src/features/formatting/snapshots/texlab__features__formatting__bibtex_internal__tests__wrap_long_lines.snap10
-rw-r--r--support/texlab/src/features/highlight/label.rs68
-rw-r--r--support/texlab/src/features/hover.rs33
-rw-r--r--support/texlab/src/features/hover/citation.rs119
-rw-r--r--support/texlab/src/features/hover/component.rs96
-rw-r--r--support/texlab/src/features/hover/entry_type.rs123
-rw-r--r--support/texlab/src/features/hover/field.rs115
-rw-r--r--support/texlab/src/features/hover/label.rs74
-rw-r--r--support/texlab/src/features/hover/snapshots/texlab__features__hover__citation__tests__inside_cite.snap25
-rw-r--r--support/texlab/src/features/hover/snapshots/texlab__features__hover__citation__tests__inside_entry.snap25
-rw-r--r--support/texlab/src/features/hover/string_ref.rs140
-rw-r--r--support/texlab/src/features/link.rs120
-rw-r--r--support/texlab/src/features/link/include.rs33
-rw-r--r--support/texlab/src/features/reference.rs34
-rw-r--r--support/texlab/src/features/reference/entry.rs186
-rw-r--r--support/texlab/src/features/reference/label.rs181
-rw-r--r--support/texlab/src/features/reference/string.rs186
-rw-r--r--support/texlab/src/features/rename.rs48
-rw-r--r--support/texlab/src/features/rename/command.rs81
-rw-r--r--support/texlab/src/features/rename/entry.rs131
-rw-r--r--support/texlab/src/features/rename/label.rs122
-rw-r--r--support/texlab/src/features/symbol.rs5
-rw-r--r--support/texlab/src/label.rs3
-rw-r--r--support/texlab/src/lang_data.rs3
-rw-r--r--support/texlab/src/main.rs2
-rw-r--r--support/texlab/src/options.rs24
-rw-r--r--support/texlab/src/server.rs68
-rw-r--r--support/texlab/src/snapshots/texlab__citation__tests__biblatex_examples_001.snap6
-rw-r--r--support/texlab/src/snapshots/texlab__citation__tests__biblatex_examples_002.snap6
-rw-r--r--support/texlab/src/snapshots/texlab__citation__tests__biblatex_examples_003.snap6
-rw-r--r--support/texlab/src/snapshots/texlab__citation__tests__biblatex_examples_004.snap6
-rw-r--r--support/texlab/src/snapshots/texlab__citation__tests__biblatex_examples_005.snap6
-rw-r--r--support/texlab/src/snapshots/texlab__citation__tests__biblatex_examples_006.snap6
-rw-r--r--support/texlab/src/snapshots/texlab__citation__tests__biblatex_examples_007.snap6
-rw-r--r--support/texlab/src/snapshots/texlab__citation__tests__biblatex_examples_008.snap6
-rw-r--r--support/texlab/src/snapshots/texlab__citation__tests__biblatex_examples_009.snap6
-rw-r--r--support/texlab/src/snapshots/texlab__citation__tests__biblatex_examples_010.snap6
-rw-r--r--support/texlab/src/snapshots/texlab__citation__tests__biblatex_examples_011.snap6
-rw-r--r--support/texlab/src/snapshots/texlab__citation__tests__biblatex_examples_012.snap6
-rw-r--r--support/texlab/src/snapshots/texlab__citation__tests__biblatex_examples_013.snap6
-rw-r--r--support/texlab/src/snapshots/texlab__citation__tests__biblatex_examples_014.snap6
-rw-r--r--support/texlab/src/snapshots/texlab__citation__tests__biblatex_examples_015.snap6
-rw-r--r--support/texlab/src/snapshots/texlab__citation__tests__biblatex_examples_016.snap6
-rw-r--r--support/texlab/src/syntax/build_log.rs1999
-rw-r--r--support/texlab/src/syntax/latex/analysis/implicit_link.rs40
-rw-r--r--support/texlab/src/syntax/latex/cst.rs2
-rw-r--r--support/texlab/src/syntax/latex/parser.rs63
-rw-r--r--support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__graphics_include_command.snap31
-rw-r--r--support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__latex_input_path_with_brackets.snap19
-rw-r--r--support/texlab/src/workspace.rs25
-rw-r--r--support/texlab/tests/integration/dev.rs17
-rw-r--r--support/texlab/tests/integration/lsp.rs4
-rw-r--r--support/texlab/tests/integration/lsp/client.rs158
-rw-r--r--support/texlab/tests/integration/lsp/fixture.rs123
-rw-r--r--support/texlab/tests/integration/lsp/text_document.rs11
-rw-r--r--support/texlab/tests/integration/lsp/text_document/completion.rs870
-rw-r--r--support/texlab/tests/integration/lsp/text_document/definition.rs142
-rw-r--r--support/texlab/tests/integration/lsp/text_document/document_highlight.rs62
-rw-r--r--support/texlab/tests/integration/lsp/text_document/document_link.rs73
-rw-r--r--support/texlab/tests/integration/lsp/text_document/document_symbol.rs427
-rw-r--r--support/texlab/tests/integration/lsp/text_document/folding_range.rs97
-rw-r--r--support/texlab/tests/integration/lsp/text_document/formatting.rs148
-rw-r--r--support/texlab/tests/integration/lsp/text_document/hover.rs302
-rw-r--r--support/texlab/tests/integration/lsp/text_document/references.rs275
-rw-r--r--support/texlab/tests/integration/lsp/text_document/rename.rs111
-rw-r--r--support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__acronym_ref_empty.snap18
-rw-r--r--support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__acronym_ref_open_brace.snap18
-rw-r--r--support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__acronym_ref_simple.snap18
-rw-r--r--support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__argument_empty.snap67
-rw-r--r--support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__argument_open_brace.snap67
-rw-r--r--support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__argument_word.snap19
-rw-r--r--support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__begin_environment_without_snippet_support.snap68
-rw-r--r--support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__citation.snap32
-rw-r--r--support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__citation_acronym.snap19
-rw-r--r--support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__citation_open_brace.snap19
-rw-r--r--support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__citation_open_brace_multiple.snap19
-rw-r--r--support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__color_model_definition_open_brace.snap62
-rw-r--r--support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__color_model_definition_set_open_brace.snap62
-rw-r--r--support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__color_model_definition_set_simple.snap62
-rw-r--r--support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__color_model_definition_simple.snap62
-rw-r--r--support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__color_open_brace.snap62
-rw-r--r--support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__color_simple.snap62
-rw-r--r--support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__color_word.snap62
-rw-r--r--support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__component_command_bibtex.snap67
-rw-r--r--support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__component_command_simple.snap69
-rw-r--r--support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__component_command_simple_package.snap67
-rw-r--r--support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__component_environment_class.snap19
-rw-r--r--support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__component_environment_command_definition.snap19
-rw-r--r--support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__component_environment_simple.snap19
-rw-r--r--support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__component_environment_simple_end.snap67
-rw-r--r--support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__entry_type_after_preamble.snap18
-rw-r--r--support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__entry_type_after_string.snap18
-rw-r--r--support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__entry_type_at_empty.snap67
-rw-r--r--support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__entry_type_before_article.snap19
-rw-r--r--support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__entry_type_before_preamble.snap18
-rw-r--r--support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__entry_type_before_string.snap18
-rw-r--r--support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__entry_type_complete_entry.snap19
-rw-r--r--support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__field_empty_entry_closed.snap67
-rw-r--r--support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__field_empty_entry_open.snap67
-rw-r--r--support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__field_entry_field_name.snap67
-rw-r--r--support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__field_entry_two_fields_name_closed.snap67
-rw-r--r--support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__field_entry_two_fields_name_open.snap67
-rw-r--r--support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__glossary_ref_open_brace.snap18
-rw-r--r--support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__glossary_ref_simple.snap18
-rw-r--r--support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__import_class_closed_brace.snap67
-rw-r--r--support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__import_class_open_brace.snap67
-rw-r--r--support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__import_package_closed_brace.snap67
-rw-r--r--support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__import_package_open_brace.snap67
-rw-r--r--support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__label.snap73
-rw-r--r--support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__theorem_begin.snap19
-rw-r--r--support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__theorem_end.snap19
-rw-r--r--support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__tikz_library_closed_brace.snap62
-rw-r--r--support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__tikz_library_open_brace.snap62
-rw-r--r--support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__user_command.snap19
-rw-r--r--support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__user_environment.snap31
-rw-r--r--support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__document_symbol__enumerate_flat.snap (renamed from support/texlab/tests/it/snapshots/it__document_symbol__enumerate_flat.snap)20
-rw-r--r--support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__document_symbol__enumerate_nested.snap (renamed from support/texlab/tests/it/snapshots/it__document_symbol__enumerate_nested.snap)10
-rw-r--r--support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__document_symbol__equation_flat.snap (renamed from support/texlab/tests/it/snapshots/it__document_symbol__equation_flat.snap)14
-rw-r--r--support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__document_symbol__equation_nested.snap (renamed from support/texlab/tests/it/snapshots/it__document_symbol__equation_nested.snap)8
-rw-r--r--support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__document_symbol__float_flat.snap (renamed from support/texlab/tests/it/snapshots/it__document_symbol__float_flat.snap)14
-rw-r--r--support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__document_symbol__float_nested.snap (renamed from support/texlab/tests/it/snapshots/it__document_symbol__float_nested.snap)8
-rw-r--r--support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__document_symbol__section_flat.snap (renamed from support/texlab/tests/it/snapshots/it__document_symbol__section_flat.snap)14
-rw-r--r--support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__document_symbol__section_nested.snap (renamed from support/texlab/tests/it/snapshots/it__document_symbol__section_nested.snap)8
-rw-r--r--support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__document_symbol__theorem_flat.snap (renamed from support/texlab/tests/it/snapshots/it__document_symbol__theorem_flat.snap)18
-rw-r--r--support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__document_symbol__theorem_nested.snap (renamed from support/texlab/tests/it/snapshots/it__document_symbol__theorem_nested.snap)10
-rw-r--r--support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__formatting__bibtex_internal_command.snap9
-rw-r--r--support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__formatting__bibtex_internal_insert_braces.snap8
-rw-r--r--support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__formatting__bibtex_internal_join_strings.snap9
-rw-r--r--support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__formatting__bibtex_internal_multiple_entries.snap17
-rw-r--r--support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__formatting__bibtex_internal_parens.snap8
-rw-r--r--support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__formatting__bibtex_internal_preamble.snap7
-rw-r--r--support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__formatting__bibtex_internal_string.snap7
-rw-r--r--support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__formatting__bibtex_internal_trailing_comma.snap9
-rw-r--r--support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__formatting__bibtex_internal_wrap_long_lines.snap11
-rw-r--r--support/texlab/tests/integration/lsp/workspace.rs1
-rw-r--r--support/texlab/tests/integration/lsp/workspace/snapshots/integration__lsp__workspace__symbol__filter_bibtex.snap (renamed from support/texlab/tests/it/snapshots/it__workspace_symbol__filter_bibtex.snap)22
-rw-r--r--support/texlab/tests/integration/lsp/workspace/snapshots/integration__lsp__workspace__symbol__filter_type_figure.snap (renamed from support/texlab/tests/it/snapshots/it__workspace_symbol__filter_type_figure.snap)14
-rw-r--r--support/texlab/tests/integration/lsp/workspace/snapshots/integration__lsp__workspace__symbol__filter_type_item.snap (renamed from support/texlab/tests/it/snapshots/it__workspace_symbol__filter_type_item.snap)30
-rw-r--r--support/texlab/tests/integration/lsp/workspace/snapshots/integration__lsp__workspace__symbol__filter_type_math.snap (renamed from support/texlab/tests/it/snapshots/it__workspace_symbol__filter_type_math.snap)22
-rw-r--r--support/texlab/tests/integration/lsp/workspace/snapshots/integration__lsp__workspace__symbol__filter_type_section.snap (renamed from support/texlab/tests/it/snapshots/it__workspace_symbol__filter_type_section.snap)38
-rw-r--r--support/texlab/tests/integration/lsp/workspace/symbol.rs147
-rw-r--r--support/texlab/tests/integration/main.rs2
-rw-r--r--support/texlab/tests/it/common.rs318
-rw-r--r--support/texlab/tests/it/completion.rs817
-rw-r--r--support/texlab/tests/it/document_symbol.rs438
-rw-r--r--support/texlab/tests/it/hover.rs89
-rw-r--r--support/texlab/tests/it/issues.rs81
-rw-r--r--support/texlab/tests/it/main.rs7
-rw-r--r--support/texlab/tests/it/snapshots/it__completion__bibtex__command_complete_entry.snap150
-rw-r--r--support/texlab/tests/it/snapshots/it__completion__bibtex__command_incomplete_entry.snap150
-rw-r--r--support/texlab/tests/it/snapshots/it__completion__bibtex__empty_document.snap9
-rw-r--r--support/texlab/tests/it/snapshots/it__completion__bibtex__entry_type_complete.snap33
-rw-r--r--support/texlab/tests/it/snapshots/it__completion__bibtex__entry_type_empty_name.snap171
-rw-r--r--support/texlab/tests/it/snapshots/it__completion__bibtex__entry_type_empty_name_before.snap9
-rw-r--r--support/texlab/tests/it/snapshots/it__completion__bibtex__entry_type_incomplete.snap79
-rw-r--r--support/texlab/tests/it/snapshots/it__completion__bibtex__field_complete_entry.snap171
-rw-r--r--support/texlab/tests/it/snapshots/it__completion__bibtex__field_incomplete_entry.snap171
-rw-r--r--support/texlab/tests/it/snapshots/it__completion__bibtex__junk.snap9
-rw-r--r--support/texlab/tests/it/snapshots/it__completion__latex__begin_command.snap162
-rw-r--r--support/texlab/tests/it/snapshots/it__completion__latex__citation.snap54
-rw-r--r--support/texlab/tests/it/snapshots/it__completion__latex__citation_after.snap9
-rw-r--r--support/texlab/tests/it/snapshots/it__completion__latex__citation_multi_word.snap34
-rw-r--r--support/texlab/tests/it/snapshots/it__completion__latex__citation_open_brace.snap34
-rw-r--r--support/texlab/tests/it/snapshots/it__completion__latex__class_command.snap150
-rw-r--r--support/texlab/tests/it/snapshots/it__completion__latex__class_environment.snap30
-rw-r--r--support/texlab/tests/it/snapshots/it__completion__latex__class_import.snap171
-rw-r--r--support/texlab/tests/it/snapshots/it__completion__latex__color_model_define_color.snap105
-rw-r--r--support/texlab/tests/it/snapshots/it__completion__latex__color_model_define_color_set.snap67
-rw-r--r--support/texlab/tests/it/snapshots/it__completion__latex__color_name.snap143
-rw-r--r--support/texlab/tests/it/snapshots/it__completion__latex__empty_document.snap9
-rw-r--r--support/texlab/tests/it/snapshots/it__completion__latex__kernel_command.snap30
-rw-r--r--support/texlab/tests/it/snapshots/it__completion__latex__kernel_command_environment.snap30
-rw-r--r--support/texlab/tests/it/snapshots/it__completion__latex__kernel_command_glyph.snap34
-rw-r--r--support/texlab/tests/it/snapshots/it__completion__latex__label.snap137
-rw-r--r--support/texlab/tests/it/snapshots/it__completion__latex__multi_line_key.snap50
-rw-r--r--support/texlab/tests/it/snapshots/it__completion__latex__package_command.snap34
-rw-r--r--support/texlab/tests/it/snapshots/it__completion__latex__package_environment.snap150
-rw-r--r--support/texlab/tests/it/snapshots/it__completion__latex__package_import.snap102
-rw-r--r--support/texlab/tests/it/snapshots/it__completion__latex__pgf_library.snap143
-rw-r--r--support/texlab/tests/it/snapshots/it__completion__latex__preselect_environment.snap150
-rw-r--r--support/texlab/tests/it/snapshots/it__completion__latex__theorem_environment.snap130
-rw-r--r--support/texlab/tests/it/snapshots/it__completion__latex__user_command.snap30
-rw-r--r--support/texlab/tests/it/snapshots/it__completion__latex__user_environment.snap50
-rw-r--r--support/texlab/tests/it/snapshots/it__hover__empty_bibtex_document.snap6
-rw-r--r--support/texlab/tests/it/snapshots/it__hover__empty_labtex_document.snap6
-rw-r--r--support/texlab/tests/it/snapshots/it__hover__label_theorem_child_file.snap21
-rw-r--r--support/texlab/tests/it/snapshots/it__hover__label_theorem_child_file_mumber.snap21
-rw-r--r--support/texlab/tests/it/snapshots/it__issues__510_completion_with_unmatched_braces.snap57
-rw-r--r--support/texlab/tests/it/workspace_symbol.rs119
-rw-r--r--support/texlab/texlab.pdfbin82740 -> 82677 bytes
-rw-r--r--support/texlab/texlab.tex2
254 files changed, 7577 insertions, 11214 deletions
diff --git a/support/texlab/CHANGELOG.md b/support/texlab/CHANGELOG.md
index 7b57cddb4f..5400a1b538 100644
--- a/support/texlab/CHANGELOG.md
+++ b/support/texlab/CHANGELOG.md
@@ -5,6 +5,22 @@ 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.1.0] - 12.06.2022
+
+### Added
+
+- Add server commands to clean build directory ([#607](https://github.com/latex-lsp/texlab/issues/607))
+
+### Changed
+
+- Improve output when hovering over BibTeX strings
+- Improve the heuristic for finding build artifacts ([#635](https://github.com/latex-lsp/texlab/issues/635))
+
+### Fixed
+
+- 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
### Added
diff --git a/support/texlab/Cargo.lock b/support/texlab/Cargo.lock
index 58549a6f3a..8b5e64f3d7 100644
--- a/support/texlab/Cargo.lock
+++ b/support/texlab/Cargo.lock
@@ -18,12 +18,30 @@ dependencies = [
]
[[package]]
+name = "ansi_term"
+version = "0.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
+dependencies = [
+ "winapi",
+]
+
+[[package]]
name = "anyhow"
version = "1.0.57"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08f9b8508dccb7687a1d6c4ce66b2b0ecef467c94667de27d8d7fe1f8d2a9cdc"
[[package]]
+name = "assert_unordered"
+version = "0.3.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1c74323b7881323eb351134e08ee5331594826789557afef8e309baf481b2264"
+dependencies = [
+ "ansi_term",
+]
+
+[[package]]
name = "atty"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -53,6 +71,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
+name = "block-buffer"
+version = "0.7.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b"
+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"
@@ -71,6 +110,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4a45a46ab1f2412e53d3a0ade76ffad2025804294569aae387231a0cd6e0899"
[[package]]
+name = "byte-tools"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7"
+
+[[package]]
name = "byteorder"
version = "1.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -310,6 +355,15 @@ dependencies = [
]
[[package]]
+name = "digest"
+version = "0.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5"
+dependencies = [
+ "generic-array",
+]
+
+[[package]]
name = "either"
version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -340,6 +394,12 @@ dependencies = [
]
[[package]]
+name = "fake-simd"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
+
+[[package]]
name = "fastrand"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -365,13 +425,11 @@ checksum = "279fb028e20b3c4c320317955b77c5e0c9701f05a1d309905d6fc702cdc5053e"
[[package]]
name = "flate2"
-version = "1.0.23"
+version = "1.0.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b39522e96686d38f4bc984b9198e3a0613264abaebaff2c5c918bfa6b6da09af"
+checksum = "f82b0f4c27ad9f8bfd1f3208d882da2b09c301bc1c828fd3a00d0216d2fbbff6"
dependencies = [
- "cfg-if",
"crc32fast",
- "libc",
"miniz_oxide",
]
@@ -401,6 +459,15 @@ dependencies = [
]
[[package]]
+name = "generic-array"
+version = "0.12.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd"
+dependencies = [
+ "typenum",
+]
+
+[[package]]
name = "getrandom"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -484,19 +551,15 @@ dependencies = [
]
[[package]]
-name = "indoc"
-version = "1.0.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "05a0bd019339e5d968b37855180087b7b9d512c5046fbd244cf8c95687927d6e"
-
-[[package]]
name = "insta"
-version = "1.14.0"
+version = "1.14.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "689960f187c43c01650c805fb6bc6f55ab944499d86d4ffe9474ad78991d8e94"
+checksum = "bcc3e639bcba360d9237acabd22014c16f3df772db463b7446cd81b070714767"
dependencies = [
"console",
"once_cell",
+ "pest",
+ "pest_derive",
"serde",
"serde_json",
"serde_yaml",
@@ -544,6 +607,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "112c678d4050afce233f4f2852bb2eb519230b3cf12f33585275537d7e41578d"
[[package]]
+name = "jod-thread"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8b23360e99b8717f20aaa4598f5a6541efbe30630039fbc7706cf954a87947ae"
+
+[[package]]
name = "js-sys"
version = "0.3.57"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -591,18 +660,18 @@ dependencies = [
[[package]]
name = "logos"
-version = "0.12.0"
+version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "427e2abca5be13136da9afdbf874e6b34ad9001dd70f2b103b083a85daa7b345"
+checksum = "bf8b031682c67a8e3d5446840f9573eb7fe26efe7ec8d195c9ac4c0647c502f1"
dependencies = [
"logos-derive",
]
[[package]]
name = "logos-derive"
-version = "0.12.0"
+version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "56a7d287fd2ac3f75b11f19a1c8a874a7d55744bd91f7a1b3e7cf87d4343c36d"
+checksum = "a1d849148dbaf9661a6151d1ca82b13bb4c4c128146a88d05253b38d4e2f496c"
dependencies = [
"beef",
"fnv",
@@ -610,7 +679,6 @@ dependencies = [
"quote",
"regex-syntax",
"syn",
- "utf8-ranges",
]
[[package]]
@@ -639,6 +707,12 @@ 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"
@@ -719,6 +793,12 @@ 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.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -754,10 +834,53 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
[[package]]
+name = "pest"
+version = "2.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "10f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53"
+dependencies = [
+ "ucd-trie",
+]
+
+[[package]]
+name = "pest_derive"
+version = "2.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "833d1ae558dc601e9a60366421196a8d94bc0ac980476d0b67e1d0988d72b2d0"
+dependencies = [
+ "pest",
+ "pest_generator",
+]
+
+[[package]]
+name = "pest_generator"
+version = "2.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "99b8db626e31e5b81787b9783425769681b347011cc59471e33ea46d2ea0cf55"
+dependencies = [
+ "pest",
+ "pest_meta",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "pest_meta"
+version = "2.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "54be6e404f5317079812fc8f9f5279de376d8856929e21c184ecf6bbd692a11d"
+dependencies = [
+ "maplit",
+ "pest",
+ "sha-1",
+]
+
+[[package]]
name = "petgraph"
-version = "0.6.1"
+version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "51b305cc4569dd4e8765bab46261f67ef5d4d11a4b6e745100ee5dad8948b46c"
+checksum = "e6d5014253a1331579ce62aa67443b4a658c5e7dd03d4bc6d302b94474888143"
dependencies = [
"fixedbitset",
"indexmap",
@@ -986,9 +1109,9 @@ dependencies = [
[[package]]
name = "rowan"
-version = "0.15.4"
+version = "0.15.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a4c1112d7b23c800be3a0dae244886b71d96b1461b57b31b56e4c679acbe614f"
+checksum = "ce1f383129e417a6265b16ed78e6e9307748f0863b2ba75f78ff14717db5b017"
dependencies = [
"countme",
"hashbrown 0.12.1",
@@ -1110,6 +1233,18 @@ dependencies = [
]
[[package]]
+name = "sha-1"
+version = "0.8.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df"
+dependencies = [
+ "block-buffer",
+ "digest",
+ "fake-simd",
+ "opaque-debug",
+]
+
+[[package]]
name = "similar"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1204,9 +1339,10 @@ dependencies = [
[[package]]
name = "texlab"
-version = "4.0.0"
+version = "4.1.0"
dependencies = [
"anyhow",
+ "assert_unordered",
"byteorder",
"chrono",
"clap 3.1.18",
@@ -1220,10 +1356,10 @@ dependencies = [
"flate2",
"fuzzy-matcher",
"human_name",
- "indoc",
"insta",
"isocountry",
"itertools",
+ "jod-thread",
"log",
"logos",
"lsp-server",
@@ -1242,9 +1378,7 @@ dependencies = [
"tempfile",
"threadpool",
"titlecase",
- "typed-builder",
"unicode-normalization",
- "unindent",
"url",
"uuid",
]
@@ -1344,15 +1478,16 @@ dependencies = [
]
[[package]]
-name = "typed-builder"
-version = "0.10.0"
+name = "typenum"
+version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "89851716b67b937e393b3daa8423e67ddfc4bbbf1654bcf05488e95e0828db0c"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
+checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987"
+
+[[package]]
+name = "ucd-trie"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c"
[[package]]
name = "unicode-bidi"
@@ -1394,12 +1529,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "402bb19d8e03f1d1a7450e2bd613980869438e0666331be3e073089124aa1adc"
[[package]]
-name = "unindent"
-version = "0.1.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "52fee519a3e570f7df377a06a1a7775cdbfb7aa460be7e08de2b1f0e69973a44"
-
-[[package]]
name = "url"
version = "2.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1413,16 +1542,10 @@ dependencies = [
]
[[package]]
-name = "utf8-ranges"
-version = "1.0.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7fcfc827f90e53a02eaef5e535ee14266c1d569214c6aa70133a624d8a3164ba"
-
-[[package]]
name = "uuid"
-version = "1.1.0"
+version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "93bbc61e655a4833cf400d0d15bf3649313422fa7572886ad6dab16d79886365"
+checksum = "dd6469f4314d5f1ffec476e05f17cc9a78bc7a27a6a857842170bdf8d6f98d2f"
dependencies = [
"getrandom",
]
diff --git a/support/texlab/Cargo.toml b/support/texlab/Cargo.toml
index df04cfba31..f85c0f31ed 100644
--- a/support/texlab/Cargo.toml
+++ b/support/texlab/Cargo.toml
@@ -1,7 +1,7 @@
[package]
name = "texlab"
description = "LaTeX Language Server"
-version = "4.0.0"
+version = "4.1.0"
license = "GPL-3.0"
readme = "README.md"
authors = [
@@ -26,6 +26,10 @@ exclude = [
"texlab.tex",
]
+[[bin]]
+name = "texlab"
+test = false
+
[lib]
doctest = false
@@ -47,20 +51,20 @@ derive_more = "0.99.17"
encoding_rs = "0.8.31"
encoding_rs_io = "0.1.7"
fern = "0.6"
-flate2 = "1.0.23"
+flate2 = "1.0.24"
fuzzy-matcher = { version = "0.3.7", optional = true }
human_name = { version = "1.0.3", default-features = false }
isocountry = "0.3.2"
itertools = "0.10.1"
log = "0.4.17"
-logos = "0.12.0"
+logos = "0.12.1"
lsp-server = "0.6.0"
lsp-types = "0.93.0"
multimap = "0.8.3"
once_cell = "1.10.0"
-petgraph = "0.6.0"
+petgraph = "0.6.2"
regex = "1.5.5"
-rowan = "0.15.4"
+rowan = "0.15.5"
rustc-hash = "1.1.0"
serde = "1.0.137"
serde_json = "1.0.81"
@@ -72,17 +76,17 @@ threadpool = "1.8.1"
titlecase = "1.1.0"
unicode-normalization = "0.1.19"
url = { version = "2.2.2", features = ["serde"] }
-uuid = { version = "1.0.0", features = ["v4"] }
+uuid = { version = "1.1.2", features = ["v4"] }
[dev-dependencies]
+assert_unordered = "0.3.5"
criterion = { version = "0.3.5" }
-indoc = "1.0.6"
-insta = { version = "1.14.0", features = ["backtrace"] }
-typed-builder = "0.10.0"
-unindent = "0.1.9"
+insta = { version = "1.14.1", features = ["backtrace", "redactions"] }
+jod-thread = "0.1.2"
[profile.release]
-lto = "fat"
+lto = "thin"
+incremental = true
[profile.bench]
lto = "thin"
diff --git a/support/texlab/README.md b/support/texlab/README.md
index 1b4bd527ec..e43082f20f 100644
--- a/support/texlab/README.md
+++ b/support/texlab/README.md
@@ -3,14 +3,8 @@
[![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)
[![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)
[![CTAN](https://img.shields.io/ctan/v/texlab)](https://ctan.org/pkg/texlab)
-[![Arch Linux](https://repology.org/badge/version-for-repo/arch/texlab.svg?header=arch%20linux)](https://www.archlinux.org/packages/community/x86_64/texlab/)
-[![NixOS Stable](https://repology.org/badge/version-for-repo/nix_stable/texlab.svg?header=nixos%20stable)](https://nixos.org/nixos/packages.html?channel=nixos-20.03&query=texlab)
-[![NixOS Unstable](https://repology.org/badge/version-for-repo/nix_unstable/texlab.svg?header=nixos%20unstable)](https://nixos.org/nixos/packages.html?channel=nixpkgs-unstable&query=texlab)
-[![Homebrew](https://repology.org/badge/version-for-repo/homebrew/texlab.svg?header=homebrew)](https://formulae.brew.sh/formula/texlab)
-[![Scoop](https://repology.org/badge/version-for-repo/scoop/texlab.svg?header=scoop)](https://scoop.sh/)
-[![FreeBSD](https://repology.org/badge/version-for-repo/freebsd/texlab.svg?header=freebsd)](https://www.freshports.org/devel/texlab)
-[![NetBSD](https://repology.org/badge/version-for-repo/pkgsrc_current/texlab.svg?header=netbsd)](https://pkgsrc.se/print/texlab)
# TexLab
@@ -27,7 +21,9 @@ you will need to install it manually.
We provide [precompiled binaries](https://github.com/latex-lsp/texlab/releases)
for Windows, Linux and macOS.
Alternatively, you can build TexLab from source or install it using your package manager.
-For a list of supported package managers, you can take a look at [Repology](https://repology.org/project/texlab/versions).
+For a list of supported package managers, you can take a look at [Repology](https://repology.org/project/texlab/versions):
+
+[![Packaging status](https://repology.org/badge/vertical-allrepos/texlab.svg)](https://repology.org/project/texlab/versions)
### Requirements
@@ -50,11 +46,10 @@ Then run the following command in the project folder:
cargo build --release
```
-Alternatively, you can run the following command
-without having to clone this repository and make TexLab available in your PATH:
+Alternatively, you can install `texlab` from [crates.io](https://crates.io/crates/texlab) and run
```shell
-cargo install --git https://github.com/latex-lsp/texlab.git --locked
+cargo install texlab
```
## Usage
diff --git a/support/texlab/docs/custom_commands.md b/support/texlab/docs/custom_commands.md
new file mode 100644
index 0000000000..2b85787f35
--- /dev/null
+++ b/support/texlab/docs/custom_commands.md
@@ -0,0 +1,21 @@
+# 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/src/citation.rs b/support/texlab/src/citation.rs
index e1d6f49268..cb6c5c3623 100644
--- a/support/texlab/src/citation.rs
+++ b/support/texlab/src/citation.rs
@@ -1,6 +1,6 @@
mod driver;
mod entry;
-mod field;
+pub(crate) mod field;
mod output;
use unicode_normalization::UnicodeNormalization;
@@ -9,6 +9,7 @@ use crate::syntax::bibtex;
use self::{driver::Driver, output::Inline};
+#[must_use]
pub fn render(entry: &bibtex::Entry) -> Option<String> {
let mut output = String::new();
let mut driver = Driver::default();
diff --git a/support/texlab/src/citation/driver.rs b/support/texlab/src/citation/driver.rs
index eaf98304c4..815474a107 100644
--- a/support/texlab/src/citation/driver.rs
+++ b/support/texlab/src/citation/driver.rs
@@ -22,8 +22,8 @@ pub struct Driver {
}
impl Driver {
- pub fn process(&mut self, entry: &bibtex::Entry) -> Option<()> {
- let entry = EntryData::parse(entry)?;
+ pub fn process(&mut self, entry: &bibtex::Entry) {
+ let entry = EntryData::from(entry);
match entry.kind {
EntryKind::Article
| EntryKind::DataSet
@@ -60,10 +60,10 @@ impl Driver {
| EntryKind::Report
| EntryKind::TechReport => self.book_like(entry),
EntryKind::Patent => self.patent(entry),
- }
+ };
}
- fn article_like(&mut self, mut entry: EntryData) -> Option<()> {
+ fn article_like(&mut self, mut entry: EntryData) {
self.author(&mut entry);
self.title(&mut entry);
self.translator(&mut entry);
@@ -99,10 +99,9 @@ impl Driver {
self.url(&mut entry);
self.addendum(&mut entry);
self.pubstate(&mut entry);
- Some(())
}
- fn book_like(&mut self, mut entry: EntryData) -> Option<()> {
+ fn book_like(&mut self, mut entry: EntryData) {
self.author(&mut entry);
self.title(&mut entry);
self.inbook_title(&mut entry);
@@ -133,10 +132,9 @@ impl Driver {
self.url(&mut entry);
self.addendum(&mut entry);
self.pubstate(&mut entry);
- Some(())
}
- fn patent(&mut self, mut entry: EntryData) -> Option<()> {
+ fn patent(&mut self, mut entry: EntryData) {
self.author(&mut entry);
self.title(&mut entry);
self.patent_number(&mut entry);
@@ -147,7 +145,6 @@ impl Driver {
self.url(&mut entry);
self.addendum(&mut entry);
self.pubstate(&mut entry);
- Some(())
}
fn author(&mut self, entry: &mut EntryData) -> Option<()> {
@@ -211,8 +208,7 @@ impl Driver {
let editor_type = entry
.text
.remove(&type_field)
- .map(|data| data.text)
- .unwrap_or_else(|| "Ed. by".to_string());
+ .map_or_else(|| "Ed. by".to_string(), |data| data.text);
self.builder.push(
Inline::Regular(format!("{editor_type} {editor}")),
diff --git a/support/texlab/src/citation/entry.rs b/support/texlab/src/citation/entry.rs
index c8b3f98753..1fee032488 100644
--- a/support/texlab/src/citation/entry.rs
+++ b/support/texlab/src/citation/entry.rs
@@ -3,7 +3,7 @@ use std::str::FromStr;
use rustc_hash::FxHashMap;
use strum::EnumString;
-use crate::syntax::bibtex::{Entry, Field, HasName, HasType};
+use crate::syntax::bibtex::{Entry, Field, HasName, HasType, HasValue, Value};
use super::field::{
author::{AuthorField, AuthorFieldData},
@@ -67,8 +67,8 @@ pub struct EntryData {
pub number: FxHashMap<NumberField, NumberFieldData>,
}
-impl EntryData {
- pub fn parse(entry: &Entry) -> Option<Self> {
+impl From<&Entry> for EntryData {
+ fn from(entry: &Entry) -> Self {
let mut data = EntryData {
kind: entry
.type_token()
@@ -81,42 +81,45 @@ impl EntryData {
let _ = data.parse_field(&field);
}
- Some(data)
+ data
}
+}
+impl EntryData {
fn parse_field(&mut self, field: &Field) -> Option<()> {
let name = field.name_token()?;
let name = name.text();
- self.parse_author_field(field, name)
- .or_else(|| self.parse_date_field(field, name))
- .or_else(|| self.parse_number_field(field, name))
- .or_else(|| self.parse_text_field(field, name))
+ let value = field.value()?;
+ self.parse_author_field(name, &value)
+ .or_else(|| self.parse_date_field(name, &value))
+ .or_else(|| self.parse_number_field(name, &value))
+ .or_else(|| self.parse_text_field(name, &value))
}
- fn parse_author_field(&mut self, field: &Field, name: &str) -> Option<()> {
+ fn parse_author_field(&mut self, name: &str, value: &Value) -> Option<()> {
let name = AuthorField::parse(name)?;
- let data = AuthorFieldData::parse(field)?;
+ let data = AuthorFieldData::parse(value)?;
self.author.insert(name, data);
Some(())
}
- fn parse_date_field(&mut self, field: &Field, name: &str) -> Option<()> {
+ fn parse_date_field(&mut self, name: &str, value: &Value) -> Option<()> {
let name = DateField::parse(name)?;
- let data = DateFieldData::parse(field)?;
+ let data = DateFieldData::parse(value)?;
self.date.insert(name, data);
Some(())
}
- fn parse_number_field(&mut self, field: &Field, name: &str) -> Option<()> {
+ fn parse_number_field(&mut self, name: &str, value: &Value) -> Option<()> {
let name = NumberField::parse(name)?;
- let data = NumberFieldData::parse(field)?;
+ let data = NumberFieldData::parse(value)?;
self.number.insert(name, data);
Some(())
}
- fn parse_text_field(&mut self, field: &Field, name: &str) -> Option<()> {
+ fn parse_text_field(&mut self, name: &str, value: &Value) -> Option<()> {
let name = TextField::parse(name).unwrap_or(TextField::Unknown);
- let data = TextFieldData::parse(field)?;
+ let data = TextFieldData::parse(value)?;
self.text.insert(name, data);
Some(())
}
diff --git a/support/texlab/src/citation/field/author.rs b/support/texlab/src/citation/field/author.rs
index a5e4368320..a0e4120559 100644
--- a/support/texlab/src/citation/field/author.rs
+++ b/support/texlab/src/citation/field/author.rs
@@ -4,7 +4,7 @@ use human_name::Name;
use itertools::Itertools;
use strum::EnumString;
-use crate::syntax::bibtex::Field;
+use crate::syntax::bibtex::Value;
use super::text::TextFieldData;
@@ -37,10 +37,7 @@ pub struct AuthorFieldData {
impl fmt::Display for AuthorFieldData {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- let names = self
- .authors
- .iter()
- .map(|author| author.display_initial_surname());
+ let names = self.authors.iter().map(Name::display_initial_surname);
for part in Itertools::intersperse(names, Cow::Borrowed(", ")) {
write!(f, "{}", part)?;
@@ -51,8 +48,8 @@ impl fmt::Display for AuthorFieldData {
}
impl AuthorFieldData {
- pub fn parse(field: &Field) -> Option<Self> {
- let TextFieldData { text } = TextFieldData::parse(field)?;
+ pub fn parse(value: &Value) -> Option<Self> {
+ let TextFieldData { text } = TextFieldData::parse(value)?;
let mut authors = Vec::new();
let mut words = Vec::new();
for word in text.split_whitespace() {
diff --git a/support/texlab/src/citation/field/date.rs b/support/texlab/src/citation/field/date.rs
index b9b3dbb438..b67972e691 100644
--- a/support/texlab/src/citation/field/date.rs
+++ b/support/texlab/src/citation/field/date.rs
@@ -3,7 +3,7 @@ use std::{fmt, ops::Add, str::FromStr};
use chrono::{Datelike, Month, NaiveDate};
use strum::EnumString;
-use crate::syntax::bibtex::Field;
+use crate::syntax::bibtex::Value;
use super::text::TextFieldData;
@@ -69,8 +69,8 @@ impl fmt::Display for DateFieldData {
}
impl DateFieldData {
- pub fn parse(field: &Field) -> Option<Self> {
- let TextFieldData { text } = TextFieldData::parse(field)?;
+ pub fn parse(value: &Value) -> Option<Self> {
+ let TextFieldData { text } = TextFieldData::parse(value)?;
NaiveDate::from_str(&text)
.ok()
.map(Self::Date)
diff --git a/support/texlab/src/citation/field/number.rs b/support/texlab/src/citation/field/number.rs
index 9f51ccef90..ad892c879f 100644
--- a/support/texlab/src/citation/field/number.rs
+++ b/support/texlab/src/citation/field/number.rs
@@ -2,7 +2,7 @@ use std::{fmt, str::FromStr};
use strum::EnumString;
-use crate::syntax::bibtex::Field;
+use crate::syntax::bibtex::Value;
use super::text::TextFieldData;
@@ -42,8 +42,8 @@ impl fmt::Display for NumberFieldData {
}
impl NumberFieldData {
- pub fn parse(field: &Field) -> Option<Self> {
- let TextFieldData { text } = TextFieldData::parse(field)?;
+ pub fn parse(value: &Value) -> Option<Self> {
+ let TextFieldData { text } = TextFieldData::parse(value)?;
text.split_once("--")
.or_else(|| text.split_once('-'))
.and_then(|(a, b)| Some((a.parse().ok()?, b.parse().ok()?)))
diff --git a/support/texlab/src/citation/field/text.rs b/support/texlab/src/citation/field/text.rs
index 87119bd47c..9b3a0b02b2 100644
--- a/support/texlab/src/citation/field/text.rs
+++ b/support/texlab/src/citation/field/text.rs
@@ -5,8 +5,8 @@ use rustc_hash::FxHashSet;
use strum::EnumString;
use crate::syntax::bibtex::{
- Accent, Command, CurlyGroup, Field, HasAccentName, HasCommandName, HasName, HasValue, HasWord,
- Join, Literal, QuoteGroup, Root, SyntaxKind::*, SyntaxToken, Value,
+ Accent, Command, CurlyGroup, HasAccentName, HasCommandName, HasName, HasValue, HasWord, Join,
+ Literal, QuoteGroup, Root, SyntaxKind::*, SyntaxToken, Value,
};
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash, EnumString)]
@@ -73,9 +73,9 @@ pub struct TextFieldData {
}
impl TextFieldData {
- pub fn parse(field: &Field) -> Option<Self> {
+ pub fn parse(value: &Value) -> Option<Self> {
let mut builder = TextFieldDataBuilder::default();
- builder.visit_value(&field.value()?)?;
+ builder.visit_value(value)?;
Some(builder.data)
}
}
@@ -90,7 +90,7 @@ impl TextFieldDataBuilder {
fn visit_value(&mut self, value: &Value) -> Option<()> {
match value {
Value::Literal(lit) => {
- self.visit_literal(lit)?;
+ self.visit_literal(lit);
}
Value::CurlyGroup(group) => {
self.visit_curly_group(group)?;
@@ -112,7 +112,7 @@ impl TextFieldDataBuilder {
Some(())
}
- fn visit_literal(&mut self, lit: &Literal) -> Option<()> {
+ fn visit_literal(&mut self, lit: &Literal) {
if lit
.name_token()
.and_then(|name| self.visit_string_reference(&name))
@@ -122,12 +122,10 @@ impl TextFieldDataBuilder {
.text()
.for_each_chunk(|text| self.data.text.push_str(text));
}
-
- Some(())
}
fn visit_string_reference(&mut self, name: &SyntaxToken) -> Option<()> {
- let root = Root::cast(name.ancestors().last()?)?;
+ let root = Root::cast(name.parent_ancestors().last()?)?;
let name = name.text();
let value = root
diff --git a/support/texlab/src/citation/output.rs b/support/texlab/src/citation/output.rs
index 555ec138db..2fc8a02361 100644
--- a/support/texlab/src/citation/output.rs
+++ b/support/texlab/src/citation/output.rs
@@ -26,31 +26,12 @@ impl Add for Punct {
fn add(self, rhs: Self) -> Self::Output {
match (self, rhs) {
- (Self::Nothing, Self::Nothing) => Self::Nothing,
- (Self::Nothing, Self::Space)
- | (Self::Space, Self::Nothing)
- | (Self::Space, Self::Space) => Self::Space,
- (Self::Nothing, Self::Comma)
- | (Self::Space, Self::Comma)
- | (Self::Comma, Self::Nothing)
- | (Self::Comma, Self::Space)
- | (Self::Comma, Self::Comma)
- | (Self::Comma, Self::Dot)
- | (Self::Dot, Self::Comma) => Self::Comma,
- (Self::Nothing, Self::Dot)
- | (Self::Space, Self::Dot)
- | (Self::Dot, Self::Nothing)
- | (Self::Dot, Self::Space)
- | (Self::Dot, Self::Dot) => Self::Dot,
- (Self::Nothing, Self::Colon)
- | (Self::Space, Self::Colon)
- | (Self::Comma, Self::Colon)
- | (Self::Dot, Self::Colon)
- | (Self::Colon, Self::Nothing)
- | (Self::Colon, Self::Space)
- | (Self::Colon, Self::Comma)
- | (Self::Colon, Self::Dot)
- | (Self::Colon, Self::Colon) => Self::Colon,
+ (Self::Nothing, punct) | (punct, Self::Nothing) => punct,
+ (_, Self::Colon) | (Self::Colon, _) => Self::Colon,
+ (Self::Space, Self::Space) => Self::Space,
+ (Self::Space | Self::Comma | Self::Dot, Self::Comma)
+ | (Self::Comma, Self::Space | Self::Dot) => Self::Comma,
+ (Self::Space | Self::Dot, Self::Dot) | (Self::Dot, Self::Space) => Self::Dot,
}
}
}
diff --git a/support/texlab/src/component_db.rs b/support/texlab/src/component_db.rs
index 68788df879..8dc547369f 100644
--- a/support/texlab/src/component_db.rs
+++ b/support/texlab/src/component_db.rs
@@ -7,7 +7,7 @@ use once_cell::sync::Lazy;
use serde::{Deserialize, Serialize};
use smol_str::SmolStr;
-use crate::Workspace;
+use crate::{syntax::latex::ExplicitLink, Workspace};
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
@@ -17,6 +17,7 @@ pub struct ComponentDatabase {
}
impl ComponentDatabase {
+ #[must_use]
pub fn find(&self, name: &str) -> Option<&Component> {
self.components.iter().find(|component| {
component
@@ -26,6 +27,7 @@ impl ComponentDatabase {
})
}
+ #[must_use]
pub fn find_no_ext(&self, name: &str) -> Option<&Component> {
self.components.iter().find(|component| {
component
@@ -35,6 +37,7 @@ impl ComponentDatabase {
})
}
+ #[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() {
@@ -42,7 +45,7 @@ impl ComponentDatabase {
data.extras
.explicit_links
.iter()
- .filter_map(|link| link.as_component_name())
+ .filter_map(ExplicitLink::as_component_name)
.filter_map(|name| self.find(&name))
.for_each(|component| start_components.push(component));
}
@@ -54,8 +57,8 @@ impl ComponentDatabase {
component
.references
.iter()
- .flat_map(|file| self.find(file))
- .for_each(|component| all_components.push(component))
+ .filter_map(|file| self.find(file))
+ .for_each(|component| all_components.push(component));
}
all_components
@@ -64,12 +67,14 @@ impl ComponentDatabase {
.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()
@@ -77,12 +82,14 @@ impl ComponentDatabase {
.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
diff --git a/support/texlab/src/diagnostics.rs b/support/texlab/src/diagnostics.rs
index 46e12d9cfc..5ce177b015 100644
--- a/support/texlab/src/diagnostics.rs
+++ b/support/texlab/src/diagnostics.rs
@@ -34,19 +34,20 @@ impl DiagnosticsManager {
self.static_diagnostics.insert(uri, diagnostics_by_uri);
}
- pub fn update_chktex(&mut self, workspace: &Workspace, uri: Arc<Url>, options: &Options) {
- analyze_latex_chktex(workspace, &mut self.chktex_diagnostics, &uri, options);
+ pub fn update_chktex(&mut self, workspace: &Workspace, uri: &Url, options: &Options) {
+ analyze_latex_chktex(workspace, &mut self.chktex_diagnostics, uri, options);
}
- pub fn publish(&self, uri: Arc<Url>) -> Vec<Diagnostic> {
+ #[must_use]
+ pub fn publish(&self, uri: &Url) -> Vec<Diagnostic> {
let mut all_diagnostics = Vec::new();
for diagnostics_by_uri in self.static_diagnostics.values() {
- if let Some(diagnostics) = diagnostics_by_uri.get_vec(&uri) {
+ if let Some(diagnostics) = diagnostics_by_uri.get_vec(uri) {
all_diagnostics.append(&mut diagnostics.clone());
}
}
- if let Some(diagnostics) = self.chktex_diagnostics.get_vec(&uri) {
+ if let Some(diagnostics) = self.chktex_diagnostics.get_vec(uri) {
all_diagnostics.append(&mut diagnostics.clone());
}
diff --git a/support/texlab/src/diagnostics/build_log.rs b/support/texlab/src/diagnostics/build_log.rs
index 8bd83f695a..e280d862bc 100644
--- a/support/texlab/src/diagnostics/build_log.rs
+++ b/support/texlab/src/diagnostics/build_log.rs
@@ -55,8 +55,7 @@ pub fn analyze_build_log_static(
.relative_path
.to_str()
.and_then(|path| root_document.uri.join(path).map(Into::into).ok())
- .map(Arc::new)
- .unwrap_or_else(|| Arc::clone(&root_document.uri))
+ .map_or_else(|| Arc::clone(&root_document.uri), Arc::new)
} else {
Arc::clone(&root_document.uri)
};
diff --git a/support/texlab/src/diagnostics/chktex.rs b/support/texlab/src/diagnostics/chktex.rs
index 6e7422d8b0..6b6405d975 100644
--- a/support/texlab/src/diagnostics/chktex.rs
+++ b/support/texlab/src/diagnostics/chktex.rs
@@ -54,10 +54,10 @@ pub static LINE_REGEX: Lazy<Regex> =
fn lint(text: &str, current_dir: &Path) -> io::Result<Vec<Diagnostic>> {
let directory = tempdir()?;
fs::write(directory.path().join("file.tex"), text)?;
- let _ = fs::copy(
+ 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"])
diff --git a/support/texlab/src/diagnostics/debouncer.rs b/support/texlab/src/diagnostics/debouncer.rs
index 5117cf2fe0..4c83636856 100644
--- a/support/texlab/src/diagnostics/debouncer.rs
+++ b/support/texlab/src/diagnostics/debouncer.rs
@@ -45,7 +45,7 @@ impl DiagnosticsDebouncer {
.unwrap_or(300);
if let Some(time) = last_task_time_by_uri.get(&document.uri) {
- if time.elapsed().as_millis() < delay as u128 {
+ if time.elapsed().as_millis() < u128::from(delay) {
continue;
}
}
diff --git a/support/texlab/src/diagnostics/latex.rs b/support/texlab/src/diagnostics/latex.rs
index 34d5e9fa29..2c271ad54a 100644
--- a/support/texlab/src/diagnostics/latex.rs
+++ b/support/texlab/src/diagnostics/latex.rs
@@ -2,7 +2,7 @@ use std::sync::Arc;
use lsp_types::{Diagnostic, DiagnosticSeverity, NumberOrString, Url};
use multimap::MultiMap;
-use rowan::{ast::AstNode, TextRange};
+use rowan::{ast::AstNode, NodeOrToken, TextRange};
use crate::{syntax::latex, Document, LineIndexExt, Workspace};
@@ -20,7 +20,7 @@ pub fn analyze_latex_static(
for node in latex::SyntaxNode::new_root(data.green.clone()).descendants() {
analyze_environment(document, diagnostics_by_uri, node.clone())
- .or_else(|| analyze_curly_group(document, diagnostics_by_uri, node.clone()))
+ .or_else(|| analyze_curly_group(document, diagnostics_by_uri, &node))
.or_else(|| {
if node.kind() == latex::ERROR && node.first_token()?.text() == "}" {
diagnostics_by_uri.insert(
@@ -79,7 +79,7 @@ fn analyze_environment(
fn analyze_curly_group(
document: &Document,
diagnostics_by_uri: &mut MultiMap<Arc<Url>, Diagnostic>,
- node: latex::SyntaxNode,
+ node: &latex::SyntaxNode,
) -> Option<()> {
if !matches!(
node.kind(),
@@ -105,7 +105,7 @@ fn analyze_curly_group(
if !is_inside_verbatim_environment
&& !node
.children_with_tokens()
- .filter_map(|element| element.into_token())
+ .filter_map(NodeOrToken::into_token)
.any(|token| token.kind() == latex::R_CURLY)
{
diagnostics_by_uri.insert(
diff --git a/support/texlab/src/distro.rs b/support/texlab/src/distro.rs
index 1e67a14285..f869392366 100644
--- a/support/texlab/src/distro.rs
+++ b/support/texlab/src/distro.rs
@@ -29,6 +29,7 @@ pub struct Distribution {
}
impl Distribution {
+ #[must_use]
pub fn detect() -> Self {
let kind = match Command::new("latex").arg("--version").output() {
Ok(output) => {
diff --git a/support/texlab/src/distro/kpsewhich.rs b/support/texlab/src/distro/kpsewhich.rs
index ad2ac9eaf2..b14e64bf56 100644
--- a/support/texlab/src/distro/kpsewhich.rs
+++ b/support/texlab/src/distro/kpsewhich.rs
@@ -18,6 +18,7 @@ pub struct Resolver {
}
impl Resolver {
+ #[must_use]
pub fn new(files_by_name: FxHashMap<SmolStr, PathBuf>) -> Self {
Self { files_by_name }
}
diff --git a/support/texlab/src/distro/miktex.rs b/support/texlab/src/distro/miktex.rs
index 563c8445e3..c7a92d572e 100644
--- a/support/texlab/src/distro/miktex.rs
+++ b/support/texlab/src/distro/miktex.rs
@@ -18,10 +18,10 @@ pub fn load_resolver() -> Result<Resolver> {
const DATABASE_PATH: &str = "miktex/data/le";
const FNDB_SIGNATURE: u32 = 0x42_44_4e_46;
-const FNDB_WORD_SIZE: usize = 4;
-const FNDB_TABLE_POINTER_OFFSET: usize = 4 * FNDB_WORD_SIZE;
-const FNDB_TABLE_SIZE_OFFSET: usize = 6 * FNDB_WORD_SIZE;
-const FNDB_ENTRY_SIZE: usize = 4 * FNDB_WORD_SIZE;
+const FNDB_WORD_SIZE: u32 = 4;
+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>> {
let database_directory = directory.join(DATABASE_PATH);
@@ -45,16 +45,16 @@ fn parse_database(bytes: &[u8]) -> io::Result<Vec<PathBuf>> {
return Err(io::ErrorKind::InvalidData.into());
}
- reader.set_position(FNDB_TABLE_POINTER_OFFSET as u64);
+ reader.set_position(u64::from(FNDB_TABLE_POINTER_OFFSET));
let table_address = reader.read_u32::<LittleEndian>()?;
- reader.set_position(FNDB_TABLE_SIZE_OFFSET as u64);
+ reader.set_position(u64::from(FNDB_TABLE_SIZE_OFFSET));
let table_size = reader.read_u32::<LittleEndian>()?;
let mut files = Vec::new();
for i in 0..table_size {
let offset = table_address + i * FNDB_ENTRY_SIZE as u32;
- reader.set_position(offset as u64);
+ 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 = read_string(bytes, file_name_offset)?;
diff --git a/support/texlab/src/distro/texlive.rs b/support/texlab/src/distro/texlive.rs
index 27f55569a7..47159b2efc 100644
--- a/support/texlab/src/distro/texlive.rs
+++ b/support/texlab/src/distro/texlive.rs
@@ -1,5 +1,5 @@
use std::{
- fs, io,
+ fs,
path::{Path, PathBuf},
str::Lines,
};
@@ -23,11 +23,11 @@ fn read_database(directory: &Path) -> Result<Vec<PathBuf>> {
}
let text = fs::read_to_string(file)?;
- let files = parse_database(text.lines())?;
+ let files = parse_database(text.lines());
Ok(files)
}
-fn parse_database(lines: Lines) -> io::Result<Vec<PathBuf>> {
+fn parse_database(lines: Lines) -> Vec<PathBuf> {
let mut paths = Vec::new();
let mut directory = "";
@@ -39,5 +39,6 @@ fn parse_database(lines: Lines) -> io::Result<Vec<PathBuf>> {
paths.push(path);
}
}
- Ok(paths)
+
+ paths
}
diff --git a/support/texlab/src/document.rs b/support/texlab/src/document.rs
index adb6bad5ac..60e295b2e4 100644
--- a/support/texlab/src/document.rs
+++ b/support/texlab/src/document.rs
@@ -31,6 +31,7 @@ pub enum DocumentData {
}
impl DocumentData {
+ #[must_use]
pub fn language(&self) -> DocumentLanguage {
match self {
Self::Latex(_) => DocumentLanguage::Latex,
@@ -39,6 +40,7 @@ impl DocumentData {
}
}
+ #[must_use]
pub fn as_latex(&self) -> Option<&LatexDocumentData> {
if let Self::Latex(data) = self {
Some(data)
@@ -47,6 +49,7 @@ impl DocumentData {
}
}
+ #[must_use]
pub fn as_bibtex(&self) -> Option<&BibtexDocumentData> {
if let Self::Bibtex(data) = self {
Some(data)
@@ -55,6 +58,7 @@ impl DocumentData {
}
}
+ #[must_use]
pub fn as_build_log(&self) -> Option<&build_log::Parse> {
if let Self::BuildLog(v) = self {
Some(v)
@@ -79,6 +83,7 @@ impl fmt::Debug for Document {
}
impl Document {
+ #[must_use]
pub fn parse(
environment: &Environment,
uri: Arc<Url>,
@@ -95,8 +100,7 @@ impl Document {
Some(root_dir) => {
let root_dir = environment.current_directory.join(&root_dir);
Url::from_directory_path(root_dir)
- .map(Arc::new)
- .unwrap_or_else(|()| Arc::clone(&uri))
+ .map_or_else(|()| Arc::clone(&uri), Arc::new)
}
None => Arc::clone(&uri),
};
diff --git a/support/texlab/src/environment.rs b/support/texlab/src/environment.rs
index 5ba80617d5..54b6279f30 100644
--- a/support/texlab/src/environment.rs
+++ b/support/texlab/src/environment.rs
@@ -14,6 +14,7 @@ pub struct Environment {
}
impl Environment {
+ #[must_use]
pub fn new(current_directory: Arc<PathBuf>) -> Self {
Self {
current_directory,
diff --git a/support/texlab/src/features.rs b/support/texlab/src/features.rs
index ed936f569f..9576f266a9 100644
--- a/support/texlab/src/features.rs
+++ b/support/texlab/src/features.rs
@@ -3,6 +3,7 @@ mod build;
mod completion;
mod cursor;
mod definition;
+mod execute_command;
mod folding;
mod formatting;
mod forward_search;
@@ -25,6 +26,7 @@ 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},
@@ -48,214 +50,3 @@ impl<P> FeatureRequest<P> {
&self.workspace.documents_by_uri[&self.uri]
}
}
-
-#[cfg(test)]
-mod testing {
- use std::{path::PathBuf, sync::Arc};
-
- use lsp_types::{
- ClientCapabilities, ClientInfo, CompletionParams, DocumentFormattingParams,
- DocumentHighlightParams, DocumentLinkParams, FoldingRangeParams, FormattingOptions,
- GotoDefinitionParams, HoverParams, PartialResultParams, Position, ReferenceContext,
- ReferenceParams, RenameParams, TextDocumentIdentifier, TextDocumentPositionParams,
- WorkDoneProgressParams,
- };
- use typed_builder::TypedBuilder;
-
- use crate::{distro::Resolver, DocumentLanguage, Environment, Options, Workspace};
-
- use super::*;
-
- #[derive(Debug, Clone, TypedBuilder)]
- pub struct FeatureTester<'a> {
- main: &'a str,
-
- files: Vec<(&'a str, &'a str)>,
-
- #[builder(default)]
- line: u32,
-
- #[builder(default)]
- character: u32,
-
- #[builder(default)]
- new_name: &'a str,
-
- #[builder(default)]
- include_declaration: bool,
-
- #[builder(default)]
- client_capabilities: ClientCapabilities,
-
- #[builder(default)]
- client_info: Option<ClientInfo>,
-
- #[builder(default)]
- resolver: Resolver,
-
- #[builder(default=std::env::temp_dir())]
- current_directory: PathBuf,
-
- #[builder(default, setter(strip_option))]
- root_directory: Option<PathBuf>,
-
- #[builder(default, setter(strip_option))]
- aux_directory: Option<PathBuf>,
- }
-
- impl<'a> FeatureTester<'a> {
- pub fn uri(&self, name: &str) -> Arc<Url> {
- let path = self.current_directory.join(name);
- Arc::new(Url::from_file_path(path).unwrap())
- }
-
- fn options(&self) -> Options {
- Options {
- aux_directory: self.aux_directory.clone(),
- root_directory: self.root_directory.clone(),
- ..Options::default()
- }
- }
-
- fn identifier(&self) -> TextDocumentIdentifier {
- let uri = self.uri(self.main);
- TextDocumentIdentifier::new(uri.as_ref().clone())
- }
-
- fn workspace(&self) -> Workspace {
- let mut workspace = Workspace::new(Environment {
- client_capabilities: Arc::new(self.client_capabilities.clone()),
- client_info: self.client_info.clone().map(Arc::new),
- options: Arc::new(self.options()),
- resolver: Arc::new(self.resolver.clone()),
- ..Environment::default()
- });
-
- for (name, source_code) in &self.files {
- let uri = self.uri(name);
- let path = uri.to_file_path().unwrap();
- let text = Arc::new(source_code.trim().to_string());
- let language = DocumentLanguage::by_path(&path).expect("unknown document language");
- let document = workspace.open(uri, text, language).unwrap();
- workspace.viewport.insert(document.uri);
- }
-
- workspace
- }
-
- fn request<P>(&self, params: P) -> FeatureRequest<P> {
- let workspace = self.workspace();
- let uri = self.uri(self.main);
- FeatureRequest {
- params,
- workspace: workspace.slice(&uri),
- uri,
- }
- }
-
- pub fn link(self) -> FeatureRequest<DocumentLinkParams> {
- let text_document = self.identifier();
- let params = DocumentLinkParams {
- text_document,
- work_done_progress_params: WorkDoneProgressParams::default(),
- partial_result_params: PartialResultParams::default(),
- };
- self.request(params)
- }
-
- pub fn folding(self) -> FeatureRequest<FoldingRangeParams> {
- let text_document = self.identifier();
- let params = FoldingRangeParams {
- text_document,
- work_done_progress_params: WorkDoneProgressParams::default(),
- partial_result_params: PartialResultParams::default(),
- };
- self.request(params)
- }
-
- pub fn reference(self) -> FeatureRequest<ReferenceParams> {
- let params = ReferenceParams {
- text_document_position: TextDocumentPositionParams::new(
- self.identifier(),
- Position::new(self.line, self.character),
- ),
- context: ReferenceContext {
- include_declaration: self.include_declaration,
- },
- work_done_progress_params: WorkDoneProgressParams::default(),
- partial_result_params: PartialResultParams::default(),
- };
- self.request(params)
- }
-
- pub fn hover(self) -> FeatureRequest<HoverParams> {
- let params = HoverParams {
- text_document_position_params: TextDocumentPositionParams::new(
- self.identifier(),
- Position::new(self.line, self.character),
- ),
- work_done_progress_params: WorkDoneProgressParams::default(),
- };
- self.request(params)
- }
-
- pub fn completion(self) -> FeatureRequest<CompletionParams> {
- let params = CompletionParams {
- text_document_position: TextDocumentPositionParams::new(
- self.identifier(),
- Position::new(self.line, self.character),
- ),
- work_done_progress_params: WorkDoneProgressParams::default(),
- partial_result_params: PartialResultParams::default(),
- context: None,
- };
-
- self.request(params)
- }
-
- pub fn definition(self) -> FeatureRequest<GotoDefinitionParams> {
- let params = GotoDefinitionParams {
- text_document_position_params: TextDocumentPositionParams::new(
- self.identifier(),
- Position::new(self.line, self.character),
- ),
- work_done_progress_params: WorkDoneProgressParams::default(),
- partial_result_params: PartialResultParams::default(),
- };
- self.request(params)
- }
-
- pub fn rename(self) -> FeatureRequest<RenameParams> {
- let params = RenameParams {
- text_document_position: TextDocumentPositionParams::new(
- self.identifier(),
- Position::new(self.line, self.character),
- ),
- new_name: self.new_name.to_string(),
- work_done_progress_params: WorkDoneProgressParams::default(),
- };
- self.request(params)
- }
-
- pub fn formatting(self) -> FeatureRequest<DocumentFormattingParams> {
- let params = DocumentFormattingParams {
- text_document: self.identifier(),
- work_done_progress_params: WorkDoneProgressParams::default(),
- options: FormattingOptions::default(),
- };
- self.request(params)
- }
-
- pub fn highlight(self) -> FeatureRequest<DocumentHighlightParams> {
- let params = DocumentHighlightParams {
- text_document_position_params: TextDocumentPositionParams::new(
- self.identifier(),
- Position::new(self.line, self.character),
- ),
- work_done_progress_params: WorkDoneProgressParams::default(),
- partial_result_params: PartialResultParams::default(),
- };
- self.request(params)
- }
- }
-}
diff --git a/support/texlab/src/features/build.rs b/support/texlab/src/features/build.rs
index 7821fac43d..ae465590fc 100644
--- a/support/texlab/src/features/build.rs
+++ b/support/texlab/src/features/build.rs
@@ -84,7 +84,7 @@ impl<'a> ProgressReporter<'a> {
impl<'a> Drop for ProgressReporter<'a> {
fn drop(&mut self) {
if self.supports_progress {
- let _ = client::send_notification::<Progress>(
+ drop(client::send_notification::<Progress>(
&self.lsp_sender,
ProgressParams {
token: NumberOrString::String(self.token.to_string()),
@@ -92,7 +92,7 @@ impl<'a> Drop for ProgressReporter<'a> {
WorkDoneProgressEnd { message: None },
)),
},
- );
+ ));
}
}
}
diff --git a/support/texlab/src/features/completion.rs b/support/texlab/src/features/completion.rs
index 3b5187f8eb..3009b437e7 100644
--- a/support/texlab/src/features/completion.rs
+++ b/support/texlab/src/features/completion.rs
@@ -71,6 +71,7 @@ use super::{
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);
@@ -172,7 +173,6 @@ fn score(context: &CursorContext<CompletionParams>, items: &mut Vec<InternalComp
token.text().into()
}
}
- Cursor::Latex(_) => "".into(),
Cursor::Bibtex(token)
if matches!(
token.kind(),
@@ -185,8 +185,7 @@ fn score(context: &CursorContext<CompletionParams>, items: &mut Vec<InternalComp
{
token.text().into()
}
- Cursor::Bibtex(_) => "".into(),
- Cursor::Nothing => "".into(),
+ Cursor::Latex(_) | Cursor::Bibtex(_) | Cursor::Nothing => "".into(),
};
let file_pattern = pattern.split('/').last().unwrap();
diff --git a/support/texlab/src/features/completion/acronym_ref.rs b/support/texlab/src/features/completion/acronym_ref.rs
index 2bb931fde4..84cbd8bc23 100644
--- a/support/texlab/src/features/completion/acronym_ref.rs
+++ b/support/texlab/src/features/completion/acronym_ref.rs
@@ -30,123 +30,3 @@ pub fn complete_acronyms<'a>(
}
Some(())
}
-
-#[cfg(test)]
-mod tests {
- use rowan::TextRange;
-
- use crate::features::testing::FeatureTester;
-
- use super::*;
-
- #[test]
- fn test_empty_latex_document() {
- let request = FeatureTester::builder()
- .files(vec![("main.tex", "")])
- .main("main.tex")
- .line(0)
- .character(0)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_acronyms(&context, &mut actual_items);
-
- assert!(actual_items.is_empty());
- }
-
- #[test]
- fn test_empty_bibtex_document() {
- let request = FeatureTester::builder()
- .files(vec![("main.bib", "")])
- .main("main.bib")
- .line(0)
- .character(0)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_acronyms(&context, &mut actual_items);
-
- assert!(actual_items.is_empty());
- }
-
- #[test]
- fn test_simple() {
- let request = FeatureTester::builder()
- .files(vec![("main.tex", "\\newacronym[longplural={Frames per Second}]{fpsLabel}{FPS}{Frame per Second}\n\\acrshort{f}")])
- .main("main.tex")
- .line(1)
- .character(11)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_acronyms(&context, &mut actual_items);
-
- assert!(!actual_items.is_empty());
- for item in actual_items {
- assert_eq!(item.range, TextRange::new(87.into(), 88.into()));
- }
- }
-
- #[test]
- fn test_empty() {
- let request = FeatureTester::builder()
- .files(vec![("main.tex", "\\newacronym[longplural={Frames per Second}]{fpsLabel}{FPS}{Frame per Second}\n\\acrshort{}")])
- .main("main.tex")
- .line(1)
- .character(10)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_acronyms(&context, &mut actual_items);
-
- assert!(!actual_items.is_empty());
- for item in actual_items {
- assert_eq!(item.range, TextRange::new(87.into(), 87.into()));
- }
- }
-
- #[test]
- fn test_after_group() {
- let request = FeatureTester::builder()
- .files(vec![("main.tex", "\\newacronym[longplural={Frames per Second}]{fpsLabel}{FPS}{Frame per Second}\n\\acrshort{}")])
- .main("main.tex")
- .line(1)
- .character(11)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_acronyms(&context, &mut actual_items);
-
- assert!(actual_items.is_empty());
- }
-
- #[test]
- fn test_open_brace() {
- let request = FeatureTester::builder()
- .files(vec![("main.tex", "\\newacronym[longplural={Frames per Second}]{fpsLabel}{FPS}{Frame per Second}\n\\acrshort{f")])
- .main("main.tex")
- .line(1)
- .character(11)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_acronyms(&context, &mut actual_items);
-
- assert!(!actual_items.is_empty());
- for item in actual_items {
- assert_eq!(item.range, TextRange::new(87.into(), 88.into()));
- }
- }
-}
diff --git a/support/texlab/src/features/completion/argument.rs b/support/texlab/src/features/completion/argument.rs
index ded16b359e..3ba28f9dea 100644
--- a/support/texlab/src/features/completion/argument.rs
+++ b/support/texlab/src/features/completion/argument.rs
@@ -65,123 +65,3 @@ pub fn complete_arguments<'a>(
Some(())
}
-
-#[cfg(test)]
-mod tests {
- use rowan::TextRange;
-
- use crate::features::testing::FeatureTester;
-
- use super::*;
-
- #[test]
- fn test_empty_latex_document() {
- let request = FeatureTester::builder()
- .files(vec![("main.tex", "")])
- .main("main.tex")
- .line(0)
- .character(0)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_arguments(&context, &mut actual_items);
-
- assert!(actual_items.is_empty());
- }
-
- #[test]
- fn test_empty_bibtex_document() {
- let request = FeatureTester::builder()
- .files(vec![("main.bib", "")])
- .main("main.bib")
- .line(0)
- .character(0)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_arguments(&context, &mut actual_items);
-
- assert!(actual_items.is_empty());
- }
-
- #[test]
- fn test_latex_simple() {
- let request = FeatureTester::builder()
- .files(vec![("main.tex", r#"\mathbb{}\usepackage{amsfonts}"#)])
- .main("main.tex")
- .line(0)
- .character(8)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_arguments(&context, &mut actual_items);
-
- assert!(!actual_items.is_empty());
- for item in actual_items {
- assert_eq!(item.range, TextRange::new(8.into(), 8.into()));
- }
- }
-
- #[test]
- fn test_latex_word() {
- let request = FeatureTester::builder()
- .files(vec![("main.tex", r#"\mathbb{foo}\usepackage{amsfonts}"#)])
- .main("main.tex")
- .line(0)
- .character(8)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_arguments(&context, &mut actual_items);
-
- assert!(!actual_items.is_empty());
- for item in actual_items {
- assert_eq!(item.range, TextRange::new(8.into(), 11.into()));
- }
- }
-
- #[test]
- fn test_latex_open_brace() {
- let request = FeatureTester::builder()
- .files(vec![("main.tex", "\\mathbb{ \\usepackage{amsfonts}")])
- .main("main.tex")
- .line(0)
- .character(8)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_arguments(&context, &mut actual_items);
-
- assert!(!actual_items.is_empty());
- for item in actual_items {
- assert_eq!(item.range, TextRange::new(8.into(), 8.into()));
- }
- }
-
- #[test]
- fn test_latex_open_brace_second() {
- let request = FeatureTester::builder()
- .files(vec![("main.tex", "\\mathbb{}{\\usepackage{amsfonts}")])
- .main("main.tex")
- .line(0)
- .character(10)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_arguments(&context, &mut actual_items);
-
- assert!(actual_items.is_empty());
- }
-}
diff --git a/support/texlab/src/features/completion/begin_command.rs b/support/texlab/src/features/completion/begin_command.rs
index b9b4f06117..699b06c067 100644
--- a/support/texlab/src/features/completion/begin_command.rs
+++ b/support/texlab/src/features/completion/begin_command.rs
@@ -16,66 +16,3 @@ pub fn complete_begin_command(
));
Some(())
}
-
-#[cfg(test)]
-mod tests {
- use rowan::TextRange;
-
- use crate::features::testing::FeatureTester;
-
- use super::*;
-
- #[test]
- fn test_empty_latex_document() {
- let request = FeatureTester::builder()
- .files(vec![("main.tex", "")])
- .main("main.tex")
- .line(0)
- .character(0)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_begin_command(&context, &mut actual_items);
-
- assert!(actual_items.is_empty());
- }
-
- #[test]
- fn test_empty_bibtex_document() {
- let request = FeatureTester::builder()
- .files(vec![("main.bib", "")])
- .main("main.bib")
- .line(0)
- .character(0)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_begin_command(&context, &mut actual_items);
-
- assert!(actual_items.is_empty());
- }
-
- #[test]
- fn test_latex_simple() {
- let request = FeatureTester::builder()
- .files(vec![("main.tex", "\\")])
- .main("main.tex")
- .line(0)
- .character(1)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_begin_command(&context, &mut actual_items);
-
- assert!(!actual_items.is_empty());
- for item in actual_items {
- assert_eq!(item.range, TextRange::new(1.into(), 1.into()));
- }
- }
-}
diff --git a/support/texlab/src/features/completion/citation.rs b/support/texlab/src/features/completion/citation.rs
index 92b21f0ffc..e6436689d7 100644
--- a/support/texlab/src/features/completion/citation.rs
+++ b/support/texlab/src/features/completion/citation.rs
@@ -42,7 +42,7 @@ pub fn complete_citations<'a>(
.children()
.filter_map(bibtex::Entry::cast)
{
- if let Some(item) = make_item(document, entry, range) {
+ if let Some(item) = make_item(document, &entry, range) {
items.push(item);
}
}
@@ -61,7 +61,9 @@ fn check_citation(context: &CursorContext<CompletionParams>) -> Option<()> {
fn check_acronym(context: &CursorContext<CompletionParams>) -> Option<()> {
let token = context.cursor.as_latex()?;
- let pair = token.ancestors().find_map(latex::KeyValuePair::cast)?;
+ let pair = token
+ .parent_ancestors()
+ .find_map(latex::KeyValuePair::cast)?;
if pair.key()?.to_string() != "cite" {
return None;
}
@@ -70,16 +72,18 @@ fn check_acronym(context: &CursorContext<CompletionParams>) -> Option<()> {
Some(())
}
-fn make_item(
- document: &Document,
- entry: bibtex::Entry,
+fn make_item<'a>(
+ document: &'a Document,
+ entry: &bibtex::Entry,
range: TextRange,
-) -> Option<InternalCompletionItem> {
+) -> Option<InternalCompletionItem<'a>> {
let key = entry.name_token()?.to_string();
let ty = LANGUAGE_DATA
.find_entry_type(&entry.type_token()?.text()[1..])
- .map(|ty| Structure::Entry(ty.category))
- .unwrap_or_else(|| Structure::Entry(BibtexEntryTypeCategory::Misc));
+ .map_or_else(
+ || Structure::Entry(BibtexEntryTypeCategory::Misc),
+ |ty| Structure::Entry(ty.category),
+ );
let entry_code = entry.syntax().text().to_string();
let text = format!(
@@ -88,8 +92,8 @@ fn make_item(
WHITESPACE_REGEX
.replace_all(
&entry_code
- .replace('{', "")
- .replace('}', "")
+ .replace('{', " ")
+ .replace('}', " ")
.replace(',', " ")
.replace('=', " "),
" "
@@ -109,188 +113,3 @@ fn make_item(
}
static WHITESPACE_REGEX: Lazy<Regex> = Lazy::new(|| Regex::new("\\s+").unwrap());
-
-#[cfg(test)]
-mod tests {
- use crate::features::testing::FeatureTester;
-
- use super::*;
-
- #[test]
- fn test_empty_latex_document() {
- let request = FeatureTester::builder()
- .files(vec![("main.tex", "")])
- .main("main.tex")
- .line(0)
- .character(0)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_citations(&context, &mut actual_items);
-
- assert!(actual_items.is_empty());
- }
-
- #[test]
- fn test_empty_bibtex_document() {
- let request = FeatureTester::builder()
- .files(vec![("main.bib", "")])
- .main("main.bib")
- .line(0)
- .character(0)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_citations(&context, &mut actual_items);
-
- assert!(actual_items.is_empty());
- }
-
- #[test]
- fn test_latex_simple() {
- let request = FeatureTester::builder()
- .files(vec![
- ("main.tex", "\\addbibresource{main.bib}\n\\cite{}"),
- ("main.bib", "@article{foo,}"),
- ])
- .main("main.tex")
- .line(1)
- .character(6)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_citations(&context, &mut actual_items);
-
- assert!(!actual_items.is_empty());
- for item in actual_items {
- assert_eq!(item.range, TextRange::new(32.into(), 32.into()));
- }
- }
-
- #[test]
- fn test_latex_two_words() {
- let request = FeatureTester::builder()
- .files(vec![
- ("main.tex", "\\addbibresource{main.bib}\n\\cite{foo}"),
- ("main.bib", "@article{foo bar,}"),
- ])
- .main("main.tex")
- .line(1)
- .character(6)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_citations(&context, &mut actual_items);
-
- assert!(!actual_items.is_empty());
- for item in actual_items {
- assert_eq!(item.range, TextRange::new(32.into(), 35.into()));
- }
- }
-
- #[test]
- fn test_latex_open_brace() {
- let request = FeatureTester::builder()
- .files(vec![
- ("main.tex", "\\addbibresource{main.bib}\n\\cite{"),
- ("main.bib", "@article{foo,}"),
- ])
- .main("main.tex")
- .line(1)
- .character(6)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_citations(&context, &mut actual_items);
-
- assert!(!actual_items.is_empty());
- for item in actual_items {
- assert_eq!(item.range, TextRange::new(32.into(), 32.into()));
- }
- }
-
- #[test]
- fn test_latex_open_brace_second() {
- let request = FeatureTester::builder()
- .files(vec![
- ("main.tex", "\\addbibresource{main.bib}\n\\cite{foo,a"),
- ("main.bib", "@article{foo,}"),
- ])
- .main("main.tex")
- .line(1)
- .character(10)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_citations(&context, &mut actual_items);
-
- assert!(!actual_items.is_empty());
- for item in actual_items {
- assert_eq!(item.range, TextRange::new(36.into(), 37.into()));
- }
- }
-
- #[test]
- fn test_latex_acronym() {
- let request = FeatureTester::builder()
- .files(vec![
- (
- "main.tex",
- "\\addbibresource{main.bib}\n\\DeclareAcronym{foo}{cite={\n}}",
- ),
- ("main.bib", "@article{foo,}"),
- ])
- .main("main.tex")
- .line(2)
- .character(0)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_citations(&context, &mut actual_items);
-
- assert!(!actual_items.is_empty());
- for item in actual_items {
- assert_eq!(item.range, TextRange::new(54.into(), 54.into()));
- }
- }
-
- #[test]
- fn test_latex_acronym_two_words() {
- let request = FeatureTester::builder()
- .files(vec![
- (
- "main.tex",
- "\\addbibresource{main.bib}\n\\DeclareAcronym{foo}{cite={\na b}}",
- ),
- ("main.bib", "@article{foo,}"),
- ])
- .main("main.tex")
- .line(2)
- .character(0)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_citations(&context, &mut actual_items);
-
- assert!(!actual_items.is_empty());
- for item in actual_items {
- assert_eq!(item.range, TextRange::new(54.into(), 57.into()));
- }
- }
-}
diff --git a/support/texlab/src/features/completion/color.rs b/support/texlab/src/features/completion/color.rs
index 1d241d2c94..a9a385c3c9 100644
--- a/support/texlab/src/features/completion/color.rs
+++ b/support/texlab/src/features/completion/color.rs
@@ -21,86 +21,3 @@ pub fn complete_colors<'a>(
Some(())
}
-
-#[cfg(test)]
-mod tests {
- use rowan::TextRange;
-
- use crate::features::testing::FeatureTester;
-
- use super::*;
-
- #[test]
- fn test_empty_latex_document() {
- let request = FeatureTester::builder()
- .files(vec![("main.tex", "")])
- .main("main.tex")
- .line(0)
- .character(0)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_colors(&context, &mut actual_items);
-
- assert!(actual_items.is_empty());
- }
-
- #[test]
- fn test_empty_bibtex_document() {
- let request = FeatureTester::builder()
- .files(vec![("main.bib", "")])
- .main("main.bib")
- .line(0)
- .character(0)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_colors(&context, &mut actual_items);
-
- assert!(actual_items.is_empty());
- }
-
- #[test]
- fn test_latex_simple() {
- let request = FeatureTester::builder()
- .files(vec![("main.tex", "\\color{}")])
- .main("main.tex")
- .line(0)
- .character(7)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_colors(&context, &mut actual_items);
-
- assert!(!actual_items.is_empty());
- for item in actual_items {
- assert_eq!(item.range, TextRange::new(7.into(), 7.into()));
- }
- }
-
- #[test]
- fn test_latex_open_brace() {
- let request = FeatureTester::builder()
- .files(vec![("main.tex", "\\color{")])
- .main("main.tex")
- .line(0)
- .character(7)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_colors(&context, &mut actual_items);
-
- assert!(!actual_items.is_empty());
- for item in actual_items {
- assert_eq!(item.range, TextRange::new(7.into(), 7.into()));
- }
- }
-}
diff --git a/support/texlab/src/features/completion/color_model.rs b/support/texlab/src/features/completion/color_model.rs
index 2190b690ad..cd582d0031 100644
--- a/support/texlab/src/features/completion/color_model.rs
+++ b/support/texlab/src/features/completion/color_model.rs
@@ -41,126 +41,3 @@ fn check_color_definition_set(context: &CursorContext<CompletionParams>) -> Opti
.filter(|model| model.syntax().text_range() == group.syntax().text_range())?;
Some(range)
}
-
-#[cfg(test)]
-mod tests {
- use rowan::TextRange;
-
- use crate::features::testing::FeatureTester;
-
- use super::*;
-
- #[test]
- fn test_empty_latex_document() {
- let request = FeatureTester::builder()
- .files(vec![("main.tex", "")])
- .main("main.tex")
- .line(0)
- .character(0)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_color_models(&context, &mut actual_items);
-
- assert!(actual_items.is_empty());
- }
-
- #[test]
- fn test_empty_bibtex_document() {
- let request = FeatureTester::builder()
- .files(vec![("main.bib", "")])
- .main("main.bib")
- .line(0)
- .character(0)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_color_models(&context, &mut actual_items);
-
- assert!(actual_items.is_empty());
- }
-
- #[test]
- fn test_definition_simple() {
- let request = FeatureTester::builder()
- .files(vec![("main.tex", "\\definecolor{foo}{}")])
- .main("main.tex")
- .line(0)
- .character(18)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_color_models(&context, &mut actual_items);
-
- assert!(!actual_items.is_empty());
- for item in actual_items {
- assert_eq!(item.range, TextRange::new(18.into(), 18.into()));
- }
- }
-
- #[test]
- fn test_definition_open_brace() {
- let request = FeatureTester::builder()
- .files(vec![("main.tex", "\\definecolor{foo}{")])
- .main("main.tex")
- .line(0)
- .character(18)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_color_models(&context, &mut actual_items);
-
- assert!(!actual_items.is_empty());
- for item in actual_items {
- assert_eq!(item.range, TextRange::new(18.into(), 18.into()));
- }
- }
-
- #[test]
- fn test_definition_set_simple() {
- let request = FeatureTester::builder()
- .files(vec![("main.tex", "\\definecolorset{}")])
- .main("main.tex")
- .line(0)
- .character(16)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_color_models(&context, &mut actual_items);
-
- assert!(!actual_items.is_empty());
- for item in actual_items {
- assert_eq!(item.range, TextRange::new(16.into(), 16.into()));
- }
- }
-
- #[test]
- fn test_definition_set_open_brace() {
- let request = FeatureTester::builder()
- .files(vec![("main.tex", "\\definecolorset{")])
- .main("main.tex")
- .line(0)
- .character(16)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_color_models(&context, &mut actual_items);
-
- assert!(!actual_items.is_empty());
- for item in actual_items {
- assert_eq!(item.range, TextRange::new(16.into(), 16.into()));
- }
- }
-}
diff --git a/support/texlab/src/features/completion/component_command.rs b/support/texlab/src/features/completion/component_command.rs
index b93a782512..097b28633f 100644
--- a/support/texlab/src/features/completion/component_command.rs
+++ b/support/texlab/src/features/completion/component_command.rs
@@ -26,147 +26,3 @@ pub fn complete_component_commands<'a>(
Some(())
}
-
-#[cfg(test)]
-mod tests {
- use rowan::TextRange;
-
- use crate::features::testing::FeatureTester;
-
- use super::*;
-
- #[test]
- fn test_empty_latex_document() {
- let request = FeatureTester::builder()
- .files(vec![("main.tex", "")])
- .main("main.tex")
- .line(0)
- .character(0)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_component_commands(&context, &mut actual_items);
-
- assert!(actual_items.is_empty());
- }
-
- #[test]
- fn test_empty_bibtex_document() {
- let request = FeatureTester::builder()
- .files(vec![("main.bib", "")])
- .main("main.bib")
- .line(0)
- .character(0)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_component_commands(&context, &mut actual_items);
-
- assert!(actual_items.is_empty());
- }
-
- #[test]
- fn test_latex_simple() {
- let request = FeatureTester::builder()
- .files(vec![("main.tex", "\\")])
- .main("main.tex")
- .line(0)
- .character(1)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_component_commands(&context, &mut actual_items);
-
- assert!(!actual_items.is_empty());
- for item in actual_items {
- assert_eq!(item.range, TextRange::new(1.into(), 1.into()));
- }
- }
-
- #[test]
- fn test_latex_simple_before() {
- let request = FeatureTester::builder()
- .files(vec![("main.tex", "\\")])
- .main("main.tex")
- .line(0)
- .character(0)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_component_commands(&context, &mut actual_items);
-
- assert!(actual_items.is_empty());
- }
-
- #[test]
- fn test_latex_simple_package() {
- let request = FeatureTester::builder()
- .files(vec![("main.tex", "\\\n\\usepackage{lipsum}")])
- .main("main.tex")
- .line(0)
- .character(1)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_component_commands(&context, &mut actual_items);
-
- assert!(!actual_items.is_empty());
- for item in &actual_items {
- assert_eq!(item.range, TextRange::new(1.into(), 1.into()));
- }
-
- assert!(actual_items
- .iter()
- .any(|item| item.data.label() == "lipsum"));
- }
-
- #[test]
- fn test_latex_simple_existing() {
- let request = FeatureTester::builder()
- .files(vec![("main.tex", "\\foo")])
- .main("main.tex")
- .line(0)
- .character(2)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_component_commands(&context, &mut actual_items);
-
- assert!(!actual_items.is_empty());
- for item in actual_items {
- assert_eq!(item.range, TextRange::new(1.into(), 4.into()));
- }
- }
-
- #[test]
- fn test_bibtex_simple() {
- let request = FeatureTester::builder()
- .files(vec![("main.bib", "@a{b,c={\\ }}")])
- .main("main.bib")
- .line(0)
- .character(9)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_component_commands(&context, &mut actual_items);
-
- assert!(!actual_items.is_empty());
- for item in actual_items {
- assert_eq!(item.range, TextRange::new(9.into(), 10.into()));
- }
- }
-}
diff --git a/support/texlab/src/features/completion/component_environment.rs b/support/texlab/src/features/completion/component_environment.rs
index 057e98e491..a9478694bb 100644
--- a/support/texlab/src/features/completion/component_environment.rs
+++ b/support/texlab/src/features/completion/component_environment.rs
@@ -24,150 +24,3 @@ pub fn complete_component_environments<'a>(
Some(())
}
-
-#[cfg(test)]
-mod tests {
- use rowan::TextRange;
-
- use crate::features::testing::FeatureTester;
-
- use super::*;
-
- #[test]
- fn test_empty_latex_document() {
- let request = FeatureTester::builder()
- .files(vec![("main.tex", "")])
- .main("main.tex")
- .line(0)
- .character(0)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_component_environments(&context, &mut actual_items);
-
- assert!(actual_items.is_empty());
- }
-
- #[test]
- fn test_empty_bibtex_document() {
- let request = FeatureTester::builder()
- .files(vec![("main.bib", "")])
- .main("main.bib")
- .line(0)
- .character(0)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_component_environments(&context, &mut actual_items);
-
- assert!(actual_items.is_empty());
- }
-
- #[test]
- fn test_simple() {
- let request = FeatureTester::builder()
- .files(vec![("main.tex", "\\begin{")])
- .main("main.tex")
- .line(0)
- .character(7)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_component_environments(&context, &mut actual_items);
-
- assert!(!actual_items.is_empty());
- for item in actual_items {
- assert_eq!(item.range, TextRange::new(7.into(), 7.into()));
- }
- }
-
- #[test]
- fn test_simple_end() {
- let request = FeatureTester::builder()
- .files(vec![("main.tex", "\\begin{a}\n\\end{")])
- .main("main.tex")
- .line(1)
- .character(5)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_component_environments(&context, &mut actual_items);
-
- assert!(!actual_items.is_empty());
- for item in actual_items {
- assert_eq!(item.range, TextRange::new(15.into(), 15.into()));
- }
- }
-
- #[test]
- fn test_simple_class() {
- let request = FeatureTester::builder()
- .files(vec![("main.tex", "\\begin{}\n\\documentclass{article}")])
- .main("main.tex")
- .line(0)
- .character(7)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_component_environments(&context, &mut actual_items);
-
- assert!(!actual_items.is_empty());
- for item in &actual_items {
- assert_eq!(item.range, TextRange::new(7.into(), 7.into()));
- }
-
- assert!(actual_items
- .iter()
- .any(|item| item.data.label() == "theindex"));
- }
-
- #[test]
- fn test_simple_existing() {
- let request = FeatureTester::builder()
- .files(vec![("main.tex", "\\begin{d}")])
- .main("main.tex")
- .line(0)
- .character(7)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_component_environments(&context, &mut actual_items);
-
- assert!(!actual_items.is_empty());
- for item in actual_items {
- assert_eq!(item.range, TextRange::new(7.into(), 8.into()));
- }
- }
-
- #[test]
- fn test_command_definition() {
- let request = FeatureTester::builder()
- .files(vec![("main.tex", "\\newcommand{\\foo}{\\begin{\nd}")])
- .main("main.tex")
- .line(1)
- .character(1)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_component_environments(&context, &mut actual_items);
-
- assert!(!actual_items.is_empty());
- for item in actual_items {
- assert_eq!(item.range, TextRange::new(26.into(), 27.into()));
- }
- }
-}
diff --git a/support/texlab/src/features/completion/entry_type.rs b/support/texlab/src/features/completion/entry_type.rs
index 06180dd8cc..519737ed08 100644
--- a/support/texlab/src/features/completion/entry_type.rs
+++ b/support/texlab/src/features/completion/entry_type.rs
@@ -13,7 +13,7 @@ pub fn complete_entry_types<'a>(
.cursor
.as_bibtex()
.filter(|token| token.kind() == bibtex::TYPE)
- .map(|token| token.text_range())
+ .map(bibtex::SyntaxToken::text_range)
.filter(|range| range.start() != context.offset)
.map(|range| TextRange::new(range.start() + TextSize::from(1), range.end()))?;
@@ -25,201 +25,3 @@ pub fn complete_entry_types<'a>(
Some(())
}
-
-#[cfg(test)]
-mod tests {
- use crate::features::testing::FeatureTester;
-
- use super::*;
-
- #[test]
- fn test_empty_latex_document() {
- let request = FeatureTester::builder()
- .files(vec![("main.tex", "")])
- .main("main.tex")
- .line(0)
- .character(0)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_entry_types(&context, &mut actual_items);
-
- assert!(actual_items.is_empty());
- }
-
- #[test]
- fn test_empty_bibtex_document() {
- let request = FeatureTester::builder()
- .files(vec![("main.bib", "")])
- .main("main.bib")
- .line(0)
- .character(0)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_entry_types(&context, &mut actual_items);
-
- assert!(actual_items.is_empty());
- }
-
- #[test]
- fn test_at_empty() {
- let request = FeatureTester::builder()
- .files(vec![("main.bib", "@")])
- .main("main.bib")
- .line(0)
- .character(1)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_entry_types(&context, &mut actual_items);
-
- assert!(!actual_items.is_empty());
- for item in actual_items {
- assert_eq!(item.range, TextRange::new(1.into(), 1.into()));
- }
- }
-
- #[test]
- fn test_before_preamble() {
- let request = FeatureTester::builder()
- .files(vec![("main.bib", "@preamble")])
- .main("main.bib")
- .line(0)
- .character(1)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_entry_types(&context, &mut actual_items);
-
- assert!(!actual_items.is_empty());
- for item in actual_items {
- assert_eq!(item.range, TextRange::new(1.into(), 9.into()));
- }
- }
-
- #[test]
- fn test_before_string() {
- let request = FeatureTester::builder()
- .files(vec![("main.bib", "@string")])
- .main("main.bib")
- .line(0)
- .character(1)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_entry_types(&context, &mut actual_items);
-
- assert!(!actual_items.is_empty());
- for item in actual_items {
- assert_eq!(item.range, TextRange::new(1.into(), 7.into()));
- }
- }
-
- #[test]
- fn test_before_article() {
- let request = FeatureTester::builder()
- .files(vec![("main.bib", "@article")])
- .main("main.bib")
- .line(0)
- .character(1)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_entry_types(&context, &mut actual_items);
-
- assert!(!actual_items.is_empty());
- for item in actual_items {
- assert_eq!(item.range, TextRange::new(1.into(), 8.into()));
- }
- }
-
- #[test]
- fn test_after_preamble() {
- let request = FeatureTester::builder()
- .files(vec![("main.bib", "@preamble{")])
- .main("main.bib")
- .line(0)
- .character(9)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_entry_types(&context, &mut actual_items);
-
- assert!(!actual_items.is_empty());
- for item in actual_items {
- assert_eq!(item.range, TextRange::new(1.into(), 9.into()));
- }
- }
-
- #[test]
- fn test_after_string() {
- let request = FeatureTester::builder()
- .files(vec![("main.bib", "@string{")])
- .main("main.bib")
- .line(0)
- .character(7)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_entry_types(&context, &mut actual_items);
-
- assert!(!actual_items.is_empty());
- for item in actual_items {
- assert_eq!(item.range, TextRange::new(1.into(), 7.into()));
- }
- }
-
- #[test]
- fn test_complete_entry() {
- let request = FeatureTester::builder()
- .files(vec![("main.bib", "@article{foo, author = {foo}}")])
- .main("main.bib")
- .line(0)
- .character(3)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_entry_types(&context, &mut actual_items);
-
- assert!(!actual_items.is_empty());
- for item in actual_items {
- assert_eq!(item.range, TextRange::new(1.into(), 8.into()));
- }
- }
-
- #[test]
- fn test_complete_entry_field() {
- let request = FeatureTester::builder()
- .files(vec![("main.bib", "@article{foo, author = {foo}}")])
- .main("main.bib")
- .line(0)
- .character(17)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_entry_types(&context, &mut actual_items);
-
- assert!(actual_items.is_empty());
- }
-}
diff --git a/support/texlab/src/features/completion/field.rs b/support/texlab/src/features/completion/field.rs
index 051b8d69b5..4f386ed1b1 100644
--- a/support/texlab/src/features/completion/field.rs
+++ b/support/texlab/src/features/completion/field.rs
@@ -37,161 +37,3 @@ pub fn complete_fields<'a>(
}
Some(())
}
-
-#[cfg(test)]
-mod tests {
- use crate::features::testing::FeatureTester;
-
- use super::*;
-
- #[test]
- fn test_empty_latex_document() {
- let request = FeatureTester::builder()
- .files(vec![("main.tex", "")])
- .main("main.tex")
- .line(0)
- .character(0)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_fields(&context, &mut actual_items);
-
- assert!(actual_items.is_empty());
- }
-
- #[test]
- fn test_empty_bibtex_document() {
- let request = FeatureTester::builder()
- .files(vec![("main.bib", "")])
- .main("main.bib")
- .line(0)
- .character(0)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_fields(&context, &mut actual_items);
-
- assert!(actual_items.is_empty());
- }
-
- #[test]
- fn test_empty_entry_open() {
- let request = FeatureTester::builder()
- .files(vec![("main.bib", "@article{foo,")])
- .main("main.bib")
- .line(0)
- .character(13)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_fields(&context, &mut actual_items);
-
- assert!(!actual_items.is_empty());
- for item in actual_items {
- assert_eq!(item.range, TextRange::new(13.into(), 13.into()));
- }
- }
-
- #[test]
- fn test_empty_entry_closed() {
- let request = FeatureTester::builder()
- .files(vec![("main.bib", "@article{foo,}")])
- .main("main.bib")
- .line(0)
- .character(13)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_fields(&context, &mut actual_items);
-
- assert!(!actual_items.is_empty());
- for item in actual_items {
- assert_eq!(item.range, TextRange::new(13.into(), 13.into()));
- }
- }
-
- #[test]
- fn test_entry_field_name() {
- let request = FeatureTester::builder()
- .files(vec![("main.bib", "@article{foo, a")])
- .main("main.bib")
- .line(0)
- .character(15)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_fields(&context, &mut actual_items);
-
- assert!(!actual_items.is_empty());
- for item in actual_items {
- assert_eq!(item.range, TextRange::new(14.into(), 15.into()));
- }
- }
-
- #[test]
- fn test_entry_field_value() {
- let request = FeatureTester::builder()
- .files(vec![("main.bib", "@article{foo, author = bar}")])
- .main("main.bib")
- .line(0)
- .character(24)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_fields(&context, &mut actual_items);
-
- assert!(actual_items.is_empty());
- }
-
- #[test]
- fn test_entry_two_fields_name_closed() {
- let request = FeatureTester::builder()
- .files(vec![("main.bib", "@article{foo, author = bar, baz}")])
- .main("main.bib")
- .line(0)
- .character(29)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_fields(&context, &mut actual_items);
-
- assert!(!actual_items.is_empty());
- for item in actual_items {
- assert_eq!(item.range, TextRange::new(28.into(), 31.into()));
- }
- }
-
- #[test]
- fn test_entry_two_fields_name_open() {
- let request = FeatureTester::builder()
- .files(vec![("main.bib", "@article{foo, author = bar, baz")])
- .main("main.bib")
- .line(0)
- .character(29)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_fields(&context, &mut actual_items);
-
- assert!(!actual_items.is_empty());
- for item in actual_items {
- assert_eq!(item.range, TextRange::new(28.into(), 31.into()));
- }
- }
-}
diff --git a/support/texlab/src/features/completion/glossary_ref.rs b/support/texlab/src/features/completion/glossary_ref.rs
index 6805108f16..6223079fdf 100644
--- a/support/texlab/src/features/completion/glossary_ref.rs
+++ b/support/texlab/src/features/completion/glossary_ref.rs
@@ -40,86 +40,3 @@ pub fn complete_glossary_entries<'a>(
Some(())
}
-
-#[cfg(test)]
-mod tests {
- use rowan::TextRange;
-
- use crate::features::testing::FeatureTester;
-
- use super::*;
-
- #[test]
- fn test_empty_latex_document() {
- let request = FeatureTester::builder()
- .files(vec![("main.tex", "")])
- .main("main.tex")
- .line(0)
- .character(0)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_glossary_entries(&context, &mut actual_items);
-
- assert!(actual_items.is_empty());
- }
-
- #[test]
- fn test_empty_bibtex_document() {
- let request = FeatureTester::builder()
- .files(vec![("main.bib", "")])
- .main("main.bib")
- .line(0)
- .character(0)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_glossary_entries(&context, &mut actual_items);
-
- assert!(actual_items.is_empty());
- }
-
- #[test]
- fn test_simple() {
- let request = FeatureTester::builder()
- .files(vec![("main.tex", "\\newacronym[longplural={Frames per Second}]{fpsLabel}{FPS}{Frame per Second}\n\\gls{f}")])
- .main("main.tex")
- .line(1)
- .character(6)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_glossary_entries(&context, &mut actual_items);
-
- assert!(!actual_items.is_empty());
- for item in actual_items {
- assert_eq!(item.range, TextRange::new(82.into(), 83.into()));
- }
- }
-
- #[test]
- fn test_open_brace() {
- let request = FeatureTester::builder()
- .files(vec![("main.tex", "\\newacronym[longplural={Frames per Second}]{fpsLabel}{FPS}{Frame per Second}\n\\gls{f")])
- .main("main.tex")
- .line(1)
- .character(6)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_glossary_entries(&context, &mut actual_items);
-
- assert!(!actual_items.is_empty());
- for item in actual_items {
- assert_eq!(item.range, TextRange::new(82.into(), 83.into()));
- }
- }
-}
diff --git a/support/texlab/src/features/completion/import.rs b/support/texlab/src/features/completion/import.rs
index 6e3a8deeaa..9cb35b68a7 100644
--- a/support/texlab/src/features/completion/import.rs
+++ b/support/texlab/src/features/completion/import.rs
@@ -38,8 +38,7 @@ pub fn complete_imports<'a>(
file_names.insert(file_name);
let stem = &file_name[0..file_name.len() - 4];
let data = factory(stem.into());
- let item = InternalCompletionItem::new(range, data);
- items.push(item);
+ items.push(InternalCompletionItem::new(range, data));
}
let resolver = &context.request.workspace.environment.resolver;
@@ -50,132 +49,8 @@ pub fn complete_imports<'a>(
{
let stem = &file_name[0..file_name.len() - 4];
let data = factory(stem.into());
- let item = InternalCompletionItem::new(range, data);
- items.push(item);
+ items.push(InternalCompletionItem::new(range, data));
}
Some(())
}
-
-#[cfg(test)]
-mod tests {
- use rowan::TextRange;
-
- use crate::features::testing::FeatureTester;
-
- use super::*;
-
- #[test]
- fn test_empty_latex_document() {
- let request = FeatureTester::builder()
- .files(vec![("main.tex", "")])
- .main("main.tex")
- .line(0)
- .character(0)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_imports(&context, &mut actual_items);
-
- assert!(actual_items.is_empty());
- }
-
- #[test]
- fn test_empty_bibtex_document() {
- let request = FeatureTester::builder()
- .files(vec![("main.bib", "")])
- .main("main.bib")
- .line(0)
- .character(0)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_imports(&context, &mut actual_items);
-
- assert!(actual_items.is_empty());
- }
-
- #[test]
- fn test_latex_simple_package() {
- let request = FeatureTester::builder()
- .files(vec![("main.tex", "\\usepackage{}")])
- .main("main.tex")
- .line(0)
- .character(12)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_imports(&context, &mut actual_items);
-
- assert!(!actual_items.is_empty());
- for item in actual_items {
- assert_eq!(item.range, TextRange::new(12.into(), 12.into()));
- }
- }
-
- #[test]
- fn test_latex_open_brace_package() {
- let request = FeatureTester::builder()
- .files(vec![("main.tex", "\\usepackage{ \\foo")])
- .main("main.tex")
- .line(0)
- .character(12)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_imports(&context, &mut actual_items);
-
- assert!(!actual_items.is_empty());
- for item in actual_items {
- assert_eq!(item.range, TextRange::new(12.into(), 12.into()));
- }
- }
-
- #[test]
- fn test_latex_simple_class() {
- let request = FeatureTester::builder()
- .files(vec![("main.tex", "\\documentclass{}")])
- .main("main.tex")
- .line(0)
- .character(15)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_imports(&context, &mut actual_items);
-
- assert!(!actual_items.is_empty());
- for item in actual_items {
- assert_eq!(item.range, TextRange::new(15.into(), 15.into()));
- }
- }
-
- #[test]
- fn test_latex_open_brace_class() {
- let request = FeatureTester::builder()
- .files(vec![("main.tex", "\\documentclass{ \\foo")])
- .main("main.tex")
- .line(0)
- .character(15)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_imports(&context, &mut actual_items);
-
- assert!(!actual_items.is_empty());
- for item in actual_items {
- assert_eq!(item.range, TextRange::new(15.into(), 15.into()));
- }
- }
-}
diff --git a/support/texlab/src/features/completion/include.rs b/support/texlab/src/features/completion/include.rs
index 7f6767b89f..d851aca820 100644
--- a/support/texlab/src/features/completion/include.rs
+++ b/support/texlab/src/features/completion/include.rs
@@ -101,19 +101,21 @@ fn current_dir(
.options
.root_directory
.as_ref()
- .map(|root_directory| {
- context
- .request
- .workspace
- .environment
- .current_directory
- .join(root_directory)
- })
- .unwrap_or_else(|| {
- let mut path = context.request.main_document().uri.to_file_path().unwrap();
- path.pop();
- path
- });
+ .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('\\', "/"));
if !path_text.is_empty() {
@@ -133,8 +135,8 @@ fn is_included(file: &Path, allowed_extensions: &[&str]) -> bool {
allowed_extensions.is_empty()
|| file
.extension()
- .and_then(|ext| ext.to_str())
- .map(|ext| ext.to_lowercase())
+ .and_then(std::ffi::OsStr::to_str)
+ .map(str::to_lowercase)
.map(|ext| allowed_extensions.contains(&ext.as_str()))
.unwrap_or_default()
}
@@ -142,51 +144,10 @@ fn is_included(file: &Path, allowed_extensions: &[&str]) -> bool {
fn remove_extension(path: &mut PathBuf) {
if let Some(stem) = path
.file_stem()
- .and_then(|stem| stem.to_str())
+ .and_then(std::ffi::OsStr::to_str)
.map(ToOwned::to_owned)
{
path.pop();
path.push(stem);
}
}
-
-#[cfg(test)]
-mod tests {
- use crate::features::testing::FeatureTester;
-
- use super::*;
-
- #[test]
- fn test_empty_latex_document() {
- let request = FeatureTester::builder()
- .files(vec![("main.tex", "")])
- .main("main.tex")
- .line(0)
- .character(0)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_includes(&context, &mut actual_items);
-
- assert!(actual_items.is_empty());
- }
-
- #[test]
- fn test_empty_bibtex_document() {
- let request = FeatureTester::builder()
- .files(vec![("main.bib", "")])
- .main("main.bib")
- .line(0)
- .character(0)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_includes(&context, &mut actual_items);
-
- assert!(actual_items.is_empty());
- }
-}
diff --git a/support/texlab/src/features/completion/label.rs b/support/texlab/src/features/completion/label.rs
index e6c02db565..b662f98c8a 100644
--- a/support/texlab/src/features/completion/label.rs
+++ b/support/texlab/src/features/completion/label.rs
@@ -99,106 +99,3 @@ fn find_reference_range(context: &CursorContext<CompletionParams>) -> Option<(Te
latex::LabelReferenceRange::cast(group.syntax().parent()?)?;
Some((range, false))
}
-
-#[cfg(test)]
-mod tests {
- use rowan::TextRange;
-
- use crate::features::testing::FeatureTester;
-
- use super::*;
-
- #[test]
- fn test_empty_latex_document() {
- let request = FeatureTester::builder()
- .files(vec![("main.tex", "")])
- .main("main.tex")
- .line(0)
- .character(0)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_labels(&context, &mut actual_items);
-
- assert!(actual_items.is_empty());
- }
-
- #[test]
- fn test_empty_bibtex_document() {
- let request = FeatureTester::builder()
- .files(vec![("main.bib", "")])
- .main("main.bib")
- .line(0)
- .character(0)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_labels(&context, &mut actual_items);
-
- assert!(actual_items.is_empty());
- }
-
- #[test]
- fn test_simple() {
- let request = FeatureTester::builder()
- .files(vec![("main.tex", "\\ref{}\\label{foo}")])
- .main("main.tex")
- .line(0)
- .character(5)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_labels(&context, &mut actual_items);
-
- assert!(!actual_items.is_empty());
- for item in actual_items {
- assert_eq!(item.range, TextRange::new(5.into(), 5.into()));
- }
- }
-
- #[test]
- fn test_simple_range() {
- let request = FeatureTester::builder()
- .files(vec![("main.tex", "\\crefrange{\n\\label{foo}")])
- .main("main.tex")
- .line(0)
- .character(11)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_labels(&context, &mut actual_items);
-
- assert!(!actual_items.is_empty());
- for item in actual_items {
- assert_eq!(item.range, TextRange::new(11.into(), 11.into()));
- }
- }
-
- #[test]
- fn test_multi_word() {
- let request = FeatureTester::builder()
- .files(vec![("main.tex", "\\ref{foo}\\label{foo bar}")])
- .main("main.tex")
- .line(0)
- .character(8)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_labels(&context, &mut actual_items);
-
- assert!(!actual_items.is_empty());
- for item in actual_items {
- assert_eq!(item.range, TextRange::new(5.into(), 8.into()));
- }
- }
-}
diff --git a/support/texlab/src/features/completion/theorem.rs b/support/texlab/src/features/completion/theorem.rs
index 0945d1df51..65b511f7ad 100644
--- a/support/texlab/src/features/completion/theorem.rs
+++ b/support/texlab/src/features/completion/theorem.rs
@@ -25,109 +25,3 @@ pub fn complete_theorem_environments<'a>(
Some(())
}
-
-#[cfg(test)]
-mod tests {
- use rowan::TextRange;
-
- use crate::features::testing::FeatureTester;
-
- use super::*;
-
- #[test]
- fn test_empty_latex_document() {
- let request = FeatureTester::builder()
- .files(vec![("main.tex", "")])
- .main("main.tex")
- .line(0)
- .character(0)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_theorem_environments(&context, &mut actual_items);
-
- assert!(actual_items.is_empty());
- }
-
- #[test]
- fn test_empty_bibtex_document() {
- let request = FeatureTester::builder()
- .files(vec![("main.bib", "")])
- .main("main.bib")
- .line(0)
- .character(0)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_theorem_environments(&context, &mut actual_items);
-
- assert!(actual_items.is_empty());
- }
-
- #[test]
- fn test_simple() {
- let request = FeatureTester::builder()
- .files(vec![("main.tex", "\\begin{ \\newtheorem{lemma}{Lemma}")])
- .main("main.tex")
- .line(0)
- .character(7)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_theorem_environments(&context, &mut actual_items);
-
- assert!(!actual_items.is_empty());
- for item in actual_items {
- assert_eq!(item.range, TextRange::new(7.into(), 7.into()));
- }
- }
-
- #[test]
- fn test_simple_end() {
- let request = FeatureTester::builder()
- .files(vec![(
- "main.tex",
- "\\newtheorem{lemma}{Lemma}\\begin{a}\n\\end{",
- )])
- .main("main.tex")
- .line(1)
- .character(5)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_theorem_environments(&context, &mut actual_items);
-
- assert!(!actual_items.is_empty());
- for item in actual_items {
- assert_eq!(item.range, TextRange::new(40.into(), 40.into()));
- }
- }
-
- #[test]
- fn test_simple_existing() {
- let request = FeatureTester::builder()
- .files(vec![("main.tex", "\\begin{d}\\newtheorem{lemma}{Lemma}")])
- .main("main.tex")
- .line(0)
- .character(7)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_theorem_environments(&context, &mut actual_items);
-
- assert!(!actual_items.is_empty());
- for item in actual_items {
- assert_eq!(item.range, TextRange::new(7.into(), 8.into()));
- }
- }
-}
diff --git a/support/texlab/src/features/completion/tikz_library.rs b/support/texlab/src/features/completion/tikz_library.rs
index 62d66782a3..bf15695722 100644
--- a/support/texlab/src/features/completion/tikz_library.rs
+++ b/support/texlab/src/features/completion/tikz_library.rs
@@ -31,126 +31,3 @@ pub fn complete_tikz_libraries<'a>(
Some(())
}
-
-#[cfg(test)]
-mod tests {
- use rowan::TextRange;
-
- use crate::features::testing::FeatureTester;
-
- use super::*;
-
- #[test]
- fn test_empty_latex_document() {
- let request = FeatureTester::builder()
- .files(vec![("main.tex", "")])
- .main("main.tex")
- .line(0)
- .character(0)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_tikz_libraries(&context, &mut actual_items);
-
- assert!(actual_items.is_empty());
- }
-
- #[test]
- fn test_empty_bibtex_document() {
- let request = FeatureTester::builder()
- .files(vec![("main.bib", "")])
- .main("main.bib")
- .line(0)
- .character(0)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_tikz_libraries(&context, &mut actual_items);
-
- assert!(actual_items.is_empty());
- }
-
- #[test]
- fn test_latex_simple_pgf() {
- let request = FeatureTester::builder()
- .files(vec![("main.tex", "\\usepgflibrary{}")])
- .main("main.tex")
- .line(0)
- .character(15)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_tikz_libraries(&context, &mut actual_items);
-
- assert!(!actual_items.is_empty());
- for item in actual_items {
- assert_eq!(item.range, TextRange::new(15.into(), 15.into()));
- }
- }
-
- #[test]
- fn test_latex_open_brace_pgf() {
- let request = FeatureTester::builder()
- .files(vec![("main.tex", "\\usepgflibrary{")])
- .main("main.tex")
- .line(0)
- .character(15)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_tikz_libraries(&context, &mut actual_items);
-
- assert!(!actual_items.is_empty());
- for item in actual_items {
- assert_eq!(item.range, TextRange::new(15.into(), 15.into()));
- }
- }
-
- #[test]
- fn test_latex_simple_tikz() {
- let request = FeatureTester::builder()
- .files(vec![("main.tex", "\\usetikzlibrary{}")])
- .main("main.tex")
- .line(0)
- .character(16)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_tikz_libraries(&context, &mut actual_items);
-
- assert!(!actual_items.is_empty());
- for item in actual_items {
- assert_eq!(item.range, TextRange::new(16.into(), 16.into()));
- }
- }
-
- #[test]
- fn test_latex_open_brace_tikz() {
- let request = FeatureTester::builder()
- .files(vec![("main.tex", "\\usetikzlibrary{")])
- .main("main.tex")
- .line(0)
- .character(16)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_tikz_libraries(&context, &mut actual_items);
-
- assert!(!actual_items.is_empty());
- for item in actual_items {
- assert_eq!(item.range, TextRange::new(16.into(), 16.into()));
- }
- }
-}
diff --git a/support/texlab/src/features/completion/user_command.rs b/support/texlab/src/features/completion/user_command.rs
index 8355025098..8c4d593bee 100644
--- a/support/texlab/src/features/completion/user_command.rs
+++ b/support/texlab/src/features/completion/user_command.rs
@@ -30,66 +30,3 @@ pub fn complete_user_commands<'a>(
Some(())
}
-
-#[cfg(test)]
-mod tests {
- use rowan::TextRange;
-
- use crate::features::testing::FeatureTester;
-
- use super::*;
-
- #[test]
- fn test_empty_latex_document() {
- let request = FeatureTester::builder()
- .files(vec![("main.tex", "")])
- .main("main.tex")
- .line(0)
- .character(0)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_user_commands(&context, &mut actual_items);
-
- assert!(actual_items.is_empty());
- }
-
- #[test]
- fn test_empty_bibtex_document() {
- let request = FeatureTester::builder()
- .files(vec![("main.bib", "")])
- .main("main.bib")
- .line(0)
- .character(0)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_user_commands(&context, &mut actual_items);
-
- assert!(actual_items.is_empty());
- }
-
- #[test]
- fn test_latex_simple() {
- let request = FeatureTester::builder()
- .files(vec![("main.tex", "\\foo\\bar")])
- .main("main.tex")
- .line(0)
- .character(4)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_user_commands(&context, &mut actual_items);
-
- assert_eq!(actual_items.len(), 1);
- for item in actual_items {
- assert_eq!(item.range, TextRange::new(1.into(), 4.into()));
- }
- }
-}
diff --git a/support/texlab/src/features/completion/user_environment.rs b/support/texlab/src/features/completion/user_environment.rs
index 3db135865e..91dd5a9ea2 100644
--- a/support/texlab/src/features/completion/user_environment.rs
+++ b/support/texlab/src/features/completion/user_environment.rs
@@ -29,69 +29,3 @@ pub fn complete_user_environments<'a>(
Some(())
}
-
-#[cfg(test)]
-mod tests {
- use rowan::TextRange;
-
- use crate::features::testing::FeatureTester;
-
- use super::*;
-
- #[test]
- fn test_empty_latex_document() {
- let request = FeatureTester::builder()
- .files(vec![("main.tex", "")])
- .main("main.tex")
- .line(0)
- .character(0)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_user_environments(&context, &mut actual_items);
-
- assert!(actual_items.is_empty());
- }
-
- #[test]
- fn test_empty_bibtex_document() {
- let request = FeatureTester::builder()
- .files(vec![("main.bib", "")])
- .main("main.bib")
- .line(0)
- .character(0)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_user_environments(&context, &mut actual_items);
-
- assert!(actual_items.is_empty());
- }
-
- #[test]
- fn test_latex_simple() {
- let request = FeatureTester::builder()
- .files(vec![(
- "main.tex",
- "\\begin{foo}\\end{foo} \\begin{bar}\\end{bar}",
- )])
- .main("main.tex")
- .line(0)
- .character(7)
- .build()
- .completion();
-
- let context = CursorContext::new(request);
- let mut actual_items = Vec::new();
- complete_user_environments(&context, &mut actual_items);
-
- assert_eq!(actual_items.len(), 1);
- for item in actual_items {
- assert_eq!(item.range, TextRange::new(7.into(), 10.into()));
- }
- }
-}
diff --git a/support/texlab/src/features/definition.rs b/support/texlab/src/features/definition.rs
index b54a2be9f0..20da72a142 100644
--- a/support/texlab/src/features/definition.rs
+++ b/support/texlab/src/features/definition.rs
@@ -4,7 +4,12 @@ mod entry;
mod label;
mod string;
-use lsp_types::{GotoDefinitionParams, GotoDefinitionResponse};
+use std::sync::Arc;
+
+use lsp_types::{GotoDefinitionParams, GotoDefinitionResponse, LocationLink, Url};
+use rowan::TextRange;
+
+use crate::LineIndexExt;
use self::{
command::goto_command_definition, document::goto_document_definition,
@@ -18,10 +23,46 @@ pub fn goto_definition(
) -> Option<GotoDefinitionResponse> {
let context = CursorContext::new(request);
log::debug!("[Definition] Cursor: {:?}", context.cursor);
- let links = goto_command_definition(&context)
+
+ 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))?;
+ .or_else(|| goto_string_definition(&context))?
+ .into_iter()
+ .map(|result| {
+ let origin_selection_range = Some(
+ origin_document
+ .line_index
+ .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);
+
+ LocationLink {
+ origin_selection_range,
+ target_uri,
+ target_range,
+ target_selection_range,
+ }
+ })
+ .collect();
+
Some(GotoDefinitionResponse::Link(links))
}
+
+#[derive(Debug, Clone)]
+struct DefinitionResult {
+ origin_selection_range: TextRange,
+ target_uri: Arc<Url>,
+ 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 72cd4b5909..599c792dfd 100644
--- a/support/texlab/src/features/definition/command.rs
+++ b/support/texlab/src/features/definition/command.rs
@@ -1,123 +1,47 @@
-use lsp_types::{GotoDefinitionParams, LocationLink};
+use std::sync::Arc;
+
+use lsp_types::GotoDefinitionParams;
use rowan::ast::AstNode;
-use crate::{features::cursor::CursorContext, syntax::latex, LineIndexExt};
+use crate::{features::cursor::CursorContext, syntax::latex};
-pub fn goto_command_definition(
- context: &CursorContext<GotoDefinitionParams>,
-) -> Option<Vec<LocationLink>> {
- let main_document = context.request.main_document();
+use super::DefinitionResult;
+pub(super) fn goto_command_definition(
+ context: &CursorContext<GotoDefinitionParams>,
+) -> Option<Vec<DefinitionResult>> {
let name = context
.cursor
.as_latex()
.filter(|token| token.kind().is_command_name())?;
- let origin_selection_range = main_document
- .line_index
- .line_col_lsp_range(name.text_range());
+ 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() {
- for node in latex::SyntaxNode::new_root(data.green.clone()).descendants() {
- if let Some(defintion) = latex::CommandDefinition::cast(node).filter(|def| {
+ let root = latex::SyntaxNode::new_root(data.green.clone());
+
+ if let Some(result) = root
+ .descendants()
+ .filter_map(latex::CommandDefinition::cast)
+ .filter(|def| {
def.name()
.and_then(|name| name.command())
.map_or(false, |node| node.text() == name.text())
- }) {
- let target_selection_range = document
- .line_index
- .line_col_lsp_range(defintion.name()?.command()?.text_range());
-
- let target_range = document
- .line_index
- .line_col_lsp_range(latex::small_range(&defintion));
-
- return Some(vec![LocationLink {
- origin_selection_range: Some(origin_selection_range),
- target_uri: document.uri.as_ref().clone(),
- target_range,
- target_selection_range,
- }]);
- }
+ })
+ .find_map(|def| {
+ Some(DefinitionResult {
+ origin_selection_range,
+ target_uri: Arc::clone(&document.uri),
+ target_range: latex::small_range(&def),
+ target_selection_range: def.name()?.command()?.text_range(),
+ })
+ })
+ {
+ return Some(vec![result]);
}
}
}
None
}
-
-#[cfg(test)]
-mod tests {
- use indoc::indoc;
- use lsp_types::Range;
-
- use crate::{features::testing::FeatureTester, RangeExt};
-
- use super::*;
-
- #[test]
- fn test_empty_latex_document() {
- let request = FeatureTester::builder()
- .files(vec![("main.tex", "")])
- .main("main.tex")
- .line(0)
- .character(0)
- .build()
- .definition();
-
- let context = CursorContext::new(request);
-
- let actual_links = goto_command_definition(&context);
-
- assert!(actual_links.is_none());
- }
-
- #[test]
- fn test_empty_bibtex_document() {
- let request = FeatureTester::builder()
- .files(vec![("main.bib", "")])
- .main("main.bib")
- .line(0)
- .character(0)
- .build()
- .definition();
-
- let context = CursorContext::new(request);
- let actual_links = goto_command_definition(&context);
-
- assert!(actual_links.is_none());
- }
-
- #[test]
- fn test_command_definition() {
- let tester = FeatureTester::builder()
- .files(vec![(
- "main.tex",
- indoc! {
- r#"
- \DeclareMathOperator{\foo}{foo}
- \foo
- "#
- },
- )])
- .main("main.tex")
- .line(1)
- .character(2)
- .build();
- let target_uri = tester.uri("main.tex").as_ref().clone();
-
- let request = tester.definition();
- let context = CursorContext::new(request);
- let actual_links = goto_command_definition(&context).unwrap();
-
- let expected_links = vec![LocationLink {
- origin_selection_range: Some(Range::new_simple(1, 0, 1, 4)),
- target_uri,
- target_range: Range::new_simple(0, 0, 0, 31),
- target_selection_range: Range::new_simple(0, 21, 0, 25),
- }];
-
- assert_eq!(actual_links, expected_links);
- }
-}
diff --git a/support/texlab/src/features/definition/document.rs b/support/texlab/src/features/definition/document.rs
index 2a93232cd7..1c09bbc88d 100644
--- a/support/texlab/src/features/definition/document.rs
+++ b/support/texlab/src/features/definition/document.rs
@@ -1,108 +1,40 @@
-use lsp_types::{GotoDefinitionParams, LocationLink, Range};
+use std::sync::Arc;
-use crate::{features::cursor::CursorContext, LineIndexExt, RangeExt};
+use lsp_types::GotoDefinitionParams;
+use rowan::TextRange;
-pub fn goto_document_definition(
+use crate::features::cursor::CursorContext;
+
+use super::DefinitionResult;
+
+pub(super) fn goto_document_definition(
context: &CursorContext<GotoDefinitionParams>,
-) -> Option<Vec<LocationLink>> {
- let main_document = context.request.main_document();
- if let Some(data) = main_document.data.as_latex() {
- for include in data
- .extras
- .explicit_links
- .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![LocationLink {
- origin_selection_range: Some(
- main_document
- .line_index
- .line_col_lsp_range(include.stem_range),
- ),
- target_uri: target.as_ref().clone(),
- target_range: Range::new_simple(0, 0, 0, 0),
- target_selection_range: Range::new_simple(0, 0, 0, 0),
- }]);
- }
+) -> Option<Vec<DefinitionResult>> {
+ let data = context.request.main_document().data.as_latex()?;
+
+ for include in data
+ .extras
+ .explicit_links
+ .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),
+ target_range: TextRange::default(),
+ target_selection_range: TextRange::default(),
+ }]);
}
}
}
- None
-}
-
-#[cfg(test)]
-mod tests {
- use lsp_types::Range;
-
- use crate::{features::testing::FeatureTester, RangeExt};
-
- use super::*;
-
- #[test]
- fn test_empty_latex_document() {
- let request = FeatureTester::builder()
- .files(vec![("main.tex", "")])
- .main("main.tex")
- .line(0)
- .character(0)
- .build()
- .definition();
-
- let context = CursorContext::new(request);
- let actual_links = goto_document_definition(&context);
-
- assert!(actual_links.is_none());
- }
-
- #[test]
- fn test_empty_bibtex_document() {
- let request = FeatureTester::builder()
- .files(vec![("main.bib", "")])
- .main("main.bib")
- .line(0)
- .character(0)
- .build()
- .definition();
-
- let context = CursorContext::new(request);
- let actual_links = goto_document_definition(&context);
-
- assert!(actual_links.is_none());
- }
- #[test]
- fn test_simple() {
- let tester = FeatureTester::builder()
- .files(vec![
- ("foo.tex", r#"\addbibresource{baz.bib}"#),
- ("bar.bib", r#"@article{foo, bar = {baz}}"#),
- ("baz.bib", r#"@article{foo, bar = {baz}}"#),
- ])
- .main("foo.tex")
- .line(0)
- .character(18)
- .build();
- let target_uri = tester.uri("baz.bib").as_ref().clone();
-
- let request = tester.definition();
- let context = CursorContext::new(request);
- let actual_links = goto_document_definition(&context).unwrap();
-
- let expected_links = vec![LocationLink {
- origin_selection_range: Some(Range::new_simple(0, 16, 0, 23)),
- target_uri,
- target_range: Range::new_simple(0, 0, 0, 0),
- target_selection_range: Range::new_simple(0, 0, 0, 0),
- }];
-
- assert_eq!(actual_links, expected_links);
- }
+ None
}
diff --git a/support/texlab/src/features/definition/entry.rs b/support/texlab/src/features/definition/entry.rs
index a1ae28705d..1dcd983af1 100644
--- a/support/texlab/src/features/definition/entry.rs
+++ b/support/texlab/src/features/definition/entry.rs
@@ -1,4 +1,6 @@
-use lsp_types::{GotoDefinitionParams, LocationLink};
+use std::sync::Arc;
+
+use lsp_types::GotoDefinitionParams;
use rowan::ast::AstNode;
use crate::{
@@ -7,14 +9,13 @@ use crate::{
bibtex::{self, HasName},
latex,
},
- LineIndexExt,
};
-pub fn goto_entry_definition(
- context: &CursorContext<GotoDefinitionParams>,
-) -> Option<Vec<LocationLink>> {
- let main_document = context.request.main_document();
+use super::DefinitionResult;
+pub(super) fn goto_entry_definition(
+ context: &CursorContext<GotoDefinitionParams>,
+) -> Option<Vec<DefinitionResult>> {
let word = context
.cursor
.as_latex()
@@ -24,9 +25,7 @@ pub fn goto_entry_definition(
latex::Citation::cast(key.syntax().parent()?.parent()?)?;
- let origin_selection_range = main_document
- .line_index
- .line_col_lsp_range(latex::small_range(&key));
+ 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() {
@@ -35,15 +34,11 @@ pub fn goto_entry_definition(
.filter_map(bibtex::Entry::cast)
{
if let Some(key) = entry.name_token().filter(|k| k.text() == word.text()) {
- return Some(vec![LocationLink {
- origin_selection_range: Some(origin_selection_range),
- target_uri: document.uri.as_ref().clone(),
- target_selection_range: document
- .line_index
- .line_col_lsp_range(key.text_range()),
- target_range: document
- .line_index
- .line_col_lsp_range(entry.syntax().text_range()),
+ return Some(vec![DefinitionResult {
+ origin_selection_range,
+ target_uri: Arc::clone(&document.uri),
+ target_selection_range: key.text_range(),
+ target_range: entry.syntax().text_range(),
}]);
}
}
@@ -52,81 +47,3 @@ pub fn goto_entry_definition(
None
}
-
-#[cfg(test)]
-mod tests {
- use indoc::indoc;
- use lsp_types::Range;
-
- use crate::{features::testing::FeatureTester, RangeExt};
-
- use super::*;
-
- #[test]
- fn test_empty_latex_document() {
- let request = FeatureTester::builder()
- .files(vec![("main.tex", "")])
- .main("main.tex")
- .line(0)
- .character(0)
- .build()
- .definition();
-
- let context = CursorContext::new(request);
- let actual_links = goto_entry_definition(&context);
-
- assert!(actual_links.is_none());
- }
-
- #[test]
- fn test_empty_bibtex_document() {
- let request = FeatureTester::builder()
- .files(vec![("main.bib", "")])
- .main("main.bib")
- .line(0)
- .character(0)
- .build()
- .definition();
-
- let context = CursorContext::new(request);
- let actual_links = goto_entry_definition(&context);
-
- assert!(actual_links.is_none());
- }
-
- #[test]
- fn test_simple() {
- let tester = FeatureTester::builder()
- .files(vec![
- (
- "foo.tex",
- indoc!(
- r#"
- \addbibresource{baz.bib}
- \cite{foo}
- "#
- ),
- ),
- ("bar.bib", r#"@article{foo, bar = {baz}}"#),
- ("baz.bib", r#"@article{foo, bar = {baz}}"#),
- ])
- .main("foo.tex")
- .line(1)
- .character(6)
- .build();
- let target_uri = tester.uri("baz.bib").as_ref().clone();
-
- let request = tester.definition();
- let context = CursorContext::new(request);
- let actual_links = goto_entry_definition(&context).unwrap();
-
- let expected_links = vec![LocationLink {
- origin_selection_range: Some(Range::new_simple(1, 6, 1, 9)),
- target_uri,
- target_range: Range::new_simple(0, 0, 0, 26),
- target_selection_range: Range::new_simple(0, 9, 0, 12),
- }];
-
- assert_eq!(actual_links, expected_links);
- }
-}
diff --git a/support/texlab/src/features/definition/label.rs b/support/texlab/src/features/definition/label.rs
index e5ccd49937..867e8a1076 100644
--- a/support/texlab/src/features/definition/label.rs
+++ b/support/texlab/src/features/definition/label.rs
@@ -1,39 +1,33 @@
-use lsp_types::{GotoDefinitionParams, LocationLink};
+use std::sync::Arc;
-use crate::{
- features::cursor::CursorContext, find_label_definition, render_label, syntax::latex,
- LineIndexExt,
-};
+use lsp_types::GotoDefinitionParams;
-pub fn goto_label_definition(
- context: &CursorContext<GotoDefinitionParams>,
-) -> Option<Vec<LocationLink>> {
- let main_document = context.request.main_document();
+use crate::{features::cursor::CursorContext, find_label_definition, render_label, syntax::latex};
+
+use super::DefinitionResult;
- let (name_text, name_range) = context
+pub(super) fn goto_label_definition(
+ context: &CursorContext<GotoDefinitionParams>,
+) -> Option<Vec<DefinitionResult>> {
+ let (name_text, origin_selection_range) = context
.find_label_name_key()
.or_else(|| context.find_label_name_command())?;
- let origin_selection_range = main_document.line_index.line_col_lsp_range(name_range);
-
for document in context.request.workspace.documents_by_uri.values() {
if let Some(data) = document.data.as_latex() {
- if let Some(definition) =
- find_label_definition(&latex::SyntaxNode::new_root(data.green.clone()), &name_text)
- {
+ 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);
- return Some(vec![LocationLink {
- origin_selection_range: Some(origin_selection_range),
- target_uri: document.uri.as_ref().clone(),
- target_range: document.line_index.line_col_lsp_range(target_range),
- target_selection_range: document
- .line_index
- .line_col_lsp_range(target_selection_range),
+ return Some(vec![DefinitionResult {
+ origin_selection_range,
+ target_uri: Arc::clone(&document.uri),
+ target_range,
+ target_selection_range,
}]);
}
}
@@ -41,42 +35,3 @@ pub fn goto_label_definition(
None
}
-
-#[cfg(test)]
-mod tests {
- use crate::features::testing::FeatureTester;
-
- use super::*;
-
- #[test]
- fn test_empty_latex_document() {
- let request = FeatureTester::builder()
- .files(vec![("main.tex", "")])
- .main("main.tex")
- .line(0)
- .character(0)
- .build()
- .definition();
-
- let context = CursorContext::new(request);
- let actual_links = goto_label_definition(&context);
-
- assert!(actual_links.is_none());
- }
-
- #[test]
- fn test_empty_bibtex_document() {
- let request = FeatureTester::builder()
- .files(vec![("main.bib", "")])
- .main("main.bib")
- .line(0)
- .character(0)
- .build()
- .definition();
-
- let context = CursorContext::new(request);
- let actual_links = goto_label_definition(&context);
-
- assert!(actual_links.is_none());
- }
-}
diff --git a/support/texlab/src/features/definition/string.rs b/support/texlab/src/features/definition/string.rs
index 09e00fdf92..c774e24e1d 100644
--- a/support/texlab/src/features/definition/string.rs
+++ b/support/texlab/src/features/definition/string.rs
@@ -1,15 +1,18 @@
-use lsp_types::{GotoDefinitionParams, LocationLink};
+use std::sync::Arc;
+
+use lsp_types::GotoDefinitionParams;
use rowan::ast::AstNode;
use crate::{
features::cursor::CursorContext,
syntax::bibtex::{self, HasName},
- LineIndexExt,
};
-pub fn goto_string_definition(
+use super::DefinitionResult;
+
+pub(super) fn goto_string_definition(
context: &CursorContext<GotoDefinitionParams>,
-) -> Option<Vec<LocationLink>> {
+) -> Option<Vec<DefinitionResult>> {
let main_document = context.request.main_document();
let data = main_document.data.as_bibtex()?;
@@ -20,157 +23,21 @@ pub fn goto_string_definition(
bibtex::Value::cast(key.parent()?)?;
- let origin_selection_range = main_document
- .line_index
- .line_col_lsp_range(key.text_range());
+ let origin_selection_range = key.text_range();
for string in bibtex::SyntaxNode::new_root(data.green.clone())
.children()
.filter_map(bibtex::StringDef::cast)
{
if let Some(string_name) = string.name_token().filter(|k| k.text() == key.text()) {
- return Some(vec![LocationLink {
- origin_selection_range: Some(origin_selection_range),
- target_uri: main_document.uri.as_ref().clone(),
- target_selection_range: main_document
- .line_index
- .line_col_lsp_range(string_name.text_range()),
- target_range: main_document
- .line_index
- .line_col_lsp_range(string.syntax().text_range()),
+ return Some(vec![DefinitionResult {
+ origin_selection_range,
+ target_uri: Arc::clone(&main_document.uri),
+ target_selection_range: string_name.text_range(),
+ target_range: string.syntax().text_range(),
}]);
}
}
None
}
-
-#[cfg(test)]
-mod tests {
- use indoc::indoc;
- use lsp_types::Range;
-
- use crate::{features::testing::FeatureTester, RangeExt};
-
- use super::*;
-
- #[test]
- fn test_empty_latex_document() {
- let request = FeatureTester::builder()
- .files(vec![("main.tex", "")])
- .main("main.tex")
- .line(0)
- .character(0)
- .build()
- .definition();
-
- let context = CursorContext::new(request);
- let actual_links = goto_string_definition(&context);
-
- assert!(actual_links.is_none());
- }
-
- #[test]
- fn test_empty_bibtex_document() {
- let request = FeatureTester::builder()
- .files(vec![("main.bib", "")])
- .main("main.bib")
- .line(0)
- .character(0)
- .build()
- .definition();
-
- let context = CursorContext::new(request);
- let actual_links = goto_string_definition(&context);
-
- assert!(actual_links.is_none());
- }
-
- #[test]
- fn test_simple() {
- let tester = FeatureTester::builder()
- .files(vec![(
- "main.bib",
- indoc! {
- r#"
- @string{foo = {bar}}
- @article{bar, author = foo}
- "#
- },
- )])
- .main("main.bib")
- .line(1)
- .character(24)
- .build();
- let target_uri = tester.uri("main.bib").as_ref().clone();
-
- let request = tester.definition();
- let context = CursorContext::new(request);
- let actual_links = goto_string_definition(&context).unwrap();
-
- let expected_links = vec![LocationLink {
- origin_selection_range: Some(Range::new_simple(1, 23, 1, 26)),
- target_uri,
- target_range: Range::new_simple(0, 0, 0, 20),
- target_selection_range: Range::new_simple(0, 8, 0, 11),
- }];
-
- assert_eq!(actual_links, expected_links);
- }
-
- #[test]
- fn test_concat() {
- let tester = FeatureTester::builder()
- .files(vec![(
- "main.bib",
- indoc! {
- r#"
- @string{foo = {bar}}
- @article{bar, author = foo # "bar"}
- "#
- },
- )])
- .main("main.bib")
- .line(1)
- .character(24)
- .build();
- let target_uri = tester.uri("main.bib").as_ref().clone();
-
- let request = tester.definition();
- let context = CursorContext::new(request);
- let actual_links = goto_string_definition(&context).unwrap();
-
- let expected_links = vec![LocationLink {
- origin_selection_range: Some(Range::new_simple(1, 23, 1, 26)),
- target_uri,
- target_range: Range::new_simple(0, 0, 0, 20),
- target_selection_range: Range::new_simple(0, 8, 0, 11),
- }];
-
- assert_eq!(actual_links, expected_links);
- }
-
- #[test]
- fn test_field() {
- let tester = FeatureTester::builder()
- .files(vec![(
- "main.bib",
- indoc! {
- r#"
- @string{foo = {bar}}
- @article{bar, author = foo}
- "#
- },
- )])
- .main("main.bib")
- .line(1)
- .character(18)
- .build();
-
- let request = tester.definition();
- let context = CursorContext::new(request);
- let actual_links = goto_string_definition(&context);
-
- assert!(actual_links.is_none());
- }
-}
diff --git a/support/texlab/src/features/execute_command.rs b/support/texlab/src/features/execute_command.rs
new file mode 100644
index 0000000000..b1b89d4f50
--- /dev/null
+++ b/support/texlab/src/features/execute_command.rs
@@ -0,0 +1,103 @@
+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(&params.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 cd1a48f1a8..71fb0bee6f 100644
--- a/support/texlab/src/features/folding.rs
+++ b/support/texlab/src/features/folding.rs
@@ -55,175 +55,3 @@ fn create_range(range: Range) -> FoldingRange {
kind: Some(FoldingRangeKind::Region),
}
}
-
-#[cfg(test)]
-mod tests {
- use indoc::indoc;
-
- use crate::features::testing::FeatureTester;
-
- use super::*;
-
- #[test]
- fn test_empty_latex_document() {
- let request = FeatureTester::builder()
- .files(vec![("main.tex", "")])
- .main("main.tex")
- .build()
- .folding();
-
- let actual_foldings = find_foldings(request);
- assert!(actual_foldings.is_empty());
- }
-
- #[test]
- fn test_empty_bibtex_document() {
- let request = FeatureTester::builder()
- .files(vec![("main.bib", "")])
- .main("main.bib")
- .build()
- .folding();
-
- let actual_foldings = find_foldings(request);
- assert!(actual_foldings.is_empty());
- }
-
- #[test]
- fn test_latex() {
- let req = FeatureTester::builder()
- .files(vec![(
- "main.tex",
- indoc! {r#"
- \begin{document}
- \section{Foo}
- foo
- \subsection{Bar}
- bar
- \section{Baz}
- baz
- \section{Qux}
- \end{document}"# },
- )])
- .main("main.tex")
- .build()
- .folding();
-
- let mut actual_foldings = find_foldings(req);
- actual_foldings.sort_by_key(|folding| (folding.start_line, folding.start_character));
-
- assert_eq!(actual_foldings.len(), 5);
- assert_eq!(
- actual_foldings[0],
- FoldingRange {
- start_line: 0,
- start_character: Some(0),
- end_line: 8,
- end_character: Some(14),
- kind: Some(FoldingRangeKind::Region)
- }
- );
- assert_eq!(
- actual_foldings[1],
- FoldingRange {
- start_line: 1,
- start_character: Some(4),
- end_line: 4,
- end_character: Some(7),
- kind: Some(FoldingRangeKind::Region)
- }
- );
- assert_eq!(
- actual_foldings[2],
- FoldingRange {
- start_line: 3,
- start_character: Some(4),
- end_line: 4,
- end_character: Some(7),
- kind: Some(FoldingRangeKind::Region)
- }
- );
- assert_eq!(
- actual_foldings[3],
- FoldingRange {
- start_line: 5,
- start_character: Some(4),
- end_line: 6,
- end_character: Some(7),
- kind: Some(FoldingRangeKind::Region)
- }
- );
- assert_eq!(
- actual_foldings[4],
- FoldingRange {
- start_line: 7,
- start_character: Some(4),
- end_line: 7,
- end_character: Some(17),
- kind: Some(FoldingRangeKind::Region)
- }
- );
- }
-
- #[test]
- fn test_bibtex() {
- let request = FeatureTester::builder()
- .files(vec![(
- "main.bib",
- indoc! {r#"
- some junk
- here
-
- @article{foo,
- author = {bar},
- title = {baz}
- }
-
- @string{foo = "bar"}
-
- @comment{foo,
- author = {bar},
- title = {baz}
- }
-
- @preamble{"foo"}"# },
- )])
- .main("main.bib")
- .build()
- .folding();
-
- let mut actual_foldings = find_foldings(request);
- actual_foldings.sort_by_key(|folding| (folding.start_line, folding.start_character));
-
- assert_eq!(actual_foldings.len(), 3);
- assert_eq!(
- actual_foldings[0],
- FoldingRange {
- start_line: 3,
- start_character: Some(0),
- end_line: 6,
- end_character: Some(1),
- kind: Some(FoldingRangeKind::Region)
- }
- );
- assert_eq!(
- actual_foldings[1],
- FoldingRange {
- start_line: 8,
- start_character: Some(0),
- end_line: 8,
- end_character: Some(20),
- kind: Some(FoldingRangeKind::Region)
- }
- );
- assert_eq!(
- actual_foldings[2],
- FoldingRange {
- start_line: 15,
- start_character: Some(0),
- end_line: 15,
- end_character: Some(16),
- kind: Some(FoldingRangeKind::Region)
- }
- );
- }
-}
diff --git a/support/texlab/src/features/formatting/bibtex_internal.rs b/support/texlab/src/features/formatting/bibtex_internal.rs
index 58aaf0635d..2dcc507be9 100644
--- a/support/texlab/src/features/formatting/bibtex_internal.rs
+++ b/support/texlab/src/features/formatting/bibtex_internal.rs
@@ -213,137 +213,3 @@ impl<'a> Formatter<'a> {
}
}
}
-
-#[cfg(test)]
-mod tests {
- use insta::{assert_debug_snapshot, assert_display_snapshot};
-
- use crate::features::testing::FeatureTester;
-
- use super::*;
-
- #[test]
- fn test_wrap_long_lines() {
- let request = FeatureTester::builder()
- .files(vec![(
- "main.bib",
- "@article{foo, bar = {Lorem ipsum dolor sit amet, consectetur adipiscing elit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Lorem ipsum dolor sit amet, consectetur adipiscing elit.},}",
- )])
- .main("main.bib")
- .build()
- .formatting();
-
- let edit = format_bibtex_internal(&request).unwrap().pop().unwrap();
-
- assert_display_snapshot!(edit.new_text);
- }
-
- #[test]
- fn test_multiple_entries() {
- let request = FeatureTester::builder()
- .files(vec![(
- "main.bib",
- "@article{foo, bar = {Lorem ipsum dolor sit amet, consectetur adipiscing elit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Lorem ipsum dolor sit amet, consectetur adipiscing elit.},}\n\n@article{foo, bar = {Lorem ipsum dolor sit amet, consectetur adipiscing elit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Lorem ipsum dolor sit amet, consectetur adipiscing elit.},}",
- )])
- .main("main.bib")
- .build()
- .formatting();
-
- let mut edits = format_bibtex_internal(&request).unwrap();
- let edit2 = edits.pop().unwrap();
- let edit1 = edits.pop().unwrap();
-
- assert_debug_snapshot!((edit1.new_text, edit2.new_text));
- }
-
- #[test]
- fn test_trailing_comma() {
- let request = FeatureTester::builder()
- .files(vec![("main.bib", "@article{foo, bar = baz}")])
- .main("main.bib")
- .build()
- .formatting();
-
- let edit = format_bibtex_internal(&request).unwrap().pop().unwrap();
-
- assert_display_snapshot!(edit.new_text);
- }
-
- #[test]
- fn test_insert_braces() {
- let request = FeatureTester::builder()
- .files(vec![("main.bib", "@article{foo, bar = baz,")])
- .main("main.bib")
- .build()
- .formatting();
-
- let edit = format_bibtex_internal(&request).unwrap().pop().unwrap();
-
- assert_display_snapshot!(edit.new_text);
- }
-
- #[test]
- fn test_command() {
- let request = FeatureTester::builder()
- .files(vec![("main.bib", "@article{foo, bar = \"\\baz\",}")])
- .main("main.bib")
- .build()
- .formatting();
-
- let edit = format_bibtex_internal(&request).unwrap().pop().unwrap();
-
- assert_display_snapshot!(edit.new_text);
- }
-
- #[test]
- fn test_concatenation() {
- let request = FeatureTester::builder()
- .files(vec![("main.bib", "@article{foo, bar = \"baz\" # \"qux\"}")])
- .main("main.bib")
- .build()
- .formatting();
-
- let edit = format_bibtex_internal(&request).unwrap().pop().unwrap();
-
- assert_display_snapshot!(edit.new_text);
- }
-
- #[test]
- fn test_parens() {
- let request = FeatureTester::builder()
- .files(vec![("main.bib", "@article(foo,)")])
- .main("main.bib")
- .build()
- .formatting();
-
- let edit = format_bibtex_internal(&request).unwrap().pop().unwrap();
-
- assert_display_snapshot!(edit.new_text);
- }
-
- #[test]
- fn test_string() {
- let request = FeatureTester::builder()
- .files(vec![("main.bib", "@string{foo=\"bar\"}")])
- .main("main.bib")
- .build()
- .formatting();
-
- let edit = format_bibtex_internal(&request).unwrap().pop().unwrap();
-
- assert_display_snapshot!(edit.new_text);
- }
-
- #[test]
- fn test_preamble() {
- let request = FeatureTester::builder()
- .files(vec![("main.bib", "@preamble{\n\"foo bar baz\"}")])
- .main("main.bib")
- .build()
- .formatting();
-
- let edit = format_bibtex_internal(&request).unwrap().pop().unwrap();
-
- assert_display_snapshot!(edit.new_text);
- }
-}
diff --git a/support/texlab/src/features/formatting/snapshots/texlab__features__formatting__bibtex_internal__tests__command.snap b/support/texlab/src/features/formatting/snapshots/texlab__features__formatting__bibtex_internal__tests__command.snap
deleted file mode 100644
index 792e7be277..0000000000
--- a/support/texlab/src/features/formatting/snapshots/texlab__features__formatting__bibtex_internal__tests__command.snap
+++ /dev/null
@@ -1,8 +0,0 @@
----
-source: src/features/formatting/bibtex_internal.rs
-expression: edit.new_text
-
----
-@article{foo,
- bar = "\baz",
-}
diff --git a/support/texlab/src/features/formatting/snapshots/texlab__features__formatting__bibtex_internal__tests__concatenation.snap b/support/texlab/src/features/formatting/snapshots/texlab__features__formatting__bibtex_internal__tests__concatenation.snap
deleted file mode 100644
index 8cd51dfa92..0000000000
--- a/support/texlab/src/features/formatting/snapshots/texlab__features__formatting__bibtex_internal__tests__concatenation.snap
+++ /dev/null
@@ -1,8 +0,0 @@
----
-source: src/features/formatting/bibtex_internal.rs
-expression: edit.new_text
-
----
-@article{foo,
- bar = "baz" # "qux",
-}
diff --git a/support/texlab/src/features/formatting/snapshots/texlab__features__formatting__bibtex_internal__tests__insert_braces.snap b/support/texlab/src/features/formatting/snapshots/texlab__features__formatting__bibtex_internal__tests__insert_braces.snap
deleted file mode 100644
index 3be9b15e9d..0000000000
--- a/support/texlab/src/features/formatting/snapshots/texlab__features__formatting__bibtex_internal__tests__insert_braces.snap
+++ /dev/null
@@ -1,8 +0,0 @@
----
-source: src/features/formatting/bibtex_internal.rs
-expression: edit.new_text
-
----
-@article{foo,
- bar = baz,
-}
diff --git a/support/texlab/src/features/formatting/snapshots/texlab__features__formatting__bibtex_internal__tests__multiple_entries.snap b/support/texlab/src/features/formatting/snapshots/texlab__features__formatting__bibtex_internal__tests__multiple_entries.snap
deleted file mode 100644
index 636b4b665c..0000000000
--- a/support/texlab/src/features/formatting/snapshots/texlab__features__formatting__bibtex_internal__tests__multiple_entries.snap
+++ /dev/null
@@ -1,9 +0,0 @@
----
-source: src/features/formatting/bibtex_internal.rs
-expression: "(edit1.new_text, edit2.new_text)"
-
----
-(
- "@article{foo,\n\tbar = {Lorem ipsum dolor sit amet, consectetur adipiscing elit. Lorem ipsum\n\t dolor sit amet, consectetur adipiscing elit. Lorem ipsum dolor sit amet,\n\t consectetur adipiscing elit.},\n}",
- "@article{foo,\n\tbar = {Lorem ipsum dolor sit amet, consectetur adipiscing elit. Lorem ipsum\n\t dolor sit amet, consectetur adipiscing elit. Lorem ipsum dolor sit amet,\n\t consectetur adipiscing elit.},\n}",
-)
diff --git a/support/texlab/src/features/formatting/snapshots/texlab__features__formatting__bibtex_internal__tests__parens.snap b/support/texlab/src/features/formatting/snapshots/texlab__features__formatting__bibtex_internal__tests__parens.snap
deleted file mode 100644
index 5aff28cb5f..0000000000
--- a/support/texlab/src/features/formatting/snapshots/texlab__features__formatting__bibtex_internal__tests__parens.snap
+++ /dev/null
@@ -1,7 +0,0 @@
----
-source: src/features/formatting/bibtex_internal.rs
-expression: edit.new_text
-
----
-@article{foo,
-}
diff --git a/support/texlab/src/features/formatting/snapshots/texlab__features__formatting__bibtex_internal__tests__preamble.snap b/support/texlab/src/features/formatting/snapshots/texlab__features__formatting__bibtex_internal__tests__preamble.snap
deleted file mode 100644
index 663569eb5b..0000000000
--- a/support/texlab/src/features/formatting/snapshots/texlab__features__formatting__bibtex_internal__tests__preamble.snap
+++ /dev/null
@@ -1,6 +0,0 @@
----
-source: src/features/formatting/bibtex_internal.rs
-expression: edit.new_text
-
----
-@preamble{"foo bar baz"}
diff --git a/support/texlab/src/features/formatting/snapshots/texlab__features__formatting__bibtex_internal__tests__string.snap b/support/texlab/src/features/formatting/snapshots/texlab__features__formatting__bibtex_internal__tests__string.snap
deleted file mode 100644
index 6d37a69e8e..0000000000
--- a/support/texlab/src/features/formatting/snapshots/texlab__features__formatting__bibtex_internal__tests__string.snap
+++ /dev/null
@@ -1,6 +0,0 @@
----
-source: src/features/formatting/bibtex_internal.rs
-expression: edit.new_text
-
----
-@string{foo = "bar"}
diff --git a/support/texlab/src/features/formatting/snapshots/texlab__features__formatting__bibtex_internal__tests__trailing_comma.snap b/support/texlab/src/features/formatting/snapshots/texlab__features__formatting__bibtex_internal__tests__trailing_comma.snap
deleted file mode 100644
index 3be9b15e9d..0000000000
--- a/support/texlab/src/features/formatting/snapshots/texlab__features__formatting__bibtex_internal__tests__trailing_comma.snap
+++ /dev/null
@@ -1,8 +0,0 @@
----
-source: src/features/formatting/bibtex_internal.rs
-expression: edit.new_text
-
----
-@article{foo,
- bar = baz,
-}
diff --git a/support/texlab/src/features/formatting/snapshots/texlab__features__formatting__bibtex_internal__tests__wrap_long_lines.snap b/support/texlab/src/features/formatting/snapshots/texlab__features__formatting__bibtex_internal__tests__wrap_long_lines.snap
deleted file mode 100644
index 6c0ec724b5..0000000000
--- a/support/texlab/src/features/formatting/snapshots/texlab__features__formatting__bibtex_internal__tests__wrap_long_lines.snap
+++ /dev/null
@@ -1,10 +0,0 @@
----
-source: src/features/formatting/bibtex_internal.rs
-expression: edit.new_text
-
----
-@article{foo,
- bar = {Lorem ipsum dolor sit amet, consectetur adipiscing elit. Lorem ipsum
- dolor sit amet, consectetur adipiscing elit. Lorem ipsum dolor sit amet,
- consectetur adipiscing elit.},
-}
diff --git a/support/texlab/src/features/highlight/label.rs b/support/texlab/src/features/highlight/label.rs
index 3e8b95eac8..cb51abdd68 100644
--- a/support/texlab/src/features/highlight/label.rs
+++ b/support/texlab/src/features/highlight/label.rs
@@ -77,71 +77,3 @@ pub fn find_label_highlights(
Some(highlights)
}
-
-#[cfg(test)]
-mod tests {
- use lsp_types::Range;
-
- use crate::{features::testing::FeatureTester, RangeExt};
-
- use super::*;
-
- #[test]
- fn test_empty_latex_document() {
- let request = FeatureTester::builder()
- .files(vec![("main.tex", "")])
- .main("main.tex")
- .line(0)
- .character(0)
- .build()
- .highlight();
- let context = CursorContext::new(request);
-
- let actual_links = find_label_highlights(&context);
-
- assert!(actual_links.is_none());
- }
-
- #[test]
- fn test_empty_bibtex_document() {
- let request = FeatureTester::builder()
- .files(vec![("main.bib", "")])
- .main("main.bib")
- .line(0)
- .character(0)
- .build()
- .highlight();
- let context = CursorContext::new(request);
-
- let actual_links = find_label_highlights(&context);
-
- assert!(actual_links.is_none());
- }
-
- #[test]
- fn test_label() {
- let tester = FeatureTester::builder()
- .files(vec![("main.tex", "\\label{foo}\n\\ref{foo}\\label{bar}")])
- .main("main.tex")
- .line(0)
- .character(7)
- .build();
- let request = tester.highlight();
- let context = CursorContext::new(request);
-
- let actual_highlights = find_label_highlights(&context).unwrap();
-
- let expected_highlights = vec![
- DocumentHighlight {
- range: Range::new_simple(0, 7, 0, 10),
- kind: Some(DocumentHighlightKind::WRITE),
- },
- DocumentHighlight {
- range: Range::new_simple(1, 5, 1, 8),
- kind: Some(DocumentHighlightKind::READ),
- },
- ];
-
- assert_eq!(actual_highlights, expected_highlights);
- }
-}
diff --git a/support/texlab/src/features/hover.rs b/support/texlab/src/features/hover.rs
index 7d349de0a3..8663f6256d 100644
--- a/support/texlab/src/features/hover.rs
+++ b/support/texlab/src/features/hover.rs
@@ -5,9 +5,13 @@ mod field;
mod label;
mod string_ref;
-use lsp_types::{Hover, HoverParams};
+use lsp_types::{Hover, HoverContents, HoverParams, MarkupContent, MarkupKind};
+use rowan::TextRange;
-use crate::features::{cursor::CursorContext, hover::citation::find_citation_hover};
+use crate::{
+ features::{cursor::CursorContext, hover::citation::find_citation_hover},
+ LineIndexExt,
+};
use self::{
component::find_component_hover, entry_type::find_entry_type_hover, field::find_field_hover,
@@ -19,10 +23,31 @@ use super::FeatureRequest;
pub fn find_hover(request: FeatureRequest<HoverParams>) -> Option<Hover> {
let context = CursorContext::new(request);
log::debug!("[Hover] Cursor: {:?}", context.cursor);
- find_label_hover(&context)
+ 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))
+ .or_else(|| find_entry_type_hover(&context))?;
+
+ 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),
+ ),
+ })
+}
+
+#[derive(Debug, Clone)]
+struct HoverResult {
+ range: TextRange,
+ value: String,
+ value_kind: MarkupKind,
}
diff --git a/support/texlab/src/features/hover/citation.rs b/support/texlab/src/features/hover/citation.rs
index 4a0e3d2313..5e86019eee 100644
--- a/support/texlab/src/features/hover/citation.rs
+++ b/support/texlab/src/features/hover/citation.rs
@@ -1,121 +1,32 @@
-use lsp_types::{Hover, HoverContents, HoverParams, MarkupContent, MarkupKind};
+use lsp_types::{HoverParams, MarkupKind};
use rowan::ast::AstNode;
-use crate::{citation, features::cursor::CursorContext, syntax::bibtex, LineIndexExt};
+use crate::{citation, features::cursor::CursorContext, syntax::bibtex};
-pub fn find_citation_hover(context: &CursorContext<HoverParams>) -> Option<Hover> {
- let main_document = context.request.main_document();
+use super::HoverResult;
- let (key_text, key_range) = context
+pub(super) fn find_citation_hover(context: &CursorContext<HoverParams>) -> Option<HoverResult> {
+ let (key, range) = context
.find_citation_key_word()
.or_else(|| context.find_citation_key_command())
.or_else(|| context.find_entry_key())?;
- let contents = context
+ let value = context
.request
.workspace
.documents_by_uri
.values()
.find_map(|document| {
- document.data.as_bibtex().and_then(|data| {
- let root = bibtex::SyntaxNode::new_root(data.green.clone());
- let root = bibtex::Root::cast(root)?;
- let entry = root.find_entry(&key_text)?;
-
- citation::render(&entry).map(|value| MarkupContent {
- kind: MarkupKind::Markdown,
- value,
- })
- })
+ 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)
})?;
- Some(Hover {
- range: Some(main_document.line_index.line_col_lsp_range(key_range)),
- contents: HoverContents::Markup(contents),
+ Some(HoverResult {
+ range,
+ value,
+ value_kind: MarkupKind::Markdown,
})
}
-
-#[cfg(test)]
-mod tests {
- use insta::assert_debug_snapshot;
-
- use crate::features::testing::FeatureTester;
-
- use super::*;
-
- #[test]
- fn test_empty_latex_document() {
- let request = FeatureTester::builder()
- .files(vec![("main.tex", "")])
- .main("main.tex")
- .line(0)
- .character(0)
- .build()
- .hover();
-
- let context = CursorContext::new(request);
- let actual_hover = find_citation_hover(&context);
-
- assert_eq!(actual_hover, None);
- }
-
- #[test]
- fn test_empty_bibtex_document() {
- let request = FeatureTester::builder()
- .files(vec![("main.bib", "")])
- .main("main.bib")
- .line(0)
- .character(0)
- .build()
- .hover();
-
- let context = CursorContext::new(request);
- let actual_hover = find_citation_hover(&context);
-
- assert_eq!(actual_hover, None);
- }
-
- #[test]
- fn test_inside_cite() {
- let request = FeatureTester::builder()
- .files(vec![
- (
- "main.bib",
- "@article{foo, author = {Foo Bar}, title = {Baz Qux}, year = 1337}",
- ),
- ("main.tex", "\\addbibresource{main.bib}\n\\cite{foo}"),
- ])
- .main("main.tex")
- .line(1)
- .character(7)
- .build()
- .hover();
-
- let context = CursorContext::new(request);
- let actual_hover = find_citation_hover(&context).unwrap();
-
- assert_debug_snapshot!(actual_hover);
- }
-
- #[test]
- fn test_inside_entry() {
- let request = FeatureTester::builder()
- .files(vec![
- (
- "main.bib",
- "@article{foo, author = {Foo Bar}, title = {Baz Qux}, year = 1337}",
- ),
- ("main.tex", "\\addbibresource{main.bib}\n\\cite{foo}"),
- ])
- .main("main.bib")
- .line(0)
- .character(11)
- .build()
- .hover();
-
- let context = CursorContext::new(request);
- let actual_hover = find_citation_hover(&context).unwrap();
-
- assert_debug_snapshot!(actual_hover);
- }
-}
diff --git a/support/texlab/src/features/hover/component.rs b/support/texlab/src/features/hover/component.rs
index 7b7e6c6e02..737a99d3ea 100644
--- a/support/texlab/src/features/hover/component.rs
+++ b/support/texlab/src/features/hover/component.rs
@@ -1,97 +1,25 @@
-use lsp_types::{Hover, HoverContents, HoverParams};
+use lsp_types::{HoverParams, MarkupKind};
-use crate::{
- component_db::COMPONENT_DATABASE, features::cursor::CursorContext, syntax::latex, LineIndexExt,
-};
+use crate::{component_db::COMPONENT_DATABASE, features::cursor::CursorContext, syntax::latex};
-pub fn find_component_hover(context: &CursorContext<HoverParams>) -> Option<Hover> {
- let main_document = context.request.main_document();
- let data = main_document.data.as_latex()?;
+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 docs = COMPONENT_DATABASE.documentation(&link.stem)?;
- return Some(Hover {
- contents: HoverContents::Markup(docs),
- range: Some(main_document.line_index.line_col_lsp_range(link.stem_range)),
+ let value = COMPONENT_DATABASE.documentation(&link.stem)?.value;
+ return Some(HoverResult {
+ value,
+ value_kind: MarkupKind::PlainText,
+ range: link.stem_range,
});
}
}
- None
-}
-
-#[cfg(test)]
-mod tests {
- use lsp_types::Range;
-
- use crate::{features::testing::FeatureTester, RangeExt};
-
- use super::*;
-
- #[test]
- fn test_empty_latex_document() {
- let request = FeatureTester::builder()
- .files(vec![("main.tex", "")])
- .main("main.tex")
- .line(0)
- .character(0)
- .build()
- .hover();
-
- let context = CursorContext::new(request);
- let actual_hover = find_component_hover(&context);
-
- assert_eq!(actual_hover, None);
- }
-
- #[test]
- fn test_empty_bibtex_document() {
- let request = FeatureTester::builder()
- .files(vec![("main.bib", "")])
- .main("main.bib")
- .line(0)
- .character(0)
- .build()
- .hover();
-
- let context = CursorContext::new(request);
- let actual_hover = find_component_hover(&context);
-
- assert_eq!(actual_hover, None);
- }
- #[test]
- fn test_known_package() {
- let request = FeatureTester::builder()
- .files(vec![("main.tex", r#"\usepackage{amsmath}"#)])
- .main("main.tex")
- .line(0)
- .character(15)
- .build()
- .hover();
-
- let context = CursorContext::new(request);
- let actual_hover = find_component_hover(&context).unwrap();
-
- assert_eq!(actual_hover.range.unwrap(), Range::new_simple(0, 12, 0, 19));
- }
-
- #[test]
- fn test_unknown_class() {
- let request = FeatureTester::builder()
- .files(vec![("main.tex", r#"\documentclass{abcdefghijklmnop}"#)])
- .main("main.tex")
- .line(0)
- .character(20)
- .build()
- .hover();
-
- let context = CursorContext::new(request);
- let actual_hover = find_component_hover(&context);
-
- assert_eq!(actual_hover, None);
- }
+ None
}
diff --git a/support/texlab/src/features/hover/entry_type.rs b/support/texlab/src/features/hover/entry_type.rs
index ab36177ae8..41a561395c 100644
--- a/support/texlab/src/features/hover/entry_type.rs
+++ b/support/texlab/src/features/hover/entry_type.rs
@@ -1,124 +1,19 @@
-use lsp_types::{Hover, HoverContents, HoverParams, MarkupContent};
+use lsp_types::{HoverParams, MarkupKind};
-use crate::{features::cursor::CursorContext, syntax::bibtex, LineIndexExt, LANGUAGE_DATA};
+use crate::{features::cursor::CursorContext, syntax::bibtex, LANGUAGE_DATA};
-pub fn find_entry_type_hover(context: &CursorContext<HoverParams>) -> Option<Hover> {
+use super::HoverResult;
+
+pub(super) fn find_entry_type_hover(context: &CursorContext<HoverParams>) -> Option<HoverResult> {
let name = context
.cursor
.as_bibtex()
.filter(|token| token.kind() == bibtex::TYPE)?;
let docs = LANGUAGE_DATA.entry_type_documentation(&name.text()[1..])?;
- Some(Hover {
- contents: HoverContents::Markup(MarkupContent {
- kind: lsp_types::MarkupKind::Markdown,
- value: docs.to_string(),
- }),
- range: Some(
- context
- .request
- .main_document()
- .line_index
- .line_col_lsp_range(name.text_range()),
- ),
+ Some(HoverResult {
+ range: name.text_range(),
+ value: docs.to_string(),
+ value_kind: MarkupKind::Markdown,
})
}
-
-#[cfg(test)]
-mod tests {
- use lsp_types::{MarkupKind, Range};
-
- use crate::{features::testing::FeatureTester, RangeExt};
-
- use super::*;
-
- #[test]
- fn test_empty_latex_document() {
- let request = FeatureTester::builder()
- .files(vec![("main.tex", "")])
- .main("main.tex")
- .line(0)
- .character(0)
- .build()
- .hover();
-
- let context = CursorContext::new(request);
- let actual_hover = find_entry_type_hover(&context);
-
- assert_eq!(actual_hover, None);
- }
-
- #[test]
- fn test_empty_bibtex_document() {
- let request = FeatureTester::builder()
- .files(vec![("main.bib", "")])
- .main("main.bib")
- .line(0)
- .character(0)
- .build()
- .hover();
-
- let context = CursorContext::new(request);
- let actual_hover = find_entry_type_hover(&context);
-
- assert_eq!(actual_hover, None);
- }
-
- #[test]
- fn test_known_entry_type() {
- let request = FeatureTester::builder()
- .files(vec![("main.bib", r#"@article{foo,}"#)])
- .main("main.bib")
- .line(0)
- .character(3)
- .build()
- .hover();
-
- let context = CursorContext::new(request);
- let actual_hover = find_entry_type_hover(&context).unwrap();
-
- let expected_hover = Hover {
- contents: HoverContents::Markup(MarkupContent {
- kind: MarkupKind::Markdown,
- value: LANGUAGE_DATA
- .entry_type_documentation("article")
- .unwrap()
- .into(),
- }),
- range: Some(Range::new_simple(0, 0, 0, 8)),
- };
- assert_eq!(actual_hover, expected_hover);
- }
-
- #[test]
- fn test_unknown_field() {
- let request = FeatureTester::builder()
- .files(vec![("main.bib", r#"@foo{bar,}"#)])
- .main("main.bib")
- .line(0)
- .character(3)
- .build()
- .hover();
-
- let context = CursorContext::new(request);
- let actual_hover = find_entry_type_hover(&context);
-
- assert_eq!(actual_hover, None);
- }
-
- #[test]
- fn test_entry_key() {
- let request = FeatureTester::builder()
- .files(vec![("main.bib", r#"@article{foo,}"#)])
- .main("main.bib")
- .line(0)
- .character(11)
- .build()
- .hover();
-
- let context = CursorContext::new(request);
- let actual_hover = find_entry_type_hover(&context);
-
- assert_eq!(actual_hover, None);
- }
-}
diff --git a/support/texlab/src/features/hover/field.rs b/support/texlab/src/features/hover/field.rs
index daa0c301cd..6102bd6b68 100644
--- a/support/texlab/src/features/hover/field.rs
+++ b/support/texlab/src/features/hover/field.rs
@@ -1,11 +1,11 @@
-use lsp_types::{Hover, HoverContents, HoverParams, MarkupContent};
+use lsp_types::{HoverParams, MarkupKind};
use rowan::ast::AstNode;
-use crate::{features::cursor::CursorContext, syntax::bibtex, LineIndexExt, LANGUAGE_DATA};
+use crate::{features::cursor::CursorContext, syntax::bibtex, LANGUAGE_DATA};
-pub fn find_field_hover(context: &CursorContext<HoverParams>) -> Option<Hover> {
- let main_document = context.request.main_document();
+use super::HoverResult;
+pub(super) fn find_field_hover(context: &CursorContext<HoverParams>) -> Option<HoverResult> {
let name = context
.cursor
.as_bibtex()
@@ -14,108 +14,9 @@ pub fn find_field_hover(context: &CursorContext<HoverParams>) -> Option<Hover> {
bibtex::Field::cast(name.parent()?)?;
let docs = LANGUAGE_DATA.field_documentation(name.text())?;
- Some(Hover {
- contents: HoverContents::Markup(MarkupContent {
- kind: lsp_types::MarkupKind::Markdown,
- value: docs.to_string(),
- }),
- range: Some(
- main_document
- .line_index
- .line_col_lsp_range(name.text_range()),
- ),
+ Some(HoverResult {
+ range: name.text_range(),
+ value: docs.to_string(),
+ value_kind: MarkupKind::Markdown,
})
}
-
-#[cfg(test)]
-mod tests {
- use lsp_types::{MarkupKind, Range};
-
- use crate::{features::testing::FeatureTester, RangeExt};
-
- use super::*;
-
- #[test]
- fn test_empty_latex_document() {
- let request = FeatureTester::builder()
- .files(vec![("main.tex", "")])
- .main("main.tex")
- .line(0)
- .character(0)
- .build()
- .hover();
-
- let context = CursorContext::new(request);
- let actual_hover = find_field_hover(&context);
-
- assert_eq!(actual_hover, None);
- }
-
- #[test]
- fn test_empty_bibtex_document() {
- let request = FeatureTester::builder()
- .files(vec![("main.bib", "")])
- .main("main.bib")
- .line(0)
- .character(0)
- .build()
- .hover();
-
- let context = CursorContext::new(request);
- let actual_hover = find_field_hover(&context);
-
- assert_eq!(actual_hover, None);
- }
-
- #[test]
- fn test_known_field() {
- let request = FeatureTester::builder()
- .files(vec![("main.bib", r#"@article{foo, author = bar}"#)])
- .main("main.bib")
- .line(0)
- .character(15)
- .build()
- .hover();
-
- let context = CursorContext::new(request);
- let actual_hover = find_field_hover(&context).unwrap();
- let expected_hover = Hover {
- contents: HoverContents::Markup(MarkupContent {
- kind: MarkupKind::Markdown,
- value: LANGUAGE_DATA.field_documentation("author").unwrap().into(),
- }),
- range: Some(Range::new_simple(0, 14, 0, 20)),
- };
- assert_eq!(actual_hover, expected_hover);
- }
-
- #[test]
- fn test_unknown_field() {
- let request = FeatureTester::builder()
- .files(vec![("main.bib", r#"@article{foo, bar = baz}"#)])
- .main("main.bib")
- .line(0)
- .character(15)
- .build()
- .hover();
-
- let context = CursorContext::new(request);
- let actual_hover = find_field_hover(&context);
- assert_eq!(actual_hover, None);
- }
-
- #[test]
- fn test_entry_key() {
- let request = FeatureTester::builder()
- .files(vec![("main.bib", r#"@article{foo, author = bar}"#)])
- .main("main.bib")
- .line(0)
- .character(11)
- .build()
- .hover();
-
- let context = CursorContext::new(request);
- let actual_hover = find_field_hover(&context);
- assert_eq!(actual_hover, None);
- }
-}
diff --git a/support/texlab/src/features/hover/label.rs b/support/texlab/src/features/hover/label.rs
index 1018c187c5..2f8489d769 100644
--- a/support/texlab/src/features/hover/label.rs
+++ b/support/texlab/src/features/hover/label.rs
@@ -1,75 +1,19 @@
-use lsp_types::{Hover, HoverContents, HoverParams};
+use lsp_types::{HoverParams, MarkupKind};
-use crate::{features::cursor::CursorContext, render_label, LineIndexExt};
+use crate::{features::cursor::CursorContext, render_label};
-pub fn find_label_hover(context: &CursorContext<HoverParams>) -> Option<Hover> {
- let main_document = context.request.main_document();
+use super::HoverResult;
- let (name_text, name_range) = context
+pub(super) fn find_label_hover(context: &CursorContext<HoverParams>) -> 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(Hover {
- range: Some(main_document.line_index.line_col_lsp_range(name_range)),
- contents: HoverContents::Markup(label.documentation()),
+ Some(HoverResult {
+ range,
+ value: label.reference(),
+ value_kind: MarkupKind::PlainText,
})
}
-
-#[cfg(test)]
-mod tests {
- use lsp_types::Range;
-
- use crate::{features::testing::FeatureTester, RangeExt};
-
- use super::*;
-
- #[test]
- fn test_empty_latex_document() {
- let request = FeatureTester::builder()
- .files(vec![("main.tex", "")])
- .main("main.tex")
- .line(0)
- .character(0)
- .build()
- .hover();
-
- let context = CursorContext::new(request);
- let actual_hover = find_label_hover(&context);
-
- assert_eq!(actual_hover, None);
- }
-
- #[test]
- fn test_empty_bibtex_document() {
- let request = FeatureTester::builder()
- .files(vec![("main.bib", "")])
- .main("main.bib")
- .line(0)
- .character(0)
- .build()
- .hover();
-
- let context = CursorContext::new(request);
- let actual_hover = find_label_hover(&context);
-
- assert_eq!(actual_hover, None);
- }
-
- #[test]
- fn test_section() {
- let request = FeatureTester::builder()
- .files(vec![("main.tex", r#"\section{Foo}\label{sec:foo}"#)])
- .main("main.tex")
- .line(0)
- .character(23)
- .build()
- .hover();
-
- let context = CursorContext::new(request);
- let actual_hover = find_label_hover(&context).unwrap();
-
- assert_eq!(actual_hover.range.unwrap(), Range::new_simple(0, 20, 0, 27));
- }
-}
diff --git a/support/texlab/src/features/hover/snapshots/texlab__features__hover__citation__tests__inside_cite.snap b/support/texlab/src/features/hover/snapshots/texlab__features__hover__citation__tests__inside_cite.snap
deleted file mode 100644
index 2bca88bbff..0000000000
--- a/support/texlab/src/features/hover/snapshots/texlab__features__hover__citation__tests__inside_cite.snap
+++ /dev/null
@@ -1,25 +0,0 @@
----
-source: src/features/hover/citation.rs
-assertion_line: 97
-expression: actual_hover
----
-Hover {
- contents: Markup(
- MarkupContent {
- kind: Markdown,
- value: "F. Bar: \"Baz Qux\". (1337).",
- },
- ),
- range: Some(
- Range {
- start: Position {
- line: 1,
- character: 6,
- },
- end: Position {
- line: 1,
- character: 9,
- },
- },
- ),
-}
diff --git a/support/texlab/src/features/hover/snapshots/texlab__features__hover__citation__tests__inside_entry.snap b/support/texlab/src/features/hover/snapshots/texlab__features__hover__citation__tests__inside_entry.snap
deleted file mode 100644
index 73ac4b7b69..0000000000
--- a/support/texlab/src/features/hover/snapshots/texlab__features__hover__citation__tests__inside_entry.snap
+++ /dev/null
@@ -1,25 +0,0 @@
----
-source: src/features/hover/citation.rs
-assertion_line: 119
-expression: actual_hover
----
-Hover {
- contents: Markup(
- MarkupContent {
- kind: Markdown,
- value: "F. Bar: \"Baz Qux\". (1337).",
- },
- ),
- range: Some(
- Range {
- start: Position {
- line: 0,
- character: 9,
- },
- end: Position {
- line: 0,
- character: 12,
- },
- },
- ),
-}
diff --git a/support/texlab/src/features/hover/string_ref.rs b/support/texlab/src/features/hover/string_ref.rs
index f1df08e8ab..adccdd556c 100644
--- a/support/texlab/src/features/hover/string_ref.rs
+++ b/support/texlab/src/features/hover/string_ref.rs
@@ -1,21 +1,27 @@
-use lsp_types::{Hover, HoverContents, HoverParams, MarkupContent, MarkupKind};
+use lsp_types::{HoverParams, MarkupKind};
use rowan::ast::AstNode;
use crate::{
+ citation::field::text::TextFieldData,
features::cursor::CursorContext,
syntax::bibtex::{self, HasName, HasValue},
- LineIndexExt,
};
-pub fn find_string_reference_hover(context: &CursorContext<HoverParams>) -> Option<Hover> {
- let main_document = context.request.main_document();
- let data = main_document.data.as_bibtex()?;
+use super::HoverResult;
- let key = context.cursor.as_bibtex().filter(|token| {
- let parent = token.parent().unwrap();
- (token.kind() == bibtex::NAME && bibtex::Value::can_cast(parent.kind()))
- || (token.kind() == bibtex::NAME && bibtex::StringDef::can_cast(parent.kind()))
- })?;
+pub(super) fn find_string_reference_hover(
+ context: &CursorContext<HoverParams>,
+) -> Option<HoverResult> {
+ let data = context.request.main_document().data.as_bibtex()?;
+
+ let name = context
+ .cursor
+ .as_bibtex()
+ .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())
.children()
@@ -23,118 +29,16 @@ pub fn find_string_reference_hover(context: &CursorContext<HoverParams>) -> Opti
{
if string
.name_token()
- .filter(|k| k.text() == key.text())
- .is_some()
+ .map_or(false, |token| token.text() == name.text())
{
- let value = string.value()?.syntax().text().to_string();
- return Some(Hover {
- range: Some(
- main_document
- .line_index
- .line_col_lsp_range(key.text_range()),
- ),
- contents: HoverContents::Markup(MarkupContent {
- kind: MarkupKind::PlainText,
- value,
- }),
+ let value = TextFieldData::parse(&string.value()?)?.text;
+ return Some(HoverResult {
+ range: name.text_range(),
+ value,
+ value_kind: MarkupKind::PlainText,
});
}
}
None
}
-
-#[cfg(test)]
-mod tests {
- use indoc::indoc;
- use lsp_types::Range;
-
- use crate::{features::testing::FeatureTester, RangeExt};
-
- use super::*;
-
- #[test]
- fn test_empty_latex_document() {
- let request = FeatureTester::builder()
- .files(vec![("main.tex", "")])
- .main("main.tex")
- .line(0)
- .character(0)
- .build()
- .hover();
-
- let context = CursorContext::new(request);
- let actual_hover = find_string_reference_hover(&context);
-
- assert_eq!(actual_hover, None);
- }
-
- #[test]
- fn test_empty_bibtex_document() {
- let request = FeatureTester::builder()
- .files(vec![("main.bib", "")])
- .main("main.bib")
- .line(0)
- .character(0)
- .build()
- .hover();
-
- let context = CursorContext::new(request);
- let actual_hover = find_string_reference_hover(&context);
-
- assert_eq!(actual_hover, None);
- }
-
- #[test]
- fn test_inside_reference() {
- let request = FeatureTester::builder()
- .files(vec![(
- "main.bib",
- indoc! { r#"
- @string{foo = "Foo"}
- @string{bar = "Bar"}
- @article{baz, author = bar}
- "# },
- )])
- .main("main.bib")
- .line(2)
- .character(24)
- .build()
- .hover();
-
- let context = CursorContext::new(request);
- let actual_hover = find_string_reference_hover(&context).unwrap();
-
- let expected_hover = Hover {
- contents: HoverContents::Markup(MarkupContent {
- kind: MarkupKind::PlainText,
- value: "\"Bar\"".into(),
- }),
- range: Some(Range::new_simple(2, 23, 2, 26)),
- };
-
- assert_eq!(actual_hover, expected_hover);
- }
-
- #[test]
- fn test_inside_field() {
- let request = FeatureTester::builder()
- .files(vec![(
- "main.bib",
- indoc! { r#"
- @string{foo = "Foo"}
- @string{bar = "Bar"}
- @article{baz, author = bar}
- "# },
- )])
- .main("main.bib")
- .line(2)
- .character(20)
- .build()
- .hover();
-
- let context = CursorContext::new(request);
- let actual_hover = find_string_reference_hover(&context);
- assert_eq!(actual_hover, None);
- }
-}
diff --git a/support/texlab/src/features/link.rs b/support/texlab/src/features/link.rs
index 0a02f7819e..c4ce4413f5 100644
--- a/support/texlab/src/features/link.rs
+++ b/support/texlab/src/features/link.rs
@@ -1,107 +1,33 @@
-use lsp_types::{DocumentLink, DocumentLinkParams};
+mod include;
-use crate::LineIndexExt;
-
-use super::FeatureRequest;
-
-pub fn find_document_links(request: FeatureRequest<DocumentLinkParams>) -> Vec<DocumentLink> {
- let mut links = Vec::new();
- let main_document = request.main_document();
- if let Some(data) = 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())
- {
- links.push(DocumentLink {
- range: main_document
- .line_index
- .line_col_lsp_range(include.stem_range),
- target: Some(target.as_ref().clone()),
- tooltip: None,
- data: None,
- });
- break;
- }
- }
- }
- }
- links
-}
-
-#[cfg(test)]
-mod tests {
- use super::*;
-
- use lsp_types::Range;
-
- use crate::{features::testing::FeatureTester, RangeExt};
-
- #[test]
- fn test_empty_latex_document() {
- let request = FeatureTester::builder()
- .files(vec![("main.tex", "")])
- .main("main.tex")
- .build()
- .link();
+use std::sync::Arc;
- let items = find_document_links(request);
- assert!(items.is_empty());
- }
+use lsp_types::{DocumentLink, DocumentLinkParams, Url};
+use rowan::TextRange;
- #[test]
- fn test_empty_bibtex_document() {
- let request = FeatureTester::builder()
- .files(vec![("main.bib", "")])
- .main("main.bib")
- .build()
- .link();
-
- let items = find_document_links(request);
- assert!(items.is_empty());
- }
+use crate::LineIndexExt;
- #[test]
- fn test_includes() {
- let tester = FeatureTester::builder()
- .files(vec![("foo.tex", r#"\input{bar.tex}"#), ("bar.tex", r#""#)])
- .main("foo.tex")
- .build();
- let target = tester.uri("bar.tex");
+use self::include::find_include_links;
- let actual_items = find_document_links(tester.link());
+use super::FeatureRequest;
- let expected_items = vec![DocumentLink {
- range: Range::new_simple(0, 7, 0, 14),
- target: Some(target.as_ref().clone()),
+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,
- }];
- assert_eq!(actual_items, expected_items);
- }
-
- #[test]
- fn test_imports() {
- let tester = FeatureTester::builder()
- .files(vec![
- ("foo.tex", r#"\import{bar/}{baz}"#),
- ("bar/baz.tex", r#""#),
- ])
- .main("foo.tex")
- .build();
- let target = tester.uri("bar/baz.tex");
-
- let actual_items = find_document_links(tester.link());
+ })
+ .collect()
+}
- let expected_items = vec![DocumentLink {
- range: Range::new_simple(0, 14, 0, 17),
- target: Some(target.as_ref().clone()),
- tooltip: None,
- data: None,
- }];
- assert_eq!(actual_items, expected_items);
- }
+#[derive(Debug, Clone)]
+struct LinkResult {
+ range: TextRange,
+ target: Arc<Url>,
}
diff --git a/support/texlab/src/features/link/include.rs b/support/texlab/src/features/link/include.rs
new file mode 100644
index 0000000000..b4d1804cce
--- /dev/null
+++ b/support/texlab/src/features/link/include.rs
@@ -0,0 +1,33 @@
+use std::sync::Arc;
+
+use lsp_types::DocumentLinkParams;
+
+use crate::features::FeatureRequest;
+
+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;
+ }
+ }
+ }
+
+ Some(())
+}
diff --git a/support/texlab/src/features/reference.rs b/support/texlab/src/features/reference.rs
index db48453b4e..f84a3f67d5 100644
--- a/support/texlab/src/features/reference.rs
+++ b/support/texlab/src/features/reference.rs
@@ -2,7 +2,12 @@ mod entry;
mod label;
mod string;
-use lsp_types::{Location, ReferenceParams};
+use std::sync::Arc;
+
+use lsp_types::{Location, ReferenceParams, Url};
+use rowan::TextRange;
+
+use crate::LineIndexExt;
use self::{
entry::find_entry_references, label::find_label_references, string::find_string_references,
@@ -10,12 +15,27 @@ use self::{
use super::{cursor::CursorContext, FeatureRequest};
-pub fn find_all_references(request: FeatureRequest<ReferenceParams>) -> Option<Vec<Location>> {
- let mut references = Vec::new();
+pub fn find_all_references(request: FeatureRequest<ReferenceParams>) -> Vec<Location> {
+ let mut results = Vec::new();
let context = CursorContext::new(request);
log::debug!("[References] Cursor: {:?}", context.cursor);
- find_label_references(&context, &mut references);
- find_entry_references(&context, &mut references);
- find_string_references(&context, &mut references);
- Some(references)
+ find_label_references(&context, &mut results);
+ find_entry_references(&context, &mut results);
+ find_string_references(&context, &mut results);
+
+ results
+ .into_iter()
+ .map(|result| Location {
+ uri: result.uri.as_ref().clone(),
+ range: context.request.workspace.documents_by_uri[&result.uri]
+ .line_index
+ .line_col_lsp_range(result.range),
+ })
+ .collect()
+}
+
+#[derive(Debug, Clone)]
+struct ReferenceResult {
+ uri: Arc<Url>,
+ range: TextRange,
}
diff --git a/support/texlab/src/features/reference/entry.rs b/support/texlab/src/features/reference/entry.rs
index f245b6eb8d..0144d2d074 100644
--- a/support/texlab/src/features/reference/entry.rs
+++ b/support/texlab/src/features/reference/entry.rs
@@ -1,4 +1,6 @@
-use lsp_types::{Location, ReferenceParams};
+use std::sync::Arc;
+
+use lsp_types::ReferenceParams;
use rowan::ast::AstNode;
use crate::{
@@ -7,12 +9,14 @@ use crate::{
bibtex::{self, HasName},
latex,
},
- DocumentData, LineIndexExt,
+ DocumentData,
};
-pub fn find_entry_references(
+use super::ReferenceResult;
+
+pub(super) fn find_entry_references(
context: &CursorContext<ReferenceParams>,
- references: &mut Vec<Location>,
+ results: &mut Vec<ReferenceResult>,
) -> Option<()> {
let (key_text, _) = context
.find_citation_key_word()
@@ -28,13 +32,10 @@ pub fn find_entry_references(
.filter_map(|citation| citation.key_list())
.flat_map(|keys| keys.keys())
.filter(|key| key.to_string() == key_text)
- .map(|key| {
- document
- .line_index
- .line_col_lsp_range(latex::small_range(&key))
- })
+ .map(|key| latex::small_range(&key))
.for_each(|range| {
- references.push(Location::new(document.uri.as_ref().clone(), range));
+ let uri = Arc::clone(&document.uri);
+ results.push(ReferenceResult { uri, range });
});
}
DocumentData::Bibtex(data) if context.request.params.context.include_declaration => {
@@ -43,172 +44,15 @@ pub fn find_entry_references(
.filter_map(bibtex::Entry::cast)
.filter_map(|entry| entry.name_token())
.filter(|key| key.text() == key_text)
- .map(|key| document.line_index.line_col_lsp_range(key.text_range()))
+ .map(|key| key.text_range())
.for_each(|range| {
- references.push(Location::new(document.uri.as_ref().clone(), range));
+ let uri = Arc::clone(&document.uri);
+ results.push(ReferenceResult { uri, range });
});
}
DocumentData::Bibtex(_) | DocumentData::BuildLog(_) => {}
}
}
- Some(())
-}
-
-#[cfg(test)]
-mod tests {
- use lsp_types::Range;
-
- use crate::{features::testing::FeatureTester, RangeExt};
-
- use super::*;
-
- fn sort_references(actual_references: &mut [Location]) {
- actual_references.sort_by(|a, b| {
- a.uri
- .cmp(&b.uri)
- .then_with(|| a.range.start.cmp(&b.range.start))
- });
- }
-
- #[test]
- fn test_empty_latex_document() {
- let request = FeatureTester::builder()
- .files(vec![("main.tex", "")])
- .main("main.tex")
- .line(0)
- .character(0)
- .build()
- .reference();
-
- let mut actual_references = Vec::new();
- let context = CursorContext::new(request);
- find_entry_references(&context, &mut actual_references);
-
- assert!(actual_references.is_empty());
- }
-
- #[test]
- fn test_empty_bibtex_document() {
- let request = FeatureTester::builder()
- .files(vec![("main.bib", "")])
- .main("main.bib")
- .line(0)
- .character(0)
- .build()
- .reference();
-
- let mut actual_references = Vec::new();
- let context = CursorContext::new(request);
- find_entry_references(&context, &mut actual_references);
-
- assert!(actual_references.is_empty());
- }
- #[test]
- fn test_definition() {
- let tester = FeatureTester::builder()
- .files(vec![
- ("foo.bib", r#"@article{foo,}"#),
- ("bar.tex", r#"\cite{foo}\addbibresource{foo.bib}"#),
- ])
- .main("foo.bib")
- .line(0)
- .character(11)
- .build();
- let uri = tester.uri("bar.tex");
- let mut actual_references = Vec::new();
-
- let request = tester.reference();
- let context = CursorContext::new(request);
- find_entry_references(&context, &mut actual_references);
-
- sort_references(&mut actual_references);
- let expected_references = vec![Location::new(
- uri.as_ref().clone(),
- Range::new_simple(0, 6, 0, 9),
- )];
- assert_eq!(actual_references, expected_references);
- }
-
- #[test]
- fn test_definition_include_declaration() {
- let tester = FeatureTester::builder()
- .files(vec![
- ("foo.bib", r#"@article{foo,}"#),
- ("bar.tex", r#"\cite{foo}\addbibresource{foo.bib}"#),
- ])
- .main("foo.bib")
- .line(0)
- .character(11)
- .include_declaration(true)
- .build();
- let uri1 = tester.uri("bar.tex");
- let uri2 = tester.uri("foo.bib");
- let mut actual_references = Vec::new();
-
- let request = tester.reference();
- let context = CursorContext::new(request);
- find_entry_references(&context, &mut actual_references);
-
- sort_references(&mut actual_references);
- let expected_references = vec![
- Location::new(uri1.as_ref().clone(), Range::new_simple(0, 6, 0, 9)),
- Location::new(uri2.as_ref().clone(), Range::new_simple(0, 9, 0, 12)),
- ];
- assert_eq!(actual_references, expected_references);
- }
-
- #[test]
- fn test_reference() {
- let tester = FeatureTester::builder()
- .files(vec![
- ("foo.bib", r#"@article{foo,}"#),
- ("bar.tex", r#"\cite{foo}\addbibresource{foo.bib}"#),
- ])
- .main("bar.tex")
- .line(0)
- .character(8)
- .build();
- let uri = tester.uri("bar.tex");
- let mut actual_references = Vec::new();
-
- let request = tester.reference();
- let context = CursorContext::new(request);
- find_entry_references(&context, &mut actual_references);
-
- sort_references(&mut actual_references);
- let expected_references = vec![Location::new(
- uri.as_ref().clone(),
- Range::new_simple(0, 6, 0, 9),
- )];
- assert_eq!(actual_references, expected_references);
- }
-
- #[test]
- fn test_reference_include_declaration() {
- let tester = FeatureTester::builder()
- .files(vec![
- ("foo.bib", r#"@article{foo,}"#),
- ("bar.tex", r#"\cite{foo}\addbibresource{foo.bib}"#),
- ])
- .main("bar.tex")
- .line(0)
- .character(6)
- .include_declaration(true)
- .build();
- let uri1 = tester.uri("foo.bib");
- let uri2 = tester.uri("bar.tex");
- let mut actual_references = Vec::new();
-
- let request = tester.reference();
- let context = CursorContext::new(request);
- find_entry_references(&context, &mut actual_references);
-
- sort_references(&mut actual_references);
- let expected_references = vec![
- Location::new(uri2.as_ref().clone(), Range::new_simple(0, 6, 0, 9)),
- Location::new(uri1.as_ref().clone(), Range::new_simple(0, 9, 0, 12)),
- ];
- assert_eq!(actual_references, expected_references);
- }
+ Some(())
}
diff --git a/support/texlab/src/features/reference/label.rs b/support/texlab/src/features/reference/label.rs
index 2fc3efc398..3dadada08b 100644
--- a/support/texlab/src/features/reference/label.rs
+++ b/support/texlab/src/features/reference/label.rs
@@ -1,10 +1,14 @@
-use lsp_types::{Location, ReferenceParams};
+use std::sync::Arc;
-use crate::{features::cursor::CursorContext, LineIndexExt};
+use lsp_types::ReferenceParams;
-pub fn find_label_references(
+use crate::features::cursor::CursorContext;
+
+use super::ReferenceResult;
+
+pub(super) fn find_label_references(
context: &CursorContext<ReferenceParams>,
- references: &mut Vec<Location>,
+ results: &mut Vec<ReferenceResult>,
) -> Option<()> {
let (name_text, _) = context
.find_label_name_key()
@@ -21,174 +25,13 @@ pub fn find_label_references(
!name.is_definition || context.request.params.context.include_declaration
})
{
- references.push(Location::new(
- document.uri.as_ref().clone(),
- document.line_index.line_col_lsp_range(name.range),
- ));
+ results.push(ReferenceResult {
+ uri: Arc::clone(&document.uri),
+ range: name.range,
+ });
}
}
}
Some(())
}
-
-#[cfg(test)]
-mod tests {
- use lsp_types::Range;
-
- use crate::{features::testing::FeatureTester, RangeExt};
-
- use super::*;
-
- fn sort_references(actual_references: &mut [Location]) {
- actual_references.sort_by(|a, b| {
- a.uri
- .cmp(&b.uri)
- .then_with(|| a.range.start.cmp(&b.range.start))
- });
- }
-
- #[test]
- fn test_definition() {
- let tester = FeatureTester::builder()
- .files(vec![
- ("foo.tex", r#"\label{foo}"#),
- ("bar.tex", r#"\ref{foo}\input{foo.tex}"#),
- ])
- .main("foo.tex")
- .line(0)
- .character(8)
- .build();
- let uri = tester.uri("bar.tex");
- let mut actual_references = Vec::new();
-
- let request = tester.reference();
- let context = CursorContext::new(request);
- find_label_references(&context, &mut actual_references);
-
- sort_references(&mut actual_references);
- let expected_references = vec![Location::new(
- uri.as_ref().clone(),
- Range::new_simple(0, 5, 0, 8),
- )];
- assert_eq!(actual_references, expected_references);
- }
-
- #[test]
- fn test_definition_include_declaration() {
- let tester = FeatureTester::builder()
- .files(vec![
- ("foo.tex", r#"\label{foo}\input{bar.tex}"#),
- ("bar.tex", r#"\ref{foo}"#),
- ])
- .main("foo.tex")
- .line(0)
- .character(9)
- .include_declaration(true)
- .build();
- let uri1 = tester.uri("bar.tex");
- let uri2 = tester.uri("foo.tex");
- let mut actual_references = Vec::new();
-
- let request = tester.reference();
- let context = CursorContext::new(request);
- find_label_references(&context, &mut actual_references);
-
- sort_references(&mut actual_references);
- let expected_references = vec![
- Location::new(uri1.as_ref().clone(), Range::new_simple(0, 5, 0, 8)),
- Location::new(uri2.as_ref().clone(), Range::new_simple(0, 7, 0, 10)),
- ];
- assert_eq!(actual_references, expected_references);
- }
-
- #[test]
- fn test_reference() {
- let tester = FeatureTester::builder()
- .files(vec![
- ("foo.tex", r#"\label{foo}\input{bar.tex}"#),
- ("bar.tex", r#"\ref{foo}"#),
- ("baz.tex", r#"\ref{foo}\input{bar.tex}"#),
- ])
- .main("bar.tex")
- .line(0)
- .character(7)
- .build();
- let uri1 = tester.uri("bar.tex");
- let uri2 = tester.uri("baz.tex");
- let mut actual_references = Vec::new();
-
- let request = tester.reference();
- let context = CursorContext::new(request);
- find_label_references(&context, &mut actual_references);
-
- sort_references(&mut actual_references);
- let expected_references = vec![
- Location::new(uri1.as_ref().clone(), Range::new_simple(0, 5, 0, 8)),
- Location::new(uri2.as_ref().clone(), Range::new_simple(0, 5, 0, 8)),
- ];
- assert_eq!(actual_references, expected_references);
- }
-
- #[test]
- fn test_reference_include_declaration() {
- let tester = FeatureTester::builder()
- .files(vec![
- ("foo.tex", r#"\label{foo}"#),
- ("bar.tex", r#"\ref{foo}\input{foo.tex}"#),
- ])
- .main("bar.tex")
- .line(0)
- .character(7)
- .include_declaration(true)
- .build();
- let uri1 = tester.uri("bar.tex");
- let uri2 = tester.uri("foo.tex");
- let mut actual_references = Vec::new();
-
- let request = tester.reference();
- let context = CursorContext::new(request);
- find_label_references(&context, &mut actual_references);
-
- sort_references(&mut actual_references);
- let expected_references = vec![
- Location::new(uri1.as_ref().clone(), Range::new_simple(0, 5, 0, 8)),
- Location::new(uri2.as_ref().clone(), Range::new_simple(0, 7, 0, 10)),
- ];
- assert_eq!(actual_references, expected_references);
- }
-
- #[test]
- fn test_empty_latex_document() {
- let request = FeatureTester::builder()
- .files(vec![("main.tex", "")])
- .main("main.tex")
- .line(0)
- .character(0)
- .build()
- .reference();
- let mut actual_references = Vec::new();
-
- let context = CursorContext::new(request);
- find_label_references(&context, &mut actual_references);
-
- assert!(actual_references.is_empty());
- }
-
- #[test]
- fn test_empty_bibtex_document() {
- let request = FeatureTester::builder()
- .files(vec![("main.bib", "")])
- .main("main.bib")
- .line(0)
- .character(0)
- .build()
- .reference();
- let mut actual_references = Vec::new();
-
- let context = CursorContext::new(request);
- find_label_references(&context, &mut actual_references);
-
- assert!(actual_references.is_empty());
- }
-}
diff --git a/support/texlab/src/features/reference/string.rs b/support/texlab/src/features/reference/string.rs
index c957244a53..c00cf93546 100644
--- a/support/texlab/src/features/reference/string.rs
+++ b/support/texlab/src/features/reference/string.rs
@@ -1,23 +1,26 @@
-use lsp_types::{Location, ReferenceParams};
+use std::sync::Arc;
+
+use lsp_types::ReferenceParams;
use rowan::ast::AstNode;
use crate::{
features::cursor::CursorContext,
syntax::bibtex::{self, HasName},
- LineIndexExt,
};
-pub fn find_string_references(
+use super::ReferenceResult;
+
+pub(super) fn find_string_references(
context: &CursorContext<ReferenceParams>,
- items: &mut Vec<Location>,
+ results: &mut Vec<ReferenceResult>,
) -> Option<()> {
let name_text = context
.cursor
.as_bibtex()
+ .filter(|token| token.kind() == bibtex::NAME)
.filter(|token| {
let parent = token.parent().unwrap();
- (token.kind() == bibtex::NAME && bibtex::Value::can_cast(parent.kind()))
- || (token.kind() == bibtex::NAME && bibtex::StringDef::can_cast(parent.kind()))
+ bibtex::Value::can_cast(parent.kind()) || bibtex::StringDef::can_cast(parent.kind())
})?
.text();
@@ -35,173 +38,12 @@ pub fn find_string_references(
.filter(|name| name.text() == name_text)
})
{
- items.push(Location::new(
- document.uri.as_ref().clone(),
- document.line_index.line_col_lsp_range(name.text_range()),
- ));
+ results.push(ReferenceResult {
+ uri: Arc::clone(&document.uri),
+ range: name.text_range(),
+ });
}
}
- Some(())
-}
-
-#[cfg(test)]
-mod tests {
- use indoc::indoc;
- use lsp_types::Range;
-
- use crate::{features::testing::FeatureTester, RangeExt};
-
- use super::*;
-
- #[test]
- fn test_definition() {
- let tester = FeatureTester::builder()
- .files(vec![(
- "main.bib",
- indoc! { r#"
- @string{foo = {Foo}}
- @string{bar = {Bar}}
- @article{baz, author = foo}
- "# },
- )])
- .main("main.bib")
- .line(2)
- .character(24)
- .build();
- let uri = tester.uri("main.bib");
-
- let mut actual_references = Vec::new();
- let request = tester.reference();
- let context = CursorContext::new(request);
- find_string_references(&context, &mut actual_references);
-
- let expected_references = vec![Location::new(
- uri.as_ref().clone(),
- Range::new_simple(2, 23, 2, 26),
- )];
- assert_eq!(actual_references, expected_references);
- }
-
- #[test]
- fn test_definition_include_declaration() {
- let tester = FeatureTester::builder()
- .files(vec![(
- "main.bib",
- indoc! { r#"
- @string{foo = {Foo}}
- @string{bar = {Bar}}
- @article{baz, author = foo}
- "# },
- )])
- .main("main.bib")
- .line(2)
- .character(24)
- .include_declaration(true)
- .build();
- let uri = tester.uri("main.bib");
-
- let mut actual_references = Vec::new();
- let request = tester.reference();
- let context = CursorContext::new(request);
- find_string_references(&context, &mut actual_references);
-
- let expected_references = vec![
- Location::new(uri.as_ref().clone(), Range::new_simple(0, 8, 0, 11)),
- Location::new(uri.as_ref().clone(), Range::new_simple(2, 23, 2, 26)),
- ];
- assert_eq!(actual_references, expected_references);
- }
-
- #[test]
- fn test_reference() {
- let tester = FeatureTester::builder()
- .files(vec![(
- "main.bib",
- indoc! { r#"
- @string{foo = {Foo}}
- @string{bar = {Bar}}
- @article{baz, author = foo}
- "# },
- )])
- .main("main.bib")
- .line(0)
- .character(10)
- .build();
- let uri = tester.uri("main.bib");
- let mut actual_references = Vec::new();
- let request = tester.reference();
- let context = CursorContext::new(request);
- find_string_references(&context, &mut actual_references);
-
- let expected_references = vec![Location::new(
- uri.as_ref().clone(),
- Range::new_simple(2, 23, 2, 26),
- )];
- assert_eq!(actual_references, expected_references);
- }
-
- #[test]
- fn test_reference_include_declaration() {
- let tester = FeatureTester::builder()
- .files(vec![(
- "main.bib",
- indoc! { r#"
- @string{foo = {Foo}}
- @string{bar = {Bar}}
- @article{baz, author = foo}
- "# },
- )])
- .main("main.bib")
- .line(0)
- .character(10)
- .include_declaration(true)
- .build();
- let uri = tester.uri("main.bib");
-
- let mut actual_references = Vec::new();
- let request = tester.reference();
- let context = CursorContext::new(request);
- find_string_references(&context, &mut actual_references);
-
- let expected_references = vec![
- Location::new(uri.as_ref().clone(), Range::new_simple(0, 8, 0, 11)),
- Location::new(uri.as_ref().clone(), Range::new_simple(2, 23, 2, 26)),
- ];
- assert_eq!(actual_references, expected_references);
- }
-
- #[test]
- fn test_empty_latex_document() {
- let request = FeatureTester::builder()
- .files(vec![("main.tex", "")])
- .main("main.tex")
- .line(0)
- .character(0)
- .build()
- .reference();
-
- let mut actual_references = Vec::new();
- let context = CursorContext::new(request);
- find_string_references(&context, &mut actual_references);
-
- assert!(actual_references.is_empty());
- }
-
- #[test]
- fn test_empty_bibtex_document() {
- let request = FeatureTester::builder()
- .files(vec![("main.bib", "")])
- .main("main.bib")
- .line(0)
- .character(0)
- .build()
- .reference();
-
- let mut actual_references = Vec::new();
- let context = CursorContext::new(request);
- find_string_references(&context, &mut actual_references);
-
- assert!(actual_references.is_empty());
- }
+ Some(())
}
diff --git a/support/texlab/src/features/rename.rs b/support/texlab/src/features/rename.rs
index a9a6732d04..c21faf262e 100644
--- a/support/texlab/src/features/rename.rs
+++ b/support/texlab/src/features/rename.rs
@@ -2,7 +2,13 @@ mod command;
mod entry;
mod label;
-use lsp_types::{Range, RenameParams, TextDocumentPositionParams, WorkspaceEdit};
+use std::sync::Arc;
+
+use lsp_types::{Range, RenameParams, TextDocumentPositionParams, TextEdit, Url, WorkspaceEdit};
+use rowan::TextRange;
+use rustc_hash::FxHashMap;
+
+use crate::LineIndexExt;
use self::{
command::{prepare_command_rename, rename_command},
@@ -14,14 +20,46 @@ use super::{cursor::CursorContext, FeatureRequest};
pub fn prepare_rename_all(request: FeatureRequest<TextDocumentPositionParams>) -> Option<Range> {
let context = CursorContext::new(request);
- prepare_entry_rename(&context)
+ let range = prepare_entry_rename(&context)
.or_else(|| prepare_label_rename(&context))
- .or_else(|| prepare_command_rename(&context))
+ .or_else(|| prepare_command_rename(&context))?;
+
+ let line_index = &context.request.main_document().line_index;
+ Some(line_index.line_col_lsp_range(range))
}
pub fn rename_all(request: FeatureRequest<RenameParams>) -> Option<WorkspaceEdit> {
let context = CursorContext::new(request);
- rename_entry(&context)
+ let result = rename_entry(&context)
.or_else(|| rename_label(&context))
- .or_else(|| rename_command(&context))
+ .or_else(|| rename_command(&context))?;
+
+ let changes = result
+ .changes
+ .into_iter()
+ .map(|(uri, old_edits)| {
+ let document = &context.request.workspace.documents_by_uri[&uri];
+ let new_edits = old_edits
+ .into_iter()
+ .map(|Indel { delete, insert }| {
+ TextEdit::new(document.line_index.line_col_lsp_range(delete), insert)
+ })
+ .collect();
+
+ (uri.as_ref().clone(), new_edits)
+ })
+ .collect();
+
+ Some(WorkspaceEdit::new(changes))
+}
+
+#[derive(Debug, PartialEq, Eq, Clone)]
+struct Indel {
+ delete: TextRange,
+ insert: String,
+}
+
+#[derive(Debug, PartialEq, Eq, Clone)]
+struct RenameResult {
+ changes: FxHashMap<Arc<Url>, Vec<Indel>>,
}
diff --git a/support/texlab/src/features/rename/command.rs b/support/texlab/src/features/rename/command.rs
index e0677f443e..aaa08f8cb4 100644
--- a/support/texlab/src/features/rename/command.rs
+++ b/support/texlab/src/features/rename/command.rs
@@ -1,88 +1,45 @@
-use std::collections::HashMap;
+use std::sync::Arc;
-use lsp_types::{Range, RenameParams, TextEdit, WorkspaceEdit};
+use lsp_types::RenameParams;
use rowan::{TextRange, TextSize};
+use rustc_hash::FxHashMap;
use crate::{
features::cursor::{CursorContext, HasPosition},
syntax::latex,
- LineIndexExt,
};
-pub fn prepare_command_rename<P: HasPosition>(context: &CursorContext<P>) -> Option<Range> {
- Some(
- context
- .request
- .main_document()
- .line_index
- .line_col_lsp_range(context.cursor.command_range(context.offset)?),
- )
+use super::{Indel, RenameResult};
+
+pub(super) fn prepare_command_rename<P: HasPosition>(
+ context: &CursorContext<P>,
+) -> Option<TextRange> {
+ context.cursor.command_range(context.offset)
}
-pub fn rename_command(context: &CursorContext<RenameParams>) -> Option<WorkspaceEdit> {
+pub(super) fn rename_command(context: &CursorContext<RenameParams>) -> Option<RenameResult> {
prepare_command_rename(context)?;
let name = context.cursor.as_latex()?.text();
- let mut changes = HashMap::new();
+ let mut changes = FxHashMap::default();
for document in context.request.workspace.documents_by_uri.values() {
if let Some(data) = document.data.as_latex() {
- let edits = latex::SyntaxNode::new_root(data.green.clone())
+ let root = latex::SyntaxNode::new_root(data.green.clone());
+ let edits = root
.descendants_with_tokens()
.filter_map(|element| element.into_token())
.filter(|token| token.kind().is_command_name() && token.text() == name)
.map(|token| {
let range = token.text_range();
- let range = document.line_index.line_col_lsp_range(TextRange::new(
- range.start() + TextSize::from(1),
- range.end(),
- ));
- TextEdit::new(range, context.request.params.new_name.clone())
+ Indel {
+ delete: TextRange::new(range.start() + TextSize::from(1), range.end()),
+ insert: context.request.params.new_name.clone(),
+ }
})
.collect();
- changes.insert(document.uri.as_ref().clone(), edits);
+ changes.insert(Arc::clone(&document.uri), edits);
}
}
- Some(WorkspaceEdit::new(changes))
-}
-
-#[cfg(test)]
-mod tests {
- use crate::{features::testing::FeatureTester, RangeExt};
-
- use super::*;
-
- #[test]
- fn test_command() {
- let tester = FeatureTester::builder()
- .files(vec![
- ("foo.tex", r#"\baz\include{bar.tex}"#),
- ("bar.tex", r#"\baz"#),
- ])
- .main("foo.tex")
- .line(0)
- .character(2)
- .new_name("qux")
- .build();
-
- let uri1 = tester.uri("foo.tex");
- let uri2 = tester.uri("bar.tex");
- let req = tester.rename();
-
- let context = CursorContext::new(req);
- let actual_edit = rename_command(&context).unwrap();
-
- let mut expected_changes = HashMap::new();
- expected_changes.insert(
- uri1.as_ref().clone(),
- vec![TextEdit::new(Range::new_simple(0, 1, 0, 4), "qux".into())],
- );
- expected_changes.insert(
- uri2.as_ref().clone(),
- vec![TextEdit::new(Range::new_simple(0, 1, 0, 4), "qux".into())],
- );
- let expected_edit = WorkspaceEdit::new(expected_changes);
-
- assert_eq!(actual_edit, expected_edit);
- }
+ Some(RenameResult { changes })
}
diff --git a/support/texlab/src/features/rename/entry.rs b/support/texlab/src/features/rename/entry.rs
index 4861b63570..6eac79030b 100644
--- a/support/texlab/src/features/rename/entry.rs
+++ b/support/texlab/src/features/rename/entry.rs
@@ -1,7 +1,8 @@
-use std::collections::HashMap;
+use std::sync::Arc;
-use lsp_types::{Range, RenameParams, TextEdit, WorkspaceEdit};
-use rowan::ast::AstNode;
+use lsp_types::RenameParams;
+use rowan::{ast::AstNode, TextRange};
+use rustc_hash::FxHashMap;
use crate::{
features::cursor::{CursorContext, HasPosition},
@@ -9,139 +10,63 @@ use crate::{
bibtex::{self, HasName},
latex,
},
- DocumentData, LineIndexExt,
+ DocumentData,
};
-pub fn prepare_entry_rename<P: HasPosition>(context: &CursorContext<P>) -> Option<Range> {
+use super::{Indel, RenameResult};
+
+pub(super) fn prepare_entry_rename<P: HasPosition>(
+ context: &CursorContext<P>,
+) -> Option<TextRange> {
let (_, range) = context
.find_citation_key_word()
.or_else(|| context.find_entry_key())?;
- Some(
- context
- .request
- .main_document()
- .line_index
- .line_col_lsp_range(range),
- )
+ Some(range)
}
-pub fn rename_entry(context: &CursorContext<RenameParams>) -> Option<WorkspaceEdit> {
+pub(super) fn rename_entry(context: &CursorContext<RenameParams>) -> Option<RenameResult> {
prepare_entry_rename(context)?;
let (key_text, _) = context
.find_citation_key_word()
.or_else(|| context.find_entry_key())?;
- let mut changes = HashMap::new();
+ 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 edits: Vec<_> = latex::SyntaxNode::new_root(data.green.clone())
+ let root = latex::SyntaxNode::new_root(data.green.clone());
+ let edits: Vec<_> = root
.descendants()
.filter_map(latex::Citation::cast)
.filter_map(|citation| citation.key_list())
.flat_map(|keys| keys.keys())
.filter(|key| key.to_string() == key_text)
- .map(|key| {
- document
- .line_index
- .line_col_lsp_range(latex::small_range(&key))
+ .map(|key| Indel {
+ delete: latex::small_range(&key),
+ insert: context.request.params.new_name.clone(),
})
- .map(|range| TextEdit::new(range, context.request.params.new_name.clone()))
.collect();
- changes.insert(document.uri.as_ref().clone(), edits);
+ changes.insert(uri, edits);
}
DocumentData::Bibtex(data) => {
- let edits: Vec<_> = bibtex::SyntaxNode::new_root(data.green.clone())
+ let root = bibtex::SyntaxNode::new_root(data.green.clone());
+ let edits: Vec<_> = root
.descendants()
.filter_map(bibtex::Entry::cast)
.filter_map(|entry| entry.name_token())
.filter(|key| key.text() == key_text)
- .map(|key| document.line_index.line_col_lsp_range(key.text_range()))
- .map(|range| TextEdit::new(range, context.request.params.new_name.clone()))
+ .map(|key| Indel {
+ delete: key.text_range(),
+ insert: context.request.params.new_name.clone(),
+ })
.collect();
- changes.insert(document.uri.as_ref().clone(), edits);
+ changes.insert(uri, edits);
}
DocumentData::BuildLog(_) => {}
}
}
- Some(WorkspaceEdit::new(changes))
-}
-
-#[cfg(test)]
-mod tests {
- use lsp_types::TextEdit;
-
- use crate::{features::testing::FeatureTester, RangeExt};
-
- use super::*;
-
- #[test]
- fn test_entry() {
- let tester = FeatureTester::builder()
- .files(vec![
- ("main.bib", r#"@article{foo, bar = baz}"#),
- ("main.tex", "\\addbibresource{main.bib}\n\\cite{foo}"),
- ])
- .main("main.bib")
- .line(0)
- .character(9)
- .new_name("qux")
- .build();
-
- let uri1 = tester.uri("main.bib");
- let uri2 = tester.uri("main.tex");
- let request = tester.rename();
-
- let context = CursorContext::new(request);
- let actual_edit = rename_entry(&context).unwrap();
-
- let mut expected_changes = HashMap::new();
- expected_changes.insert(
- uri1.as_ref().clone(),
- vec![TextEdit::new(Range::new_simple(0, 9, 0, 12), "qux".into())],
- );
- expected_changes.insert(
- uri2.as_ref().clone(),
- vec![TextEdit::new(Range::new_simple(1, 6, 1, 9), "qux".into())],
- );
- let expected_edit = WorkspaceEdit::new(expected_changes);
-
- assert_eq!(actual_edit, expected_edit);
- }
-
- #[test]
- fn test_citation() {
- let tester = FeatureTester::builder()
- .files(vec![
- ("main.bib", r#"@article{foo, bar = baz}"#),
- ("main.tex", "\\addbibresource{main.bib}\n\\cite{foo}"),
- ])
- .main("main.tex")
- .line(1)
- .character(6)
- .new_name("qux")
- .build();
-
- let uri1 = tester.uri("main.bib");
- let uri2 = tester.uri("main.tex");
- let request = tester.rename();
-
- let context = CursorContext::new(request);
- let actual_edit = rename_entry(&context).unwrap();
-
- let mut expected_changes = HashMap::new();
- expected_changes.insert(
- uri1.as_ref().clone(),
- vec![TextEdit::new(Range::new_simple(0, 9, 0, 12), "qux".into())],
- );
- expected_changes.insert(
- uri2.as_ref().clone(),
- vec![TextEdit::new(Range::new_simple(1, 6, 1, 9), "qux".into())],
- );
- let expected_edit = WorkspaceEdit::new(expected_changes);
-
- assert_eq!(actual_edit, expected_edit);
- }
+ Some(RenameResult { changes })
}
diff --git a/support/texlab/src/features/rename/label.rs b/support/texlab/src/features/rename/label.rs
index f24b86810b..30a99c3b36 100644
--- a/support/texlab/src/features/rename/label.rs
+++ b/support/texlab/src/features/rename/label.rs
@@ -1,31 +1,28 @@
-use std::collections::HashMap;
+use std::sync::Arc;
-use lsp_types::{Range, RenameParams, TextEdit, WorkspaceEdit};
-use rowan::ast::AstNode;
+use lsp_types::RenameParams;
+use rowan::{ast::AstNode, TextRange};
+use rustc_hash::FxHashMap;
use crate::{
features::cursor::{CursorContext, HasPosition},
syntax::latex,
- LineIndexExt,
};
-pub fn prepare_label_rename<P: HasPosition>(context: &CursorContext<P>) -> Option<Range> {
- let (_, range) = context.find_label_name_key()?;
+use super::{Indel, RenameResult};
- Some(
- context
- .request
- .main_document()
- .line_index
- .line_col_lsp_range(range),
- )
+pub(super) fn prepare_label_rename<P: HasPosition>(
+ context: &CursorContext<P>,
+) -> Option<TextRange> {
+ let (_, range) = context.find_label_name_key()?;
+ Some(range)
}
-pub fn rename_label(context: &CursorContext<RenameParams>) -> Option<WorkspaceEdit> {
+pub(super) fn rename_label(context: &CursorContext<RenameParams>) -> Option<RenameResult> {
prepare_label_rename(context)?;
let (name_text, _) = context.find_label_name_key()?;
- let mut changes = HashMap::new();
+ let mut changes = FxHashMap::default();
for document in context.request.workspace.documents_by_uri.values() {
if let Some(data) = document.data.as_latex() {
let mut edits = Vec::new();
@@ -34,16 +31,12 @@ pub fn rename_label(context: &CursorContext<RenameParams>) -> Option<WorkspaceEd
.and_then(|label| label.name())
.and_then(|name| name.key())
.filter(|name| name.to_string() == name_text)
- .map(|name| {
- document
- .line_index
- .line_col_lsp_range(latex::small_range(&name))
- })
+ .map(|name| latex::small_range(&name))
{
- edits.push(TextEdit::new(
- range,
- context.request.params.new_name.clone(),
- ));
+ edits.push(Indel {
+ delete: range,
+ insert: context.request.params.new_name.clone(),
+ });
}
latex::LabelReference::cast(node.clone())
@@ -51,16 +44,11 @@ pub fn rename_label(context: &CursorContext<RenameParams>) -> Option<WorkspaceEd
.into_iter()
.flat_map(|label| label.keys())
.filter(|name| name.to_string() == name_text)
- .map(|name| {
- document
- .line_index
- .line_col_lsp_range(latex::small_range(&name))
- })
- .for_each(|range| {
- edits.push(TextEdit::new(
- range,
- context.request.params.new_name.clone(),
- ));
+ .for_each(|name| {
+ edits.push(Indel {
+ delete: latex::small_range(&name),
+ insert: context.request.params.new_name.clone(),
+ });
});
if let Some(label) = latex::LabelReferenceRange::cast(node.clone()) {
@@ -69,12 +57,10 @@ pub fn rename_label(context: &CursorContext<RenameParams>) -> Option<WorkspaceEd
.and_then(|name| name.key())
.filter(|name| name.to_string() == name_text)
{
- edits.push(TextEdit::new(
- document
- .line_index
- .line_col_lsp_range(latex::small_range(&name1)),
- context.request.params.new_name.clone(),
- ));
+ edits.push(Indel {
+ delete: latex::small_range(&name1),
+ insert: context.request.params.new_name.clone(),
+ });
}
if let Some(name2) = label
@@ -82,61 +68,17 @@ pub fn rename_label(context: &CursorContext<RenameParams>) -> Option<WorkspaceEd
.and_then(|name| name.key())
.filter(|name| name.to_string() == name_text)
{
- edits.push(TextEdit::new(
- document
- .line_index
- .line_col_lsp_range(latex::small_range(&name2)),
- context.request.params.new_name.clone(),
- ));
+ edits.push(Indel {
+ delete: latex::small_range(&name2),
+ insert: context.request.params.new_name.clone(),
+ });
}
}
}
- changes.insert(document.uri.as_ref().clone(), edits);
+ changes.insert(Arc::clone(&document.uri), edits);
}
}
- Some(WorkspaceEdit::new(changes))
-}
-
-#[cfg(test)]
-mod tests {
- use crate::{features::testing::FeatureTester, RangeExt};
-
- use super::*;
-
- #[test]
- fn test_label() {
- let tester = FeatureTester::builder()
- .files(vec![
- ("foo.tex", r#"\label{foo}\include{bar}"#),
- ("bar.tex", r#"\ref{foo}"#),
- ("baz.tex", r#"\ref{foo}"#),
- ])
- .main("foo.tex")
- .line(0)
- .character(7)
- .new_name("bar")
- .build();
-
- let uri1 = tester.uri("foo.tex");
- let uri2 = tester.uri("bar.tex");
- let request = tester.rename();
-
- let context = CursorContext::new(request);
- let actual_edit = rename_label(&context).unwrap();
-
- let mut expected_changes = HashMap::new();
- expected_changes.insert(
- uri1.as_ref().clone(),
- vec![TextEdit::new(Range::new_simple(0, 7, 0, 10), "bar".into())],
- );
- expected_changes.insert(
- uri2.as_ref().clone(),
- vec![TextEdit::new(Range::new_simple(0, 5, 0, 8), "bar".into())],
- );
- let expected_edit = WorkspaceEdit::new(expected_changes);
-
- assert_eq!(actual_edit, expected_edit);
- }
+ Some(RenameResult { changes })
}
diff --git a/support/texlab/src/features/symbol.rs b/support/texlab/src/features/symbol.rs
index 42b9d03d3f..24d599c3e1 100644
--- a/support/texlab/src/features/symbol.rs
+++ b/support/texlab/src/features/symbol.rs
@@ -14,10 +14,12 @@ use crate::{ClientCapabilitiesExt, Workspace};
use self::{
bibtex::find_bibtex_symbols, latex::find_latex_symbols, project_order::ProjectOrdering,
+ types::InternalSymbol,
};
use super::FeatureRequest;
+#[must_use]
pub fn find_document_symbols(req: FeatureRequest<DocumentSymbolParams>) -> DocumentSymbolResponse {
let mut buf = Vec::new();
find_latex_symbols(&req, &mut buf);
@@ -30,7 +32,7 @@ pub fn find_document_symbols(req: FeatureRequest<DocumentSymbolParams>) -> Docum
{
DocumentSymbolResponse::Nested(
buf.into_iter()
- .map(|symbol| symbol.into_document_symbol())
+ .map(InternalSymbol::into_document_symbol)
.collect(),
)
} else {
@@ -53,6 +55,7 @@ struct WorkspaceSymbol {
search_text: String,
}
+#[must_use]
pub fn find_workspace_symbols(
workspace: &Workspace,
params: &WorkspaceSymbolParams,
diff --git a/support/texlab/src/label.rs b/support/texlab/src/label.rs
index 9212c49222..b66db836f2 100644
--- a/support/texlab/src/label.rs
+++ b/support/texlab/src/label.rs
@@ -69,6 +69,7 @@ pub struct RenderedLabel {
}
impl RenderedLabel {
+ #[must_use]
pub fn reference(&self) -> String {
match &self.number {
Some(number) => match &self.object {
@@ -102,6 +103,7 @@ impl RenderedLabel {
}
}
+ #[must_use]
pub fn detail(&self) -> Option<String> {
match &self.object {
Section { .. } | Theorem { .. } | Equation | EnumItem => Some(self.reference()),
@@ -115,6 +117,7 @@ impl RenderedLabel {
}
}
+ #[must_use]
pub fn documentation(&self) -> MarkupContent {
MarkupContent {
kind: MarkupKind::PlainText,
diff --git a/support/texlab/src/lang_data.rs b/support/texlab/src/lang_data.rs
index 9aa939c483..28e6a540e0 100644
--- a/support/texlab/src/lang_data.rs
+++ b/support/texlab/src/lang_data.rs
@@ -41,6 +41,7 @@ pub struct LanguageData {
}
impl LanguageData {
+ #[must_use]
pub fn find_entry_type(&self, name: &str) -> Option<&BibtexEntryTypeDoc> {
let name = name.to_lowercase();
self.entry_types
@@ -48,11 +49,13 @@ impl LanguageData {
.find(|ty| ty.name.to_lowercase() == name)
}
+ #[must_use]
pub fn entry_type_documentation(&self, name: &str) -> Option<&str> {
self.find_entry_type(name)
.and_then(|ty| ty.documentation.as_ref().map(AsRef::as_ref))
}
+ #[must_use]
pub fn field_documentation(&self, name: &str) -> Option<&str> {
self.fields
.iter()
diff --git a/support/texlab/src/main.rs b/support/texlab/src/main.rs
index c3616a3e96..71338f1bcd 100644
--- a/support/texlab/src/main.rs
+++ b/support/texlab/src/main.rs
@@ -32,7 +32,7 @@ fn main() -> Result<()> {
setup_logger(opts);
let (connection, threads) = Connection::stdio();
- Server::with_connection(connection, env::current_dir()?, true)?.run()?;
+ Server::with_connection(connection, env::current_dir()?, true).run()?;
threads.join()?;
Ok(())
diff --git a/support/texlab/src/options.rs b/support/texlab/src/options.rs
index 211b3468c4..fe0d81c639 100644
--- a/support/texlab/src/options.rs
+++ b/support/texlab/src/options.rs
@@ -85,22 +85,26 @@ pub struct BuildOptions {
}
impl BuildOptions {
+ #[must_use]
pub fn executable(&self) -> String {
self.executable
.as_ref()
- .map(Clone::clone)
- .unwrap_or_else(|| "latexmk".to_string())
+ .map_or_else(|| "latexmk".to_string(), Clone::clone)
}
+ #[must_use]
pub fn args(&self) -> Vec<String> {
- self.args.as_ref().map(Clone::clone).unwrap_or_else(|| {
- vec![
- "-pdf".to_string(),
- "-interaction=nonstopmode".to_string(),
- "-synctex=1".to_string(),
- "%f".to_string(),
- ]
- })
+ self.args.as_ref().map_or_else(
+ || {
+ vec![
+ "-pdf".to_string(),
+ "-interaction=nonstopmode".to_string(),
+ "-synctex=1".to_string(),
+ "%f".to_string(),
+ ]
+ },
+ Clone::clone,
+ )
}
}
diff --git a/support/texlab/src/server.rs b/support/texlab/src/server.rs
index 5f833b65bb..f3d2bf44f4 100644
--- a/support/texlab/src/server.rs
+++ b/support/texlab/src/server.rs
@@ -17,10 +17,11 @@ use crate::{
dispatch::{NotificationDispatcher, RequestDispatcher},
distro::Distribution,
features::{
- 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,
+ 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,
},
req_queue::{IncomingData, ReqQueue},
ClientCapabilitiesExt, DocumentLanguage, Environment, LineIndex, LineIndexExt, Options,
@@ -52,7 +53,7 @@ impl Server {
connection: Connection,
current_dir: PathBuf,
load_resolver: bool,
- ) -> Result<Self> {
+ ) -> Self {
let req_queue = Arc::default();
let workspace = Workspace::new(Environment::new(Arc::new(current_dir)));
let diag_manager = Arc::new(Mutex::new(DiagnosticsManager::default()));
@@ -66,7 +67,7 @@ impl Server {
let (internal_tx, internal_rx) = crossbeam_channel::unbounded();
- Ok(Self {
+ Self {
connection: Arc::new(connection),
internal_tx,
internal_rx,
@@ -77,7 +78,7 @@ impl Server {
pool: Arc::new(Mutex::new(threadpool::Builder::new().build())),
load_resolver,
build_engine: Arc::default(),
- })
+ }
}
fn spawn(&self, job: impl FnOnce(Self) + Send + 'static) {
@@ -127,6 +128,13 @@ impl Server {
})),
document_highlight_provider: Some(OneOf::Left(true)),
document_formatting_provider: Some(OneOf::Left(true)),
+ execute_command_provider: Some(ExecuteCommandOptions {
+ commands: vec![
+ "texlab.cleanAuxiliary".into(),
+ "texlab.cleanArtifacts".into(),
+ ],
+ ..Default::default()
+ }),
..ServerCapabilities::default()
}
}
@@ -506,12 +514,19 @@ impl Server {
{
self.spawn(move |server| {
let request = server.feature_request(uri, params);
- let result = handler(request);
- server
- .connection
- .sender
- .send(lsp_server::Response::new_ok(id, result).into())
- .unwrap();
+ 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())
+ .unwrap();
+ }
});
Ok(())
@@ -668,6 +683,24 @@ impl Server {
Ok(())
}
+ fn execute_command(&self, id: RequestId, params: ExecuteCommandParams) -> Result<()> {
+ self.spawn(move |server| {
+ let result = execute_command(&server.workspace, &params.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(),
+ ),
+ };
+
+ server.connection.sender.send(response.into()).unwrap();
+ });
+
+ Ok(())
+ }
+
fn semantic_tokens_range(
&self,
_id: RequestId,
@@ -765,6 +798,7 @@ impl Server {
.on::<ForwardSearchRequest, _>(|id, params| {
self.forward_search(id, params)
})?
+ .on::<ExecuteCommand,_>(|id, params| self.execute_command(id, params))?
.on::<SemanticTokensRangeRequest, _>(|id, params| {
self.semantic_tokens_range(id, params)
})?
@@ -847,11 +881,7 @@ fn create_chktex_debouncer(
let sender = conn.sender.clone();
DiagnosticsDebouncer::launch(move |workspace, document| {
let mut manager = manager.lock().unwrap();
- manager.update_chktex(
- &workspace,
- Arc::clone(&document.uri),
- &workspace.environment.options,
- );
+ manager.update_chktex(&workspace, &document.uri, &workspace.environment.options);
if let Err(why) = publish_diagnostics(&sender, &workspace, &manager) {
warn!("Failed to publish diagnostics: {}", why);
}
@@ -864,7 +894,7 @@ fn publish_diagnostics(
diag_manager: &DiagnosticsManager,
) -> Result<()> {
for document in workspace.documents_by_uri.values() {
- let diagnostics = diag_manager.publish(Arc::clone(&document.uri));
+ let diagnostics = diag_manager.publish(&document.uri);
send_notification::<PublishDiagnostics>(
sender,
PublishDiagnosticsParams {
diff --git a/support/texlab/src/snapshots/texlab__citation__tests__biblatex_examples_001.snap b/support/texlab/src/snapshots/texlab__citation__tests__biblatex_examples_001.snap
deleted file mode 100644
index 40b6a6ad00..0000000000
--- a/support/texlab/src/snapshots/texlab__citation__tests__biblatex_examples_001.snap
+++ /dev/null
@@ -1,6 +0,0 @@
----
-source: src/citation.rs
-assertion_line: 133
-expression: "render_simple(r#\"\n@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}\"#)"
----
-Westfahl, Gary. (n.d.). *The True Frontier: Confronting and Avoiding the Realities of Space in American Science Fiction Films*.
diff --git a/support/texlab/src/snapshots/texlab__citation__tests__biblatex_examples_002.snap b/support/texlab/src/snapshots/texlab__citation__tests__biblatex_examples_002.snap
deleted file mode 100644
index ed55dc0b88..0000000000
--- a/support/texlab/src/snapshots/texlab__citation__tests__biblatex_examples_002.snap
+++ /dev/null
@@ -1,6 +0,0 @@
----
-source: src/citation.rs
-assertion_line: 174
-expression: "render_simple(r#\"\n@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}\"#)"
----
-Aksın, Özge, Türkmen, Hayati, Artok, Levent, \\cCetinkaya, Bekir, Ni, Chaoying, Büyükgüngör, Orhan, & Özkal, Erhan. (n.d.). Effect of immobilization on catalytic characteristics of saturated Pd-N-heterocyclic carbenes in Mizoroki-Heck reactions. *J. Organomet. Chem.*, *691*(13), 3027–3036.
diff --git a/support/texlab/src/snapshots/texlab__citation__tests__biblatex_examples_003.snap b/support/texlab/src/snapshots/texlab__citation__tests__biblatex_examples_003.snap
deleted file mode 100644
index a6455425eb..0000000000
--- a/support/texlab/src/snapshots/texlab__citation__tests__biblatex_examples_003.snap
+++ /dev/null
@@ -1,6 +0,0 @@
----
-source: src/citation.rs
-assertion_line: 197
-expression: "render_simple(r#\"\n@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}\"#)"
----
-Angenendt, Arnold. (n.d.). In Honore Salvatoris – Vom Sinn und Unsinn der Patrozinienkunde. *Revue d’Histoire Ecclésiastique*, *97*, 431–456,.
diff --git a/support/texlab/src/snapshots/texlab__citation__tests__biblatex_examples_004.snap b/support/texlab/src/snapshots/texlab__citation__tests__biblatex_examples_004.snap
deleted file mode 100644
index acf616c4d4..0000000000
--- a/support/texlab/src/snapshots/texlab__citation__tests__biblatex_examples_004.snap
+++ /dev/null
@@ -1,6 +0,0 @@
----
-source: src/citation.rs
-assertion_line: 219
-expression: "render_simple(r#\"\n@article{baez/article,\n author = {Baez, John C. and Lauda, Aaron D.},\n title = {Higher-Dimensional Algebra {V}: 2-Groups},\n journaltitle = {Theory and Applications of Categories},\n date = 2004,\n volume = 12,\n pages = {423-491},\n version = 3,\n eprint = {math/0307200v3},\n eprinttype = {arxiv},\n langid = {english},\n langidopts = {variant=american},\n annotation = {An \\texttt{article} with \\texttt{eprint} and\n \\texttt{eprinttype} fields. Note that the arXiv reference is\n transformed into a clickable link if \\texttt{hyperref} support\n has been enabled. Compare \\texttt{baez\\slash online}, which\n is the same item given as an \\texttt{online} entry},\n}\"#)"
----
-Baez, John C., & Lauda, Aaron D. (n.d.). Higher-Dimensional Algebra V: 2-Groups. *Theory and Applications of Categories*, *12*, 423–491. Retrieved from [http://arxiv.org/abs/math/0307200v3](http://arxiv.org/abs/math/0307200v3)
diff --git a/support/texlab/src/snapshots/texlab__citation__tests__biblatex_examples_005.snap b/support/texlab/src/snapshots/texlab__citation__tests__biblatex_examples_005.snap
deleted file mode 100644
index 0b6fc6a658..0000000000
--- a/support/texlab/src/snapshots/texlab__citation__tests__biblatex_examples_005.snap
+++ /dev/null
@@ -1,6 +0,0 @@
----
-source: src/citation.rs
-assertion_line: 244
-expression: "render_simple(r#\"\n@string{jams = {J.~Amer. Math. Soc.}}\n\n@article{bertram,\n author = {Bertram, Aaron and Wentworth, Richard},\n title = {Gromov invariants for holomorphic maps on {Riemann} surfaces},\n journaltitle = jams,\n date = 1996,\n volume = 9,\n number = 2,\n pages = {529-571},\n langid = {english},\n langidopts = {variant=american},\n shorttitle = {Gromov invariants},\n annotation = {An \\texttt{article} entry with a \\texttt{volume} and a\n \\texttt{number} field},\n}\"#)"
----
-Bertram, Aaron, & Wentworth, Richard. (n.d.). Gromov invariants for holomorphic maps on Riemann surfaces. *J. Amer. Math. Soc.*, *9*(2), 529–571.
diff --git a/support/texlab/src/snapshots/texlab__citation__tests__biblatex_examples_006.snap b/support/texlab/src/snapshots/texlab__citation__tests__biblatex_examples_006.snap
deleted file mode 100644
index cf38243313..0000000000
--- a/support/texlab/src/snapshots/texlab__citation__tests__biblatex_examples_006.snap
+++ /dev/null
@@ -1,6 +0,0 @@
----
-source: src/citation.rs
-assertion_line: 267
-expression: "render_simple(r#\"\n@article{doody,\n author = {Doody, Terrence},\n title = {Hemingway's Style and {Jake's} Narration},\n year = 1974,\n volume = 4,\n number = 3,\n pages = {212-225},\n langid = {english},\n langidopts = {variant=american},\n related = {matuz:doody},\n relatedstring= {\\autocap{e}xcerpt in},\n journal = {The Journal of Narrative Technique},\n annotation = {An \\texttt{article} entry cited as an excerpt from a\n \\texttt{collection} entry. Note the format of the\n \\texttt{related} and \\texttt{relatedstring} fields},\n}\"#)"
----
-Doody, Terrence. (1974). Hemingway’s Style and Jake’s Narration. *The Journal of Narrative Technique*, *4*(3), 212–225.
diff --git a/support/texlab/src/snapshots/texlab__citation__tests__biblatex_examples_007.snap b/support/texlab/src/snapshots/texlab__citation__tests__biblatex_examples_007.snap
deleted file mode 100644
index 7ad251527a..0000000000
--- a/support/texlab/src/snapshots/texlab__citation__tests__biblatex_examples_007.snap
+++ /dev/null
@@ -1,6 +0,0 @@
----
-source: src/citation.rs
-assertion_line: 290
-expression: "render_simple(r#\"\n@article{gillies,\n author = {Gillies, Alexander},\n title = {Herder and the Preparation of {Goethe's} Idea of World\n Literature},\n journaltitle = {Publications of the English Goethe Society},\n date = 1933,\n series = {newseries},\n volume = 9,\n pages = {46-67},\n langid = {english},\n langidopts = {variant=british},\n annotation = {An \\texttt{article} entry with a \\texttt{series} and a\n \\texttt{volume} field. Note that format of the \\texttt{series}\n field in the database file},\n}\"#)"
----
-Gillies, Alexander. (n.d.). Herder and the Preparation of Goethe’s Idea of World Literature. *Publications of the English Goethe Society*, *9*, 46–67.
diff --git a/support/texlab/src/snapshots/texlab__citation__tests__biblatex_examples_008.snap b/support/texlab/src/snapshots/texlab__citation__tests__biblatex_examples_008.snap
deleted file mode 100644
index 1d99cc8d85..0000000000
--- a/support/texlab/src/snapshots/texlab__citation__tests__biblatex_examples_008.snap
+++ /dev/null
@@ -1,6 +0,0 @@
----
-source: src/citation.rs
-assertion_line: 312
-expression: "render_simple(r#\"\n@article{glashow,\n author = {Glashow, Sheldon},\n title = {Partial Symmetries of Weak Interactions},\n journaltitle = {Nucl.~Phys.},\n date = 1961,\n volume = 22,\n pages = {579-588},\n}\"#)"
----
-Glashow, Sheldon. (n.d.). Partial Symmetries of Weak Interactions. *Nucl. Phys.*, *22*, 579–588.
diff --git a/support/texlab/src/snapshots/texlab__citation__tests__biblatex_examples_009.snap b/support/texlab/src/snapshots/texlab__citation__tests__biblatex_examples_009.snap
deleted file mode 100644
index 8bd943fafb..0000000000
--- a/support/texlab/src/snapshots/texlab__citation__tests__biblatex_examples_009.snap
+++ /dev/null
@@ -1,6 +0,0 @@
----
-source: src/citation.rs
-assertion_line: 327
-expression: "render_simple(r#\"\n@string{anch-ie = {Angew.~Chem. Int.~Ed.}}\n\n@article{herrmann,\n author = {Herrmann, Wolfgang A. and {\\\"O}fele, Karl and Schneider,\n Sabine K. and Herdtweck, Eberhardt and Hoffmann, Stephan D.},\n title = {A carbocyclic carbene as an efficient catalyst ligand for {C--C}\n coupling reactions},\n journaltitle = anch-ie,\n date = 2006,\n volume = 45,\n number = 23,\n pages = {3859-3862},\n indextitle = {Carbocyclic carbene as an efficient catalyst, A},\n}\"#)"
----
-Herrmann, Wolfgang A., Öfele, Karl, Schneider, Sabine K., Herdtweck, Eberhardt, & Hoffmann, Stephan D. (n.d.). A carbocyclic carbene as an efficient catalyst ligand for C–C coupling reactions. *Angew. Chem. Int. Ed.*, *45*(23), 3859–3862.
diff --git a/support/texlab/src/snapshots/texlab__citation__tests__biblatex_examples_010.snap b/support/texlab/src/snapshots/texlab__citation__tests__biblatex_examples_010.snap
deleted file mode 100644
index 09e341c790..0000000000
--- a/support/texlab/src/snapshots/texlab__citation__tests__biblatex_examples_010.snap
+++ /dev/null
@@ -1,6 +0,0 @@
----
-source: src/citation.rs
-assertion_line: 348
-expression: "render_simple(r#\"\n@string{jchph = {J.~Chem. Phys.}}\n\n@article{kastenholz,\n author = {Kastenholz, M. A. and H{\\\"u}nenberger, Philippe H.},\n title = {Computation of methodology\\hyphen independent ionic solvation\n free energies from molecular simulations},\n journaltitle = jchph,\n date = 2006,\n subtitle = {{I}. {The} electrostatic potential in molecular liquids},\n volume = 124,\n eid = 124106,\n doi = {10.1063/1.2172593},\n langid = {english},\n langidopts = {variant=american},\n indextitle = {Computation of ionic solvation free energies},\n annotation = {An \\texttt{article} entry with an \\texttt{eid} and a\n \\texttt{doi} field. Note that the \\textsc{doi} is transformed\n into a clickable link if \\texttt{hyperref} support has been\n enabled},\n abstract = {The computation of ionic solvation free energies from\n atomistic simulations is a surprisingly difficult problem that\n has found no satisfactory solution for more than 15 years. The\n reason is that the charging free energies evaluated from such\n simulations are affected by very large errors. One of these is\n related to the choice of a specific convention for summing up\n the contributions of solvent charges to the electrostatic\n potential in the ionic cavity, namely, on the basis of point\n charges within entire solvent molecules (M scheme) or on the\n basis of individual point charges (P scheme). The use of an\n inappropriate convention may lead to a charge-independent\n offset in the calculated potential, which depends on the\n details of the summation scheme, on the quadrupole-moment\n trace of the solvent molecule, and on the approximate form\n used to represent electrostatic interactions in the\n system. However, whether the M or P scheme (if any) represents\n the appropriate convention is still a matter of on-going\n debate. The goal of the present article is to settle this\n long-standing controversy by carefully analyzing (both\n analytically and numerically) the properties of the\n electrostatic potential in molecular liquids (and inside\n cavities within them).}, \n}\"#)"
----
-Kastenholz, M. A., & Hünenberger, Philippe H. (n.d.). Computation of methodology\\hyphen independent ionic solvation free energies from molecular simulations: I. The electrostatic potential in molecular liquids. *J. Chem. Phys.*, *124*. [https://doi.org/10.1063/1.2172593](https://doi.org/10.1063/1.2172593)
diff --git a/support/texlab/src/snapshots/texlab__citation__tests__biblatex_examples_011.snap b/support/texlab/src/snapshots/texlab__citation__tests__biblatex_examples_011.snap
deleted file mode 100644
index cb07b2f730..0000000000
--- a/support/texlab/src/snapshots/texlab__citation__tests__biblatex_examples_011.snap
+++ /dev/null
@@ -1,6 +0,0 @@
----
-source: src/citation.rs
-assertion_line: 397
-expression: "render_simple(r#\"\n@article{murray,\n author = {Hostetler, Michael J. and Wingate, Julia E. and Zhong,\n Chuan-Jian and Harris, Jay E. and Vachet, Richard W. and\n Clark, Michael R. and Londono, J. David and Green, Stephen\n J. and Stokes, Jennifer J. and Wignall, George D. and Glish,\n Gary L. and Porter, Marc D. and Evans, Neal D. and Murray,\n Royce W.},\n title = {Alkanethiolate gold cluster molecules with core diameters from\n 1.5 to 5.2~{nm}},\n journaltitle = {Langmuir},\n date = 1998,\n subtitle = {Core and monolayer properties as a function of core size},\n volume = 14,\n number = 1,\n pages = {17-30},\n langid = {english},\n langidopts = {variant=american},\n indextitle = {Alkanethiolate gold cluster molecules},\n shorttitle = {Alkanethiolate gold cluster molecules},\n annotation = {An \\texttt{article} entry with \\arabic{author} authors. By\n default, long author and editor lists are automatically\n truncated. This is configurable},\n}\"#)"
----
-Hostetler, Michael J., Wingate, Julia E., Zhong, Chuan-Jian, Harris, Jay E., Vachet, Richard W., Clark, Michael R., … Murray, Royce W. (n.d.). Alkanethiolate gold cluster molecules with core diameters from 1.5 to 5.2 nm: Core and monolayer properties as a function of core size. *Langmuir*, *14*(1), 17–30.
diff --git a/support/texlab/src/snapshots/texlab__citation__tests__biblatex_examples_012.snap b/support/texlab/src/snapshots/texlab__citation__tests__biblatex_examples_012.snap
deleted file mode 100644
index a99fa01b9c..0000000000
--- a/support/texlab/src/snapshots/texlab__citation__tests__biblatex_examples_012.snap
+++ /dev/null
@@ -1,6 +0,0 @@
----
-source: src/citation.rs
-assertion_line: 427
-expression: "render_simple(r#\"\n@article{reese,\n author = {Reese, Trevor R.},\n title = {Georgia in {Anglo-Spanish} Diplomacy, 1736--1739},\n journaltitle = {William and Mary Quarterly},\n date = 1958,\n series = 3,\n volume = 15,\n pages = {168-190},\n langid = {english},\n langidopts = {variant=american},\n annotation = {An \\texttt{article} entry with a \\texttt{series} and a\n \\texttt{volume} field. Note the format of the series. If the\n value of the \\texttt{series} field is an integer, this number\n is printed as an ordinal and the string \\enquote*{series} is\n appended automatically},\n}\"#)"
----
-Reese, Trevor R. (n.d.). Georgia in Anglo-Spanish Diplomacy, 1736–1739. *William and Mary Quarterly*, *15*, 168–190.
diff --git a/support/texlab/src/snapshots/texlab__citation__tests__biblatex_examples_013.snap b/support/texlab/src/snapshots/texlab__citation__tests__biblatex_examples_013.snap
deleted file mode 100644
index cdca99c3b4..0000000000
--- a/support/texlab/src/snapshots/texlab__citation__tests__biblatex_examples_013.snap
+++ /dev/null
@@ -1,6 +0,0 @@
----
-source: src/citation.rs
-assertion_line: 450
-expression: "render_simple(r#\"\n@article{sarfraz,\n author = {M. Sarfraz and M. F. A. Razzak},\n title = {Technical section: {An} algorithm for automatic capturing of\n the font outlines},\n year = 2002,\n volume = 26,\n number = 5,\n pages = {795-804},\n issn = {0097-8493},\n journal = {Computers and Graphics},\n annotation = {An \\texttt{article} entry with an \\texttt{issn} field},\n}\"#)"
----
-Sarfraz, M., & Razzak, M. F. A. (2002). Technical section: An algorithm for automatic capturing of the font outlines. *Computers and Graphics*, *26*(5), 795–804.
diff --git a/support/texlab/src/snapshots/texlab__citation__tests__biblatex_examples_014.snap b/support/texlab/src/snapshots/texlab__citation__tests__biblatex_examples_014.snap
deleted file mode 100644
index 436d4fcbd9..0000000000
--- a/support/texlab/src/snapshots/texlab__citation__tests__biblatex_examples_014.snap
+++ /dev/null
@@ -1,6 +0,0 @@
----
-source: src/citation.rs
-assertion_line: 469
-expression: "render_simple(r#\"\n@article{shore,\n author = {Shore, Bradd},\n title = {Twice-Born, Once Conceived},\n journaltitle = {American Anthropologist},\n date = {1991-03},\n subtitle = {Meaning Construction and Cultural Cognition},\n series = {newseries},\n volume = 93,\n number = 1,\n pages = {9-27},\n annotation = {An \\texttt{article} entry with \\texttt{series},\n \\texttt{volume}, and \\texttt{number} fields. Note the format\n of the \\texttt{series} which is a localization key},\n}\"#)"
----
-Shore, Bradd. (n.d.). Twice-Born, Once Conceived: Meaning Construction and Cultural Cognition. *American Anthropologist*, *93*(1), 9–27.
diff --git a/support/texlab/src/snapshots/texlab__citation__tests__biblatex_examples_015.snap b/support/texlab/src/snapshots/texlab__citation__tests__biblatex_examples_015.snap
deleted file mode 100644
index 4d787a627a..0000000000
--- a/support/texlab/src/snapshots/texlab__citation__tests__biblatex_examples_015.snap
+++ /dev/null
@@ -1,6 +0,0 @@
----
-source: src/citation.rs
-assertion_line: 490
-expression: "render_simple(r#\"\n@article{sigfridsson,\n author = {Sigfridsson, Emma and Ryde, Ulf},\n title = {Comparison of methods for deriving atomic charges from the\n electrostatic potential and moments},\n journaltitle = {Journal of Computational Chemistry},\n date = 1998,\n volume = 19,\n number = 4,\n pages = {377-395},\n doi = {10.1002/(SICI)1096-987X(199803)19:4<377::AID-JCC1>3.0.CO;2-P},\n langid = {english},\n langidopts = {variant=american},\n indextitle = {Methods for deriving atomic charges},\n annotation = {An \\texttt{article} entry with \\texttt{volume},\n \\texttt{number}, and \\texttt{doi} fields. Note that the\n \\textsc{doi} is transformed into a clickable link if\n \\texttt{hyperref} support has been enabled},\n abstract = {Four methods for deriving partial atomic charges from the\n quantum chemical electrostatic potential (CHELP, CHELPG,\n Merz-Kollman, and RESP) have been compared and critically\n evaluated. It is shown that charges strongly depend on how and\n where the potential points are selected. Two alternative\n methods are suggested to avoid the arbitrariness in the\n point-selection schemes and van der Waals exclusion radii:\n CHELP-BOW, which also estimates the charges from the\n electrostatic potential, but with potential points that are\n Boltzmann-weighted after their occurrence in actual\n simulations using the energy function of the program in which\n the charges will be used, and CHELMO, which estimates the\n charges directly from the electrostatic multipole\n moments. Different criteria for the quality of the charges are\n discussed.},\n}\"#)"
----
-Sigfridsson, Emma, & Ryde, Ulf. (n.d.). Comparison of methods for deriving atomic charges from the electrostatic potential and moments. *Journal of Computational Chemistry*, *19*(4), 377–395. [https://doi.org/10.1002/(SICI)1096-987X(199803)19:4%3C377::AID-JCC1%3E3.0.CO;2-P](https://doi.org/10.1002/(SICI)1096-987X(199803)19:4%3C377::AID-JCC1%3E3.0.CO;2-P)
diff --git a/support/texlab/src/snapshots/texlab__citation__tests__biblatex_examples_016.snap b/support/texlab/src/snapshots/texlab__citation__tests__biblatex_examples_016.snap
deleted file mode 100644
index 1d08417a11..0000000000
--- a/support/texlab/src/snapshots/texlab__citation__tests__biblatex_examples_016.snap
+++ /dev/null
@@ -1,6 +0,0 @@
----
-source: src/citation.rs
-assertion_line: 530
-expression: "render_simple(r#\"\n@article{spiegelberg,\n author = {Spiegelberg, Herbert},\n title = {\\mkbibquote{Intention} und \\mkbibquote{Intentionalit{\\\"a}t} in\n der Scholastik, bei Brentano und Husserl},\n journaltitle = {Studia Philosophica},\n date = 1969,\n volume = 29,\n pages = {189-216},\n langid = {german},\n sorttitle = {Intention und Intentionalitat in der Scholastik, bei Brentano\n und Husserl},\n indexsorttitle= {Intention und Intentionalitat in der Scholastik, bei Brentano\n und Husserl},\n shorttitle = {Intention und Intentionalit{\\\"a}t},\n annotation = {An \\texttt{article} entry. Note the \\texttt{sorttitle} and\n \\texttt{indexsorttitle} fields and the markup of the quotes in\n the database file},\n}\"#)"
----
-Spiegelberg, Herbert. (n.d.). Intention und Intentionalität in der Scholastik, bei Brentano und Husserl. *Studia Philosophica*, *29*, 189–216.
diff --git a/support/texlab/src/syntax/build_log.rs b/support/texlab/src/syntax/build_log.rs
index a717bdb877..af03e51d11 100644
--- a/support/texlab/src/syntax/build_log.rs
+++ b/support/texlab/src/syntax/build_log.rs
@@ -182,97 +182,94 @@ impl PartialOrd for FileRange {
#[cfg(test)]
mod tests {
use super::*;
- use indoc::indoc;
use insta::assert_debug_snapshot;
#[test]
- fn test_parse_001() {
- let log = indoc! {
- 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)"#,
- };
+ 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,
@@ -295,74 +292,72 @@ mod tests {
}
#[test]
- fn test_parse_002() {
- let log = indoc! {
- 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)"#,
- };
+ 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,
@@ -376,75 +371,73 @@ mod tests {
}
#[test]
- fn test_parse_003() {
- let log = indoc! {
- 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)"#,
- };
+ 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,
@@ -466,93 +459,91 @@ mod tests {
}
#[test]
- fn test_parse_004() {
- let log = indoc! {
- 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)"#,
- };
+ 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,
@@ -574,395 +565,393 @@ mod tests {
}
#[test]
- fn test_parse_005() {
- let log = indoc! {
- 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)"#,
- };
+ 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,
@@ -990,132 +979,130 @@ mod tests {
}
#[test]
- fn test_parse_006() {
- let log = indoc! {
- 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)"#,
- };
+ 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,
@@ -1161,186 +1148,184 @@ mod tests {
}
#[test]
- fn test_parse_007() {
- let log = indoc! {
- 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)"#,
- };
+ 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/analysis/implicit_link.rs b/support/texlab/src/syntax/latex/analysis/implicit_link.rs
index bba3acfb80..60524c623e 100644
--- a/support/texlab/src/syntax/latex/analysis/implicit_link.rs
+++ b/support/texlab/src/syntax/latex/analysis/implicit_link.rs
@@ -1,4 +1,4 @@
-use std::sync::Arc;
+use std::{path::Path, sync::Arc};
use lsp_types::Url;
@@ -19,26 +19,40 @@ fn find_by_extension(context: &LatexAnalyzerContext, extension: &str) -> Option<
let options = &context.environment.options;
if let Some(root_dir) = options.root_directory.as_ref() {
- let path = context
- .environment
- .current_directory
- .join(root_dir)
- .join(&aux_name);
- targets.push(Arc::new(Url::from_file_path(path).ok()?));
+ find_inside_directory(context, root_dir, &aux_name, &mut targets)?;
}
if let Some(build_dir) = options.aux_directory.as_ref() {
- let path = context
- .environment
- .current_directory
- .join(build_dir)
- .join(&aux_name);
- targets.push(Arc::new(Url::from_file_path(path).ok()?));
+ 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
diff --git a/support/texlab/src/syntax/latex/cst.rs b/support/texlab/src/syntax/latex/cst.rs
index 06c187213d..a83246571d 100644
--- a/support/texlab/src/syntax/latex/cst.rs
+++ b/support/texlab/src/syntax/latex/cst.rs
@@ -233,7 +233,7 @@ impl Key {
self.syntax()
.children_with_tokens()
.filter_map(|node| node.into_token())
- .filter(|node| node.kind() == WORD)
+ .filter(|node| !matches!(node.kind(), WHITESPACE | LINE_BREAK | COMMENT))
}
}
diff --git a/support/texlab/src/syntax/latex/parser.rs b/support/texlab/src/syntax/latex/parser.rs
index db9462874b..a43a77ebc9 100644
--- a/support/texlab/src/syntax/latex/parser.rs
+++ b/support/texlab/src/syntax/latex/parser.rs
@@ -854,7 +854,10 @@ 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)) {
+ while matches!(
+ self.peek(),
+ Some(WORD | L_BRACK | R_BRACK | GENERIC_COMMAND_NAME)
+ ) {
self.path();
}
@@ -866,17 +869,24 @@ impl<'a> Parser<'a> {
self.builder.start_node(CURLY_GROUP_WORD_LIST.into());
self.eat();
- while self
- .peek()
- .filter(|&kind| {
- matches!(
- kind,
- LINE_BREAK | WHITESPACE | COMMENT | WORD | COMMA | EQUALITY_SIGN
- )
- })
- .is_some()
- {
- if self.peek() == Some(WORD) {
+ 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();
@@ -890,11 +900,18 @@ impl<'a> Parser<'a> {
fn path(&mut self) {
self.builder.start_node(KEY.into());
self.eat();
- while self
- .peek()
- .filter(|&kind| matches!(kind, WHITESPACE | COMMENT | WORD | EQUALITY_SIGN))
- .is_some()
- {
+ while self.peek().map_or(false, |kind| {
+ matches!(
+ kind,
+ WHITESPACE
+ | COMMENT
+ | WORD
+ | EQUALITY_SIGN
+ | L_BRACK
+ | R_BRACK
+ | GENERIC_COMMAND_NAME
+ )
+ }) {
self.eat();
}
@@ -1583,6 +1600,11 @@ mod tests {
}
#[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}"#));
}
@@ -1613,6 +1635,13 @@ mod tests {
}
#[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}"#));
}
diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__graphics_include_command.snap b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__graphics_include_command.snap
new file mode 100644
index 0000000000..d279eda7f7
--- /dev/null
+++ b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__graphics_include_command.snap
@@ -0,0 +1,31 @@
+---
+source: src/syntax/latex/parser.rs
+assertion_line: 1639
+expression: "setup(r#\"\\includegraphics[width=0.5\\textwidth]{\\foo.\\bar.pdf}\"#)"
+---
+ROOT@0..52
+ PREAMBLE@0..52
+ GRAPHICS_INCLUDE@0..52
+ GRAPHICS_INCLUDE_NAME@0..16 "\\includegraphics"
+ BRACK_GROUP_KEY_VALUE@16..37
+ L_BRACK@16..17 "["
+ KEY_VALUE_BODY@17..36
+ KEY_VALUE_PAIR@17..36
+ KEY@17..22
+ WORD@17..22 "width"
+ EQUALITY_SIGN@22..23 "="
+ VALUE@23..36
+ TEXT@23..26
+ WORD@23..26 "0.5"
+ GENERIC_COMMAND@26..36
+ GENERIC_COMMAND_NAME@26..36 "\\textwidth"
+ R_BRACK@36..37 "]"
+ CURLY_GROUP_WORD_LIST@37..52
+ L_CURLY@37..38 "{"
+ KEY@38..51
+ GENERIC_COMMAND_NAME@38..42 "\\foo"
+ WORD@42..43 "."
+ GENERIC_COMMAND_NAME@43..47 "\\bar"
+ WORD@47..51 ".pdf"
+ R_CURLY@51..52 "}"
+
diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__latex_input_path_with_brackets.snap b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__latex_input_path_with_brackets.snap
new file mode 100644
index 0000000000..cb99f39728
--- /dev/null
+++ b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__latex_input_path_with_brackets.snap
@@ -0,0 +1,19 @@
+---
+source: src/syntax/latex/parser.rs
+assertion_line: 1591
+expression: "setup(r#\"\\input{foo[bar].tex}\"#)"
+---
+ROOT@0..20
+ PREAMBLE@0..20
+ LATEX_INCLUDE@0..20
+ LATEX_INCLUDE_NAME@0..6 "\\input"
+ CURLY_GROUP_WORD_LIST@6..20
+ L_CURLY@6..7 "{"
+ KEY@7..19
+ WORD@7..10 "foo"
+ L_BRACK@10..11 "["
+ WORD@11..14 "bar"
+ R_BRACK@14..15 "]"
+ WORD@15..19 ".tex"
+ R_CURLY@19..20 "}"
+
diff --git a/support/texlab/src/workspace.rs b/support/texlab/src/workspace.rs
index 8fda9c7c1b..e01a2fede4 100644
--- a/support/texlab/src/workspace.rs
+++ b/support/texlab/src/workspace.rs
@@ -1,4 +1,8 @@
-use std::{fs, path::PathBuf, sync::Arc};
+use std::{
+ fs::{self, FileType},
+ path::PathBuf,
+ sync::Arc,
+};
use anyhow::Result;
use crossbeam_channel::Sender;
@@ -6,7 +10,10 @@ use lsp_types::Url;
use petgraph::{graphmap::UnGraphMap, visit::Dfs};
use rustc_hash::{FxHashMap, FxHashSet};
-use crate::{component_db::COMPONENT_DATABASE, Document, DocumentLanguage, Environment};
+use crate::{
+ component_db::COMPONENT_DATABASE, syntax::latex::ExplicitLink, Document, DocumentLanguage,
+ Environment,
+};
#[derive(Debug, Clone)]
pub enum WorkspaceEvent {
@@ -22,6 +29,7 @@ pub struct Workspace {
}
impl Workspace {
+ #[must_use]
pub fn new(environment: Environment) -> Self {
Self {
environment,
@@ -137,7 +145,8 @@ impl Workspace {
.unwrap_or_default()
}
- fn find_parent(&self, uri: &Url) -> Option<Document> {
+ #[must_use]
+ pub fn find_parent(&self, uri: &Url) -> Option<Document> {
self.slice(uri)
.documents_by_uri
.values()
@@ -148,7 +157,7 @@ impl Workspace {
.extras
.explicit_links
.iter()
- .filter_map(|link| link.as_component_name())
+ .filter_map(ExplicitLink::as_component_name)
.any(|name| name == "subfiles.cls")
})
})
@@ -168,8 +177,8 @@ impl Workspace {
std::fs::read_dir(&path)
.into_iter()
.flatten()
- .filter_map(|entry| entry.ok())
- .filter(|entry| entry.file_type().ok().filter(|ty| ty.is_file()).is_some())
+ .filter_map(Result::ok)
+ .filter(|entry| entry.file_type().ok().filter(FileType::is_file).is_some())
.map(|entry| entry.path())
.filter(|path| {
matches!(
@@ -200,7 +209,7 @@ impl Workspace {
}
}
- all_targets.into_iter().for_each(|targets| {
+ for targets in all_targets {
for path in targets
.iter()
.filter(|uri| uri.scheme() == "file" && uri.fragment().is_none())
@@ -210,7 +219,7 @@ impl Workspace {
break;
}
}
- });
+ }
}
}
}
diff --git a/support/texlab/tests/integration/dev.rs b/support/texlab/tests/integration/dev.rs
new file mode 100644
index 0000000000..7ba1e93d0c
--- /dev/null
+++ b/support/texlab/tests/integration/dev.rs
@@ -0,0 +1,17 @@
+use std::process::{Command, Stdio};
+
+use anyhow::Result;
+
+#[test]
+fn rustfmt() -> Result<()> {
+ let success = Command::new("cargo")
+ .args(&["fmt", "--check"])
+ .current_dir(env!("CARGO_MANIFEST_DIR"))
+ .stdout(Stdio::null())
+ .stderr(Stdio::null())
+ .status()?
+ .success();
+
+ assert!(success);
+ Ok(())
+}
diff --git a/support/texlab/tests/integration/lsp.rs b/support/texlab/tests/integration/lsp.rs
new file mode 100644
index 0000000000..9ef1a4f2b4
--- /dev/null
+++ b/support/texlab/tests/integration/lsp.rs
@@ -0,0 +1,4 @@
+mod client;
+mod fixture;
+mod text_document;
+mod workspace;
diff --git a/support/texlab/tests/integration/lsp/client.rs b/support/texlab/tests/integration/lsp/client.rs
new file mode 100644
index 0000000000..dc6b66795c
--- /dev/null
+++ b/support/texlab/tests/integration/lsp/client.rs
@@ -0,0 +1,158 @@
+use anyhow::{bail, Result};
+use crossbeam_channel::{Receiver, Sender};
+use lsp_server::{Connection, Message, Notification, Request, Response};
+use lsp_types::{
+ notification::{Exit, Initialized},
+ request::{Initialize, Shutdown},
+ ClientCapabilities, ClientInfo, DidOpenTextDocumentParams, InitializeParams, InitializeResult,
+ InitializedParams, Url,
+};
+use tempfile::{tempdir, TempDir};
+use texlab::Server;
+
+pub struct IncomingHandler {
+ _handle: jod_thread::JoinHandle<Result<()>>,
+ pub requests: Receiver<Request>,
+ pub notifications: Receiver<Notification>,
+ pub responses: Receiver<Response>,
+}
+
+impl IncomingHandler {
+ pub fn spawn(receiver: Receiver<Message>) -> Result<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();
+
+ let _handle = jod_thread::spawn(move || {
+ for message in &receiver {
+ match message {
+ Message::Request(req) => req_sender.send(req)?,
+ Message::Response(res) => res_sender.send(res)?,
+ Message::Notification(not) => not_sender.send(not)?,
+ };
+ }
+
+ Ok(())
+ });
+
+ Ok(Self {
+ _handle,
+ requests: req_receiver,
+ notifications: not_receiver,
+ responses: res_receiver,
+ })
+ }
+}
+
+pub struct ClientResult {
+ pub directory: TempDir,
+ pub incoming: IncomingHandler,
+}
+
+pub struct Client {
+ outgoing: Sender<Message>,
+ incoming: IncomingHandler,
+ directory: TempDir,
+ request_id: i32,
+ _handle: jod_thread::JoinHandle,
+}
+
+impl Client {
+ pub fn spawn() -> Result<Self> {
+ let directory = tempdir()?;
+ let (client, server) = Connection::memory();
+ let incoming = IncomingHandler::spawn(client.receiver)?;
+ let outgoing = client.sender;
+ let server = Server::with_connection(server, directory.path().to_path_buf(), false);
+ let _handle = jod_thread::spawn(move || {
+ server.run().expect("server failed to run");
+ });
+
+ Ok(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)
+ }
+
+ pub fn request<R: lsp_types::request::Request>(
+ &mut self,
+ params: R::Params,
+ ) -> Result<R::Result> {
+ self.request_id += 1;
+
+ self.outgoing
+ .send(Request::new(self.request_id.into(), R::METHOD.into(), params).into())?;
+
+ let response = self.incoming.responses.recv()?;
+ assert_eq!(response.id, self.request_id.into());
+
+ let result = match response.result {
+ Some(result) => result,
+ None => bail!("request failed: {:?}", response.error),
+ };
+
+ Ok(serde_json::from_value(result)?)
+ }
+
+ pub fn notify<N: lsp_types::notification::Notification>(
+ &mut self,
+ params: N::Params,
+ ) -> Result<()> {
+ self.outgoing
+ .send(Notification::new(N::METHOD.into(), serde_json::to_value(params)?).into())?;
+
+ Ok(())
+ }
+
+ pub fn open(&mut self, name: &str, language_id: &str, text: String) -> Result<()> {
+ self.notify::<lsp_types::notification::DidOpenTextDocument>(DidOpenTextDocumentParams {
+ text_document: lsp_types::TextDocumentItem {
+ uri: self.uri(name)?,
+ language_id: language_id.to_string(),
+ version: 0,
+ text,
+ },
+ })?;
+
+ Ok(())
+ }
+
+ pub fn shutdown(mut self) -> Result<ClientResult> {
+ self.request::<Shutdown>(())?;
+ self.notify::<Exit>(())?;
+ Ok(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"))
+ }
+}
diff --git a/support/texlab/tests/integration/lsp/fixture.rs b/support/texlab/tests/integration/lsp/fixture.rs
new file mode 100644
index 0000000000..17eb659923
--- /dev/null
+++ b/support/texlab/tests/integration/lsp/fixture.rs
@@ -0,0 +1,123 @@
+use std::collections::BTreeMap;
+
+use anyhow::Result;
+use lsp_types::{Position, Range, TextDocumentIdentifier, TextDocumentPositionParams};
+use rustc_hash::FxHashMap;
+
+use crate::lsp::client::Client;
+
+#[derive(Debug, PartialEq, Eq, Clone, Hash)]
+enum Line<'a> {
+ File(&'a str, &'a str),
+ Plain(&'a str),
+ Range(u32, u32, std::ops::Range<usize>),
+ Cursor(usize),
+ Empty,
+}
+
+fn parse_line(line: &str) -> Line {
+ if let Some(name) = line.strip_prefix("%TEX ") {
+ Line::File(name, "latex")
+ } else if let Some(name) = line.strip_prefix("%BIB ") {
+ Line::File(name, "bibtex")
+ } else if let Some(text) = line.strip_prefix("%SRC ") {
+ Line::Plain(text)
+ } else if let Some(text) = line.strip_prefix("%CUR ") {
+ let position = text.find('^').unwrap();
+ Line::Cursor(position)
+ } else if line.is_empty() {
+ Line::Empty
+ } else {
+ let key1 = line[1..2].parse().unwrap();
+ let key2 = line[3..4].parse().unwrap();
+ let line = &line[5..];
+ let range = line
+ .find('^')
+ .map_or(0..0, |start| start..(line.rfind('^').unwrap() + 1));
+ Line::Range(key1, key2, range)
+ }
+}
+
+#[derive(Debug, Default)]
+pub struct FileRange<'a> {
+ pub name: &'a str,
+ pub range: Range,
+}
+
+#[derive(Debug, Default)]
+pub struct File<'a> {
+ pub name: &'a str,
+ pub lang: &'a str,
+ pub text: String,
+}
+
+#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
+pub struct FileCursor<'a> {
+ pub name: &'a str,
+ pub position: Position,
+}
+
+impl<'a> FileCursor<'a> {
+ pub fn into_params(self, server: &Client) -> Result<TextDocumentPositionParams> {
+ let text_document = TextDocumentIdentifier::new(server.uri(self.name)?);
+ Ok(TextDocumentPositionParams {
+ text_document,
+ position: self.position,
+ })
+ }
+}
+
+#[derive(Debug, Default)]
+pub struct Fixture<'a> {
+ pub files: Vec<File<'a>>,
+ pub cursor: Option<FileCursor<'a>>,
+ pub ranges: BTreeMap<u32, FxHashMap<u32, FileRange<'a>>>,
+}
+
+pub fn parse(input: &str) -> Fixture {
+ let mut fixture = Fixture::default();
+ let mut file = File::default();
+ let mut file_line_index = 0;
+ for line in input.lines().map(parse_line) {
+ match line {
+ Line::File(name, lang) => {
+ if !file.name.is_empty() {
+ fixture.files.push(file);
+ file = File::default();
+ }
+
+ file.name = name;
+ file.lang = lang;
+ file_line_index = 0;
+ }
+ Line::Plain(line) => {
+ file.text.push_str(line);
+ file.text.push('\n');
+ file_line_index += 1;
+ }
+ Line::Range(key1, key2, range) => {
+ let line = file_line_index - 1;
+ let start = Position::new(line, range.start.try_into().unwrap());
+ let end = Position::new(line, range.end.try_into().unwrap());
+ let range = Range::new(start, end);
+ fixture.ranges.entry(key1).or_default().insert(
+ key2,
+ FileRange {
+ name: file.name,
+ range,
+ },
+ );
+ }
+ Line::Cursor(position) => {
+ fixture.cursor = Some(FileCursor {
+ name: file.name,
+ position: Position::new(file_line_index - 1, position.try_into().unwrap()),
+ });
+ }
+ Line::Empty => {}
+ };
+ }
+
+ fixture.files.push(file);
+ fixture
+}
diff --git a/support/texlab/tests/integration/lsp/text_document.rs b/support/texlab/tests/integration/lsp/text_document.rs
new file mode 100644
index 0000000000..56ad1ee09f
--- /dev/null
+++ b/support/texlab/tests/integration/lsp/text_document.rs
@@ -0,0 +1,11 @@
+#[cfg(feature = "completion")]
+mod completion;
+mod definition;
+mod document_highlight;
+mod document_link;
+mod document_symbol;
+mod folding_range;
+mod formatting;
+mod hover;
+mod references;
+mod rename;
diff --git a/support/texlab/tests/integration/lsp/text_document/completion.rs b/support/texlab/tests/integration/lsp/text_document/completion.rs
new file mode 100644
index 0000000000..5e160904fe
--- /dev/null
+++ b/support/texlab/tests/integration/lsp/text_document/completion.rs
@@ -0,0 +1,870 @@
+use anyhow::Result;
+use insta::assert_json_snapshot;
+use lsp_types::{
+ request::{Completion, ResolveCompletionItem},
+ ClientCapabilities, CompletionItem, CompletionList, CompletionParams, CompletionResponse,
+ CompletionTextEdit, Range,
+};
+
+use crate::lsp::{client::Client, fixture};
+
+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)?;
+ }
+
+ let range = fixture
+ .ranges
+ .values()
+ .next()
+ .and_then(|map| map.values().next())
+ .map_or_else(
+ || {
+ let position = fixture.cursor.unwrap().position;
+ Range::new(position, position)
+ },
+ |file_range| file_range.range,
+ );
+
+ let actual_list = client
+ .request::<Completion>(CompletionParams {
+ text_document_position: fixture.cursor.unwrap().into_params(&client)?,
+ partial_result_params: Default::default(),
+ work_done_progress_params: Default::default(),
+ context: None,
+ })?
+ .map_or(CompletionList::default(), |actual| match actual {
+ CompletionResponse::List(list) => list,
+ CompletionResponse::Array(_) => unreachable!(),
+ });
+
+ for item in &actual_list.items {
+ if let Some(CompletionTextEdit::Edit(edit)) = item.text_edit.as_ref() {
+ assert_eq!(edit.range, range);
+ }
+ }
+
+ let actual_items = actual_list
+ .items
+ .into_iter()
+ .take(5)
+ .map(|item| client.request::<ResolveCompletionItem>(item))
+ .collect::<Result<Vec<_>>>()?;
+
+ client.shutdown()?;
+ Ok(actual_items)
+}
+
+macro_rules! assert_items {
+ ($items:expr) => {
+ assert_json_snapshot!($items, {
+ "[].data" => "[data]",
+ "[].sortText" => "[sortText]",
+ "[].documentation" => "[documentation]",
+ "[].textEdit.range" => "[range]",
+ "[]" => insta::sorted_redaction()
+ });
+ };
+}
+
+#[test]
+fn acronym_ref_simple() -> Result<()> {
+ assert_items!(complete(
+ r#"
+%TEX main.tex
+%SRC \newacronym[longplural={Frames per Second}]{fpsLabel}{FPS}{Frame per Second}
+%SRC \acrshort{f}
+%CUR ^
+%1.1 ^"#
+ )?);
+
+ Ok(())
+}
+
+#[test]
+fn acronym_ref_empty() -> Result<()> {
+ 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<()> {
+ let actual_items = complete(
+ r#"
+%TEX main.tex
+%SRC \newacronym[longplural={Frames per Second}]{fpsLabel}{FPS}{Frame per Second}
+%SRC \acrshort{}
+%CUR ^
+%1.1 ^"#,
+ )?;
+
+ assert_eq!(actual_items, Vec::new());
+ Ok(())
+}
+
+#[test]
+fn acronym_ref_open_brace() -> Result<()> {
+ assert_items!(complete(
+ r#"
+%TEX main.tex
+%SRC \newacronym[longplural={Frames per Second}]{fpsLabel}{FPS}{Frame per Second}
+%SRC \acrshort{f
+%CUR ^
+%1.1 ^"#
+ )?);
+
+ Ok(())
+}
+
+#[test]
+fn glossary_ref_simple() -> Result<()> {
+ assert_items!(complete(
+ r#"
+%TEX main.tex
+%SRC \newacronym[longplural={Frames per Second}]{fpsLabel}{FPS}{Frame per Second}
+%SRC \gls{f}
+%CUR ^
+%1.1 ^"#
+ )?);
+
+ Ok(())
+}
+
+#[test]
+fn glossary_ref_open_brace() -> Result<()> {
+ assert_items!(complete(
+ r#"
+%TEX main.tex
+%SRC \newacronym[longplural={Frames per Second}]{fpsLabel}{FPS}{Frame per Second}
+%SRC \gls{f
+%CUR ^
+%1.1 ^"#
+ )?);
+
+ Ok(())
+}
+
+#[test]
+fn argument_empty() -> Result<()> {
+ assert_items!(complete(
+ r#"
+%TEX main.tex
+%SRC \usepackage{amsfonts}
+%SRC \mathbb{}
+%CUR ^"#
+ )?);
+
+ Ok(())
+}
+
+#[test]
+fn argument_word() -> Result<()> {
+ assert_items!(complete(
+ r#"
+%TEX main.tex
+%SRC \usepackage{amsfonts}
+%SRC \mathbb{A}
+%CUR ^
+%1.1 ^"#
+ )?);
+
+ Ok(())
+}
+
+#[test]
+fn argument_open_brace() -> Result<()> {
+ assert_items!(complete(
+ r#"
+%TEX main.tex
+%SRC \usepackage{amsfonts}
+%SRC \mathbb{
+%CUR ^
+%SRC Test"#
+ )?);
+
+ Ok(())
+}
+
+#[test]
+fn argument_open_brace_unrelated() -> Result<()> {
+ let actual_items = complete(
+ r#"
+%TEX main.tex
+%SRC \usepackage{amsfonts}
+%SRC \mathbb{}{
+%CUR ^
+%SRC Test"#,
+ )?;
+
+ assert_eq!(actual_items, Vec::new());
+ Ok(())
+}
+
+#[test]
+fn begin_environment_without_snippet_support() -> Result<()> {
+ assert_items!(complete(
+ r#"
+%TEX main.tex
+%SRC \beg
+%CUR ^
+%1.1 ^^^"#
+ )?);
+
+ Ok(())
+}
+
+#[test]
+fn citation() -> Result<()> {
+ assert_items!(complete(
+ r#"
+%TEX main.tex
+%SRC \documentclass{article}
+%SRC \bibliography{main}
+%SRC \begin{document}
+%SRC \cite{
+%CUR ^
+%SRC \end{document}
+
+%BIB main.bib
+%SRC @article{foo:2019,
+%SRC author = {Foo Bar},
+%SRC title = {Baz Qux},
+%SRC year = {2019},
+%SRC }
+%SRC
+%SRC @article{bar:2005,}"#
+ )?);
+
+ Ok(())
+}
+
+#[test]
+fn citation_open_brace() -> Result<()> {
+ assert_items!(complete(
+ r#"
+%TEX main.tex
+%SRC \addbibresource{main.bib}
+%SRC \cite{
+%CUR ^
+
+%BIB main.bib
+%SRC @article{foo,}"#
+ )?);
+
+ Ok(())
+}
+
+#[test]
+fn citation_open_brace_multiple() -> Result<()> {
+ assert_items!(complete(
+ r#"
+%TEX main.tex
+%SRC \addbibresource{main.bib}
+%SRC \cite{foo,a
+%CUR ^
+%1.1 ^
+
+%BIB main.bib
+%SRC @article{foo,}"#
+ )?);
+
+ Ok(())
+}
+
+#[test]
+fn citation_acronym() -> Result<()> {
+ assert_items!(complete(
+ r#"
+%TEX main.tex
+%SRC \addbibresource{main.bib}
+%SRC \DeclareAcronym{foo}{cite={}}
+%CUR ^
+
+%BIB main.bib
+%SRC @article{foo,}"#
+ )?);
+
+ Ok(())
+}
+
+#[test]
+fn citation_after_brace() -> Result<()> {
+ let actual_items = complete(
+ r#"
+%TEX main.tex
+%SRC \documentclass{article}
+%SRC \bibliography{main}
+%SRC \begin{document}
+%SRC \cite{}
+%CUR ^
+%SRC \end{document}
+
+%BIB main.bib
+%SRC @article{foo,}"#,
+ )?;
+
+ assert_eq!(actual_items, Vec::new());
+ Ok(())
+}
+
+#[test]
+fn color_model_definition_simple() -> Result<()> {
+ assert_items!(complete(
+ r#"
+%TEX main.tex
+%SRC \definecolor{foo}{}
+%CUR ^"#
+ )?);
+
+ Ok(())
+}
+
+#[test]
+fn color_model_definition_open_brace() -> Result<()> {
+ assert_items!(complete(
+ r#"
+%TEX main.tex
+%SRC \definecolor{foo}{
+%CUR ^"#
+ )?);
+
+ Ok(())
+}
+
+#[test]
+fn color_model_definition_set_simple() -> Result<()> {
+ assert_items!(complete(
+ r#"
+%TEX main.tex
+%SRC \definecolorset{}
+%CUR ^"#
+ )?);
+
+ Ok(())
+}
+
+#[test]
+fn color_model_definition_set_open_brace() -> Result<()> {
+ assert_items!(complete(
+ r#"
+%TEX main.tex
+%SRC \definecolorset{
+%CUR ^"#
+ )?);
+
+ Ok(())
+}
+
+#[test]
+fn color_simple() -> Result<()> {
+ assert_items!(complete(
+ r#"
+%TEX main.tex
+%SRC \color{}
+%CUR ^"#
+ )?);
+
+ Ok(())
+}
+
+#[test]
+fn color_word() -> Result<()> {
+ assert_items!(complete(
+ r#"
+%TEX main.tex
+%SRC \color{re}
+%CUR ^
+%1.1 ^^"#
+ )?);
+
+ Ok(())
+}
+
+#[test]
+fn color_open_brace() -> Result<()> {
+ assert_items!(complete(
+ r#"
+%TEX main.tex
+%SRC \color{
+%CUR ^"#
+ )?);
+
+ Ok(())
+}
+
+#[test]
+fn component_command_simple() -> Result<()> {
+ assert_items!(complete(
+ r#"
+%TEX main.tex
+%SRC \
+%CUR ^"#
+ )?);
+
+ Ok(())
+}
+
+#[test]
+fn component_command_simple_before() -> Result<()> {
+ let actual_items = complete(
+ r#"
+%TEX main.tex
+%SRC \
+%CUR ^"#,
+ )?;
+
+ assert_eq!(actual_items, Vec::new());
+ Ok(())
+}
+
+#[test]
+fn component_command_simple_package() -> Result<()> {
+ assert_items!(complete(
+ r#"
+%TEX main.tex
+%SRC \usepackage{lipsum}
+%SRC \lips
+%CUR ^
+%1.1 ^^^^"#
+ )?);
+
+ Ok(())
+}
+
+#[test]
+fn component_command_bibtex() -> Result<()> {
+ assert_items!(complete(
+ r#"
+%BIB main.bib
+%SRC @article{b,
+%SRC c = {\LaT }
+%CUR ^
+%1.1 ^^^
+%SRC }"#
+ )?);
+
+ Ok(())
+}
+
+#[test]
+fn component_environment_simple() -> Result<()> {
+ assert_items!(complete(
+ r#"
+%TEX main.tex
+%SRC \begin{doc
+%CUR ^
+%1.1 ^^^"#
+ )?);
+
+ Ok(())
+}
+
+#[test]
+fn component_environment_simple_end() -> Result<()> {
+ assert_items!(complete(
+ r#"
+%TEX main.tex
+%SRC \begin{document}
+%SRC \end{
+%CUR ^"#
+ )?);
+
+ Ok(())
+}
+
+#[test]
+fn component_environment_class() -> Result<()> {
+ assert_items!(complete(
+ r#"
+%TEX main.tex
+%SRC \documentclass{article}
+%SRC \begin{thein}
+%CUR ^
+%1.1 ^^^^^"#
+ )?);
+
+ Ok(())
+}
+
+#[test]
+fn component_environment_command_definition() -> Result<()> {
+ assert_items!(complete(
+ r#"
+%TEX main.tex
+%SRC \newcommand{\foo}{\begin{doc}
+%CUR ^
+%1.1 ^^^"#
+ )?);
+
+ Ok(())
+}
+
+#[test]
+fn entry_type_at_empty() -> Result<()> {
+ assert_items!(complete(
+ r#"
+%BIB main.bib
+%SRC @
+%CUR ^"#
+ )?);
+
+ Ok(())
+}
+
+#[test]
+fn entry_type_before_preamble() -> Result<()> {
+ assert_items!(complete(
+ r#"
+%BIB main.bib
+%SRC @preamble
+%CUR ^
+%1.1 ^^^^^^^^"#
+ )?);
+
+ Ok(())
+}
+
+#[test]
+fn entry_type_before_string() -> Result<()> {
+ assert_items!(complete(
+ r#"
+%BIB main.bib
+%SRC @string
+%CUR ^
+%1.1 ^^^^^^"#
+ )?);
+
+ Ok(())
+}
+
+#[test]
+fn entry_type_before_article() -> Result<()> {
+ assert_items!(complete(
+ r#"
+%BIB main.bib
+%SRC @article
+%CUR ^
+%1.1 ^^^^^^^"#
+ )?);
+
+ Ok(())
+}
+
+#[test]
+fn entry_type_after_preamble() -> Result<()> {
+ assert_items!(complete(
+ r#"
+%BIB main.bib
+%SRC @preamble{
+%CUR ^
+%1.1 ^^^^^^^^"#
+ )?);
+
+ Ok(())
+}
+
+#[test]
+fn entry_type_after_string() -> Result<()> {
+ assert_items!(complete(
+ r#"
+%BIB main.bib
+%SRC @string{
+%CUR ^
+%1.1 ^^^^^^"#
+ )?);
+
+ Ok(())
+}
+
+#[test]
+fn entry_type_complete_entry() -> Result<()> {
+ assert_items!(complete(
+ r#"
+%BIB main.bib
+%SRC @article{foo, author = {foo}}
+%CUR ^
+%1.1 ^^^^^^^"#
+ )?);
+
+ Ok(())
+}
+
+#[test]
+fn field_empty_entry_open() -> Result<()> {
+ assert_items!(complete(
+ r#"
+%BIB main.bib
+%SRC @article{foo,
+%CUR ^"#
+ )?);
+
+ Ok(())
+}
+
+#[test]
+fn field_empty_entry_closed() -> Result<()> {
+ assert_items!(complete(
+ r#"
+%BIB main.bib
+%SRC @article{foo,}
+%CUR ^"#
+ )?);
+
+ Ok(())
+}
+
+#[test]
+fn field_entry_field_name() -> Result<()> {
+ assert_items!(complete(
+ r#"
+%BIB main.bib
+%SRC @article{foo, a
+%CUR ^
+%1.1 ^"#
+ )?);
+
+ Ok(())
+}
+
+#[test]
+fn field_entry_two_fields_name_open() -> Result<()> {
+ 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<()> {
+ assert_items!(complete(
+ r#"
+%BIB main.bib
+%SRC @article{foo, author = bar, edit}
+%CUR ^
+%1.1 ^^^^"#
+ )?);
+
+ Ok(())
+}
+
+#[test]
+fn import_package_open_brace() -> Result<()> {
+ assert_items!(complete(
+ r#"
+%TEX main.tex
+%SRC \usepackage{lips
+%CUR ^
+%1.1 ^^^^"#
+ )?);
+
+ Ok(())
+}
+
+#[test]
+fn import_package_closed_brace() -> Result<()> {
+ assert_items!(complete(
+ r#"
+%TEX main.tex
+%SRC \usepackage{lips}
+%CUR ^
+%1.1 ^^^^"#
+ )?);
+
+ Ok(())
+}
+
+#[test]
+fn import_class_open_brace() -> Result<()> {
+ assert_items!(complete(
+ r#"
+%TEX main.tex
+%SRC \documentclass{art \foo
+%CUR ^
+%1.1 ^^^"#
+ )?);
+
+ Ok(())
+}
+
+#[test]
+fn import_class_closed_brace() -> Result<()> {
+ assert_items!(complete(
+ r#"
+%TEX main.tex
+%SRC \documentclass{art}
+%CUR ^
+%1.1 ^^^"#
+ )?);
+
+ Ok(())
+}
+
+#[test]
+fn label() -> Result<()> {
+ assert_items!(complete(
+ r#"
+%TEX foo.tex
+%SRC \documentclass{article}
+%SRC
+%SRC \usepackage{amsmath}
+%SRC \usepackage{caption}
+%SRC \usepackage{amsthm}
+%SRC \newtheorem{lemma}{Lemma}
+%SRC
+%SRC \begin{document}
+%SRC
+%SRC \section{Foo}%
+%SRC \label{sec:foo}
+%SRC
+%SRC \begin{equation}%
+%SRC \label{eq:foo}
+%SRC 1 + 1 = 2
+%SRC \end{equation}
+%SRC
+%SRC \begin{equation}%
+%SRC \label{eq:bar}
+%SRC 1 + 1 = 2
+%SRC \end{equation}
+%SRC
+%SRC \begin{figure}%
+%SRC \LaTeX{}
+%SRC \caption{Baz}%
+%SRC \label{fig:baz}
+%SRC \end{figure}
+%SRC
+%SRC \begin{lemma}%
+%SRC \label{thm:foo}
+%SRC 1 + 1 = 2
+%SRC \end{lemma}
+%SRC
+%SRC \include{bar}
+%SRC
+%SRC \end{document}
+
+%TEX bar.tex
+%SRC \section{Bar}%
+%SRC \label{sec:bar}
+%SRC
+%SRC Lorem ipsum dolor sit amet.
+%SRC \ref{}
+%CUR ^
+
+%TEX foo.aux
+%SRC \relax
+%SRC \@writefile{lof}{\contentsline {figure}{\numberline {1}{\ignorespaces Baz\relax }}{1}\protected@file@percent }
+%SRC \providecommand*\caption@xref[2]{\@setref\relax\@undefined{#1}}
+%SRC \newlabel{fig:baz}{{1}{1}}
+%SRC \@writefile{toc}{\contentsline {section}{\numberline {1}Foo}{1}\protected@file@percent }
+%SRC \newlabel{sec:foo}{{1}{1}}
+%SRC \newlabel{eq:foo}{{1}{1}}
+%SRC \newlabel{eq:bar}{{2}{1}}
+%SRC \newlabel{thm:foo}{{1}{1}}
+%SRC \@input{bar.aux}"#
+ )?);
+
+ Ok(())
+}
+
+#[test]
+fn theorem_begin() -> Result<()> {
+ assert_items!(complete(
+ r#"
+%TEX main.tex
+%SRC \newtheorem{lemma}{Lemma}
+%SRC \begin{lem
+%CUR ^
+%1.1 ^^^"#
+ )?);
+
+ Ok(())
+}
+
+#[test]
+fn theorem_end() -> Result<()> {
+ assert_items!(complete(
+ r#"
+%TEX main.tex
+%SRC \newtheorem{lemma}{Lemma}
+%SRC \begin{}
+%SRC \end{lem
+%CUR ^
+%1.1 ^^^"#
+ )?);
+
+ Ok(())
+}
+
+#[test]
+fn tikz_library_open_brace() -> Result<()> {
+ assert_items!(complete(
+ r#"
+%TEX main.tex
+%SRC \usepgflibrary{
+%CUR ^"#
+ )?);
+
+ Ok(())
+}
+
+#[test]
+fn tikz_library_closed_brace() -> Result<()> {
+ assert_items!(complete(
+ r#"
+%TEX main.tex
+%SRC \usepgflibrary{}
+%CUR ^"#
+ )?);
+
+ Ok(())
+}
+
+#[test]
+fn test_user_command() -> Result<()> {
+ assert_items!(complete(
+ r#"
+%TEX main.tex
+%SRC \foobar
+%SRC \fooba
+%CUR ^
+%1.1 ^^^^^
+%SRC \begin{foo}
+%SRC \end{foo}
+%SRC \begin{fo}
+"#
+ )?);
+
+ Ok(())
+}
+
+#[test]
+fn test_user_environment() -> Result<()> {
+ assert_items!(complete(
+ r#"
+%TEX main.tex
+%SRC \foobar
+%SRC \fooba
+%SRC \begin{foo}
+%SRC \end{foo}
+%SRC \begin{fo}
+%CUR ^
+%1.1 ^^
+"#
+ )?);
+
+ Ok(())
+}
diff --git a/support/texlab/tests/integration/lsp/text_document/definition.rs b/support/texlab/tests/integration/lsp/text_document/definition.rs
new file mode 100644
index 0000000000..203c350464
--- /dev/null
+++ b/support/texlab/tests/integration/lsp/text_document/definition.rs
@@ -0,0 +1,142 @@
+use anyhow::Result;
+use assert_unordered::assert_eq_unordered;
+use lsp_types::{
+ request::GotoDefinition, ClientCapabilities, GotoDefinitionParams, GotoDefinitionResponse,
+ LocationLink,
+};
+
+use crate::lsp::{client::Client, fixture};
+
+fn check(fixture: &str) -> Result<()> {
+ 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)?;
+ }
+
+ 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_range: ranges[&2].range,
+ target_selection_range: ranges[&3].range,
+ });
+ }
+
+ let actual_links = client
+ .request::<GotoDefinition>(GotoDefinitionParams {
+ text_document_position_params: fixture.cursor.unwrap().into_params(&client)?,
+ partial_result_params: Default::default(),
+ work_done_progress_params: Default::default(),
+ })?
+ .map_or(Vec::new(), |actual| match actual {
+ GotoDefinitionResponse::Link(links) => links,
+ GotoDefinitionResponse::Array(_) | GotoDefinitionResponse::Scalar(_) => unreachable!(),
+ });
+
+ client.shutdown()?;
+
+ assert_eq_unordered!(actual_links, expected_links);
+ Ok(())
+}
+
+#[test]
+fn command_definition() -> Result<()> {
+ check(
+ r#"
+%TEX main.tex
+%SRC \DeclareMathOperator{\foo}{foo}
+%1.3 ^^^^
+%1.2 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+%SRC \foo
+%CUR ^
+%1.1 ^^^^
+"#,
+ )
+}
+
+#[test]
+fn document() -> Result<()> {
+ check(
+ r#"
+%TEX foo.tex
+%SRC \addbibresource{baz.bib}
+%CUR ^
+%1.1 ^^^^^^^
+
+%TEX bar.bib
+%SRC @article{foo, bar = {baz}}
+
+%TEX baz.bib
+%SRC @article{foo, bar = {baz}}
+%1.3
+%1.2
+"#,
+ )
+}
+
+#[test]
+fn entry() -> Result<()> {
+ check(
+ r#"
+%TEX foo.tex
+%SRC \addbibresource{baz.bib}
+%SRC \cite{foo}
+%CUR ^
+%1.1 ^^^
+
+%BIB bar.bib
+%SRC @article{foo, bar = {baz}}
+
+%BIB baz.bib
+%SRC @article{foo, bar = {baz}}
+%1.3 ^^^
+%1.2 ^^^^^^^^^^^^^^^^^^^^^^^^^^
+"#,
+ )
+}
+
+#[test]
+fn string_simple() -> Result<()> {
+ check(
+ r#"
+%BIB main.bib
+%SRC @string{foo = {bar}}
+%1.3 ^^^
+%1.2 ^^^^^^^^^^^^^^^^^^^^
+%SRC @article{bar, author = foo}
+%CUR ^
+%1.1 ^^^
+"#,
+ )
+}
+
+#[test]
+fn string_join() -> Result<()> {
+ check(
+ r#"
+%BIB main.bib
+%SRC @string{foo = {bar}}
+%1.3 ^^^
+%1.2 ^^^^^^^^^^^^^^^^^^^^
+%SRC @article{bar, author = foo # "bar"}
+%CUR ^
+%1.1 ^^^
+"#,
+ )
+}
+
+#[test]
+fn string_field() -> Result<()> {
+ check(
+ r#"
+%BIB main.bib
+%SRC @string{foo = {bar}}
+%SRC @article{bar, author = foo # "bar"}
+%CUR ^
+"#,
+ )
+}
diff --git a/support/texlab/tests/integration/lsp/text_document/document_highlight.rs b/support/texlab/tests/integration/lsp/text_document/document_highlight.rs
new file mode 100644
index 0000000000..92102ce0ca
--- /dev/null
+++ b/support/texlab/tests/integration/lsp/text_document/document_highlight.rs
@@ -0,0 +1,62 @@
+use anyhow::Result;
+use assert_unordered::assert_eq_unordered;
+use lsp_types::{
+ request::DocumentHighlightRequest, ClientCapabilities, DocumentHighlight,
+ DocumentHighlightKind, DocumentHighlightParams,
+};
+
+use crate::lsp::{client::Client, fixture};
+
+fn check(fixture: &str) -> Result<()> {
+ 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)?;
+ }
+
+ let mut expected_highlights = Vec::new();
+ for ranges in fixture.ranges.values() {
+ let (i, file_range) = ranges.iter().next().unwrap();
+ let kind = match i {
+ 1 => DocumentHighlightKind::TEXT,
+ 2 => DocumentHighlightKind::READ,
+ 3 => DocumentHighlightKind::WRITE,
+ _ => unreachable!(),
+ };
+
+ expected_highlights.push(DocumentHighlight {
+ range: file_range.range,
+ kind: Some(kind),
+ });
+ }
+
+ let actual_highlights = client
+ .request::<DocumentHighlightRequest>(DocumentHighlightParams {
+ text_document_position_params: fixture.cursor.unwrap().into_params(&client)?,
+ partial_result_params: Default::default(),
+ work_done_progress_params: Default::default(),
+ })?
+ .unwrap_or_default();
+
+ client.shutdown()?;
+
+ assert_eq_unordered!(actual_highlights, expected_highlights);
+ Ok(())
+}
+
+#[test]
+fn test_label() -> Result<()> {
+ check(
+ r#"
+%TEX main.tex
+%SRC \label{foo}
+%CUR ^
+%1.3 ^^^
+%SRC \ref{foo}
+%2.2 ^^^
+%SRC \label{bar}
+"#,
+ )
+}
diff --git a/support/texlab/tests/integration/lsp/text_document/document_link.rs b/support/texlab/tests/integration/lsp/text_document/document_link.rs
new file mode 100644
index 0000000000..1a773fd478
--- /dev/null
+++ b/support/texlab/tests/integration/lsp/text_document/document_link.rs
@@ -0,0 +1,73 @@
+use anyhow::Result;
+use assert_unordered::assert_eq_unordered;
+use lsp_types::{
+ request::DocumentLinkRequest, ClientCapabilities, DocumentLink, DocumentLinkParams,
+ TextDocumentIdentifier,
+};
+
+use crate::lsp::{client::Client, fixture};
+
+fn check(fixture: &str) -> Result<()> {
+ 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)?;
+ }
+
+ 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)?),
+ tooltip: None,
+ data: None,
+ });
+ }
+
+ let actual_links = client
+ .request::<DocumentLinkRequest>(DocumentLinkParams {
+ text_document: TextDocumentIdentifier::new(client.uri(fixture.cursor.unwrap().name)?),
+ work_done_progress_params: Default::default(),
+ partial_result_params: Default::default(),
+ })?
+ .unwrap_or_default();
+
+ client.shutdown()?;
+
+ assert_eq_unordered!(actual_links, expected_links);
+ Ok(())
+}
+
+#[test]
+fn document_include() -> Result<()> {
+ check(
+ r#"
+%TEX foo.tex
+%SRC \input{bar.tex}
+%1.1 ^^^^^^^
+%CUR ^
+
+%TEX bar.tex
+%SRC
+%1.2
+"#,
+ )
+}
+
+#[test]
+fn document_import() -> Result<()> {
+ check(
+ r#"
+%TEX foo.tex
+%SRC \import{bar/}{baz}
+%1.1 ^^^
+%CUR ^
+
+%TEX bar/baz.tex
+%SRC
+%1.2
+"#,
+ )
+}
diff --git a/support/texlab/tests/integration/lsp/text_document/document_symbol.rs b/support/texlab/tests/integration/lsp/text_document/document_symbol.rs
new file mode 100644
index 0000000000..50bb9db3fe
--- /dev/null
+++ b/support/texlab/tests/integration/lsp/text_document/document_symbol.rs
@@ -0,0 +1,427 @@
+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};
+
+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)?;
+
+ let fixture = fixture::parse(fixture);
+ let file = fixture.files.into_iter().next().unwrap();
+ 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 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 {
+ response,
+ uri_redaction,
+ })
+}
+
+macro_rules! assert_symbols {
+ ($result:expr) => {
+ let result = $result;
+ assert_json_snapshot!(result.response, {
+ "[].location.uri" => result.uri_redaction
+ });
+ };
+}
+
+#[test]
+fn enumerate_nested() -> Result<()> {
+ assert_symbols!(find_symbols(
+ r#"
+%TEX main.tex
+%SRC \documentclass{article}
+%SRC
+%SRC \begin{document}
+%SRC
+%SRC \begin{enumerate}
+%SRC \item\label{it:foo} Foo
+%SRC \item\label{it:bar} Bar
+%SRC \item[Baz] Baz
+%SRC \item[Qux]\label{it:qux} Qux
+%SRC \end{enumerate}
+%SRC
+%SRC \end{document}
+
+%TEX main.aux
+%SRC \relax
+%SRC \newlabel{it:foo}{{1}{1}}
+%SRC \newlabel{it:qux}{{2}{1}}
+"#,
+ serde_json::json!({
+ "textDocument": {
+ "documentSymbol": {
+ "hierarchicalDocumentSymbolSupport": true,
+ },
+ },
+ }),
+ )?);
+
+ Ok(())
+}
+
+#[test]
+fn enumerate_flat() -> Result<()> {
+ assert_symbols!(find_symbols(
+ r#"
+%TEX main.tex
+%SRC \documentclass{article}
+%SRC
+%SRC \begin{document}
+%SRC
+%SRC \begin{enumerate}
+%SRC \item\label{it:foo} Foo
+%SRC \item\label{it:bar} Bar
+%SRC \item[Baz] Baz
+%SRC \item[Qux]\label{it:qux} Qux
+%SRC \end{enumerate}
+%SRC
+%SRC \end{document}
+
+%TEX main.aux
+%SRC \relax
+%SRC \newlabel{it:foo}{{1}{1}}
+%SRC \newlabel{it:qux}{{2}{1}}
+"#,
+ serde_json::json!({}),
+ )?);
+
+ Ok(())
+}
+
+#[test]
+fn equation_nested() -> Result<()> {
+ assert_symbols!(find_symbols(
+ r#"
+%TEX main.tex
+%SRC \documentclass{article}
+%SRC
+%SRC \begin{document}
+%SRC
+%SRC \begin{equation}\label{eq:foo}
+%SRC Foo
+%SRC \end{equation}
+%SRC
+%SRC \begin{equation}\label{eq:bar}
+%SRC Bar
+%SRC \end{equation}
+%SRC
+%SRC \begin{equation}
+%SRC Baz
+%SRC \end{equation}
+%SRC
+%SRC \end{document}
+
+%TEX main.aux
+%SRC \relax
+%SRC \newlabel{eq:foo}{{1}{1}}
+"#,
+ serde_json::json!({
+ "textDocument": {
+ "documentSymbol": {
+ "hierarchicalDocumentSymbolSupport": true,
+ },
+ },
+ }),
+ )?);
+
+ Ok(())
+}
+
+#[test]
+fn equation_flat() -> Result<()> {
+ assert_symbols!(find_symbols(
+ r#"
+%TEX main.tex
+%SRC \documentclass{article}
+%SRC
+%SRC \begin{document}
+%SRC
+%SRC \begin{equation}\label{eq:foo}
+%SRC Foo
+%SRC \end{equation}
+%SRC
+%SRC \begin{equation}\label{eq:bar}
+%SRC Bar
+%SRC \end{equation}
+%SRC
+%SRC \begin{equation}
+%SRC Baz
+%SRC \end{equation}
+%SRC
+%SRC \end{document}
+
+%TEX main.aux
+%SRC \relax
+%SRC \newlabel{eq:foo}{{1}{1}}
+"#,
+ serde_json::json!({}),
+ )?);
+
+ Ok(())
+}
+
+#[test]
+fn float_nested() -> Result<()> {
+ assert_symbols!(find_symbols(
+ r#"
+%TEX main.tex
+%SRC \documentclass{article}
+%SRC
+%SRC \begin{document}
+%SRC
+%SRC \begin{figure}
+%SRC Foo
+%SRC \caption{Foo}\label{fig:foo}
+%SRC \end{figure}
+%SRC
+%SRC \begin{figure}
+%SRC Bar
+%SRC \caption{Bar}\label{fig:bar}
+%SRC \end{figure}
+%SRC
+%SRC \begin{figure}
+%SRC Baz
+%SRC \caption{Baz}
+%SRC \end{figure}
+%SRC
+%SRC \begin{figure}
+%SRC Qux
+%SRC \end{figure}
+%SRC
+%SRC \end{document}
+
+%TEX main.aux
+%SRC \relax
+%SRC \@writefile{lof}{\contentsline {figure}{\numberline {1}{\ignorespaces Foo}}{1}\protected@file@percent }
+%SRC \newlabel{fig:foo}{{1}{1}}
+%SRC \@writefile{lof}{\contentsline {figure}{\numberline {2}{\ignorespaces Bar}}{1}\protected@file@percent }
+%SRC \@writefile{lof}{\contentsline {figure}{\numberline {3}{\ignorespaces Baz}}{1}\protected@file@percent }
+"#,
+ serde_json::json!({
+ "textDocument": {
+ "documentSymbol": {
+ "hierarchicalDocumentSymbolSupport": true,
+ },
+ },
+ }),
+ )?);
+
+ Ok(())
+}
+
+#[test]
+fn float_flat() -> Result<()> {
+ assert_symbols!(find_symbols(
+ r#"
+%TEX main.tex
+%SRC \documentclass{article}
+%SRC
+%SRC \begin{document}
+%SRC
+%SRC \begin{figure}
+%SRC Foo
+%SRC \caption{Foo}\label{fig:foo}
+%SRC \end{figure}
+%SRC
+%SRC \begin{figure}
+%SRC Bar
+%SRC \caption{Bar}\label{fig:bar}
+%SRC \end{figure}
+%SRC
+%SRC \begin{figure}
+%SRC Baz
+%SRC \caption{Baz}
+%SRC \end{figure}
+%SRC
+%SRC \begin{figure}
+%SRC Qux
+%SRC \end{figure}
+%SRC
+%SRC \end{document}
+
+%TEX main.aux
+%SRC \relax
+%SRC \@writefile{lof}{\contentsline {figure}{\numberline {1}{\ignorespaces Foo}}{1}\protected@file@percent }
+%SRC \newlabel{fig:foo}{{1}{1}}
+%SRC \@writefile{lof}{\contentsline {figure}{\numberline {2}{\ignorespaces Bar}}{1}\protected@file@percent }
+%SRC \@writefile{lof}{\contentsline {figure}{\numberline {3}{\ignorespaces Baz}}{1}\protected@file@percent }
+"#,
+ serde_json::json!({}),
+ )?);
+
+ Ok(())
+}
+
+#[test]
+fn section_nested() -> Result<()> {
+ assert_symbols!(find_symbols(
+ r#"
+%TEX main.tex
+%SRC \documentclass{article}
+%SRC
+%SRC \begin{document}
+%SRC
+%SRC \section{Foo}
+%SRC
+%SRC \section{Bar}\label{sec:bar}
+%SRC
+%SRC \subsection{Baz}\label{sec:baz}
+%SRC
+%SRC \end{document}
+
+%TEX main.aux
+%SRC \relax
+%SRC \@writefile{toc}{\contentsline {section}{\numberline {1}Foo}{1}\protected@file@percent }
+%SRC \@writefile{toc}{\contentsline {section}{\numberline {2}Bar}{1}\protected@file@percent }
+%SRC \newlabel{sec:bar}{{2}{1}}
+"#,
+ serde_json::json!({
+ "textDocument": {
+ "documentSymbol": {
+ "hierarchicalDocumentSymbolSupport": true,
+ },
+ },
+ }),
+ )?);
+
+ Ok(())
+}
+
+#[test]
+fn section_flat() -> Result<()> {
+ assert_symbols!(find_symbols(
+ r#"
+%TEX main.tex
+%SRC \documentclass{article}
+%SRC
+%SRC \begin{document}
+%SRC
+%SRC \section{Foo}
+%SRC
+%SRC \section{Bar}\label{sec:bar}
+%SRC
+%SRC \subsection{Baz}\label{sec:baz}
+%SRC
+%SRC \end{document}
+
+%TEX main.aux
+%SRC \relax
+%SRC \@writefile{toc}{\contentsline {section}{\numberline {1}Foo}{1}\protected@file@percent }
+%SRC \@writefile{toc}{\contentsline {section}{\numberline {2}Bar}{1}\protected@file@percent }
+%SRC \newlabel{sec:bar}{{2}{1}}
+"#,
+ serde_json::json!({}),
+ )?);
+
+ Ok(())
+}
+
+#[test]
+fn theorem_nested() -> Result<()> {
+ assert_symbols!(find_symbols(
+ r#"
+%TEX main.tex
+%SRC \documentclass{article}
+%SRC \usepackage{amsthm}
+%SRC \newtheorem{lemma}{Lemma}
+%SRC
+%SRC \begin{document}
+%SRC
+%SRC \begin{lemma}[Foo]\label{thm:foo}
+%SRC Foo
+%SRC \end{lemma}
+%SRC
+%SRC \begin{lemma}\label{thm:bar}
+%SRC Bar
+%SRC \end{lemma}
+%SRC
+%SRC \begin{lemma}\label{thm:baz}
+%SRC Baz
+%SRC \end{lemma}
+%SRC
+%SRC \begin{lemma}[Qux]
+%SRC Qux
+%SRC \end{lemma}
+%SRC
+%SRC \end{document}
+
+%TEX main.aux
+%SRC \relax
+%SRC \newlabel{thm:foo}{{1}{1}}
+%SRC \newlabel{thm:bar}{{2}{1}}
+"#,
+ serde_json::json!({
+ "textDocument": {
+ "documentSymbol": {
+ "hierarchicalDocumentSymbolSupport": true,
+ },
+ },
+ }),
+ )?);
+
+ Ok(())
+}
+
+#[test]
+fn theorem_flat() -> Result<()> {
+ assert_symbols!(find_symbols(
+ r#"
+%TEX main.tex
+%SRC \documentclass{article}
+%SRC \usepackage{amsthm}
+%SRC \newtheorem{lemma}{Lemma}
+%SRC
+%SRC \begin{document}
+%SRC
+%SRC \begin{lemma}[Foo]\label{thm:foo}
+%SRC Foo
+%SRC \end{lemma}
+%SRC
+%SRC \begin{lemma}\label{thm:bar}
+%SRC Bar
+%SRC \end{lemma}
+%SRC
+%SRC \begin{lemma}\label{thm:baz}
+%SRC Baz
+%SRC \end{lemma}
+%SRC
+%SRC \begin{lemma}[Qux]
+%SRC Qux
+%SRC \end{lemma}
+%SRC
+%SRC \end{document}
+
+%TEX main.aux
+%SRC \relax
+%SRC \newlabel{thm:foo}{{1}{1}}
+%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/tests/integration/lsp/text_document/folding_range.rs
new file mode 100644
index 0000000000..1d75ba3e0e
--- /dev/null
+++ b/support/texlab/tests/integration/lsp/text_document/folding_range.rs
@@ -0,0 +1,97 @@
+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};
+
+fn check(fixture: &str, expected_ranges: Vec<(u32, u32, u32, u32)>) -> Result<()> {
+ 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)?;
+ }
+
+ let actual_foldings = client
+ .request::<FoldingRangeRequest>(FoldingRangeParams {
+ text_document: TextDocumentIdentifier::new(client.uri(fixture.cursor.unwrap().name)?),
+ work_done_progress_params: Default::default(),
+ partial_result_params: Default::default(),
+ })?
+ .unwrap_or_default();
+
+ client.shutdown()?;
+
+ let expected_foldings = expected_ranges
+ .into_iter()
+ .map(
+ |(start_line, start_character, end_line, end_character)| FoldingRange {
+ start_line,
+ start_character: Some(start_character),
+ end_line,
+ end_character: Some(end_character),
+ kind: Some(FoldingRangeKind::Region),
+ },
+ )
+ .collect();
+
+ assert_eq_unordered!(actual_foldings, expected_foldings);
+ Ok(())
+}
+
+#[test]
+fn latex() -> Result<()> {
+ check(
+ r#"
+%TEX main.tex
+%SRC \begin{document}
+%SRC \section{Foo}
+%SRC foo
+%SRC \subsection{Bar}
+%SRC bar
+%SRC \section{Baz}
+%SRC baz
+%SRC \section{Qux}
+%SRC \end{document}
+%CUR ^
+"#,
+ vec![
+ (0, 0, 8, 14),
+ (1, 4, 4, 7),
+ (3, 4, 4, 7),
+ (5, 4, 6, 7),
+ (7, 4, 7, 17),
+ ],
+ )
+}
+
+#[test]
+fn bibtex() -> Result<()> {
+ check(
+ r#"
+%BIB main.bib
+%SRC some junk
+%SRC here
+%SRC
+%SRC @article{foo,
+%SRC author = {bar},
+%SRC title = {baz}
+%SRC }
+%SRC
+%SRC @string{foo = "bar"}
+%SRC
+%SRC @comment{foo,
+%SRC author = {bar},
+%SRC title = {baz}
+%SRC }
+%SRC
+%SRC @preamble{"foo"}
+%CUR ^
+"#,
+ vec![(3, 0, 6, 1), (8, 0, 8, 20), (15, 0, 15, 16)],
+ )
+}
diff --git a/support/texlab/tests/integration/lsp/text_document/formatting.rs b/support/texlab/tests/integration/lsp/text_document/formatting.rs
new file mode 100644
index 0000000000..a0c02bf4b1
--- /dev/null
+++ b/support/texlab/tests/integration/lsp/text_document/formatting.rs
@@ -0,0 +1,148 @@
+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};
+
+fn format(fixture: &str) -> Result<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)?;
+
+ let actual_edits = client
+ .request::<Formatting>(DocumentFormattingParams {
+ 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_or_default();
+
+ client.shutdown()?;
+
+ let line_index = LineIndex::new(&old_text);
+ let mut actual_text = old_text;
+ for edit in actual_edits.into_iter().rev() {
+ let range = line_index.offset_lsp_range(edit.range);
+ actual_text.replace_range::<std::ops::Range<usize>>(range.into(), &edit.new_text);
+ }
+
+ Ok(actual_text)
+}
+
+#[test]
+fn bibtex_internal_wrap_long_lines() -> Result<()> {
+ 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<()> {
+ assert_snapshot!(format(
+ r#"
+%BIB main.bib
+%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.},}
+%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<()> {
+ assert_snapshot!(format(
+ r#"
+%BIB main.bib
+%SRC @article{foo, bar = baz}"#,
+ )?);
+
+ Ok(())
+}
+
+#[test]
+fn bibtex_internal_insert_braces() -> Result<()> {
+ assert_snapshot!(format(
+ r#"
+%BIB main.bib
+%SRC @article{foo, bar = baz,"#,
+ )?);
+
+ Ok(())
+}
+
+#[test]
+fn bibtex_internal_command() -> Result<()> {
+ assert_snapshot!(format(
+ r#"
+%BIB main.bib
+%SRC @article{foo, bar = "\baz",}"#,
+ )?);
+
+ Ok(())
+}
+
+#[test]
+fn bibtex_internal_join_strings() -> Result<()> {
+ assert_snapshot!(format(
+ r#"
+%BIB main.bib
+%SRC @article{foo, bar = "baz" # "qux"}"#,
+ )?);
+
+ Ok(())
+}
+
+#[test]
+fn bibtex_internal_parens() -> Result<()> {
+ assert_snapshot!(format(
+ r#"
+%BIB main.bib
+%SRC @article(foo,)"#,
+ )?);
+
+ Ok(())
+}
+
+#[test]
+fn bibtex_internal_string() -> Result<()> {
+ assert_snapshot!(format(
+ r#"
+%BIB main.bib
+%SRC @string{foo="bar"}"#,
+ )?);
+
+ Ok(())
+}
+
+#[test]
+fn bibtex_internal_preamble() -> Result<()> {
+ 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/tests/integration/lsp/text_document/hover.rs
new file mode 100644
index 0000000000..2a9e8c271f
--- /dev/null
+++ b/support/texlab/tests/integration/lsp/text_document/hover.rs
@@ -0,0 +1,302 @@
+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};
+
+fn check(fixture: &str, contents: Option<HoverContents>) -> Result<()> {
+ 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)?;
+ }
+
+ let range = fixture
+ .ranges
+ .values()
+ .next()
+ .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(),
+ })?;
+
+ client.shutdown()?;
+
+ let expected_hover = contents.map(|contents| Hover { range, contents });
+
+ assert_eq!(actual_hover, expected_hover);
+ Ok(())
+}
+
+#[test]
+fn empty_latex_document() -> Result<()> {
+ check(
+ r#"
+%TEX main.tex
+%SRC
+%CUR ^
+"#,
+ None,
+ )
+}
+
+#[test]
+fn empty_bibtex_document() -> Result<()> {
+ check(
+ r#"
+%BIB main.bib
+%SRC
+%CUR ^
+"#,
+ None,
+ )
+}
+
+#[test]
+fn citation_inside_cite() -> Result<()> {
+ check(
+ r#"
+%BIB main.bib
+%SRC @article{foo, author = {Foo Bar}, title = {Baz Qux}, year = 1337}
+
+%TEX main.tex
+%SRC \addbibresource{main.bib}
+%SRC \cite{foo}
+%CUR ^
+%1.1 ^^^
+"#,
+ Some(HoverContents::Markup(MarkupContent {
+ kind: MarkupKind::Markdown,
+ value: "F. Bar: \"Baz Qux\". (1337).".to_string(),
+ })),
+ )
+}
+
+#[test]
+fn citation_inside_entry() -> Result<()> {
+ check(
+ r#"
+%BIB main.bib
+%SRC @article{foo, author = {Foo Bar}, title = {Baz Qux}, year = 1337}
+%CUR ^
+%1.1 ^^^
+
+%TEX main.tex
+%SRC \addbibresource{main.bib}
+%SRC \cite{foo}
+"#,
+ Some(HoverContents::Markup(MarkupContent {
+ kind: MarkupKind::Markdown,
+ value: "F. Bar: \"Baz Qux\". (1337).".to_string(),
+ })),
+ )
+}
+
+#[test]
+fn component_known_package() -> Result<()> {
+ check(
+ r#"
+%TEX main.tex
+%SRC \usepackage{amsmath}
+%CUR ^
+%1.1 ^^^^^^^
+"#,
+ COMPONENT_DATABASE
+ .documentation("amsmath")
+ .map(HoverContents::Markup),
+ )
+}
+
+#[test]
+fn component_unknown_class() -> Result<()> {
+ check(
+ r#"
+%TEX main.tex
+%SRC \documentclass{abcdefghijklmnop}
+%CUR ^
+"#,
+ None,
+ )
+}
+
+#[test]
+fn entry_type_known_type() -> Result<()> {
+ check(
+ r#"
+%BIB main.bib
+%SRC @article{foo,}
+%CUR ^
+%1.1 ^^^^^^^^
+"#,
+ Some(HoverContents::Markup(MarkupContent {
+ kind: MarkupKind::Markdown,
+ value: LANGUAGE_DATA
+ .entry_type_documentation("article")
+ .unwrap()
+ .to_string(),
+ })),
+ )
+}
+
+#[test]
+fn entry_type_unknown_field() -> Result<()> {
+ check(
+ r#"
+%BIB main.bib
+%SRC @foo{bar,}
+%CUR ^
+"#,
+ None,
+ )
+}
+
+#[test]
+fn entry_type_key() -> Result<()> {
+ check(
+ r#"
+%BIB main.bib
+%SRC @foo{bar,}
+%CUR ^
+"#,
+ None,
+ )
+}
+
+#[test]
+fn field_known() -> Result<()> {
+ check(
+ r#"
+%BIB main.bib
+%SRC @article{foo, author = bar}
+%CUR ^
+%1.1 ^^^^^^
+"#,
+ Some(HoverContents::Markup(MarkupContent {
+ kind: MarkupKind::Markdown,
+ value: LANGUAGE_DATA
+ .field_documentation("author")
+ .unwrap()
+ .to_string(),
+ })),
+ )
+}
+
+#[test]
+fn field_unknown() -> Result<()> {
+ check(
+ r#"
+%BIB main.bib
+%SRC @article{foo, bar = baz}
+%CUR ^
+"#,
+ None,
+ )
+}
+
+#[test]
+fn section() -> Result<()> {
+ check(
+ r#"
+%TEX main.tex
+%SRC \section{Foo}
+%SRC \label{sec:foo}
+%CUR ^
+%1.1 ^^^^^^^
+"#,
+ Some(HoverContents::Markup(MarkupContent {
+ kind: MarkupKind::PlainText,
+ value: "Section (Foo)".to_string(),
+ })),
+ )
+}
+
+#[test]
+fn string_inside_reference() -> Result<()> {
+ check(
+ r#"
+%BIB main.bib
+%SRC @string{foo = "Foo"}
+%SRC @string{bar = "Bar"}
+%SRC @article{baz, author = bar}
+%CUR ^
+%1.1 ^^^
+"#,
+ Some(HoverContents::Markup(MarkupContent {
+ kind: MarkupKind::PlainText,
+ value: "Bar".to_string(),
+ })),
+ )
+}
+
+#[test]
+fn string_inside_field() -> Result<()> {
+ check(
+ r#"
+%BIB main.bib
+%SRC @string{foo = "Foo"}
+%SRC @string{bar = "Bar"}
+%SRC @article{baz, author = bar}
+%CUR ^
+"#,
+ None,
+ )
+}
+
+#[test]
+fn label_theorem_child_file() -> Result<()> {
+ check(
+ r#"
+%TEX main.tex
+%SRC \documentclass{article}
+%SRC \newtheorem{lemma}{Lemma}
+%SRC \include{child}
+%SRC \ref{thm:foo}
+%CUR ^
+%1.1 ^^^^^^^
+
+%TEX child.tex
+%SRC \begin{lemma}\label{thm:foo}
+%SRC 1 + 1 = 2
+%SRC \end{lemma}
+"#,
+ Some(HoverContents::Markup(MarkupContent {
+ kind: MarkupKind::PlainText,
+ value: "Lemma".to_string(),
+ })),
+ )
+}
+
+#[test]
+fn label_theorem_child_file_mumber() -> Result<()> {
+ check(
+ r#"
+%TEX main.tex
+%SRC \documentclass{article}
+%SRC \newtheorem{lemma}{Lemma}
+%SRC \include{child}
+%SRC \ref{thm:foo}
+%CUR ^
+%1.1 ^^^^^^^
+
+%TEX child.tex
+%SRC \begin{lemma}[Foo]\label{thm:foo}
+%SRC 1 + 1 = 2
+%SRC \end{lemma}
+
+%TEX child.aux
+%SRC \newlabel{thm:foo}{{1}{1}{Foo}{lemma.1}{}}
+"#,
+ Some(HoverContents::Markup(MarkupContent {
+ kind: MarkupKind::PlainText,
+ value: "Lemma 1 (Foo)".to_string(),
+ })),
+ )
+}
diff --git a/support/texlab/tests/integration/lsp/text_document/references.rs b/support/texlab/tests/integration/lsp/text_document/references.rs
new file mode 100644
index 0000000000..ff272673dd
--- /dev/null
+++ b/support/texlab/tests/integration/lsp/text_document/references.rs
@@ -0,0 +1,275 @@
+use anyhow::Result;
+use assert_unordered::assert_eq_unordered;
+use lsp_types::{
+ request::References, ClientCapabilities, Location, ReferenceContext, ReferenceParams,
+};
+
+use crate::lsp::{client::Client, fixture};
+
+fn check(fixture: &str, context: ReferenceContext) -> Result<()> {
+ 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)?;
+ }
+
+ 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,
+ ));
+ }
+
+ let actual_locations = client
+ .request::<References>(ReferenceParams {
+ text_document_position: fixture.cursor.unwrap().into_params(&client)?,
+ context,
+ partial_result_params: Default::default(),
+ work_done_progress_params: Default::default(),
+ })?
+ .unwrap_or_default();
+
+ client.shutdown()?;
+
+ assert_eq_unordered!(actual_locations, expected_locations);
+ Ok(())
+}
+
+#[test]
+fn entry_definition() -> Result<()> {
+ check(
+ r#"
+%BIB foo.bib
+%SRC @article{foo,}
+%CUR ^
+
+%TEX bar.tex
+%SRC \cite{foo}
+%1.1 ^^^
+%SRC \addbibresource{foo.bib}
+"#,
+ ReferenceContext {
+ include_declaration: false,
+ },
+ )
+}
+
+#[test]
+fn entry_definition_include_decl() -> Result<()> {
+ check(
+ r#"
+%BIB foo.bib
+%SRC @article{foo,}
+%CUR ^
+%2.1 ^^^
+
+%TEX bar.tex
+%SRC \cite{foo}
+%1.1 ^^^
+%SRC \addbibresource{foo.bib}
+"#,
+ ReferenceContext {
+ include_declaration: true,
+ },
+ )
+}
+
+#[test]
+fn entry_reference() -> Result<()> {
+ check(
+ r#"
+%BIB foo.bib
+%SRC @article{foo,}
+
+%TEX bar.tex
+%SRC \cite{foo}
+%CUR ^
+%1.1 ^^^
+%SRC \addbibresource{foo.bib}
+"#,
+ ReferenceContext {
+ include_declaration: false,
+ },
+ )
+}
+
+#[test]
+fn entry_reference_include_decl() -> Result<()> {
+ check(
+ r#"
+%BIB foo.bib
+%SRC @article{foo,}
+%2.1 ^^^
+
+%TEX bar.tex
+%SRC \cite{foo}
+%CUR ^
+%1.1 ^^^
+%SRC \addbibresource{foo.bib}
+"#,
+ ReferenceContext {
+ include_declaration: true,
+ },
+ )
+}
+
+#[test]
+fn label_definition() -> Result<()> {
+ check(
+ r#"
+%TEX foo.tex
+%SRC \label{foo}
+%CUR ^
+
+%TEX bar.tex
+%SRC \ref{foo}
+%1.1 ^^^
+%SRC \input{foo.tex}
+"#,
+ ReferenceContext {
+ include_declaration: false,
+ },
+ )
+}
+
+#[test]
+fn label_definition_include_decl() -> Result<()> {
+ check(
+ r#"
+%TEX foo.tex
+%SRC \label{foo}
+%CUR ^
+%2.1 ^^^
+
+%TEX bar.tex
+%SRC \ref{foo}
+%1.1 ^^^
+%SRC \input{foo.tex}
+"#,
+ ReferenceContext {
+ include_declaration: true,
+ },
+ )
+}
+
+#[test]
+fn label_reference() -> Result<()> {
+ check(
+ r#"
+%TEX foo.tex
+%SRC \label{foo}
+%SRC \input{bar.tex}
+
+%TEX bar.tex
+%SRC \ref{foo}
+%CUR ^
+%1.1 ^^^
+
+%TEX baz.tex
+%SRC \ref{foo}
+%2.1 ^^^
+%SRC \input{bar.tex}
+"#,
+ ReferenceContext {
+ include_declaration: false,
+ },
+ )
+}
+
+#[test]
+fn label_reference_include_decl() -> Result<()> {
+ check(
+ r#"
+%TEX foo.tex
+%SRC \label{foo}
+%3.1 ^^^
+%SRC \input{bar.tex}
+
+%TEX bar.tex
+%SRC \ref{foo}
+%CUR ^
+%1.1 ^^^
+
+%TEX baz.tex
+%SRC \ref{foo}
+%2.1 ^^^
+%SRC \input{bar.tex}
+"#,
+ ReferenceContext {
+ include_declaration: true,
+ },
+ )
+}
+
+#[test]
+fn string_reference() -> Result<()> {
+ check(
+ r#"
+%BIB main.bib
+%SRC @string{foo = {Foo}}
+%SRC @string{bar = {Bar}}
+%SRC @article{baz, author = foo}
+%CUR ^
+%1.1 ^^^
+"#,
+ ReferenceContext {
+ include_declaration: false,
+ },
+ )
+}
+
+#[test]
+fn string_reference_include_decl() -> Result<()> {
+ check(
+ r#"
+%BIB main.bib
+%SRC @string{foo = {Foo}}
+%2.1 ^^^
+%SRC @string{bar = {Bar}}
+%SRC @article{baz, author = foo}
+%CUR ^
+%1.1 ^^^
+"#,
+ ReferenceContext {
+ include_declaration: true,
+ },
+ )
+}
+
+#[test]
+fn string_definition() -> Result<()> {
+ check(
+ r#"
+%BIB main.bib
+%SRC @string{foo = {Foo}}
+%CUR ^
+%SRC @string{bar = {Bar}}
+%SRC @article{baz, author = foo}
+%1.1 ^^^
+"#,
+ ReferenceContext {
+ include_declaration: false,
+ },
+ )
+}
+
+#[test]
+fn string_definition_include_decl() -> Result<()> {
+ check(
+ r#"
+%BIB main.bib
+%SRC @string{foo = {Foo}}
+%CUR ^
+%2.1 ^^^
+%SRC @string{bar = {Bar}}
+%SRC @article{baz, author = foo}
+%1.1 ^^^
+"#,
+ ReferenceContext {
+ include_declaration: true,
+ },
+ )
+}
diff --git a/support/texlab/tests/integration/lsp/text_document/rename.rs b/support/texlab/tests/integration/lsp/text_document/rename.rs
new file mode 100644
index 0000000000..6b5a7e4978
--- /dev/null
+++ b/support/texlab/tests/integration/lsp/text_document/rename.rs
@@ -0,0 +1,111 @@
+use std::collections::HashMap;
+
+use anyhow::Result;
+use lsp_types::{request::Rename, ClientCapabilities, RenameParams, TextEdit, Url, WorkspaceEdit};
+
+use crate::lsp::{client::Client, fixture};
+
+fn check(fixture: &str, new_name: &str) -> Result<()> {
+ 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)?;
+ }
+
+ let mut expected_changes: HashMap<Url, Vec<TextEdit>> = HashMap::new();
+ for ranges in fixture.ranges.values() {
+ expected_changes
+ .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)?,
+ new_name: new_name.to_string(),
+ work_done_progress_params: Default::default(),
+ })?
+ .unwrap_or_default();
+
+ client.shutdown()?;
+
+ assert_eq!(actual_edit, WorkspaceEdit::new(expected_changes));
+ Ok(())
+}
+
+#[test]
+fn command() -> Result<()> {
+ check(
+ r#"
+%TEX foo.tex
+%SRC \baz
+%CUR ^
+%1.1 ^^^
+%SRC \include{bar.tex}
+
+%TEX bar.tex
+%SRC \baz
+%2.1 ^^^
+"#,
+ "qux",
+ )
+}
+
+#[test]
+fn entry() -> Result<()> {
+ check(
+ r#"
+%BIB main.bib
+%SRC @article{foo, bar = baz}
+%CUR ^
+%1.1 ^^^
+
+%TEX main.tex
+%SRC \addbibresource{main.bib}
+%SRC \cite{foo}
+%2.1 ^^^
+"#,
+ "qux",
+ )
+}
+
+#[test]
+fn citation() -> Result<()> {
+ check(
+ r#"
+%BIB main.bib
+%SRC @article{foo, bar = baz}
+%1.1 ^^^
+
+%TEX main.tex
+%SRC \addbibresource{main.bib}
+%SRC \cite{foo}
+%CUR ^
+%2.1 ^^^
+"#,
+ "qux",
+ )
+}
+
+#[test]
+fn label() -> Result<()> {
+ check(
+ r#"
+%TEX foo.tex
+%SRC \label{foo}\include{bar}
+%CUR ^
+%1.1 ^^^
+
+%TEX bar.tex
+%SRC \ref{foo}
+%2.1 ^^^
+
+%TEX baz.tex
+%SRC \ref{foo}
+"#,
+ "bar",
+ )
+}
diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__acronym_ref_empty.snap b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__acronym_ref_empty.snap
new file mode 100644
index 0000000000..33c5b459e1
--- /dev/null
+++ b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__acronym_ref_empty.snap
@@ -0,0 +1,18 @@
+---
+source: tests/integration/lsp/text_document/completion.rs
+assertion_line: 89
+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,
+ "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_open_brace.snap b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__acronym_ref_open_brace.snap
new file mode 100644
index 0000000000..41a71b7951
--- /dev/null
+++ b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__acronym_ref_open_brace.snap
@@ -0,0 +1,18 @@
+---
+source: tests/integration/lsp/text_document/completion.rs
+assertion_line: 117
+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,
+ "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_simple.snap b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__acronym_ref_simple.snap
new file mode 100644
index 0000000000..3d31151a72
--- /dev/null
+++ b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__acronym_ref_simple.snap
@@ -0,0 +1,18 @@
+---
+source: tests/integration/lsp/text_document/completion.rs
+assertion_line: 75
+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,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "fpsLabel"
+ }
+ }
+]
diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__argument_empty.snap b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__argument_empty.snap
new file mode 100644
index 0000000000..41c438baf6
--- /dev/null
+++ b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__argument_empty.snap
@@ -0,0 +1,67 @@
+---
+source: tests/integration/lsp/text_document/completion.rs
+assertion_line: 159
+expression: "complete(r#\"\n%TEX main.tex\n%SRC \\usepackage{amsfonts}\n%SRC \\mathbb{}\n%CUR ^\"#)?"
+---
+[
+ {
+ "data": "[data]",
+ "documentation": "[documentation]",
+ "kind": 1,
+ "label": "A",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "A"
+ }
+ },
+ {
+ "data": "[data]",
+ "documentation": "[documentation]",
+ "kind": 1,
+ "label": "B",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "B"
+ }
+ },
+ {
+ "data": "[data]",
+ "documentation": "[documentation]",
+ "kind": 1,
+ "label": "C",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "C"
+ }
+ },
+ {
+ "data": "[data]",
+ "documentation": "[documentation]",
+ "kind": 1,
+ "label": "D",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "D"
+ }
+ },
+ {
+ "data": "[data]",
+ "documentation": "[documentation]",
+ "kind": 1,
+ "label": "E",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "E"
+ }
+ }
+]
diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__argument_open_brace.snap b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__argument_open_brace.snap
new file mode 100644
index 0000000000..7009557720
--- /dev/null
+++ b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__argument_open_brace.snap
@@ -0,0 +1,67 @@
+---
+source: tests/integration/lsp/text_document/completion.rs
+assertion_line: 186
+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",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "A"
+ }
+ },
+ {
+ "data": "[data]",
+ "documentation": "[documentation]",
+ "kind": 1,
+ "label": "B",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "B"
+ }
+ },
+ {
+ "data": "[data]",
+ "documentation": "[documentation]",
+ "kind": 1,
+ "label": "C",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "C"
+ }
+ },
+ {
+ "data": "[data]",
+ "documentation": "[documentation]",
+ "kind": 1,
+ "label": "D",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "D"
+ }
+ },
+ {
+ "data": "[data]",
+ "documentation": "[documentation]",
+ "kind": 1,
+ "label": "E",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "E"
+ }
+ }
+]
diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__argument_word.snap b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__argument_word.snap
new file mode 100644
index 0000000000..2ea7a4649d
--- /dev/null
+++ b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__argument_word.snap
@@ -0,0 +1,19 @@
+---
+source: tests/integration/lsp/text_document/completion.rs
+assertion_line: 172
+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",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "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/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__begin_environment_without_snippet_support.snap
new file mode 100644
index 0000000000..468ea3ea5f
--- /dev/null
+++ b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__begin_environment_without_snippet_support.snap
@@ -0,0 +1,68 @@
+---
+source: tests/integration/lsp/text_document/completion.rs
+assertion_line: 215
+expression: "complete(r#\"\n%TEX main.tex\n%SRC \\beg\n%CUR ^\n%1.1 ^^^\"#)?"
+---
+[
+ {
+ "data": "[data]",
+ "detail": "built-in",
+ "kind": 1,
+ "label": "begin",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "begin"
+ }
+ },
+ {
+ "data": "[data]",
+ "detail": "built-in",
+ "kind": 1,
+ "label": "begingroup",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "begingroup"
+ }
+ },
+ {
+ "data": "[data]",
+ "detail": "built-in",
+ "kind": 1,
+ "label": "AtBeginDocument",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "AtBeginDocument"
+ }
+ },
+ {
+ "data": "[data]",
+ "detail": "built-in",
+ "kind": 1,
+ "label": "AtBeginDvi",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "AtBeginDvi"
+ }
+ },
+ {
+ "data": "[data]",
+ "detail": "â‹€, built-in",
+ "documentation": "[documentation]",
+ "kind": 1,
+ "label": "bigwedge",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "bigwedge"
+ }
+ }
+]
diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__citation.snap b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__citation.snap
new file mode 100644
index 0000000000..517df0a0df
--- /dev/null
+++ b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__citation.snap
@@ -0,0 +1,32 @@
+---
+source: tests/integration/lsp/text_document/completion.rs
+assertion_line: 228
+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,}\"#)?"
+---
+[
+ {
+ "data": "[data]",
+ "filterText": "bar:2005 @article bar:2005",
+ "kind": 1,
+ "label": "bar:2005",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "bar:2005"
+ }
+ },
+ {
+ "data": "[data]",
+ "documentation": "[documentation]",
+ "filterText": "foo:2019 @article foo:2019 author Foo Bar title Baz Qux year 2019",
+ "kind": 1,
+ "label": "foo:2019",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "foo:2019"
+ }
+ }
+]
diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__citation_acronym.snap b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__citation_acronym.snap
new file mode 100644
index 0000000000..a679c4c42b
--- /dev/null
+++ b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__citation_acronym.snap
@@ -0,0 +1,19 @@
+---
+source: tests/integration/lsp/text_document/completion.rs
+assertion_line: 286
+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,}\"#)?"
+---
+[
+ {
+ "data": "[data]",
+ "filterText": "foo @article foo",
+ "kind": 1,
+ "label": "foo",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "foo"
+ }
+ }
+]
diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__citation_open_brace.snap b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__citation_open_brace.snap
new file mode 100644
index 0000000000..cf2056b7e7
--- /dev/null
+++ b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__citation_open_brace.snap
@@ -0,0 +1,19 @@
+---
+source: tests/integration/lsp/text_document/completion.rs
+assertion_line: 253
+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,}\"#)?"
+---
+[
+ {
+ "data": "[data]",
+ "filterText": "foo @article foo",
+ "kind": 1,
+ "label": "foo",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "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/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__citation_open_brace_multiple.snap
new file mode 100644
index 0000000000..7619c22002
--- /dev/null
+++ b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__citation_open_brace_multiple.snap
@@ -0,0 +1,19 @@
+---
+source: tests/integration/lsp/text_document/completion.rs
+assertion_line: 269
+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,}\"#)?"
+---
+[
+ {
+ "data": "[data]",
+ "filterText": "foo @article foo",
+ "kind": 1,
+ "label": "foo",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "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/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__color_model_definition_open_brace.snap
new file mode 100644
index 0000000000..651c6e4f36
--- /dev/null
+++ b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__color_model_definition_open_brace.snap
@@ -0,0 +1,62 @@
+---
+source: tests/integration/lsp/text_document/completion.rs
+assertion_line: 334
+expression: "complete(r#\"\n%TEX main.tex\n%SRC \\definecolor{foo}{\n%CUR ^\"#)?"
+---
+[
+ {
+ "data": "[data]",
+ "kind": 1,
+ "label": "HTML",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "HTML"
+ }
+ },
+ {
+ "data": "[data]",
+ "kind": 1,
+ "label": "RGB",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "RGB"
+ }
+ },
+ {
+ "data": "[data]",
+ "kind": 1,
+ "label": "cmyk",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "cmyk"
+ }
+ },
+ {
+ "data": "[data]",
+ "kind": 1,
+ "label": "gray",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "gray"
+ }
+ },
+ {
+ "data": "[data]",
+ "kind": 1,
+ "label": "rgb",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "rgb"
+ }
+ }
+]
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/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__color_model_definition_set_open_brace.snap
new file mode 100644
index 0000000000..4fb23233c9
--- /dev/null
+++ b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__color_model_definition_set_open_brace.snap
@@ -0,0 +1,62 @@
+---
+source: tests/integration/lsp/text_document/completion.rs
+assertion_line: 358
+expression: "complete(r#\"\n%TEX main.tex\n%SRC \\definecolorset{\n%CUR ^\"#)?"
+---
+[
+ {
+ "data": "[data]",
+ "kind": 1,
+ "label": "HTML",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "HTML"
+ }
+ },
+ {
+ "data": "[data]",
+ "kind": 1,
+ "label": "RGB",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "RGB"
+ }
+ },
+ {
+ "data": "[data]",
+ "kind": 1,
+ "label": "cmyk",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "cmyk"
+ }
+ },
+ {
+ "data": "[data]",
+ "kind": 1,
+ "label": "gray",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "gray"
+ }
+ },
+ {
+ "data": "[data]",
+ "kind": 1,
+ "label": "rgb",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "rgb"
+ }
+ }
+]
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/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__color_model_definition_set_simple.snap
new file mode 100644
index 0000000000..4b7f137e4f
--- /dev/null
+++ b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__color_model_definition_set_simple.snap
@@ -0,0 +1,62 @@
+---
+source: tests/integration/lsp/text_document/completion.rs
+assertion_line: 346
+expression: "complete(r#\"\n%TEX main.tex\n%SRC \\definecolorset{}\n%CUR ^\"#)?"
+---
+[
+ {
+ "data": "[data]",
+ "kind": 1,
+ "label": "HTML",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "HTML"
+ }
+ },
+ {
+ "data": "[data]",
+ "kind": 1,
+ "label": "RGB",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "RGB"
+ }
+ },
+ {
+ "data": "[data]",
+ "kind": 1,
+ "label": "cmyk",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "cmyk"
+ }
+ },
+ {
+ "data": "[data]",
+ "kind": 1,
+ "label": "gray",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "gray"
+ }
+ },
+ {
+ "data": "[data]",
+ "kind": 1,
+ "label": "rgb",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "rgb"
+ }
+ }
+]
diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__color_model_definition_simple.snap b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__color_model_definition_simple.snap
new file mode 100644
index 0000000000..a160c859c3
--- /dev/null
+++ b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__color_model_definition_simple.snap
@@ -0,0 +1,62 @@
+---
+source: tests/integration/lsp/text_document/completion.rs
+assertion_line: 322
+expression: "complete(r#\"\n%TEX main.tex\n%SRC \\definecolor{foo}{}\n%CUR ^\"#)?"
+---
+[
+ {
+ "data": "[data]",
+ "kind": 1,
+ "label": "HTML",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "HTML"
+ }
+ },
+ {
+ "data": "[data]",
+ "kind": 1,
+ "label": "RGB",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "RGB"
+ }
+ },
+ {
+ "data": "[data]",
+ "kind": 1,
+ "label": "cmyk",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "cmyk"
+ }
+ },
+ {
+ "data": "[data]",
+ "kind": 1,
+ "label": "gray",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "gray"
+ }
+ },
+ {
+ "data": "[data]",
+ "kind": 1,
+ "label": "rgb",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "rgb"
+ }
+ }
+]
diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__color_open_brace.snap b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__color_open_brace.snap
new file mode 100644
index 0000000000..df57a6e6ef
--- /dev/null
+++ b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__color_open_brace.snap
@@ -0,0 +1,62 @@
+---
+source: tests/integration/lsp/text_document/completion.rs
+assertion_line: 395
+expression: "complete(r#\"\n%TEX main.tex\n%SRC \\color{\n%CUR ^\"#)?"
+---
+[
+ {
+ "data": "[data]",
+ "kind": 1,
+ "label": "Apricot",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "Apricot"
+ }
+ },
+ {
+ "data": "[data]",
+ "kind": 1,
+ "label": "Aquamarine",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "Aquamarine"
+ }
+ },
+ {
+ "data": "[data]",
+ "kind": 1,
+ "label": "Bittersweet",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "Bittersweet"
+ }
+ },
+ {
+ "data": "[data]",
+ "kind": 1,
+ "label": "Black",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "Black"
+ }
+ },
+ {
+ "data": "[data]",
+ "kind": 1,
+ "label": "Blue",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "Blue"
+ }
+ }
+]
diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__color_simple.snap b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__color_simple.snap
new file mode 100644
index 0000000000..fb4e2bee73
--- /dev/null
+++ b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__color_simple.snap
@@ -0,0 +1,62 @@
+---
+source: tests/integration/lsp/text_document/completion.rs
+assertion_line: 370
+expression: "complete(r#\"\n%TEX main.tex\n%SRC \\color{}\n%CUR ^\"#)?"
+---
+[
+ {
+ "data": "[data]",
+ "kind": 1,
+ "label": "Apricot",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "Apricot"
+ }
+ },
+ {
+ "data": "[data]",
+ "kind": 1,
+ "label": "Aquamarine",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "Aquamarine"
+ }
+ },
+ {
+ "data": "[data]",
+ "kind": 1,
+ "label": "Bittersweet",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "Bittersweet"
+ }
+ },
+ {
+ "data": "[data]",
+ "kind": 1,
+ "label": "Black",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "Black"
+ }
+ },
+ {
+ "data": "[data]",
+ "kind": 1,
+ "label": "Blue",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "Blue"
+ }
+ }
+]
diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__color_word.snap b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__color_word.snap
new file mode 100644
index 0000000000..b730f14a42
--- /dev/null
+++ b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__color_word.snap
@@ -0,0 +1,62 @@
+---
+source: tests/integration/lsp/text_document/completion.rs
+assertion_line: 382
+expression: "complete(r#\"\n%TEX main.tex\n%SRC \\color{re}\n%CUR ^\n%1.1 ^^\"#)?"
+---
+[
+ {
+ "data": "[data]",
+ "kind": 1,
+ "label": "red",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "red"
+ }
+ },
+ {
+ "data": "[data]",
+ "kind": 1,
+ "label": "Red",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "Red"
+ }
+ },
+ {
+ "data": "[data]",
+ "kind": 1,
+ "label": "RedOrange",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "RedOrange"
+ }
+ },
+ {
+ "data": "[data]",
+ "kind": 1,
+ "label": "RedViolet",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "RedViolet"
+ }
+ },
+ {
+ "data": "[data]",
+ "kind": 1,
+ "label": "BrickRed",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "BrickRed"
+ }
+ }
+]
diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__component_command_bibtex.snap b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__component_command_bibtex.snap
new file mode 100644
index 0000000000..545a13af3c
--- /dev/null
+++ b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__component_command_bibtex.snap
@@ -0,0 +1,67 @@
+---
+source: tests/integration/lsp/text_document/completion.rs
+assertion_line: 446
+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",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "LaTeX"
+ }
+ },
+ {
+ "data": "[data]",
+ "detail": "built-in",
+ "kind": 1,
+ "label": "LaTeXe",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "LaTeXe"
+ }
+ },
+ {
+ "data": "[data]",
+ "detail": "built-in",
+ "kind": 1,
+ "label": "latexreleaseversion",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "latexreleaseversion"
+ }
+ },
+ {
+ "data": "[data]",
+ "detail": "built-in",
+ "kind": 1,
+ "label": "LastDeclaredEncoding",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "LastDeclaredEncoding"
+ }
+ },
+ {
+ "data": "[data]",
+ "detail": "built-in",
+ "kind": 1,
+ "label": "last",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "last"
+ }
+ }
+]
diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__component_command_simple.snap b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__component_command_simple.snap
new file mode 100644
index 0000000000..8414866ca1
--- /dev/null
+++ b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__component_command_simple.snap
@@ -0,0 +1,69 @@
+---
+source: tests/integration/lsp/text_document/completion.rs
+assertion_line: 407
+expression: "complete(r#\"\n%TEX main.tex\n%SRC \\\n%CUR ^\"#)?"
+---
+[
+ {
+ "data": "[data]",
+ "detail": "built-in",
+ "kind": 1,
+ "label": "!",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "!"
+ }
+ },
+ {
+ "data": "[data]",
+ "detail": "built-in",
+ "documentation": "[documentation]",
+ "kind": 1,
+ "label": "\"",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "\""
+ }
+ },
+ {
+ "data": "[data]",
+ "detail": "built-in",
+ "kind": 1,
+ "label": "#",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "#"
+ }
+ },
+ {
+ "data": "[data]",
+ "detail": "$, built-in",
+ "documentation": "[documentation]",
+ "kind": 1,
+ "label": "$",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "$"
+ }
+ },
+ {
+ "data": "[data]",
+ "detail": "built-in",
+ "kind": 1,
+ "label": "%",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "%"
+ }
+ }
+]
diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__component_command_simple_package.snap b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__component_command_simple_package.snap
new file mode 100644
index 0000000000..c08f480f7e
--- /dev/null
+++ b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__component_command_simple_package.snap
@@ -0,0 +1,67 @@
+---
+source: tests/integration/lsp/text_document/completion.rs
+assertion_line: 432
+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",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "lipsum"
+ }
+ },
+ {
+ "data": "[data]",
+ "detail": "lipsum.sty",
+ "kind": 1,
+ "label": "lipsumexp",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "lipsumexp"
+ }
+ },
+ {
+ "data": "[data]",
+ "detail": "lipsum.sty",
+ "kind": 1,
+ "label": "LipsumPar",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "LipsumPar"
+ }
+ },
+ {
+ "data": "[data]",
+ "detail": "lipsum.sty",
+ "kind": 1,
+ "label": "LipsumProtect",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "LipsumProtect"
+ }
+ },
+ {
+ "data": "[data]",
+ "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__component_environment_class.snap b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__component_environment_class.snap
new file mode 100644
index 0000000000..ff16b8e7b6
--- /dev/null
+++ b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__component_environment_class.snap
@@ -0,0 +1,19 @@
+---
+source: tests/integration/lsp/text_document/completion.rs
+assertion_line: 487
+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",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "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/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__component_environment_command_definition.snap
new file mode 100644
index 0000000000..e07204dd14
--- /dev/null
+++ b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__component_environment_command_definition.snap
@@ -0,0 +1,19 @@
+---
+source: tests/integration/lsp/text_document/completion.rs
+assertion_line: 501
+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",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "document"
+ }
+ }
+]
diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__component_environment_simple.snap b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__component_environment_simple.snap
new file mode 100644
index 0000000000..6c3be2426e
--- /dev/null
+++ b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__component_environment_simple.snap
@@ -0,0 +1,19 @@
+---
+source: tests/integration/lsp/text_document/completion.rs
+assertion_line: 461
+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",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "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/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__component_environment_simple_end.snap
new file mode 100644
index 0000000000..af0e4ca762
--- /dev/null
+++ b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__component_environment_simple_end.snap
@@ -0,0 +1,67 @@
+---
+source: tests/integration/lsp/text_document/completion.rs
+assertion_line: 474
+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",
+ "preselect": true,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "document"
+ }
+ },
+ {
+ "data": "[data]",
+ "detail": "built-in",
+ "kind": 1,
+ "label": "abstract",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "abstract"
+ }
+ },
+ {
+ "data": "[data]",
+ "detail": "built-in",
+ "kind": 1,
+ "label": "array",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "array"
+ }
+ },
+ {
+ "data": "[data]",
+ "detail": "built-in",
+ "kind": 1,
+ "label": "center",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "center"
+ }
+ },
+ {
+ "data": "[data]",
+ "detail": "built-in",
+ "kind": 1,
+ "label": "csname",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "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/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__entry_type_after_preamble.snap
new file mode 100644
index 0000000000..281254f2b8
--- /dev/null
+++ b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__entry_type_after_preamble.snap
@@ -0,0 +1,18 @@
+---
+source: tests/integration/lsp/text_document/completion.rs
+assertion_line: 565
+expression: "complete(r#\"\n%BIB main.bib\n%SRC @preamble{\n%CUR ^\n%1.1 ^^^^^^^^\"#)?"
+---
+[
+ {
+ "data": "[data]",
+ "kind": 1,
+ "label": "preamble",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "preamble"
+ }
+ }
+]
diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__entry_type_after_string.snap b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__entry_type_after_string.snap
new file mode 100644
index 0000000000..706bd78d07
--- /dev/null
+++ b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__entry_type_after_string.snap
@@ -0,0 +1,18 @@
+---
+source: tests/integration/lsp/text_document/completion.rs
+assertion_line: 578
+expression: "complete(r#\"\n%BIB main.bib\n%SRC @string{\n%CUR ^\n%1.1 ^^^^^^\"#)?"
+---
+[
+ {
+ "data": "[data]",
+ "kind": 1,
+ "label": "string",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "string"
+ }
+ }
+]
diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__entry_type_at_empty.snap b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__entry_type_at_empty.snap
new file mode 100644
index 0000000000..19d2a451af
--- /dev/null
+++ b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__entry_type_at_empty.snap
@@ -0,0 +1,67 @@
+---
+source: tests/integration/lsp/text_document/completion.rs
+assertion_line: 514
+expression: "complete(r#\"\n%BIB main.bib\n%SRC @\n%CUR ^\"#)?"
+---
+[
+ {
+ "data": "[data]",
+ "documentation": "[documentation]",
+ "kind": 1,
+ "label": "article",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "article"
+ }
+ },
+ {
+ "data": "[data]",
+ "documentation": "[documentation]",
+ "kind": 1,
+ "label": "artwork",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "artwork"
+ }
+ },
+ {
+ "data": "[data]",
+ "documentation": "[documentation]",
+ "kind": 1,
+ "label": "audio",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "audio"
+ }
+ },
+ {
+ "data": "[data]",
+ "documentation": "[documentation]",
+ "kind": 1,
+ "label": "bibnote",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "bibnote"
+ }
+ },
+ {
+ "data": "[data]",
+ "documentation": "[documentation]",
+ "kind": 1,
+ "label": "book",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "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/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__entry_type_before_article.snap
new file mode 100644
index 0000000000..654258a594
--- /dev/null
+++ b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__entry_type_before_article.snap
@@ -0,0 +1,19 @@
+---
+source: tests/integration/lsp/text_document/completion.rs
+assertion_line: 552
+expression: "complete(r#\"\n%BIB main.bib\n%SRC @article\n%CUR ^\n%1.1 ^^^^^^^\"#)?"
+---
+[
+ {
+ "data": "[data]",
+ "documentation": "[documentation]",
+ "kind": 1,
+ "label": "article",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "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/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__entry_type_before_preamble.snap
new file mode 100644
index 0000000000..6a4a79f14d
--- /dev/null
+++ b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__entry_type_before_preamble.snap
@@ -0,0 +1,18 @@
+---
+source: tests/integration/lsp/text_document/completion.rs
+assertion_line: 526
+expression: "complete(r#\"\n%BIB main.bib\n%SRC @preamble\n%CUR ^\n%1.1 ^^^^^^^^\"#)?"
+---
+[
+ {
+ "data": "[data]",
+ "kind": 1,
+ "label": "preamble",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "preamble"
+ }
+ }
+]
diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__entry_type_before_string.snap b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__entry_type_before_string.snap
new file mode 100644
index 0000000000..b3b6f2928b
--- /dev/null
+++ b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__entry_type_before_string.snap
@@ -0,0 +1,18 @@
+---
+source: tests/integration/lsp/text_document/completion.rs
+assertion_line: 539
+expression: "complete(r#\"\n%BIB main.bib\n%SRC @string\n%CUR ^\n%1.1 ^^^^^^\"#)?"
+---
+[
+ {
+ "data": "[data]",
+ "kind": 1,
+ "label": "string",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "string"
+ }
+ }
+]
diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__entry_type_complete_entry.snap b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__entry_type_complete_entry.snap
new file mode 100644
index 0000000000..2a18a34789
--- /dev/null
+++ b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__entry_type_complete_entry.snap
@@ -0,0 +1,19 @@
+---
+source: tests/integration/lsp/text_document/completion.rs
+assertion_line: 591
+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",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "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/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__field_empty_entry_closed.snap
new file mode 100644
index 0000000000..10f3b1d89a
--- /dev/null
+++ b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__field_empty_entry_closed.snap
@@ -0,0 +1,67 @@
+---
+source: tests/integration/lsp/text_document/completion.rs
+assertion_line: 616
+expression: "complete(r#\"\n%BIB main.bib\n%SRC @article{foo,}\n%CUR ^\"#)?"
+---
+[
+ {
+ "data": "[data]",
+ "documentation": "[documentation]",
+ "kind": 1,
+ "label": "abstract",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "abstract"
+ }
+ },
+ {
+ "data": "[data]",
+ "documentation": "[documentation]",
+ "kind": 1,
+ "label": "addendum",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "addendum"
+ }
+ },
+ {
+ "data": "[data]",
+ "documentation": "[documentation]",
+ "kind": 1,
+ "label": "address",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "address"
+ }
+ },
+ {
+ "data": "[data]",
+ "documentation": "[documentation]",
+ "kind": 1,
+ "label": "afterword",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "afterword"
+ }
+ },
+ {
+ "data": "[data]",
+ "documentation": "[documentation]",
+ "kind": 1,
+ "label": "annotation",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "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/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__field_empty_entry_open.snap
new file mode 100644
index 0000000000..bb8b03efda
--- /dev/null
+++ b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__field_empty_entry_open.snap
@@ -0,0 +1,67 @@
+---
+source: tests/integration/lsp/text_document/completion.rs
+assertion_line: 604
+expression: "complete(r#\"\n%BIB main.bib\n%SRC @article{foo,\n%CUR ^\"#)?"
+---
+[
+ {
+ "data": "[data]",
+ "documentation": "[documentation]",
+ "kind": 1,
+ "label": "abstract",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "abstract"
+ }
+ },
+ {
+ "data": "[data]",
+ "documentation": "[documentation]",
+ "kind": 1,
+ "label": "addendum",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "addendum"
+ }
+ },
+ {
+ "data": "[data]",
+ "documentation": "[documentation]",
+ "kind": 1,
+ "label": "address",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "address"
+ }
+ },
+ {
+ "data": "[data]",
+ "documentation": "[documentation]",
+ "kind": 1,
+ "label": "afterword",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "afterword"
+ }
+ },
+ {
+ "data": "[data]",
+ "documentation": "[documentation]",
+ "kind": 1,
+ "label": "annotation",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "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/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__field_entry_field_name.snap
new file mode 100644
index 0000000000..32f1df6369
--- /dev/null
+++ b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__field_entry_field_name.snap
@@ -0,0 +1,67 @@
+---
+source: tests/integration/lsp/text_document/completion.rs
+assertion_line: 628
+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",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "abstract"
+ }
+ },
+ {
+ "data": "[data]",
+ "documentation": "[documentation]",
+ "kind": 1,
+ "label": "addendum",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "addendum"
+ }
+ },
+ {
+ "data": "[data]",
+ "documentation": "[documentation]",
+ "kind": 1,
+ "label": "address",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "address"
+ }
+ },
+ {
+ "data": "[data]",
+ "documentation": "[documentation]",
+ "kind": 1,
+ "label": "afterword",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "afterword"
+ }
+ },
+ {
+ "data": "[data]",
+ "documentation": "[documentation]",
+ "kind": 1,
+ "label": "annotation",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "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/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__field_entry_two_fields_name_closed.snap
new file mode 100644
index 0000000000..e1c61bab4c
--- /dev/null
+++ b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__field_entry_two_fields_name_closed.snap
@@ -0,0 +1,67 @@
+---
+source: tests/integration/lsp/text_document/completion.rs
+assertion_line: 654
+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",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "edition"
+ }
+ },
+ {
+ "data": "[data]",
+ "documentation": "[documentation]",
+ "kind": 1,
+ "label": "editor",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "editor"
+ }
+ },
+ {
+ "data": "[data]",
+ "documentation": "[documentation]",
+ "kind": 1,
+ "label": "editora",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "editora"
+ }
+ },
+ {
+ "data": "[data]",
+ "documentation": "[documentation]",
+ "kind": 1,
+ "label": "editoratype",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "editoratype"
+ }
+ },
+ {
+ "data": "[data]",
+ "documentation": "[documentation]",
+ "kind": 1,
+ "label": "editorb",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "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/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__field_entry_two_fields_name_open.snap
new file mode 100644
index 0000000000..b86d4e96b0
--- /dev/null
+++ b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__field_entry_two_fields_name_open.snap
@@ -0,0 +1,67 @@
+---
+source: tests/integration/lsp/text_document/completion.rs
+assertion_line: 641
+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",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "edition"
+ }
+ },
+ {
+ "data": "[data]",
+ "documentation": "[documentation]",
+ "kind": 1,
+ "label": "editor",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "editor"
+ }
+ },
+ {
+ "data": "[data]",
+ "documentation": "[documentation]",
+ "kind": 1,
+ "label": "editora",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "editora"
+ }
+ },
+ {
+ "data": "[data]",
+ "documentation": "[documentation]",
+ "kind": 1,
+ "label": "editoratype",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "editoratype"
+ }
+ },
+ {
+ "data": "[data]",
+ "documentation": "[documentation]",
+ "kind": 1,
+ "label": "editorb",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "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/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__glossary_ref_open_brace.snap
new file mode 100644
index 0000000000..25c90c0a4e
--- /dev/null
+++ b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__glossary_ref_open_brace.snap
@@ -0,0 +1,18 @@
+---
+source: tests/integration/lsp/text_document/completion.rs
+assertion_line: 145
+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,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "fpsLabel"
+ }
+ }
+]
diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__glossary_ref_simple.snap b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__glossary_ref_simple.snap
new file mode 100644
index 0000000000..a9c8bc5478
--- /dev/null
+++ b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__glossary_ref_simple.snap
@@ -0,0 +1,18 @@
+---
+source: tests/integration/lsp/text_document/completion.rs
+assertion_line: 131
+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,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "fpsLabel"
+ }
+ }
+]
diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__import_class_closed_brace.snap b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__import_class_closed_brace.snap
new file mode 100644
index 0000000000..1b15dff00b
--- /dev/null
+++ b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__import_class_closed_brace.snap
@@ -0,0 +1,67 @@
+---
+source: tests/integration/lsp/text_document/completion.rs
+assertion_line: 706
+expression: "complete(r#\"\n%TEX main.tex\n%SRC \\documentclass{art}\n%CUR ^\n%1.1 ^^^\"#)?"
+---
+[
+ {
+ "data": "[data]",
+ "documentation": "[documentation]",
+ "kind": 1,
+ "label": "article",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "article"
+ }
+ },
+ {
+ "data": "[data]",
+ "documentation": "[documentation]",
+ "kind": 1,
+ "label": "articleingud",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "articleingud"
+ }
+ },
+ {
+ "data": "[data]",
+ "documentation": "[documentation]",
+ "kind": 1,
+ "label": "articoletteracdp",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "articoletteracdp"
+ }
+ },
+ {
+ "data": "[data]",
+ "documentation": "[documentation]",
+ "kind": 1,
+ "label": "artikel1",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "artikel1"
+ }
+ },
+ {
+ "data": "[data]",
+ "documentation": "[documentation]",
+ "kind": 1,
+ "label": "artikel2",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "artikel2"
+ }
+ }
+]
diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__import_class_open_brace.snap b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__import_class_open_brace.snap
new file mode 100644
index 0000000000..4118d60707
--- /dev/null
+++ b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__import_class_open_brace.snap
@@ -0,0 +1,67 @@
+---
+source: tests/integration/lsp/text_document/completion.rs
+assertion_line: 693
+expression: "complete(r#\"\n%TEX main.tex\n%SRC \\documentclass{art \\foo\n%CUR ^\n%1.1 ^^^\"#)?"
+---
+[
+ {
+ "data": "[data]",
+ "documentation": "[documentation]",
+ "kind": 1,
+ "label": "article",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "article"
+ }
+ },
+ {
+ "data": "[data]",
+ "documentation": "[documentation]",
+ "kind": 1,
+ "label": "articleingud",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "articleingud"
+ }
+ },
+ {
+ "data": "[data]",
+ "documentation": "[documentation]",
+ "kind": 1,
+ "label": "articoletteracdp",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "articoletteracdp"
+ }
+ },
+ {
+ "data": "[data]",
+ "documentation": "[documentation]",
+ "kind": 1,
+ "label": "artikel1",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "artikel1"
+ }
+ },
+ {
+ "data": "[data]",
+ "documentation": "[documentation]",
+ "kind": 1,
+ "label": "artikel2",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "artikel2"
+ }
+ }
+]
diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__import_package_closed_brace.snap b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__import_package_closed_brace.snap
new file mode 100644
index 0000000000..141441047f
--- /dev/null
+++ b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__import_package_closed_brace.snap
@@ -0,0 +1,67 @@
+---
+source: tests/integration/lsp/text_document/completion.rs
+assertion_line: 680
+expression: "complete(r#\"\n%TEX main.tex\n%SRC \\usepackage{lips}\n%CUR ^\n%1.1 ^^^^\"#)?"
+---
+[
+ {
+ "data": "[data]",
+ "documentation": "[documentation]",
+ "kind": 1,
+ "label": "lips",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "lips"
+ }
+ },
+ {
+ "data": "[data]",
+ "documentation": "[documentation]",
+ "kind": 1,
+ "label": "lipsum",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "lipsum"
+ }
+ },
+ {
+ "data": "[data]",
+ "documentation": "[documentation]",
+ "kind": 1,
+ "label": "lisp-simple-alloc",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "lisp-simple-alloc"
+ }
+ },
+ {
+ "data": "[data]",
+ "documentation": "[documentation]",
+ "kind": 1,
+ "label": "lisp-string",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "lisp-string"
+ }
+ },
+ {
+ "data": "[data]",
+ "documentation": "[documentation]",
+ "kind": 1,
+ "label": "lwarp-lips",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "lwarp-lips"
+ }
+ }
+]
diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__import_package_open_brace.snap b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__import_package_open_brace.snap
new file mode 100644
index 0000000000..c188633107
--- /dev/null
+++ b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__import_package_open_brace.snap
@@ -0,0 +1,67 @@
+---
+source: tests/integration/lsp/text_document/completion.rs
+assertion_line: 667
+expression: "complete(r#\"\n%TEX main.tex\n%SRC \\usepackage{lips\n%CUR ^\n%1.1 ^^^^\"#)?"
+---
+[
+ {
+ "data": "[data]",
+ "documentation": "[documentation]",
+ "kind": 1,
+ "label": "lips",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "lips"
+ }
+ },
+ {
+ "data": "[data]",
+ "documentation": "[documentation]",
+ "kind": 1,
+ "label": "lipsum",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "lipsum"
+ }
+ },
+ {
+ "data": "[data]",
+ "documentation": "[documentation]",
+ "kind": 1,
+ "label": "lisp-simple-alloc",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "lisp-simple-alloc"
+ }
+ },
+ {
+ "data": "[data]",
+ "documentation": "[documentation]",
+ "kind": 1,
+ "label": "lisp-string",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "lisp-string"
+ }
+ },
+ {
+ "data": "[data]",
+ "documentation": "[documentation]",
+ "kind": 1,
+ "label": "lwarp-lips",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "lwarp-lips"
+ }
+ }
+]
diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__label.snap b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__label.snap
new file mode 100644
index 0000000000..e30dd28ab9
--- /dev/null
+++ b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__label.snap
@@ -0,0 +1,73 @@
+---
+source: tests/integration/lsp/text_document/completion.rs
+assertion_line: 719
+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,
+ "label": "eq:bar",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "eq:bar"
+ }
+ },
+ {
+ "data": "[data]",
+ "detail": "Equation (1)",
+ "filterText": "eq:foo Equation (1)",
+ "kind": 1,
+ "label": "eq:foo",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "eq:foo"
+ }
+ },
+ {
+ "data": "[data]",
+ "detail": "Figure 1",
+ "documentation": "[documentation]",
+ "filterText": "fig:baz Figure 1: Baz",
+ "kind": 1,
+ "label": "fig:baz",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "fig:baz"
+ }
+ },
+ {
+ "data": "[data]",
+ "detail": "Section (Bar)",
+ "filterText": "sec:bar Section (Bar)",
+ "kind": 1,
+ "label": "sec:bar",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "sec:bar"
+ }
+ },
+ {
+ "data": "[data]",
+ "detail": "Section 1 (Foo)",
+ "filterText": "sec:foo Section 1 (Foo)",
+ "kind": 1,
+ "label": "sec:foo",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "sec:foo"
+ }
+ }
+]
diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__theorem_begin.snap b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__theorem_begin.snap
new file mode 100644
index 0000000000..b6964fe89c
--- /dev/null
+++ b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__theorem_begin.snap
@@ -0,0 +1,19 @@
+---
+source: tests/integration/lsp/text_document/completion.rs
+assertion_line: 785
+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",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "lemma"
+ }
+ }
+]
diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__theorem_end.snap b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__theorem_end.snap
new file mode 100644
index 0000000000..60fdc37edb
--- /dev/null
+++ b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__theorem_end.snap
@@ -0,0 +1,19 @@
+---
+source: tests/integration/lsp/text_document/completion.rs
+assertion_line: 799
+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",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "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/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__tikz_library_closed_brace.snap
new file mode 100644
index 0000000000..a1d7354f8f
--- /dev/null
+++ b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__tikz_library_closed_brace.snap
@@ -0,0 +1,62 @@
+---
+source: tests/integration/lsp/text_document/completion.rs
+assertion_line: 826
+expression: "complete(r#\"\n%TEX main.tex\n%SRC \\usepgflibrary{}\n%CUR ^\"#)?"
+---
+[
+ {
+ "data": "[data]",
+ "kind": 1,
+ "label": "arrows",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "arrows"
+ }
+ },
+ {
+ "data": "[data]",
+ "kind": 1,
+ "label": "arrows.meta",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "arrows.meta"
+ }
+ },
+ {
+ "data": "[data]",
+ "kind": 1,
+ "label": "arrows.spaced",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "arrows.spaced"
+ }
+ },
+ {
+ "data": "[data]",
+ "kind": 1,
+ "label": "curvilinear",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "curvilinear"
+ }
+ },
+ {
+ "data": "[data]",
+ "kind": 1,
+ "label": "datavisualization.barcharts",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "datavisualization.barcharts"
+ }
+ }
+]
diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__tikz_library_open_brace.snap b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__tikz_library_open_brace.snap
new file mode 100644
index 0000000000..3c8a7a4b79
--- /dev/null
+++ b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__tikz_library_open_brace.snap
@@ -0,0 +1,62 @@
+---
+source: tests/integration/lsp/text_document/completion.rs
+assertion_line: 814
+expression: "complete(r#\"\n%TEX main.tex\n%SRC \\usepgflibrary{\n%CUR ^\"#)?"
+---
+[
+ {
+ "data": "[data]",
+ "kind": 1,
+ "label": "arrows",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "arrows"
+ }
+ },
+ {
+ "data": "[data]",
+ "kind": 1,
+ "label": "arrows.meta",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "arrows.meta"
+ }
+ },
+ {
+ "data": "[data]",
+ "kind": 1,
+ "label": "arrows.spaced",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "arrows.spaced"
+ }
+ },
+ {
+ "data": "[data]",
+ "kind": 1,
+ "label": "curvilinear",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "curvilinear"
+ }
+ },
+ {
+ "data": "[data]",
+ "kind": 1,
+ "label": "datavisualization.barcharts",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "datavisualization.barcharts"
+ }
+ }
+]
diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__user_command.snap b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__user_command.snap
new file mode 100644
index 0000000000..c5c6b741f3
--- /dev/null
+++ b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__user_command.snap
@@ -0,0 +1,19 @@
+---
+source: tests/integration/lsp/text_document/completion.rs
+assertion_line: 838
+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",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "foobar"
+ }
+ }
+]
diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__user_environment.snap b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__user_environment.snap
new file mode 100644
index 0000000000..d760617880
--- /dev/null
+++ b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__completion__user_environment.snap
@@ -0,0 +1,31 @@
+---
+source: tests/integration/lsp/text_document/completion.rs
+assertion_line: 856
+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",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "foo"
+ }
+ },
+ {
+ "data": "[data]",
+ "detail": "built-in",
+ "kind": 1,
+ "label": "filecontents",
+ "preselect": false,
+ "sortText": "[sortText]",
+ "textEdit": {
+ "range": "[range]",
+ "newText": "filecontents"
+ }
+ }
+]
diff --git a/support/texlab/tests/it/snapshots/it__document_symbol__enumerate_flat.snap b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__document_symbol__enumerate_flat.snap
index 52fb082eb0..3293d55600 100644
--- a/support/texlab/tests/it/snapshots/it__document_symbol__enumerate_flat.snap
+++ b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__document_symbol__enumerate_flat.snap
@@ -1,7 +1,7 @@
---
-source: tests/it/document_symbol.rs
-assertion_line: 90
-expression: server.find_document_symbols(uri)?
+source: tests/integration/lsp/text_document/document_symbol.rs
+assertion_line: 88
+expression: result.response
---
[
{
@@ -9,7 +9,7 @@ expression: server.find_document_symbols(uri)?
"kind": 10,
"deprecated": false,
"location": {
- "uri": "http://www.example.com/main.tex",
+ "uri": "[tmp]/main.tex",
"range": {
"start": {
"line": 4,
@@ -23,11 +23,11 @@ expression: server.find_document_symbols(uri)?
}
},
{
- "name": "1",
+ "name": "Item",
"kind": 22,
"deprecated": false,
"location": {
- "uri": "http://www.example.com/main.tex",
+ "uri": "[tmp]/main.tex",
"range": {
"start": {
"line": 5,
@@ -45,7 +45,7 @@ expression: server.find_document_symbols(uri)?
"kind": 22,
"deprecated": false,
"location": {
- "uri": "http://www.example.com/main.tex",
+ "uri": "[tmp]/main.tex",
"range": {
"start": {
"line": 6,
@@ -63,7 +63,7 @@ expression: server.find_document_symbols(uri)?
"kind": 22,
"deprecated": false,
"location": {
- "uri": "http://www.example.com/main.tex",
+ "uri": "[tmp]/main.tex",
"range": {
"start": {
"line": 7,
@@ -77,11 +77,11 @@ expression: server.find_document_symbols(uri)?
}
},
{
- "name": "2",
+ "name": "Qux",
"kind": 22,
"deprecated": false,
"location": {
- "uri": "http://www.example.com/main.tex",
+ "uri": "[tmp]/main.tex",
"range": {
"start": {
"line": 8,
diff --git a/support/texlab/tests/it/snapshots/it__document_symbol__enumerate_nested.snap b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__document_symbol__enumerate_nested.snap
index 10fc2f79ea..b2753ba69f 100644
--- a/support/texlab/tests/it/snapshots/it__document_symbol__enumerate_nested.snap
+++ b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__document_symbol__enumerate_nested.snap
@@ -1,7 +1,7 @@
---
-source: tests/it/document_symbol.rs
-assertion_line: 54
-expression: server.find_document_symbols(uri)?
+source: tests/integration/lsp/text_document/document_symbol.rs
+assertion_line: 53
+expression: result.response
---
[
{
@@ -30,7 +30,7 @@ expression: server.find_document_symbols(uri)?
},
"children": [
{
- "name": "1",
+ "name": "Item",
"detail": "it:foo",
"kind": 22,
"deprecated": false,
@@ -110,7 +110,7 @@ expression: server.find_document_symbols(uri)?
"children": []
},
{
- "name": "2",
+ "name": "Qux",
"detail": "it:qux",
"kind": 22,
"deprecated": false,
diff --git a/support/texlab/tests/it/snapshots/it__document_symbol__equation_flat.snap b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__document_symbol__equation_flat.snap
index 94a220cb97..b1a4630dab 100644
--- a/support/texlab/tests/it/snapshots/it__document_symbol__equation_flat.snap
+++ b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__document_symbol__equation_flat.snap
@@ -1,15 +1,15 @@
---
-source: tests/it/document_symbol.rs
-assertion_line: 170
-expression: server.find_document_symbols(uri)?
+source: tests/integration/lsp/text_document/document_symbol.rs
+assertion_line: 156
+expression: result.response
---
[
{
- "name": "Equation (1)",
+ "name": "Equation",
"kind": 14,
"deprecated": false,
"location": {
- "uri": "http://www.example.com/main.tex",
+ "uri": "[tmp]/main.tex",
"range": {
"start": {
"line": 4,
@@ -27,7 +27,7 @@ expression: server.find_document_symbols(uri)?
"kind": 14,
"deprecated": false,
"location": {
- "uri": "http://www.example.com/main.tex",
+ "uri": "[tmp]/main.tex",
"range": {
"start": {
"line": 8,
@@ -45,7 +45,7 @@ expression: server.find_document_symbols(uri)?
"kind": 14,
"deprecated": false,
"location": {
- "uri": "http://www.example.com/main.tex",
+ "uri": "[tmp]/main.tex",
"range": {
"start": {
"line": 12,
diff --git a/support/texlab/tests/it/snapshots/it__document_symbol__equation_nested.snap b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__document_symbol__equation_nested.snap
index 477a9cb585..fc707bd031 100644
--- a/support/texlab/tests/it/snapshots/it__document_symbol__equation_nested.snap
+++ b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__document_symbol__equation_nested.snap
@@ -1,11 +1,11 @@
---
-source: tests/it/document_symbol.rs
-assertion_line: 130
-expression: server.find_document_symbols(uri)?
+source: tests/integration/lsp/text_document/document_symbol.rs
+assertion_line: 117
+expression: result.response
---
[
{
- "name": "Equation (1)",
+ "name": "Equation",
"detail": "eq:foo",
"kind": 14,
"deprecated": false,
diff --git a/support/texlab/tests/it/snapshots/it__document_symbol__float_flat.snap b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__document_symbol__float_flat.snap
index ba3a5babe6..da456f914e 100644
--- a/support/texlab/tests/it/snapshots/it__document_symbol__float_flat.snap
+++ b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__document_symbol__float_flat.snap
@@ -1,15 +1,15 @@
---
-source: tests/it/document_symbol.rs
-assertion_line: 270
-expression: server.find_document_symbols(uri)?
+source: tests/integration/lsp/text_document/document_symbol.rs
+assertion_line: 238
+expression: result.response
---
[
{
- "name": "Figure 1: Foo",
+ "name": "Figure: Foo",
"kind": 6,
"deprecated": false,
"location": {
- "uri": "http://www.example.com/main.tex",
+ "uri": "[tmp]/main.tex",
"range": {
"start": {
"line": 4,
@@ -27,7 +27,7 @@ expression: server.find_document_symbols(uri)?
"kind": 6,
"deprecated": false,
"location": {
- "uri": "http://www.example.com/main.tex",
+ "uri": "[tmp]/main.tex",
"range": {
"start": {
"line": 9,
@@ -45,7 +45,7 @@ expression: server.find_document_symbols(uri)?
"kind": 6,
"deprecated": false,
"location": {
- "uri": "http://www.example.com/main.tex",
+ "uri": "[tmp]/main.tex",
"range": {
"start": {
"line": 14,
diff --git a/support/texlab/tests/it/snapshots/it__document_symbol__float_nested.snap b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__document_symbol__float_nested.snap
index 99262cf5c3..4f60c21c92 100644
--- a/support/texlab/tests/it/snapshots/it__document_symbol__float_nested.snap
+++ b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__document_symbol__float_nested.snap
@@ -1,11 +1,11 @@
---
-source: tests/it/document_symbol.rs
-assertion_line: 220
-expression: server.find_document_symbols(uri)?
+source: tests/integration/lsp/text_document/document_symbol.rs
+assertion_line: 189
+expression: result.response
---
[
{
- "name": "Figure 1: Foo",
+ "name": "Figure: Foo",
"detail": "fig:foo",
"kind": 6,
"deprecated": false,
diff --git a/support/texlab/tests/it/snapshots/it__document_symbol__section_flat.snap b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__document_symbol__section_flat.snap
index 1b8fecce0a..85e72e90e1 100644
--- a/support/texlab/tests/it/snapshots/it__document_symbol__section_flat.snap
+++ b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__document_symbol__section_flat.snap
@@ -1,7 +1,7 @@
---
-source: tests/it/document_symbol.rs
-assertion_line: 342
-expression: server.find_document_symbols(uri)?
+source: tests/integration/lsp/text_document/document_symbol.rs
+assertion_line: 316
+expression: result.response
---
[
{
@@ -9,7 +9,7 @@ expression: server.find_document_symbols(uri)?
"kind": 2,
"deprecated": false,
"location": {
- "uri": "http://www.example.com/main.tex",
+ "uri": "[tmp]/main.tex",
"range": {
"start": {
"line": 4,
@@ -23,11 +23,11 @@ expression: server.find_document_symbols(uri)?
}
},
{
- "name": "2 Bar",
+ "name": "Bar",
"kind": 2,
"deprecated": false,
"location": {
- "uri": "http://www.example.com/main.tex",
+ "uri": "[tmp]/main.tex",
"range": {
"start": {
"line": 6,
@@ -45,7 +45,7 @@ expression: server.find_document_symbols(uri)?
"kind": 2,
"deprecated": false,
"location": {
- "uri": "http://www.example.com/main.tex",
+ "uri": "[tmp]/main.tex",
"range": {
"start": {
"line": 8,
diff --git a/support/texlab/tests/it/snapshots/it__document_symbol__section_nested.snap b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__document_symbol__section_nested.snap
index 8443ca4c96..97ae75eac4 100644
--- a/support/texlab/tests/it/snapshots/it__document_symbol__section_nested.snap
+++ b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__document_symbol__section_nested.snap
@@ -1,7 +1,7 @@
---
-source: tests/it/document_symbol.rs
-assertion_line: 306
-expression: server.find_document_symbols(uri)?
+source: tests/integration/lsp/text_document/document_symbol.rs
+assertion_line: 281
+expression: result.response
---
[
{
@@ -31,7 +31,7 @@ expression: server.find_document_symbols(uri)?
"children": []
},
{
- "name": "2 Bar",
+ "name": "Bar",
"detail": "sec:bar",
"kind": 2,
"deprecated": false,
diff --git a/support/texlab/tests/it/snapshots/it__document_symbol__theorem_flat.snap b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__document_symbol__theorem_flat.snap
index 46765f2039..9af601da0d 100644
--- a/support/texlab/tests/it/snapshots/it__document_symbol__theorem_flat.snap
+++ b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__document_symbol__theorem_flat.snap
@@ -1,15 +1,15 @@
---
-source: tests/it/document_symbol.rs
-assertion_line: 436
-expression: server.find_document_symbols(uri)?
+source: tests/integration/lsp/text_document/document_symbol.rs
+assertion_line: 391
+expression: result.response
---
[
{
- "name": "Lemma 1 (Foo)",
+ "name": "Lemma (Foo)",
"kind": 13,
"deprecated": false,
"location": {
- "uri": "http://www.example.com/main.tex",
+ "uri": "[tmp]/main.tex",
"range": {
"start": {
"line": 6,
@@ -23,11 +23,11 @@ expression: server.find_document_symbols(uri)?
}
},
{
- "name": "Lemma 2",
+ "name": "Lemma",
"kind": 13,
"deprecated": false,
"location": {
- "uri": "http://www.example.com/main.tex",
+ "uri": "[tmp]/main.tex",
"range": {
"start": {
"line": 10,
@@ -45,7 +45,7 @@ expression: server.find_document_symbols(uri)?
"kind": 13,
"deprecated": false,
"location": {
- "uri": "http://www.example.com/main.tex",
+ "uri": "[tmp]/main.tex",
"range": {
"start": {
"line": 14,
@@ -63,7 +63,7 @@ expression: server.find_document_symbols(uri)?
"kind": 13,
"deprecated": false,
"location": {
- "uri": "http://www.example.com/main.tex",
+ "uri": "[tmp]/main.tex",
"range": {
"start": {
"line": 18,
diff --git a/support/texlab/tests/it/snapshots/it__document_symbol__theorem_nested.snap b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__document_symbol__theorem_nested.snap
index 2748a2ba0b..6a81f96fa6 100644
--- a/support/texlab/tests/it/snapshots/it__document_symbol__theorem_nested.snap
+++ b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__document_symbol__theorem_nested.snap
@@ -1,11 +1,11 @@
---
-source: tests/it/document_symbol.rs
-assertion_line: 389
-expression: server.find_document_symbols(uri)?
+source: tests/integration/lsp/text_document/document_symbol.rs
+assertion_line: 345
+expression: result.response
---
[
{
- "name": "Lemma 1 (Foo)",
+ "name": "Lemma (Foo)",
"detail": "thm:foo",
"kind": 13,
"deprecated": false,
@@ -32,7 +32,7 @@ expression: server.find_document_symbols(uri)?
"children": []
},
{
- "name": "Lemma 2",
+ "name": "Lemma",
"detail": "thm:bar",
"kind": 13,
"deprecated": false,
diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__formatting__bibtex_internal_command.snap b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__formatting__bibtex_internal_command.snap
new file mode 100644
index 0000000000..1add9efc6a
--- /dev/null
+++ b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__formatting__bibtex_internal_command.snap
@@ -0,0 +1,9 @@
+---
+source: tests/integration/lsp/text_document/formatting.rs
+assertion_line: 96
+expression: "format(r#\"\n%BIB main.bib\n%SRC @article{foo, bar = \"\\baz\",}\"#)?"
+---
+@article{foo,
+ bar = "\baz",
+}
+
diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__formatting__bibtex_internal_insert_braces.snap b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__formatting__bibtex_internal_insert_braces.snap
new file mode 100644
index 0000000000..ee9be8c822
--- /dev/null
+++ b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__formatting__bibtex_internal_insert_braces.snap
@@ -0,0 +1,8 @@
+---
+source: tests/integration/lsp/text_document/formatting.rs
+assertion_line: 85
+expression: "format(r#\"\n%BIB main.bib\n%SRC @article{foo, bar = baz,\"#)?"
+---
+@article{foo,
+ bar = baz,
+}
diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__formatting__bibtex_internal_join_strings.snap b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__formatting__bibtex_internal_join_strings.snap
new file mode 100644
index 0000000000..8c2a21f579
--- /dev/null
+++ b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__formatting__bibtex_internal_join_strings.snap
@@ -0,0 +1,9 @@
+---
+source: tests/integration/lsp/text_document/formatting.rs
+assertion_line: 107
+expression: "format(r#\"\n%BIB main.bib\n%SRC @article{foo, bar = \"baz\" # \"qux\"}\"#)?"
+---
+@article{foo,
+ bar = "baz" # "qux",
+}
+
diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__formatting__bibtex_internal_multiple_entries.snap b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__formatting__bibtex_internal_multiple_entries.snap
new file mode 100644
index 0000000000..cf228db867
--- /dev/null
+++ b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__formatting__bibtex_internal_multiple_entries.snap
@@ -0,0 +1,17 @@
+---
+source: tests/integration/lsp/text_document/formatting.rs
+assertion_line: 59
+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,
+ bar = {Lorem ipsum dolor sit amet, consectetur adipiscing elit. Lorem ipsum
+ dolor sit amet, consectetur adipiscing elit. Lorem ipsum dolor sit
+ amet, consectetur adipiscing elit.},
+}
+
+@article{foo,
+ bar = {Lorem ipsum dolor sit amet, consectetur adipiscing elit. Lorem ipsum
+ dolor sit amet, consectetur adipiscing elit. Lorem ipsum dolor sit
+ amet, consectetur adipiscing elit.},
+}"
+
diff --git a/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__formatting__bibtex_internal_parens.snap b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__formatting__bibtex_internal_parens.snap
new file mode 100644
index 0000000000..58e98f7ba5
--- /dev/null
+++ b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__formatting__bibtex_internal_parens.snap
@@ -0,0 +1,8 @@
+---
+source: tests/integration/lsp/text_document/formatting.rs
+assertion_line: 118
+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/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__formatting__bibtex_internal_preamble.snap
new file mode 100644
index 0000000000..a82706dbf6
--- /dev/null
+++ b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__formatting__bibtex_internal_preamble.snap
@@ -0,0 +1,7 @@
+---
+source: tests/integration/lsp/text_document/formatting.rs
+assertion_line: 140
+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/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__formatting__bibtex_internal_string.snap
new file mode 100644
index 0000000000..3234fca52c
--- /dev/null
+++ b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__formatting__bibtex_internal_string.snap
@@ -0,0 +1,7 @@
+---
+source: tests/integration/lsp/text_document/formatting.rs
+assertion_line: 129
+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/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__formatting__bibtex_internal_trailing_comma.snap
new file mode 100644
index 0000000000..1231f1795f
--- /dev/null
+++ b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__formatting__bibtex_internal_trailing_comma.snap
@@ -0,0 +1,9 @@
+---
+source: tests/integration/lsp/text_document/formatting.rs
+assertion_line: 74
+expression: "format(r#\"\n%BIB main.bib\n%SRC @article{foo, bar = baz}\"#)?"
+---
+@article{foo,
+ bar = baz,
+}
+
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/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__formatting__bibtex_internal_wrap_long_lines.snap
new file mode 100644
index 0000000000..fd9355025c
--- /dev/null
+++ b/support/texlab/tests/integration/lsp/text_document/snapshots/integration__lsp__text_document__formatting__bibtex_internal_wrap_long_lines.snap
@@ -0,0 +1,11 @@
+---
+source: tests/integration/lsp/text_document/formatting.rs
+assertion_line: 46
+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,
+ bar = {Lorem ipsum dolor sit amet, consectetur adipiscing elit. Lorem ipsum
+ dolor sit amet, consectetur adipiscing elit. Lorem ipsum dolor sit
+ amet, consectetur adipiscing elit.},
+}
+
diff --git a/support/texlab/tests/integration/lsp/workspace.rs b/support/texlab/tests/integration/lsp/workspace.rs
new file mode 100644
index 0000000000..15e0679dea
--- /dev/null
+++ b/support/texlab/tests/integration/lsp/workspace.rs
@@ -0,0 +1 @@
+mod symbol;
diff --git a/support/texlab/tests/it/snapshots/it__workspace_symbol__filter_bibtex.snap b/support/texlab/tests/integration/lsp/workspace/snapshots/integration__lsp__workspace__symbol__filter_bibtex.snap
index a5db160f9a..8b71b0519e 100644
--- a/support/texlab/tests/it/snapshots/it__workspace_symbol__filter_bibtex.snap
+++ b/support/texlab/tests/integration/lsp/workspace/snapshots/integration__lsp__workspace__symbol__filter_bibtex.snap
@@ -1,15 +1,14 @@
---
-source: tests/it/workspace_symbol.rs
-assertion_line: 117
-expression: "run(\"bibtex\")?"
+source: tests/integration/lsp/workspace/symbol.rs
+assertion_line: 145
+expression: result.actual_symbols
---
[
{
- "name": "foo",
- "kind": 24,
"deprecated": false,
+ "kind": 24,
"location": {
- "uri": "http://www.example.com/main.bib",
+ "uri": "[tmp]/main.bib",
"range": {
"start": {
"line": 0,
@@ -20,14 +19,14 @@ expression: "run(\"bibtex\")?"
"character": 14
}
}
- }
+ },
+ "name": "foo"
},
{
- "name": "bar",
- "kind": 15,
"deprecated": false,
+ "kind": 15,
"location": {
- "uri": "http://www.example.com/main.bib",
+ "uri": "[tmp]/main.bib",
"range": {
"start": {
"line": 2,
@@ -38,6 +37,7 @@ expression: "run(\"bibtex\")?"
"character": 20
}
}
- }
+ },
+ "name": "bar"
}
]
diff --git a/support/texlab/tests/it/snapshots/it__workspace_symbol__filter_type_figure.snap b/support/texlab/tests/integration/lsp/workspace/snapshots/integration__lsp__workspace__symbol__filter_type_figure.snap
index aef75c18a1..a2343d994b 100644
--- a/support/texlab/tests/it/snapshots/it__workspace_symbol__filter_type_figure.snap
+++ b/support/texlab/tests/integration/lsp/workspace/snapshots/integration__lsp__workspace__symbol__filter_type_figure.snap
@@ -1,15 +1,14 @@
---
-source: tests/it/workspace_symbol.rs
-assertion_line: 99
-expression: "run(\"figure\")?"
+source: tests/integration/lsp/workspace/symbol.rs
+assertion_line: 127
+expression: result.actual_symbols
---
[
{
- "name": "Figure 1: Bar",
- "kind": 6,
"deprecated": false,
+ "kind": 6,
"location": {
- "uri": "http://www.example.com/main.tex",
+ "uri": "[tmp]/main.tex",
"range": {
"start": {
"line": 15,
@@ -20,6 +19,7 @@ expression: "run(\"figure\")?"
"character": 12
}
}
- }
+ },
+ "name": "Figure 1: Bar"
}
]
diff --git a/support/texlab/tests/it/snapshots/it__workspace_symbol__filter_type_item.snap b/support/texlab/tests/integration/lsp/workspace/snapshots/integration__lsp__workspace__symbol__filter_type_item.snap
index 9f43f48dae..37dad570c9 100644
--- a/support/texlab/tests/it/snapshots/it__workspace_symbol__filter_type_item.snap
+++ b/support/texlab/tests/integration/lsp/workspace/snapshots/integration__lsp__workspace__symbol__filter_type_item.snap
@@ -1,15 +1,14 @@
---
-source: tests/it/workspace_symbol.rs
-assertion_line: 105
-expression: "run(\"item\")?"
+source: tests/integration/lsp/workspace/symbol.rs
+assertion_line: 133
+expression: result.actual_symbols
---
[
{
- "name": "1",
- "kind": 22,
"deprecated": false,
+ "kind": 22,
"location": {
- "uri": "http://www.example.com/main.tex",
+ "uri": "[tmp]/main.tex",
"range": {
"start": {
"line": 24,
@@ -20,14 +19,14 @@ expression: "run(\"item\")?"
"character": 28
}
}
- }
+ },
+ "name": "1"
},
{
- "name": "2",
- "kind": 22,
"deprecated": false,
+ "kind": 22,
"location": {
- "uri": "http://www.example.com/main.tex",
+ "uri": "[tmp]/main.tex",
"range": {
"start": {
"line": 25,
@@ -38,14 +37,14 @@ expression: "run(\"item\")?"
"character": 28
}
}
- }
+ },
+ "name": "2"
},
{
- "name": "3",
- "kind": 22,
"deprecated": false,
+ "kind": 22,
"location": {
- "uri": "http://www.example.com/main.tex",
+ "uri": "[tmp]/main.tex",
"range": {
"start": {
"line": 26,
@@ -56,6 +55,7 @@ expression: "run(\"item\")?"
"character": 28
}
}
- }
+ },
+ "name": "3"
}
]
diff --git a/support/texlab/tests/it/snapshots/it__workspace_symbol__filter_type_math.snap b/support/texlab/tests/integration/lsp/workspace/snapshots/integration__lsp__workspace__symbol__filter_type_math.snap
index 5e8e3f9f1e..8b98b614a3 100644
--- a/support/texlab/tests/it/snapshots/it__workspace_symbol__filter_type_math.snap
+++ b/support/texlab/tests/integration/lsp/workspace/snapshots/integration__lsp__workspace__symbol__filter_type_math.snap
@@ -1,15 +1,14 @@
---
-source: tests/it/workspace_symbol.rs
-assertion_line: 111
-expression: "run(\"math\")?"
+source: tests/integration/lsp/workspace/symbol.rs
+assertion_line: 139
+expression: result.actual_symbols
---
[
{
- "name": "Equation (1)",
- "kind": 14,
"deprecated": false,
+ "kind": 14,
"location": {
- "uri": "http://www.example.com/main.tex",
+ "uri": "[tmp]/main.tex",
"range": {
"start": {
"line": 9,
@@ -20,14 +19,14 @@ expression: "run(\"math\")?"
"character": 14
}
}
- }
+ },
+ "name": "Equation (1)"
},
{
- "name": "Lemma 1 (Qux)",
- "kind": 13,
"deprecated": false,
+ "kind": 13,
"location": {
- "uri": "http://www.example.com/main.tex",
+ "uri": "[tmp]/main.tex",
"range": {
"start": {
"line": 33,
@@ -38,6 +37,7 @@ expression: "run(\"math\")?"
"character": 11
}
}
- }
+ },
+ "name": "Lemma 1 (Qux)"
}
]
diff --git a/support/texlab/tests/it/snapshots/it__workspace_symbol__filter_type_section.snap b/support/texlab/tests/integration/lsp/workspace/snapshots/integration__lsp__workspace__symbol__filter_type_section.snap
index c075a080b5..b4974c9d7f 100644
--- a/support/texlab/tests/it/snapshots/it__workspace_symbol__filter_type_section.snap
+++ b/support/texlab/tests/integration/lsp/workspace/snapshots/integration__lsp__workspace__symbol__filter_type_section.snap
@@ -1,15 +1,14 @@
---
-source: tests/it/workspace_symbol.rs
-assertion_line: 93
-expression: "run(\"section\")?"
+source: tests/integration/lsp/workspace/symbol.rs
+assertion_line: 121
+expression: result.actual_symbols
---
[
{
- "name": "1 Foo",
- "kind": 2,
"deprecated": false,
+ "kind": 2,
"location": {
- "uri": "http://www.example.com/main.tex",
+ "uri": "[tmp]/main.tex",
"range": {
"start": {
"line": 7,
@@ -20,14 +19,14 @@ expression: "run(\"section\")?"
"character": 14
}
}
- }
+ },
+ "name": "1 Foo"
},
{
- "name": "2 Bar",
- "kind": 2,
"deprecated": false,
+ "kind": 2,
"location": {
- "uri": "http://www.example.com/main.tex",
+ "uri": "[tmp]/main.tex",
"range": {
"start": {
"line": 13,
@@ -38,14 +37,14 @@ expression: "run(\"section\")?"
"character": 12
}
}
- }
+ },
+ "name": "2 Bar"
},
{
- "name": "3 Baz",
- "kind": 2,
"deprecated": false,
+ "kind": 2,
"location": {
- "uri": "http://www.example.com/main.tex",
+ "uri": "[tmp]/main.tex",
"range": {
"start": {
"line": 21,
@@ -56,14 +55,14 @@ expression: "run(\"section\")?"
"character": 15
}
}
- }
+ },
+ "name": "3 Baz"
},
{
- "name": "4 Qux",
- "kind": 2,
"deprecated": false,
+ "kind": 2,
"location": {
- "uri": "http://www.example.com/main.tex",
+ "uri": "[tmp]/main.tex",
"range": {
"start": {
"line": 29,
@@ -74,6 +73,7 @@ expression: "run(\"section\")?"
"character": 11
}
}
- }
+ },
+ "name": "4 Qux"
}
]
diff --git a/support/texlab/tests/integration/lsp/workspace/symbol.rs b/support/texlab/tests/integration/lsp/workspace/symbol.rs
new file mode 100644
index 0000000000..0af7534af3
--- /dev/null
+++ b/support/texlab/tests/integration/lsp/workspace/symbol.rs
@@ -0,0 +1,147 @@
+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};
+
+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)?;
+
+ let fixture = fixture::parse(fixture);
+ for file in fixture.files {
+ client.open(file.name, file.lang, file.text)?;
+ }
+
+ let actual_symbols = client
+ .request::<WorkspaceSymbol>(WorkspaceSymbolParams {
+ query: query.to_string(),
+ work_done_progress_params: Default::default(),
+ partial_result_params: Default::default(),
+ })?
+ .unwrap_or_default();
+
+ 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 {
+ actual_symbols,
+ uri_redaction,
+ })
+}
+
+macro_rules! assert_symbols {
+ ($result:expr) => {
+ let result = $result;
+ assert_json_snapshot!(result.actual_symbols, {
+ "[].location.uri" => result.uri_redaction,
+ "[]" => insta::sorted_redaction()
+ });
+ };
+}
+
+const FIXTURE: &str = r#"
+%TEX main.tex
+%SRC \documentclass{article}
+%SRC \usepackage{caption}
+%SRC \usepackage{amsmath}
+%SRC \usepackage{amsthm}
+%SRC
+%SRC \begin{document}
+%SRC
+%SRC \section{Foo}\label{sec:foo}
+%SRC
+%SRC \begin{equation}\label{eq:foo}
+%SRC Foo
+%SRC \end{equation}
+%SRC
+%SRC \section{Bar}\label{sec:bar}
+%SRC
+%SRC \begin{figure}
+%SRC Bar
+%SRC \caption{Bar}
+%SRC \label{fig:bar}
+%SRC \end{figure}
+%SRC
+%SRC \section{Baz}\label{sec:baz}
+%SRC
+%SRC \begin{enumerate}
+%SRC \item\label{itm:foo} Foo
+%SRC \item\label{itm:bar} Bar
+%SRC \item\label{itm:baz} Baz
+%SRC \end{enumerate}
+%SRC
+%SRC \section{Qux}\label{sec:qux}
+%SRC
+%SRC \newtheorem{lemma}{Lemma}
+%SRC
+%SRC \begin{lemma}[Qux]\label{thm:qux}
+%SRC Qux
+%SRC \end{lemma}
+%SRC
+%SRC \end{document}
+
+%TEX main.aux
+%SRC \relax
+%SRC \@writefile{lof}{\contentsline {figure}{\numberline {1}{\ignorespaces Bar\relax }}{1}\protected@file@percent }
+%SRC \providecommand*\caption@xref[2]{\@setref\relax\@undefined{#1}}
+%SRC \newlabel{fig:bar}{{1}{1}}
+%SRC \@writefile{toc}{\contentsline {section}{\numberline {1}Foo}{1}\protected@file@percent }
+%SRC \newlabel{sec:foo}{{1}{1}}
+%SRC \newlabel{eq: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 {section}{\numberline {3}Baz}{1}\protected@file@percent }
+%SRC \newlabel{sec:baz}{{3}{1}}
+%SRC \newlabel{itm:foo}{{1}{1}}
+%SRC \newlabel{itm:bar}{{2}{1}}
+%SRC \newlabel{itm:baz}{{3}{1}}
+%SRC \@writefile{toc}{\contentsline {section}{\numberline {4}Qux}{1}\protected@file@percent }
+%SRC \newlabel{sec:qux}{{4}{1}}
+%SRC \newlabel{thm:qux}{{1}{1}}
+
+%BIB main.bib
+%SRC @article{foo,}
+%SRC
+%SRC @string{bar = "bar"}"#;
+
+#[test]
+fn filter_type_section() -> Result<()> {
+ assert_symbols!(find_symbols(FIXTURE, "section")?);
+ Ok(())
+}
+
+#[test]
+fn filter_type_figure() -> Result<()> {
+ assert_symbols!(find_symbols(FIXTURE, "figure")?);
+ Ok(())
+}
+
+#[test]
+fn filter_type_item() -> Result<()> {
+ assert_symbols!(find_symbols(FIXTURE, "item")?);
+ Ok(())
+}
+
+#[test]
+fn filter_type_math() -> Result<()> {
+ assert_symbols!(find_symbols(FIXTURE, "math")?);
+ Ok(())
+}
+
+#[test]
+fn filter_bibtex() -> Result<()> {
+ assert_symbols!(find_symbols(FIXTURE, "bibtex")?);
+ Ok(())
+}
diff --git a/support/texlab/tests/integration/main.rs b/support/texlab/tests/integration/main.rs
new file mode 100644
index 0000000000..508158af91
--- /dev/null
+++ b/support/texlab/tests/integration/main.rs
@@ -0,0 +1,2 @@
+mod dev;
+mod lsp;
diff --git a/support/texlab/tests/it/common.rs b/support/texlab/tests/it/common.rs
deleted file mode 100644
index 5430bfd2be..0000000000
--- a/support/texlab/tests/it/common.rs
+++ /dev/null
@@ -1,318 +0,0 @@
-use std::{
- fs,
- sync::{
- atomic::{AtomicI32, Ordering},
- Mutex,
- },
- thread::{self, JoinHandle},
-};
-
-use anyhow::Result;
-use lsp_server::{Connection, RequestId};
-use lsp_types::{notification::Notification, request::Request, *};
-use rustc_hash::FxHashMap;
-use tempfile::{tempdir, TempDir};
-use texlab::Server;
-use unindent::unindent;
-
-pub struct ServerTester {
- pub directory: TempDir,
- client: Connection,
- handle: Option<JoinHandle<()>>,
- request_id: AtomicI32,
- pub diagnostics_by_uri: Mutex<FxHashMap<Url, Vec<Diagnostic>>>,
-}
-
-impl ServerTester {
- pub fn launch_new_instance() -> Result<Self> {
- let directory = tempdir()?;
- let (conn, client) = Connection::memory();
- let server = Server::with_connection(conn, directory.path().to_path_buf(), false)?;
- let handle = thread::spawn(move || server.run().unwrap());
- Ok(Self {
- directory,
- client,
- handle: Some(handle),
- request_id: AtomicI32::new(0),
- diagnostics_by_uri: Mutex::default(),
- })
- }
-
- fn wait_for_response(&self, request_id: RequestId) -> Result<lsp_server::Response> {
- loop {
- match self.client.receiver.recv()? {
- lsp_server::Message::Request(request) => {
- match request.method.as_str() {
- request::RegisterCapability::METHOD => {
- self.client
- .sender
- .send(lsp_server::Response::new_ok(request.id, ()).into())?;
- }
- method => {
- panic!("unknown request: {}", method);
- }
- };
- }
- lsp_server::Message::Notification(notification) => {
- match notification.method.as_str() {
- notification::PublishDiagnostics::METHOD => {
- let params = serde_json::from_value::<PublishDiagnosticsParams>(
- notification.params,
- )?;
- let mut diagnostics_by_uri = self.diagnostics_by_uri.lock().unwrap();
- diagnostics_by_uri.insert(params.uri, params.diagnostics);
- }
- method => {
- panic!("unknown notification: {}", method);
- }
- };
- }
- lsp_server::Message::Response(response) => {
- assert_eq!(response.id, request_id);
- return Ok(response);
- }
- }
- }
- }
-
- #[allow(deprecated)]
- pub fn initialize(
- &self,
- client_capabilities: ClientCapabilities,
- client_info: Option<ClientInfo>,
- ) -> anyhow::Result<()> {
- let request_id = RequestId::from(self.request_id.fetch_add(1, Ordering::SeqCst));
- self.client.sender.send(
- lsp_server::Request::new(
- request_id.clone(),
- request::Initialize::METHOD.to_string(),
- InitializeParams {
- process_id: None,
- root_path: None,
- root_uri: None,
- initialization_options: None,
- capabilities: client_capabilities,
- trace: None,
- workspace_folders: None,
- client_info,
- locale: None,
- },
- )
- .into(),
- )?;
- self.wait_for_response(request_id)?;
-
- self.client.sender.send(
- lsp_server::Notification::new(notification::Initialized::METHOD.to_string(), ()).into(),
- )?;
-
- Ok(())
- }
-
- pub fn open(&self, name: &str, text: &str, language_id: &str, store: bool) -> Result<Url> {
- let text = unindent(text).trim().to_string();
- let path = self.directory.path().join(name);
- if store {
- fs::create_dir_all(path.parent().unwrap())?;
- fs::write(&path, &text)?;
- }
-
- let uri = Url::from_file_path(path).unwrap();
- self.client.sender.send(
- lsp_server::Notification::new(
- notification::DidOpenTextDocument::METHOD.to_string(),
- DidOpenTextDocumentParams {
- text_document: TextDocumentItem::new(
- uri.clone(),
- language_id.to_string(),
- 0,
- text,
- ),
- },
- )
- .into(),
- )?;
- Ok(uri)
- }
-
- pub fn open_memory(&self, uri: Url, text: &str, language_id: &str) -> Result<()> {
- let text = unindent(text).trim().to_string();
- let text_document = TextDocumentItem::new(uri, language_id.to_string(), 0, text);
- self.client.sender.send(
- lsp_server::Notification::new(
- notification::DidOpenTextDocument::METHOD.to_string(),
- DidOpenTextDocumentParams { text_document },
- )
- .into(),
- )?;
- Ok(())
- }
-
- // pub fn edit(&self, uri: Url, text: &str) -> Result<()> {
- // let text = unindent(text).trim().to_string();
- // self.client.sender.send(
- // lsp_server::Notification::new(
- // notification::DidChangeTextDocument::METHOD.to_string(),
- // DidChangeTextDocumentParams {
- // text_document: VersionedTextDocumentIdentifier::new(uri, 0),
- // content_changes: vec![TextDocumentContentChangeEvent {
- // text,
- // range: None,
- // range_length: None,
- // }],
- // },
- // )
- // .into(),
- // )?;
- // Ok(())
- // }
-
- pub fn complete(&self, uri: Url, line: u32, character: u32) -> Result<CompletionList> {
- let request_id = RequestId::from(self.request_id.fetch_add(1, Ordering::SeqCst));
-
- self.client.sender.send(
- lsp_server::Request::new(
- request_id.clone(),
- request::Completion::METHOD.to_string(),
- CompletionParams {
- text_document_position: TextDocumentPositionParams::new(
- TextDocumentIdentifier::new(uri),
- Position::new(line, character),
- ),
- work_done_progress_params: WorkDoneProgressParams::default(),
- partial_result_params: PartialResultParams::default(),
- context: None,
- },
- )
- .into(),
- )?;
-
- let response = self.wait_for_response(request_id)?;
- let list = serde_json::from_value(response.result.expect("completion request failed"))?;
- Ok(list)
- }
-
- pub fn resolve_completion_item(&self, item: CompletionItem) -> Result<CompletionItem> {
- let request_id = RequestId::from(self.request_id.fetch_add(1, Ordering::SeqCst));
-
- self.client.sender.send(
- lsp_server::Request::new(
- request_id.clone(),
- request::ResolveCompletionItem::METHOD.to_string(),
- item,
- )
- .into(),
- )?;
-
- let response = self.wait_for_response(request_id)?;
- let result = serde_json::from_value(
- response
- .result
- .expect("resolve completion item request failed"),
- )?;
- Ok(result)
- }
-
- pub fn hover(&self, uri: Url, line: u32, character: u32) -> Result<Option<Hover>> {
- let request_id = RequestId::from(self.request_id.fetch_add(1, Ordering::SeqCst));
-
- self.client.sender.send(
- lsp_server::Request::new(
- request_id.clone(),
- request::HoverRequest::METHOD.to_string(),
- HoverParams {
- text_document_position_params: TextDocumentPositionParams::new(
- TextDocumentIdentifier::new(uri),
- Position::new(line, character),
- ),
- work_done_progress_params: WorkDoneProgressParams::default(),
- },
- )
- .into(),
- )?;
-
- let response = self.wait_for_response(request_id)?;
- let hover = serde_json::from_value(response.result.expect("hover request failed"))?;
- Ok(hover)
- }
-
- pub fn find_document_symbols(&self, uri: Url) -> Result<DocumentSymbolResponse> {
- let request_id = RequestId::from(self.request_id.fetch_add(1, Ordering::SeqCst));
-
- self.client.sender.send(
- lsp_server::Request::new(
- request_id.clone(),
- request::DocumentSymbolRequest::METHOD.to_string(),
- DocumentSymbolParams {
- text_document: TextDocumentIdentifier::new(uri),
- work_done_progress_params: WorkDoneProgressParams::default(),
- partial_result_params: PartialResultParams::default(),
- },
- )
- .into(),
- )?;
-
- let response = self.wait_for_response(request_id)?;
- let symbols =
- serde_json::from_value(response.result.expect("document symbol request failed"))?;
- Ok(symbols)
- }
-
- pub fn find_workspace_symbols(&self, query: &str) -> Result<Vec<SymbolInformation>> {
- let request_id = RequestId::from(self.request_id.fetch_add(1, Ordering::SeqCst));
-
- self.client.sender.send(
- lsp_server::Request::new(
- request_id.clone(),
- request::WorkspaceSymbol::METHOD.to_string(),
- WorkspaceSymbolParams {
- partial_result_params: PartialResultParams::default(),
- work_done_progress_params: WorkDoneProgressParams::default(),
- query: query.to_string(),
- },
- )
- .into(),
- )?;
-
- let response = self.wait_for_response(request_id)?;
- let symbols =
- serde_json::from_value(response.result.expect("workspace symbol request failed"))?;
- Ok(symbols)
- }
-
- // pub fn change_configuration(&self, options: Options) -> Result<()> {
- // self.client.sender.send(
- // lsp_server::Notification::new(
- // notification::DidChangeConfiguration::METHOD.to_string(),
- // DidChangeConfigurationParams {
- // settings: serde_json::to_value(options)?,
- // },
- // )
- // .into(),
- // )?;
- // Ok(())
- // }
-}
-
-impl Drop for ServerTester {
- fn drop(&mut self) {
- self.client
- .sender
- .send(
- lsp_server::Request::new(
- RequestId::from(self.request_id.fetch_add(1, Ordering::SeqCst)),
- request::Shutdown::METHOD.to_string(),
- (),
- )
- .into(),
- )
- .unwrap();
-
- self.client
- .sender
- .send(lsp_server::Notification::new(notification::Exit::METHOD.to_string(), ()).into())
- .unwrap();
-
- self.handle.take().unwrap().join().unwrap();
- }
-}
diff --git a/support/texlab/tests/it/completion.rs b/support/texlab/tests/it/completion.rs
deleted file mode 100644
index 58ad1970ba..0000000000
--- a/support/texlab/tests/it/completion.rs
+++ /dev/null
@@ -1,817 +0,0 @@
-use anyhow::Result;
-use lsp_types::{CompletionList, Url};
-
-use crate::common::ServerTester;
-
-fn complete_and_resolve(
- server: &ServerTester,
- uri: Url,
- line: u32,
- character: u32,
-) -> Result<CompletionList> {
- let mut list = server.complete(uri, line, character)?;
- let mut new_items = Vec::new();
- for item in list.items.into_iter().take(7) {
- let mut new_item = server.resolve_completion_item(item)?;
- new_item.data = None;
- new_items.push(new_item);
- }
- list.items = new_items;
- Ok(list)
-}
-
-mod bibtex {
- use insta::assert_json_snapshot;
- use lsp_types::ClientCapabilities;
-
- use super::*;
-
- #[test]
- fn test_empty_document() -> Result<()> {
- let server = ServerTester::launch_new_instance()?;
- server.initialize(ClientCapabilities::default(), None)?;
- let uri = server.open("main.bib", "", "bibtex", false)?;
- assert_json_snapshot!(complete_and_resolve(&server, uri, 0, 0)?);
- Ok(())
- }
-
- #[test]
- fn test_junk() -> Result<()> {
- let server = ServerTester::launch_new_instance()?;
- server.initialize(ClientCapabilities::default(), None)?;
- let uri = server.open("main.bib", "foo", "bibtex", false)?;
- assert_json_snapshot!(complete_and_resolve(&server, uri, 0, 0)?);
- Ok(())
- }
-
- #[test]
- fn test_command_incomplete_entry() -> Result<()> {
- let server = ServerTester::launch_new_instance()?;
- server.initialize(ClientCapabilities::default(), None)?;
- let uri = server.open(
- "main.bib",
- r#"
- @article{foo,
- author = {\LaT
- }
- "#,
- "bibtex",
- false,
- )?;
- assert_json_snapshot!(complete_and_resolve(&server, uri, 1, 18)?);
- Ok(())
- }
-
- #[test]
- fn test_command_complete_entry() -> Result<()> {
- let server = ServerTester::launch_new_instance()?;
- server.initialize(ClientCapabilities::default(), None)?;
- let uri = server.open(
- "main.bib",
- r#"
- @article{foo,
- author = {\LaT}
- }
- "#,
- "bibtex",
- false,
- )?;
- assert_json_snapshot!(complete_and_resolve(&server, uri, 1, 18)?);
- Ok(())
- }
-
- #[test]
- fn test_entry_type_empty_name() -> Result<()> {
- let server = ServerTester::launch_new_instance()?;
- server.initialize(ClientCapabilities::default(), None)?;
- let uri = server.open(
- "main.bib",
- r#"
- @
- "#,
- "bibtex",
- false,
- )?;
- assert_json_snapshot!(complete_and_resolve(&server, uri, 0, 1)?);
- Ok(())
- }
-
- #[test]
- fn test_entry_type_empty_name_before() -> Result<()> {
- let server = ServerTester::launch_new_instance()?;
- server.initialize(ClientCapabilities::default(), None)?;
- let uri = server.open(
- "main.bib",
- r#"
- @
- "#,
- "bibtex",
- false,
- )?;
- assert_json_snapshot!(complete_and_resolve(&server, uri, 0, 0)?);
- Ok(())
- }
-
- #[test]
- fn test_entry_type_incomplete() -> Result<()> {
- let server = ServerTester::launch_new_instance()?;
- server.initialize(ClientCapabilities::default(), None)?;
- let uri = server.open(
- "main.bib",
- r#"
- @art
- "#,
- "bibtex",
- false,
- )?;
- assert_json_snapshot!(complete_and_resolve(&server, uri, 0, 1)?);
- Ok(())
- }
-
- #[test]
- fn test_entry_type_complete() -> Result<()> {
- let server = ServerTester::launch_new_instance()?;
- server.initialize(ClientCapabilities::default(), None)?;
- let uri = server.open(
- "main.bib",
- r#"
- @article
- "#,
- "bibtex",
- false,
- )?;
- assert_json_snapshot!(complete_and_resolve(&server, uri, 0, 1)?);
- Ok(())
- }
-
- #[test]
- fn test_field_incomplete_entry() -> Result<()> {
- let server = ServerTester::launch_new_instance()?;
- server.initialize(ClientCapabilities::default(), None)?;
- let uri = server.open(
- "main.bib",
- r#"
- @article{foo,
- titl
- "#,
- "bibtex",
- false,
- )?;
- assert_json_snapshot!(complete_and_resolve(&server, uri, 1, 6)?);
- Ok(())
- }
-
- #[test]
- fn test_field_complete_entry() -> Result<()> {
- let server = ServerTester::launch_new_instance()?;
- server.initialize(ClientCapabilities::default(), None)?;
- let uri = server.open(
- "main.bib",
- r#"
- @article{foo,
- title = {}
- }
- "#,
- "bibtex",
- false,
- )?;
- assert_json_snapshot!(complete_and_resolve(&server, uri, 1, 6)?);
- Ok(())
- }
-}
-
-mod latex {
- use insta::assert_json_snapshot;
- use lsp_types::ClientCapabilities;
-
- use super::*;
-
- #[test]
- fn test_empty_document() -> Result<()> {
- let server = ServerTester::launch_new_instance()?;
- server.initialize(ClientCapabilities::default(), None)?;
- let uri = server.open("main.tex", "", "latex", false)?;
- assert_json_snapshot!(complete_and_resolve(&server, uri, 0, 0)?);
- Ok(())
- }
-
- #[test]
- fn test_begin_command() -> Result<()> {
- let server = ServerTester::launch_new_instance()?;
- server.initialize(ClientCapabilities::default(), None)?;
- let uri = server.open("main.tex", r#"\b"#, "latex", false)?;
- assert_json_snapshot!(complete_and_resolve(&server, uri, 0, 2)?);
- Ok(())
- }
-
- #[test]
- fn test_citation() -> Result<()> {
- let server = ServerTester::launch_new_instance()?;
- server.initialize(ClientCapabilities::default(), None)?;
- let tex_uri = server.open(
- "main.tex",
- r#"
- \documentclass{article}
- \bibliography{main}
- \begin{document}
- \cite{
- \end{document}
- "#,
- "latex",
- false,
- )?;
- server.open(
- "main.bib",
- r#"
- @article{foo:2019,
- author = {Foo Bar},
- title = {Baz Qux},
- year = {2019},
- }
-
- @article{bar:2005,}
- "#,
- "bibtex",
- false,
- )?;
- assert_json_snapshot!(complete_and_resolve(&server, tex_uri, 3, 6)?);
- Ok(())
- }
-
- #[test]
- fn test_citation_multi_word() -> Result<()> {
- let server = ServerTester::launch_new_instance()?;
- server.initialize(ClientCapabilities::default(), None)?;
- let tex_uri = server.open(
- "main.tex",
- r#"
- \documentclass{article}
- \bibliography{main}
- \begin{document}
- \cite{foo 2
- \end{document}
- "#,
- "latex",
- false,
- )?;
- server.open(
- "main.bib",
- r#"
- @article{foo,
- author = {Foo Bar},
- title = {Baz Qux},
- year = {2019},
- }
-
- @article{bar:2005,}
- "#,
- "bibtex",
- false,
- )?;
- assert_json_snapshot!(complete_and_resolve(&server, tex_uri, 3, 7)?);
- Ok(())
- }
-
- #[test]
- fn test_citation_after() -> Result<()> {
- let server = ServerTester::launch_new_instance()?;
- server.initialize(ClientCapabilities::default(), None)?;
- let tex_uri = server.open(
- "main.tex",
- r#"
- \documentclass{article}
- \bibliography{main}
- \begin{document}
- \cite{}
- \end{document}
- "#,
- "latex",
- false,
- )?;
- server.open(
- "main.bib",
- r#"
- @article{foo:2019,
- author = {Foo Bar},
- title = {Baz Qux},
- year = {2019},
- }
-
- @article{bar:2005,}
- "#,
- "bibtex",
- false,
- )?;
- assert_json_snapshot!(complete_and_resolve(&server, tex_uri, 3, 7)?);
- Ok(())
- }
-
- #[test]
- fn test_citation_open_brace() -> Result<()> {
- let server = ServerTester::launch_new_instance()?;
- server.initialize(ClientCapabilities::default(), None)?;
- let tex_uri = server.open(
- "main.tex",
- r#"
- \documentclass{article}
- \bibliography{main}
- \begin{document}
- \cite{Foo
- \end{document}
- "#,
- "latex",
- false,
- )?;
- server.open(
- "main.bib",
- r#"
- @article{FooBar,
- author = {Foo Bar},
- title = {Baz Qux},
- year = {2019},
- }
- "#,
- "bibtex",
- false,
- )?;
- assert_json_snapshot!(complete_and_resolve(&server, tex_uri, 3, 9)?);
- Ok(())
- }
-
- #[test]
- fn test_color_name() -> Result<()> {
- let server = ServerTester::launch_new_instance()?;
- server.initialize(ClientCapabilities::default(), None)?;
- let uri = server.open(
- "main.tex",
- r#"
- \color{re}
- \definecolor{foo}{
- \definecolorset{R}
- "#,
- "latex",
- false,
- )?;
- assert_json_snapshot!(complete_and_resolve(&server, uri, 0, 9)?);
- Ok(())
- }
-
- #[test]
- fn test_color_model_define_color() -> Result<()> {
- let server = ServerTester::launch_new_instance()?;
- server.initialize(ClientCapabilities::default(), None)?;
- let uri = server.open(
- "main.tex",
- r#"
- \color{re}
- \definecolor{foo}{
- \definecolorset{R}
- "#,
- "latex",
- false,
- )?;
- assert_json_snapshot!(complete_and_resolve(&server, uri, 1, 18)?);
- Ok(())
- }
-
- #[test]
- fn test_color_model_define_color_set() -> Result<()> {
- let server = ServerTester::launch_new_instance()?;
- server.initialize(ClientCapabilities::default(), None)?;
- let uri = server.open(
- "main.tex",
- r#"
- \color{re}
- \definecolor{foo}{
- \definecolorset{R}
- "#,
- "latex",
- false,
- )?;
- assert_json_snapshot!(complete_and_resolve(&server, uri, 2, 17)?);
- Ok(())
- }
-
- #[test]
- fn test_kernel_command() -> Result<()> {
- let server = ServerTester::launch_new_instance()?;
- server.initialize(ClientCapabilities::default(), None)?;
- let uri = server.open(
- "main.tex",
- r#"
- \documentclass{book}
- \usepackage{amsmath}
- \chap
- \varDel
- \begin{theind}
- \end{alig}
- \begin{doc}
- \vareps
- "#,
- "latex",
- false,
- )?;
- assert_json_snapshot!(complete_and_resolve(&server, uri, 0, 2)?);
- Ok(())
- }
-
- #[test]
- fn test_kernel_command_glyph() -> Result<()> {
- let server = ServerTester::launch_new_instance()?;
- server.initialize(ClientCapabilities::default(), None)?;
- let uri = server.open(
- "main.tex",
- r#"
- \documentclass{book}
- \usepackage{amsmath}
- \chap
- \varDel
- \begin{theind}
- \end{alig}
- \begin{doc}
- \vareps
- "#,
- "latex",
- false,
- )?;
- assert_json_snapshot!(complete_and_resolve(&server, uri, 7, 7)?);
- Ok(())
- }
-
- #[test]
- fn test_kernel_command_environment() -> Result<()> {
- let server = ServerTester::launch_new_instance()?;
- server.initialize(ClientCapabilities::default(), None)?;
- let uri = server.open(
- "main.tex",
- r#"
- \documentclass{book}
- \usepackage{amsmath}
- \chap
- \varDel
- \begin{theind}
- \end{alig}
- \begin{doc}
- \vareps
- "#,
- "latex",
- false,
- )?;
- assert_json_snapshot!(complete_and_resolve(&server, uri, 6, 10)?);
- Ok(())
- }
-
- #[test]
- fn test_class_command() -> Result<()> {
- let server = ServerTester::launch_new_instance()?;
- server.initialize(ClientCapabilities::default(), None)?;
- let uri = server.open(
- "main.tex",
- r#"
- \documentclass{book}
- \usepackage{amsmath}
- \chap
- \varDel
- \begin{theind}
- \end{alig}
- \begin{doc}
- \vareps
- "#,
- "latex",
- false,
- )?;
- assert_json_snapshot!(complete_and_resolve(&server, uri, 2, 5)?);
- Ok(())
- }
-
- #[test]
- fn test_class_environment() -> Result<()> {
- let server = ServerTester::launch_new_instance()?;
- server.initialize(ClientCapabilities::default(), None)?;
- let uri = server.open(
- "main.tex",
- r#"
- \documentclass{book}
- \usepackage{amsmath}
- \chap
- \varDel
- \begin{theind}
- \end{alig}
- \begin{doc}
- \vareps
- "#,
- "latex",
- false,
- )?;
- assert_json_snapshot!(complete_and_resolve(&server, uri, 4, 13)?);
- Ok(())
- }
-
- #[test]
- fn test_package_command() -> Result<()> {
- let server = ServerTester::launch_new_instance()?;
- server.initialize(ClientCapabilities::default(), None)?;
- let uri = server.open(
- "main.tex",
- r#"
- \documentclass{book}
- \usepackage{amsmath}
- \chap
- \varDel
- \begin{theind}
- \end{alig}
- \begin{doc}
- \vareps
- "#,
- "latex",
- false,
- )?;
- assert_json_snapshot!(complete_and_resolve(&server, uri, 3, 7)?);
- Ok(())
- }
-
- #[test]
- fn test_package_environment() -> Result<()> {
- let server = ServerTester::launch_new_instance()?;
- server.initialize(ClientCapabilities::default(), None)?;
- let uri = server.open(
- "main.tex",
- r#"
- \documentclass{book}
- \usepackage{amsmath}
- \chap
- \varDel
- \begin{theind}
- \end{alig}
- \begin{doc}
- \vareps
- "#,
- "latex",
- false,
- )?;
- assert_json_snapshot!(complete_and_resolve(&server, uri, 5, 6)?);
- Ok(())
- }
-
- #[test]
- fn test_class_import() -> Result<()> {
- let server = ServerTester::launch_new_instance()?;
- server.initialize(ClientCapabilities::default(), None)?;
- let uri = server.open(
- "main.tex",
- r#"
- \documentclass{book}
- \usepackage{amsmath}
- "#,
- "latex",
- false,
- )?;
- assert_json_snapshot!(complete_and_resolve(&server, uri, 0, 19)?);
- Ok(())
- }
-
- #[test]
- fn test_package_import() -> Result<()> {
- let server = ServerTester::launch_new_instance()?;
- server.initialize(ClientCapabilities::default(), None)?;
- let uri = server.open(
- "main.tex",
- r#"
- \documentclass{book}
- \usepackage{amsmath}
- "#,
- "latex",
- false,
- )?;
- assert_json_snapshot!(complete_and_resolve(&server, uri, 1, 15)?);
- Ok(())
- }
-
- #[test]
- fn test_label() -> Result<()> {
- let server = ServerTester::launch_new_instance()?;
- server.initialize(ClientCapabilities::default(), None)?;
-
- server.open(
- "foo.tex",
- r#"
- \documentclass{article}
-
- \usepackage{amsmath}
- \usepackage{caption}
- \usepackage{amsthm}
- \newtheorem{lemma}{Lemma}
-
- \begin{document}
-
- \section{Foo}%
- \label{sec:foo}
-
- \begin{equation}%
- \label{eq:foo}
- 1 + 1 = 2
- \end{equation}
-
- \begin{equation}%
- \label{eq:bar}
- 1 + 1 = 2
- \end{equation}
-
- \begin{figure}%
- \LaTeX{}
- \caption{Baz}%
- \label{fig:baz}
- \end{figure}
-
- \begin{lemma}%
- \label{thm:foo}
- 1 + 1 = 2
- \end{lemma}
-
- \include{bar}
-
- \end{document}
- "#,
- "latex",
- true,
- )?;
- server.open(
- "foo.aux",
- r#"
- \relax
- \@writefile{lof}{\contentsline {figure}{\numberline {1}{\ignorespaces Baz\relax }}{1}\protected@file@percent }
- \providecommand*\caption@xref[2]{\@setref\relax\@undefined{#1}}
- \newlabel{fig:baz}{{1}{1}}
- \@writefile{toc}{\contentsline {section}{\numberline {1}Foo}{1}\protected@file@percent }
- \newlabel{sec:foo}{{1}{1}}
- \newlabel{eq:foo}{{1}{1}}
- \newlabel{eq:bar}{{2}{1}}
- \newlabel{thm:foo}{{1}{1}}
- \@input{bar.aux}
- "#,
- "latex",
- true,
- )?;
- let uri = server.open(
- "bar.tex",
- r#"
- \section{Bar}%
- \label{sec:bar}
-
- Lorem ipsum dolor sit amet.
- \ref{}
- \eqref{}
- "#,
- "latex",
- true,
- )?;
- server.open(
- "bar.aux",
- r#"
- \relax
- \@writefile{toc}{\contentsline {section}{\numberline {2}Bar}{2}\protected@file@percent }
- \newlabel{sec:bar}{{2}{2}}
- \@setckpt{bar}{
- \setcounter{page}{3}
- \setcounter{equation}{2}
- \setcounter{enumi}{0}
- \setcounter{enumii}{0}
- \setcounter{enumiii}{0}
- \setcounter{enumiv}{0}
- \setcounter{footnote}{0}
- \setcounter{mpfootnote}{0}
- \setcounter{part}{0}
- \setcounter{section}{2}
- \setcounter{subsection}{0}
- \setcounter{subsubsection}{0}
- \setcounter{paragraph}{0}
- \setcounter{subparagraph}{0}
- \setcounter{figure}{1}
- \setcounter{table}{0}
- \setcounter{parentequation}{0}
- \setcounter{caption@flags}{0}
- \setcounter{ContinuedFloat}{0}
- \setcounter{lemma}{1}
- "#,
- "latex",
- true,
- )?;
- assert_json_snapshot!(complete_and_resolve(&server, uri, 4, 5)?);
- Ok(())
- }
-
- #[test]
- fn test_preselect_environment() -> Result<()> {
- let server = ServerTester::launch_new_instance()?;
- server.initialize(ClientCapabilities::default(), None)?;
- let uri = server.open(
- "main.tex",
- r#"
- \begin{document}
- \end{
- "#,
- "latex",
- false,
- )?;
- assert_json_snapshot!(complete_and_resolve(&server, uri, 1, 5)?);
- Ok(())
- }
-
- #[test]
- fn test_theorem_environment() -> Result<()> {
- let server = ServerTester::launch_new_instance()?;
- server.initialize(ClientCapabilities::default(), None)?;
- let uri = server.open(
- "main.tex",
- r#"
- \documentclass{article}
- \usepackage{amsthm}
- \newtheorem{foo}{Foo}
- \begin{f}
- "#,
- "latex",
- false,
- )?;
- assert_json_snapshot!(complete_and_resolve(&server, uri, 3, 8)?);
- Ok(())
- }
-
- #[test]
- fn test_pgf_library() -> Result<()> {
- let server = ServerTester::launch_new_instance()?;
- server.initialize(ClientCapabilities::default(), None)?;
- let uri = server.open(
- "main.tex",
- r#"
- \usepackage{tikz}
- \usepgflibrary{}
- \usetikzlibrary{}
- "#,
- "latex",
- false,
- )?;
- assert_json_snapshot!(complete_and_resolve(&server, uri, 1, 15)?);
- Ok(())
- }
-
- #[test]
- fn test_user_command() -> Result<()> {
- let server = ServerTester::launch_new_instance()?;
- server.initialize(ClientCapabilities::default(), None)?;
- let uri = server.open(
- "main.tex",
- r#"
- \foobar
- \fooba
- \begin{foo}
- \end{foo}
- \begin{fo}
- "#,
- "latex",
- false,
- )?;
- assert_json_snapshot!(complete_and_resolve(&server, uri, 1, 3)?);
- Ok(())
- }
-
- #[test]
- fn test_user_environment() -> Result<()> {
- let server = ServerTester::launch_new_instance()?;
- server.initialize(ClientCapabilities::default(), None)?;
- let uri = server.open(
- "main.tex",
- r#"
- \foobar
- \fooba
- \begin{foo}
- \end{foo}
- \begin{fo}
- "#,
- "latex",
- false,
- )?;
- assert_json_snapshot!(complete_and_resolve(&server, uri, 4, 8)?);
- Ok(())
- }
-
- #[test]
- fn test_multi_line_key() -> Result<()> {
- let server = ServerTester::launch_new_instance()?;
- server.initialize(ClientCapabilities::default(), None)?;
- let uri = server.open(
- "main.tex",
- r#"
- \begin{verb
- Velit tri-tip fig1n shoulder buffalo pariatur porkchop magna chuck sausage,
- sed hamburger fatback ribeye biltong id lorem culpa cow, frankfurter
- deserunt shortloin pancetta dolor et veniam aliqua andouille, pork fugiat eu
- pig landjaeger proident aliquip voluptate.
- "#,
- "latex",
- false,
- )?;
-
- assert_json_snapshot!(complete_and_resolve(&server, uri, 0, 11)?);
- Ok(())
- }
-}
diff --git a/support/texlab/tests/it/document_symbol.rs b/support/texlab/tests/it/document_symbol.rs
deleted file mode 100644
index dbdbe64972..0000000000
--- a/support/texlab/tests/it/document_symbol.rs
+++ /dev/null
@@ -1,438 +0,0 @@
-use anyhow::Result;
-use insta::assert_json_snapshot;
-use lsp_types::{
- ClientCapabilities, DocumentSymbolClientCapabilities, TextDocumentClientCapabilities, Url,
-};
-
-use crate::common::ServerTester;
-
-fn nested_symbol_capabilities() -> ClientCapabilities {
- ClientCapabilities {
- text_document: Some(TextDocumentClientCapabilities {
- document_symbol: Some(DocumentSymbolClientCapabilities {
- hierarchical_document_symbol_support: Some(true),
- ..DocumentSymbolClientCapabilities::default()
- }),
- ..TextDocumentClientCapabilities::default()
- }),
- ..ClientCapabilities::default()
- }
-}
-
-#[test]
-fn test_enumerate_nested() -> Result<()> {
- let server = ServerTester::launch_new_instance()?;
- server.initialize(nested_symbol_capabilities(), None)?;
- let uri = Url::parse("http://www.example.com/main.tex")?;
- server.open_memory(
- uri.clone(),
- r#"
- \documentclass{article}
-
- \begin{document}
-
- \begin{enumerate}
- \item\label{it:foo} Foo
- \item\label{it:bar} Bar
- \item[Baz] Baz
- \item[Qux]\label{it:qux} Qux
- \end{enumerate}
-
- \end{document}
- "#,
- "latex",
- )?;
- server.open_memory(
- Url::parse("http://www.example.com/main.aux")?,
- r#"
- \relax
- \newlabel{it:foo}{{1}{1}}
- \newlabel{it:qux}{{2}{1}}
- "#,
- "latex",
- )?;
- assert_json_snapshot!(server.find_document_symbols(uri)?);
- Ok(())
-}
-
-#[test]
-fn test_enumerate_flat() -> Result<()> {
- let server = ServerTester::launch_new_instance()?;
- server.initialize(ClientCapabilities::default(), None)?;
- let uri = Url::parse("http://www.example.com/main.tex")?;
- server.open_memory(
- uri.clone(),
- r#"
- \documentclass{article}
-
- \begin{document}
-
- \begin{enumerate}
- \item\label{it:foo} Foo
- \item\label{it:bar} Bar
- \item[Baz] Baz
- \item[Qux]\label{it:qux} Qux
- \end{enumerate}
-
- \end{document}
- "#,
- "latex",
- )?;
- server.open_memory(
- Url::parse("http://www.example.com/main.aux")?,
- r#"
- \relax
- \newlabel{it:foo}{{1}{1}}
- \newlabel{it:qux}{{2}{1}}
- "#,
- "latex",
- )?;
- assert_json_snapshot!(server.find_document_symbols(uri)?);
- Ok(())
-}
-
-#[test]
-fn test_equation_nested() -> Result<()> {
- let server = ServerTester::launch_new_instance()?;
- server.initialize(nested_symbol_capabilities(), None)?;
- let uri = Url::parse("http://www.example.com/main.tex")?;
- server.open_memory(
- uri.clone(),
- r#"
- \documentclass{article}
-
- \begin{document}
-
- \begin{equation}\label{eq:foo}
- Foo
- \end{equation}
-
- \begin{equation}\label{eq:bar}
- Bar
- \end{equation}
-
- \begin{equation}
- Baz
- \end{equation}
-
- \end{document}
- "#,
- "latex",
- )?;
- server.open_memory(
- Url::parse("http://www.example.com/main.aux")?,
- r#"
- \relax
- \newlabel{eq:foo}{{1}{1}}
- "#,
- "latex",
- )?;
- assert_json_snapshot!(server.find_document_symbols(uri)?);
- Ok(())
-}
-
-#[test]
-fn test_equation_flat() -> Result<()> {
- let server = ServerTester::launch_new_instance()?;
- server.initialize(ClientCapabilities::default(), None)?;
- let uri = Url::parse("http://www.example.com/main.tex")?;
- server.open_memory(
- uri.clone(),
- r#"
- \documentclass{article}
-
- \begin{document}
-
- \begin{equation}\label{eq:foo}
- Foo
- \end{equation}
-
- \begin{equation}\label{eq:bar}
- Bar
- \end{equation}
-
- \begin{equation}
- Baz
- \end{equation}
-
- \end{document}
- "#,
- "latex",
- )?;
- server.open_memory(
- Url::parse("http://www.example.com/main.aux")?,
- r#"
- \relax
- \newlabel{eq:foo}{{1}{1}}
- "#,
- "latex",
- )?;
- assert_json_snapshot!(server.find_document_symbols(uri)?);
- Ok(())
-}
-
-#[test]
-fn test_float_nested() -> Result<()> {
- let server = ServerTester::launch_new_instance()?;
- server.initialize(nested_symbol_capabilities(), None)?;
- let uri = Url::parse("http://www.example.com/main.tex")?;
- server.open_memory(
- uri.clone(),
- r#"
- \documentclass{article}
-
- \begin{document}
-
- \begin{figure}
- Foo
- \caption{Foo}\label{fig:foo}
- \end{figure}
-
- \begin{figure}
- Bar
- \caption{Bar}\label{fig:bar}
- \end{figure}
-
- \begin{figure}
- Baz
- \caption{Baz}
- \end{figure}
-
- \begin{figure}
- Qux
- \end{figure}
-
- \end{document}
- "#,
- "latex",
- )?;
- server.open_memory(
- Url::parse("http://www.example.com/main.aux")?,
- r#"
- \relax
- \@writefile{lof}{\contentsline {figure}{\numberline {1}{\ignorespaces Foo}}{1}\protected@file@percent }
- \newlabel{fig:foo}{{1}{1}}
- \@writefile{lof}{\contentsline {figure}{\numberline {2}{\ignorespaces Bar}}{1}\protected@file@percent }
- \@writefile{lof}{\contentsline {figure}{\numberline {3}{\ignorespaces Baz}}{1}\protected@file@percent }
- "#,
- "latex",
- )?;
- assert_json_snapshot!(server.find_document_symbols(uri)?);
- Ok(())
-}
-
-#[test]
-fn test_float_flat() -> Result<()> {
- let server = ServerTester::launch_new_instance()?;
- server.initialize(ClientCapabilities::default(), None)?;
- let uri = Url::parse("http://www.example.com/main.tex")?;
- server.open_memory(
- uri.clone(),
- r#"
- \documentclass{article}
-
- \begin{document}
-
- \begin{figure}
- Foo
- \caption{Foo}\label{fig:foo}
- \end{figure}
-
- \begin{figure}
- Bar
- \caption{Bar}\label{fig:bar}
- \end{figure}
-
- \begin{figure}
- Baz
- \caption{Baz}
- \end{figure}
-
- \begin{figure}
- Qux
- \end{figure}
-
- \end{document}
- "#,
- "latex",
- )?;
- server.open_memory(
- Url::parse("http://www.example.com/main.aux")?,
- r#"
- \relax
- \@writefile{lof}{\contentsline {figure}{\numberline {1}{\ignorespaces Foo}}{1}\protected@file@percent }
- \newlabel{fig:foo}{{1}{1}}
- \@writefile{lof}{\contentsline {figure}{\numberline {2}{\ignorespaces Bar}}{1}\protected@file@percent }
- \@writefile{lof}{\contentsline {figure}{\numberline {3}{\ignorespaces Baz}}{1}\protected@file@percent }
- "#,
- "latex",
- )?;
- assert_json_snapshot!(server.find_document_symbols(uri)?);
- Ok(())
-}
-
-#[test]
-fn test_section_nested() -> Result<()> {
- let server = ServerTester::launch_new_instance()?;
- server.initialize(nested_symbol_capabilities(), None)?;
- let uri = Url::parse("http://www.example.com/main.tex")?;
- server.open_memory(
- uri.clone(),
- r#"
- \documentclass{article}
-
- \begin{document}
-
- \section{Foo}
-
- \section{Bar}\label{sec:bar}
-
- \subsection{Baz}\label{sec:baz}
-
- \end{document}
- "#,
- "latex",
- )?;
- server.open_memory(
- Url::parse("http://www.example.com/main.aux")?,
- r#"
- \relax
- \@writefile{toc}{\contentsline {section}{\numberline {1}Foo}{1}\protected@file@percent }
- \@writefile{toc}{\contentsline {section}{\numberline {2}Bar}{1}\protected@file@percent }
- \newlabel{sec:bar}{{2}{1}}
- "#,
- "latex",
- )?;
- assert_json_snapshot!(server.find_document_symbols(uri)?);
- Ok(())
-}
-
-#[test]
-fn test_section_flat() -> Result<()> {
- let server = ServerTester::launch_new_instance()?;
- server.initialize(ClientCapabilities::default(), None)?;
- let uri = Url::parse("http://www.example.com/main.tex")?;
- server.open_memory(
- uri.clone(),
- r#"
- \documentclass{article}
-
- \begin{document}
-
- \section{Foo}
-
- \section{Bar}\label{sec:bar}
-
- \subsection{Baz}\label{sec:baz}
-
- \end{document}
- "#,
- "latex",
- )?;
- server.open_memory(
- Url::parse("http://www.example.com/main.aux")?,
- r#"
- \relax
- \@writefile{toc}{\contentsline {section}{\numberline {1}Foo}{1}\protected@file@percent }
- \@writefile{toc}{\contentsline {section}{\numberline {2}Bar}{1}\protected@file@percent }
- \newlabel{sec:bar}{{2}{1}}
- "#,
- "latex",
- )?;
- assert_json_snapshot!(server.find_document_symbols(uri)?);
- Ok(())
-}
-
-#[test]
-fn test_theorem_nested() -> Result<()> {
- let server = ServerTester::launch_new_instance()?;
- server.initialize(nested_symbol_capabilities(), None)?;
- let uri = Url::parse("http://www.example.com/main.tex")?;
- server.open_memory(
- uri.clone(),
- r#"
- \documentclass{article}
- \usepackage{amsthm}
- \newtheorem{lemma}{Lemma}
-
- \begin{document}
-
- \begin{lemma}[Foo]\label{thm:foo}
- Foo
- \end{lemma}
-
- \begin{lemma}\label{thm:bar}
- Bar
- \end{lemma}
-
- \begin{lemma}\label{thm:baz}
- Baz
- \end{lemma}
-
- \begin{lemma}[Qux]
- Qux
- \end{lemma}
-
- \end{document}
- "#,
- "latex",
- )?;
- server.open_memory(
- Url::parse("http://www.example.com/main.aux")?,
- r#"
- \relax
- \newlabel{thm:foo}{{1}{1}}
- \newlabel{thm:bar}{{2}{1}}
- "#,
- "latex",
- )?;
- assert_json_snapshot!(server.find_document_symbols(uri)?);
- Ok(())
-}
-
-#[test]
-fn test_theorem_flat() -> Result<()> {
- let server = ServerTester::launch_new_instance()?;
- server.initialize(ClientCapabilities::default(), None)?;
- let uri = Url::parse("http://www.example.com/main.tex")?;
- server.open_memory(
- uri.clone(),
- r#"
- \documentclass{article}
- \usepackage{amsthm}
- \newtheorem{lemma}{Lemma}
-
- \begin{document}
-
- \begin{lemma}[Foo]\label{thm:foo}
- Foo
- \end{lemma}
-
- \begin{lemma}\label{thm:bar}
- Bar
- \end{lemma}
-
- \begin{lemma}\label{thm:baz}
- Baz
- \end{lemma}
-
- \begin{lemma}[Qux]
- Qux
- \end{lemma}
-
- \end{document}
- "#,
- "latex",
- )?;
- server.open_memory(
- Url::parse("http://www.example.com/main.aux")?,
- r#"
- \relax
- \newlabel{thm:foo}{{1}{1}}
- \newlabel{thm:bar}{{2}{1}}
- "#,
- "latex",
- )?;
- assert_json_snapshot!(server.find_document_symbols(uri)?);
- Ok(())
-}
diff --git a/support/texlab/tests/it/hover.rs b/support/texlab/tests/it/hover.rs
deleted file mode 100644
index 70b14cccd0..0000000000
--- a/support/texlab/tests/it/hover.rs
+++ /dev/null
@@ -1,89 +0,0 @@
-use anyhow::Result;
-use insta::assert_json_snapshot;
-use lsp_types::ClientCapabilities;
-
-use crate::common::ServerTester;
-
-#[test]
-fn test_empty_bibtex_document() -> Result<()> {
- let server = ServerTester::launch_new_instance()?;
- server.initialize(ClientCapabilities::default(), None)?;
- let uri = server.open("main.bib", "", "bibtex", false)?;
- assert_json_snapshot!(server.hover(uri, 0, 0)?);
- Ok(())
-}
-
-#[test]
-fn test_empty_labtex_document() -> Result<()> {
- let server = ServerTester::launch_new_instance()?;
- server.initialize(ClientCapabilities::default(), None)?;
- let uri = server.open("main.tex", "", "latex", false)?;
- assert_json_snapshot!(server.hover(uri, 0, 0)?);
- Ok(())
-}
-
-#[test]
-fn test_label_theorem_child_file() -> Result<()> {
- let server = ServerTester::launch_new_instance()?;
- server.initialize(ClientCapabilities::default(), None)?;
- let uri = server.open(
- "main.tex",
- r#"
- \documentclass{article}
- \newtheorem{lemma}{Lemma}
- \include{child}
- \ref{thm:foo}
- "#,
- "latex",
- false,
- )?;
- server.open(
- "child.tex",
- r#"
- \begin{lemma}\label{thm:foo}
- 1 + 1 = 2
- \end{lemma}
- "#,
- "latex",
- false,
- )?;
-
- assert_json_snapshot!(server.hover(uri, 3, 8)?);
- Ok(())
-}
-
-#[test]
-fn test_label_theorem_child_file_mumber() -> Result<()> {
- let server = ServerTester::launch_new_instance()?;
- server.initialize(ClientCapabilities::default(), None)?;
- let uri = server.open(
- "main.tex",
- r#"
- \documentclass{article}
- \newtheorem{lemma}{Lemma}
- \include{child}
- \ref{thm:foo}
- "#,
- "latex",
- false,
- )?;
- server.open(
- "child.tex",
- r#"
- \begin{lemma}[Foo]\label{thm:foo}
- 1 + 1 = 2
- \end{lemma}
- "#,
- "latex",
- false,
- )?;
- server.open(
- "child.aux",
- r#"\newlabel{thm:foo}{{1}{1}{Foo}{lemma.1}{}}"#,
- "latex",
- false,
- )?;
-
- assert_json_snapshot!(server.hover(uri, 3, 8)?);
- Ok(())
-}
diff --git a/support/texlab/tests/it/issues.rs b/support/texlab/tests/it/issues.rs
deleted file mode 100644
index 1fb66dc4a9..0000000000
--- a/support/texlab/tests/it/issues.rs
+++ /dev/null
@@ -1,81 +0,0 @@
-use std::{fs, thread, time::Duration};
-
-use anyhow::Result;
-use lsp_types::ClientCapabilities;
-
-use crate::common::ServerTester;
-
-#[test]
-#[cfg(feature = "completion")]
-fn test_408_parent_expansion() -> Result<()> {
- let server = ServerTester::launch_new_instance()?;
- server.initialize(ClientCapabilities::default(), None)?;
- let root = server.directory.path();
-
- let level1 = root.join("level1");
- let level2 = level1.join("level2");
- let level3 = level2.join("level3");
- fs::create_dir_all(&level3)?;
- fs::write(level3.join("d.tex"), "d")?;
- fs::write(
- level2.join("c.tex"),
- r#"\documentclass{subfiles}\begin{document}\include{level3/d}\end{document}"#,
- )?;
- fs::write(
- level1.join("b.tex"),
- r#"\documentclass{article}\begin{document}\include{level2/c}\end{document}"#,
- )?;
- fs::write(root.join("a.tex"), "}")?;
-
- thread::sleep(Duration::from_millis(300));
-
- let uri = server.open("level1/level2/level3/d.tex", "d", "latex", false)?;
- server.complete(uri, 0, 0)?;
-
- let diagnostics_by_uri = server.diagnostics_by_uri.lock().unwrap();
- assert!(diagnostics_by_uri
- .iter()
- .all(|(uri, _)| !uri.as_str().ends_with("a.tex")));
-
- Ok(())
-}
-
-#[test]
-#[cfg(feature = "completion")]
-fn test_510_completion_with_unmatched_braces() -> Result<()> {
- use insta::assert_debug_snapshot;
-
- let server = ServerTester::launch_new_instance()?;
- server.initialize(ClientCapabilities::default(), None)?;
-
- let uri = server.open(
- "main.tex",
- "\\label{eq:foo}\n\\ref{eq is a \\emph{useful} identity.",
- "latex",
- false,
- )?;
-
- assert_debug_snapshot!(server.complete(uri, 1, 7)?);
-
- Ok(())
-}
-
-#[test]
-#[cfg(feature = "completion")]
-fn test_540_subimport_link() -> Result<()> {
- let server = ServerTester::launch_new_instance()?;
- server.initialize(ClientCapabilities::default(), None)?;
-
- server.open("stuff.tex", "\\usepackage{lipsum}", "latex", false)?;
- let uri = server.open("main.tex", "\\subimport{}{stuff}\n\\lipsu", "latex", false)?;
-
- let success = server
- .complete(uri, 1, 4)?
- .items
- .into_iter()
- .any(|item| item.label == "lipsum");
-
- assert!(success);
-
- Ok(())
-}
diff --git a/support/texlab/tests/it/main.rs b/support/texlab/tests/it/main.rs
deleted file mode 100644
index ebccca7396..0000000000
--- a/support/texlab/tests/it/main.rs
+++ /dev/null
@@ -1,7 +0,0 @@
-mod common;
-#[cfg(feature = "completion")]
-mod completion;
-mod document_symbol;
-mod hover;
-mod issues;
-mod workspace_symbol;
diff --git a/support/texlab/tests/it/snapshots/it__completion__bibtex__command_complete_entry.snap b/support/texlab/tests/it/snapshots/it__completion__bibtex__command_complete_entry.snap
deleted file mode 100644
index 8f3aa3a4b2..0000000000
--- a/support/texlab/tests/it/snapshots/it__completion__bibtex__command_complete_entry.snap
+++ /dev/null
@@ -1,150 +0,0 @@
----
-source: tests/it/completion.rs
-assertion_line: 79
-expression: "complete_and_resolve(&server, uri, 1, 18)?"
----
-{
- "isIncomplete": true,
- "items": [
- {
- "label": "LaTeX",
- "kind": 1,
- "detail": "built-in",
- "preselect": false,
- "sortText": "00",
- "textEdit": {
- "range": {
- "start": {
- "line": 1,
- "character": 15
- },
- "end": {
- "line": 1,
- "character": 18
- }
- },
- "newText": "LaTeX"
- }
- },
- {
- "label": "LaTeXe",
- "kind": 1,
- "detail": "built-in",
- "preselect": false,
- "sortText": "01",
- "textEdit": {
- "range": {
- "start": {
- "line": 1,
- "character": 15
- },
- "end": {
- "line": 1,
- "character": 18
- }
- },
- "newText": "LaTeXe"
- }
- },
- {
- "label": "latexreleaseversion",
- "kind": 1,
- "detail": "built-in",
- "preselect": false,
- "sortText": "02",
- "textEdit": {
- "range": {
- "start": {
- "line": 1,
- "character": 15
- },
- "end": {
- "line": 1,
- "character": 18
- }
- },
- "newText": "latexreleaseversion"
- }
- },
- {
- "label": "LastDeclaredEncoding",
- "kind": 1,
- "detail": "built-in",
- "preselect": false,
- "sortText": "03",
- "textEdit": {
- "range": {
- "start": {
- "line": 1,
- "character": 15
- },
- "end": {
- "line": 1,
- "character": 18
- }
- },
- "newText": "LastDeclaredEncoding"
- }
- },
- {
- "label": "last",
- "kind": 1,
- "detail": "built-in",
- "preselect": false,
- "sortText": "04",
- "textEdit": {
- "range": {
- "start": {
- "line": 1,
- "character": 15
- },
- "end": {
- "line": 1,
- "character": 18
- }
- },
- "newText": "last"
- }
- },
- {
- "label": "lastbox",
- "kind": 1,
- "detail": "built-in",
- "preselect": false,
- "sortText": "05",
- "textEdit": {
- "range": {
- "start": {
- "line": 1,
- "character": 15
- },
- "end": {
- "line": 1,
- "character": 18
- }
- },
- "newText": "lastbox"
- }
- },
- {
- "label": "lastkern",
- "kind": 1,
- "detail": "built-in",
- "preselect": false,
- "sortText": "06",
- "textEdit": {
- "range": {
- "start": {
- "line": 1,
- "character": 15
- },
- "end": {
- "line": 1,
- "character": 18
- }
- },
- "newText": "lastkern"
- }
- }
- ]
-}
diff --git a/support/texlab/tests/it/snapshots/it__completion__bibtex__command_incomplete_entry.snap b/support/texlab/tests/it/snapshots/it__completion__bibtex__command_incomplete_entry.snap
deleted file mode 100644
index 272e527920..0000000000
--- a/support/texlab/tests/it/snapshots/it__completion__bibtex__command_incomplete_entry.snap
+++ /dev/null
@@ -1,150 +0,0 @@
----
-source: tests/it/completion.rs
-assertion_line: 61
-expression: "complete_and_resolve(&server, uri, 1, 18)?"
----
-{
- "isIncomplete": true,
- "items": [
- {
- "label": "LaTeX",
- "kind": 1,
- "detail": "built-in",
- "preselect": false,
- "sortText": "00",
- "textEdit": {
- "range": {
- "start": {
- "line": 1,
- "character": 15
- },
- "end": {
- "line": 1,
- "character": 18
- }
- },
- "newText": "LaTeX"
- }
- },
- {
- "label": "LaTeXe",
- "kind": 1,
- "detail": "built-in",
- "preselect": false,
- "sortText": "01",
- "textEdit": {
- "range": {
- "start": {
- "line": 1,
- "character": 15
- },
- "end": {
- "line": 1,
- "character": 18
- }
- },
- "newText": "LaTeXe"
- }
- },
- {
- "label": "latexreleaseversion",
- "kind": 1,
- "detail": "built-in",
- "preselect": false,
- "sortText": "02",
- "textEdit": {
- "range": {
- "start": {
- "line": 1,
- "character": 15
- },
- "end": {
- "line": 1,
- "character": 18
- }
- },
- "newText": "latexreleaseversion"
- }
- },
- {
- "label": "LastDeclaredEncoding",
- "kind": 1,
- "detail": "built-in",
- "preselect": false,
- "sortText": "03",
- "textEdit": {
- "range": {
- "start": {
- "line": 1,
- "character": 15
- },
- "end": {
- "line": 1,
- "character": 18
- }
- },
- "newText": "LastDeclaredEncoding"
- }
- },
- {
- "label": "last",
- "kind": 1,
- "detail": "built-in",
- "preselect": false,
- "sortText": "04",
- "textEdit": {
- "range": {
- "start": {
- "line": 1,
- "character": 15
- },
- "end": {
- "line": 1,
- "character": 18
- }
- },
- "newText": "last"
- }
- },
- {
- "label": "lastbox",
- "kind": 1,
- "detail": "built-in",
- "preselect": false,
- "sortText": "05",
- "textEdit": {
- "range": {
- "start": {
- "line": 1,
- "character": 15
- },
- "end": {
- "line": 1,
- "character": 18
- }
- },
- "newText": "lastbox"
- }
- },
- {
- "label": "lastkern",
- "kind": 1,
- "detail": "built-in",
- "preselect": false,
- "sortText": "06",
- "textEdit": {
- "range": {
- "start": {
- "line": 1,
- "character": 15
- },
- "end": {
- "line": 1,
- "character": 18
- }
- },
- "newText": "lastkern"
- }
- }
- ]
-}
diff --git a/support/texlab/tests/it/snapshots/it__completion__bibtex__empty_document.snap b/support/texlab/tests/it/snapshots/it__completion__bibtex__empty_document.snap
deleted file mode 100644
index 339ed48749..0000000000
--- a/support/texlab/tests/it/snapshots/it__completion__bibtex__empty_document.snap
+++ /dev/null
@@ -1,9 +0,0 @@
----
-source: tests/it/completion.rs
-assertion_line: 34
-expression: "complete_and_resolve(&server, uri, 0, 0)?"
----
-{
- "isIncomplete": false,
- "items": []
-}
diff --git a/support/texlab/tests/it/snapshots/it__completion__bibtex__entry_type_complete.snap b/support/texlab/tests/it/snapshots/it__completion__bibtex__entry_type_complete.snap
deleted file mode 100644
index 2bc50f8505..0000000000
--- a/support/texlab/tests/it/snapshots/it__completion__bibtex__entry_type_complete.snap
+++ /dev/null
@@ -1,33 +0,0 @@
----
-source: tests/it/completion.rs
-assertion_line: 143
-expression: "complete_and_resolve(&server, uri, 0, 1)?"
----
-{
- "isIncomplete": false,
- "items": [
- {
- "label": "article",
- "kind": 1,
- "documentation": {
- "kind": "markdown",
- "value": "An article in a journal, magazine, newspaper, or other periodical which forms a \n self-contained unit with its own title. The title of the periodical is given in the \n journaltitle field. If the issue has its own title in addition to the main title of \n the periodical, it goes in the issuetitle field. Note that editor and related \n fields refer to the journal while translator and related fields refer to the article.\n\nRequired fields: `author`, `title`, `journaltitle`, `year/date`"
- },
- "preselect": false,
- "sortText": "00",
- "textEdit": {
- "range": {
- "start": {
- "line": 0,
- "character": 1
- },
- "end": {
- "line": 0,
- "character": 8
- }
- },
- "newText": "article"
- }
- }
- ]
-}
diff --git a/support/texlab/tests/it/snapshots/it__completion__bibtex__entry_type_empty_name.snap b/support/texlab/tests/it/snapshots/it__completion__bibtex__entry_type_empty_name.snap
deleted file mode 100644
index ddc3f29f5f..0000000000
--- a/support/texlab/tests/it/snapshots/it__completion__bibtex__entry_type_empty_name.snap
+++ /dev/null
@@ -1,171 +0,0 @@
----
-source: tests/it/completion.rs
-assertion_line: 95
-expression: "complete_and_resolve(&server, uri, 0, 1)?"
----
-{
- "isIncomplete": true,
- "items": [
- {
- "label": "article",
- "kind": 1,
- "documentation": {
- "kind": "markdown",
- "value": "An article in a journal, magazine, newspaper, or other periodical which forms a \n self-contained unit with its own title. The title of the periodical is given in the \n journaltitle field. If the issue has its own title in addition to the main title of \n the periodical, it goes in the issuetitle field. Note that editor and related \n fields refer to the journal while translator and related fields refer to the article.\n\nRequired fields: `author`, `title`, `journaltitle`, `year/date`"
- },
- "preselect": false,
- "sortText": "00",
- "textEdit": {
- "range": {
- "start": {
- "line": 0,
- "character": 1
- },
- "end": {
- "line": 0,
- "character": 1
- }
- },
- "newText": "article"
- }
- },
- {
- "label": "artwork",
- "kind": 1,
- "documentation": {
- "kind": "markdown",
- "value": "Works of the visual arts such as paintings, sculpture, and installations."
- },
- "preselect": false,
- "sortText": "01",
- "textEdit": {
- "range": {
- "start": {
- "line": 0,
- "character": 1
- },
- "end": {
- "line": 0,
- "character": 1
- }
- },
- "newText": "artwork"
- }
- },
- {
- "label": "audio",
- "kind": 1,
- "documentation": {
- "kind": "markdown",
- "value": "Audio recordings, typically on audio cd, dvd, audio cassette, or similar media. See\n also `@music`."
- },
- "preselect": false,
- "sortText": "02",
- "textEdit": {
- "range": {
- "start": {
- "line": 0,
- "character": 1
- },
- "end": {
- "line": 0,
- "character": 1
- }
- },
- "newText": "audio"
- }
- },
- {
- "label": "bibnote",
- "kind": 1,
- "documentation": {
- "kind": "markdown",
- "value": "This special entry type is not meant to be used in the `bib` file like other types. It is\n provided for third-party packages like `notes2bib` which merge notes into the bibliography.\n The notes should go into the `note` field. Be advised that the `@bibnote`\n type is not related to the `defbibnote` command in any way. `defbibnote`\n is for adding comments at the beginning or the end of the bibliography, whereas\n the `@bibnote` type is meant for packages which render endnotes as bibliography\n entries."
- },
- "preselect": false,
- "sortText": "03",
- "textEdit": {
- "range": {
- "start": {
- "line": 0,
- "character": 1
- },
- "end": {
- "line": 0,
- "character": 1
- }
- },
- "newText": "bibnote"
- }
- },
- {
- "label": "book",
- "kind": 1,
- "documentation": {
- "kind": "markdown",
- "value": "A single-volume book with one or more authors where the authors share credit for\n the work as a whole. This entry type also covers the function of the `@inbook` type\n of traditional BibTeX.\n\nRequired fields: `author`, `title`, `year/date`"
- },
- "preselect": false,
- "sortText": "04",
- "textEdit": {
- "range": {
- "start": {
- "line": 0,
- "character": 1
- },
- "end": {
- "line": 0,
- "character": 1
- }
- },
- "newText": "book"
- }
- },
- {
- "label": "bookinbook",
- "kind": 1,
- "documentation": {
- "kind": "markdown",
- "value": "This type is similar to `@inbook` but intended for works originally published as a\n stand-alone book. A typical example are books reprinted in the collected works of\n an author."
- },
- "preselect": false,
- "sortText": "05",
- "textEdit": {
- "range": {
- "start": {
- "line": 0,
- "character": 1
- },
- "end": {
- "line": 0,
- "character": 1
- }
- },
- "newText": "bookinbook"
- }
- },
- {
- "label": "booklet",
- "kind": 1,
- "documentation": {
- "kind": "markdown",
- "value": "A book-like work without a formal publisher or sponsoring institution. Use the field\n howpublished to supply publishing information in free format, if applicable. The\n field type may be useful as well.\n\nRequired fields: `author/editor`, `title`, `year/date`"
- },
- "preselect": false,
- "sortText": "06",
- "textEdit": {
- "range": {
- "start": {
- "line": 0,
- "character": 1
- },
- "end": {
- "line": 0,
- "character": 1
- }
- },
- "newText": "booklet"
- }
- }
- ]
-}
diff --git a/support/texlab/tests/it/snapshots/it__completion__bibtex__entry_type_empty_name_before.snap b/support/texlab/tests/it/snapshots/it__completion__bibtex__entry_type_empty_name_before.snap
deleted file mode 100644
index b6cf4a29dd..0000000000
--- a/support/texlab/tests/it/snapshots/it__completion__bibtex__entry_type_empty_name_before.snap
+++ /dev/null
@@ -1,9 +0,0 @@
----
-source: tests/it/completion.rs
-assertion_line: 111
-expression: "complete_and_resolve(&server, uri, 0, 0)?"
----
-{
- "isIncomplete": false,
- "items": []
-}
diff --git a/support/texlab/tests/it/snapshots/it__completion__bibtex__entry_type_incomplete.snap b/support/texlab/tests/it/snapshots/it__completion__bibtex__entry_type_incomplete.snap
deleted file mode 100644
index 2e7226985d..0000000000
--- a/support/texlab/tests/it/snapshots/it__completion__bibtex__entry_type_incomplete.snap
+++ /dev/null
@@ -1,79 +0,0 @@
----
-source: tests/it/completion.rs
-assertion_line: 127
-expression: "complete_and_resolve(&server, uri, 0, 1)?"
----
-{
- "isIncomplete": false,
- "items": [
- {
- "label": "article",
- "kind": 1,
- "documentation": {
- "kind": "markdown",
- "value": "An article in a journal, magazine, newspaper, or other periodical which forms a \n self-contained unit with its own title. The title of the periodical is given in the \n journaltitle field. If the issue has its own title in addition to the main title of \n the periodical, it goes in the issuetitle field. Note that editor and related \n fields refer to the journal while translator and related fields refer to the article.\n\nRequired fields: `author`, `title`, `journaltitle`, `year/date`"
- },
- "preselect": false,
- "sortText": "00",
- "textEdit": {
- "range": {
- "start": {
- "line": 0,
- "character": 1
- },
- "end": {
- "line": 0,
- "character": 4
- }
- },
- "newText": "article"
- }
- },
- {
- "label": "artwork",
- "kind": 1,
- "documentation": {
- "kind": "markdown",
- "value": "Works of the visual arts such as paintings, sculpture, and installations."
- },
- "preselect": false,
- "sortText": "01",
- "textEdit": {
- "range": {
- "start": {
- "line": 0,
- "character": 1
- },
- "end": {
- "line": 0,
- "character": 4
- }
- },
- "newText": "artwork"
- }
- },
- {
- "label": "mastersthesis",
- "kind": 1,
- "documentation": {
- "kind": "markdown",
- "value": "Similar to `@thesis` except that the `type` field is optional and defaults to the\n localised term ‘Master’s thesis’. You may still use the `type` field to override that."
- },
- "preselect": false,
- "sortText": "02",
- "textEdit": {
- "range": {
- "start": {
- "line": 0,
- "character": 1
- },
- "end": {
- "line": 0,
- "character": 4
- }
- },
- "newText": "mastersthesis"
- }
- }
- ]
-}
diff --git a/support/texlab/tests/it/snapshots/it__completion__bibtex__field_complete_entry.snap b/support/texlab/tests/it/snapshots/it__completion__bibtex__field_complete_entry.snap
deleted file mode 100644
index 9340866462..0000000000
--- a/support/texlab/tests/it/snapshots/it__completion__bibtex__field_complete_entry.snap
+++ /dev/null
@@ -1,171 +0,0 @@
----
-source: tests/it/completion.rs
-assertion_line: 178
-expression: "complete_and_resolve(&server, uri, 1, 6)?"
----
-{
- "isIncomplete": false,
- "items": [
- {
- "label": "title",
- "kind": 1,
- "documentation": {
- "kind": "markdown",
- "value": "The title of the work."
- },
- "preselect": false,
- "sortText": "00",
- "textEdit": {
- "range": {
- "start": {
- "line": 1,
- "character": 4
- },
- "end": {
- "line": 1,
- "character": 9
- }
- },
- "newText": "title"
- }
- },
- {
- "label": "titleaddon",
- "kind": 1,
- "documentation": {
- "kind": "markdown",
- "value": "An annex to the `title`, to be printed in a different font."
- },
- "preselect": false,
- "sortText": "01",
- "textEdit": {
- "range": {
- "start": {
- "line": 1,
- "character": 4
- },
- "end": {
- "line": 1,
- "character": 9
- }
- },
- "newText": "titleaddon"
- }
- },
- {
- "label": "booksubtitle",
- "kind": 1,
- "documentation": {
- "kind": "markdown",
- "value": "The subtitle related to the `booktitle`. If the subtitle field refers to a work which is part of a larger publication, a possible subtitle of the main work is given in this field. See also `subtitle`."
- },
- "preselect": false,
- "sortText": "02",
- "textEdit": {
- "range": {
- "start": {
- "line": 1,
- "character": 4
- },
- "end": {
- "line": 1,
- "character": 9
- }
- },
- "newText": "booksubtitle"
- }
- },
- {
- "label": "booktitle",
- "kind": 1,
- "documentation": {
- "kind": "markdown",
- "value": "If the `title` field indicates the title of a work which is part of a larger publication, the title of the main work is given in this field. See also `title`."
- },
- "preselect": false,
- "sortText": "03",
- "textEdit": {
- "range": {
- "start": {
- "line": 1,
- "character": 4
- },
- "end": {
- "line": 1,
- "character": 9
- }
- },
- "newText": "booktitle"
- }
- },
- {
- "label": "booktitleaddon",
- "kind": 1,
- "documentation": {
- "kind": "markdown",
- "value": "An annex to the `booktitle`, to be printed in a different font."
- },
- "preselect": false,
- "sortText": "04",
- "textEdit": {
- "range": {
- "start": {
- "line": 1,
- "character": 4
- },
- "end": {
- "line": 1,
- "character": 9
- }
- },
- "newText": "booktitleaddon"
- }
- },
- {
- "label": "eventtitle",
- "kind": 1,
- "documentation": {
- "kind": "markdown",
- "value": "The title of a conference, a symposium, or some other event in `@proceedings` and `@inproceedings` entries. Note that this field holds the plain title of the event. Things like \"Proceedings of the Fifth XYZ Conference\" go into the `titleaddon` or `booktitleaddon` field, respectively. See also `eventdate` and `venue`."
- },
- "preselect": false,
- "sortText": "05",
- "textEdit": {
- "range": {
- "start": {
- "line": 1,
- "character": 4
- },
- "end": {
- "line": 1,
- "character": 9
- }
- },
- "newText": "eventtitle"
- }
- },
- {
- "label": "eventtitleaddon",
- "kind": 1,
- "documentation": {
- "kind": "markdown",
- "value": "An annex to the `eventtitle` field. Can be used for known event acronyms, for example."
- },
- "preselect": false,
- "sortText": "06",
- "textEdit": {
- "range": {
- "start": {
- "line": 1,
- "character": 4
- },
- "end": {
- "line": 1,
- "character": 9
- }
- },
- "newText": "eventtitleaddon"
- }
- }
- ]
-}
diff --git a/support/texlab/tests/it/snapshots/it__completion__bibtex__field_incomplete_entry.snap b/support/texlab/tests/it/snapshots/it__completion__bibtex__field_incomplete_entry.snap
deleted file mode 100644
index 398ed710ce..0000000000
--- a/support/texlab/tests/it/snapshots/it__completion__bibtex__field_incomplete_entry.snap
+++ /dev/null
@@ -1,171 +0,0 @@
----
-source: tests/it/completion.rs
-assertion_line: 160
-expression: "complete_and_resolve(&server, uri, 1, 6)?"
----
-{
- "isIncomplete": false,
- "items": [
- {
- "label": "title",
- "kind": 1,
- "documentation": {
- "kind": "markdown",
- "value": "The title of the work."
- },
- "preselect": false,
- "sortText": "00",
- "textEdit": {
- "range": {
- "start": {
- "line": 1,
- "character": 4
- },
- "end": {
- "line": 1,
- "character": 8
- }
- },
- "newText": "title"
- }
- },
- {
- "label": "titleaddon",
- "kind": 1,
- "documentation": {
- "kind": "markdown",
- "value": "An annex to the `title`, to be printed in a different font."
- },
- "preselect": false,
- "sortText": "01",
- "textEdit": {
- "range": {
- "start": {
- "line": 1,
- "character": 4
- },
- "end": {
- "line": 1,
- "character": 8
- }
- },
- "newText": "titleaddon"
- }
- },
- {
- "label": "booksubtitle",
- "kind": 1,
- "documentation": {
- "kind": "markdown",
- "value": "The subtitle related to the `booktitle`. If the subtitle field refers to a work which is part of a larger publication, a possible subtitle of the main work is given in this field. See also `subtitle`."
- },
- "preselect": false,
- "sortText": "02",
- "textEdit": {
- "range": {
- "start": {
- "line": 1,
- "character": 4
- },
- "end": {
- "line": 1,
- "character": 8
- }
- },
- "newText": "booksubtitle"
- }
- },
- {
- "label": "booktitle",
- "kind": 1,
- "documentation": {
- "kind": "markdown",
- "value": "If the `title` field indicates the title of a work which is part of a larger publication, the title of the main work is given in this field. See also `title`."
- },
- "preselect": false,
- "sortText": "03",
- "textEdit": {
- "range": {
- "start": {
- "line": 1,
- "character": 4
- },
- "end": {
- "line": 1,
- "character": 8
- }
- },
- "newText": "booktitle"
- }
- },
- {
- "label": "booktitleaddon",
- "kind": 1,
- "documentation": {
- "kind": "markdown",
- "value": "An annex to the `booktitle`, to be printed in a different font."
- },
- "preselect": false,
- "sortText": "04",
- "textEdit": {
- "range": {
- "start": {
- "line": 1,
- "character": 4
- },
- "end": {
- "line": 1,
- "character": 8
- }
- },
- "newText": "booktitleaddon"
- }
- },
- {
- "label": "eventtitle",
- "kind": 1,
- "documentation": {
- "kind": "markdown",
- "value": "The title of a conference, a symposium, or some other event in `@proceedings` and `@inproceedings` entries. Note that this field holds the plain title of the event. Things like \"Proceedings of the Fifth XYZ Conference\" go into the `titleaddon` or `booktitleaddon` field, respectively. See also `eventdate` and `venue`."
- },
- "preselect": false,
- "sortText": "05",
- "textEdit": {
- "range": {
- "start": {
- "line": 1,
- "character": 4
- },
- "end": {
- "line": 1,
- "character": 8
- }
- },
- "newText": "eventtitle"
- }
- },
- {
- "label": "eventtitleaddon",
- "kind": 1,
- "documentation": {
- "kind": "markdown",
- "value": "An annex to the `eventtitle` field. Can be used for known event acronyms, for example."
- },
- "preselect": false,
- "sortText": "06",
- "textEdit": {
- "range": {
- "start": {
- "line": 1,
- "character": 4
- },
- "end": {
- "line": 1,
- "character": 8
- }
- },
- "newText": "eventtitleaddon"
- }
- }
- ]
-}
diff --git a/support/texlab/tests/it/snapshots/it__completion__bibtex__junk.snap b/support/texlab/tests/it/snapshots/it__completion__bibtex__junk.snap
deleted file mode 100644
index 72c29cf065..0000000000
--- a/support/texlab/tests/it/snapshots/it__completion__bibtex__junk.snap
+++ /dev/null
@@ -1,9 +0,0 @@
----
-source: tests/it/completion.rs
-assertion_line: 43
-expression: "complete_and_resolve(&server, uri, 0, 0)?"
----
-{
- "isIncomplete": false,
- "items": []
-}
diff --git a/support/texlab/tests/it/snapshots/it__completion__latex__begin_command.snap b/support/texlab/tests/it/snapshots/it__completion__latex__begin_command.snap
deleted file mode 100644
index ff1fed0a8d..0000000000
--- a/support/texlab/tests/it/snapshots/it__completion__latex__begin_command.snap
+++ /dev/null
@@ -1,162 +0,0 @@
----
-source: tests/it/completion.rs
-assertion_line: 203
-expression: "complete_and_resolve(&server, uri, 0, 2)?"
----
-{
- "isIncomplete": true,
- "items": [
- {
- "label": "b",
- "kind": 1,
- "detail": "built-in",
- "documentation": {
- "kind": "markdown",
- "value": "![b](data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAA6CAIAAAB5+022AAAHLklEQVR4nO2ZX0hTbRzHz9nZ5jb2V8O5mqaOWrrUCJZgLqmkhBDroghSCYr+UDdGXRQFRnQTBUU3o4tjRGgJQZg4Jkgs5pIkM4uZtmzqnJa5s7X/5+w8570477v3cJzbMe19veh7+dvzfM/nnOd3fs/vPIMpioLWknj/NwBbf4Ayac0B8TmOi8Vi4+PjdrvdZrN9/Phxbm4uFAoBAMRicU5Ojl6vr66u3r17d3l5uUwmWwkQnPEti0ajdrv90aNHNpttbm4OhmGVSqVSqSQSCUmSGIbNz89Ho1Eej5ednW00GhsbG+vq6rKzs3+RiFpaAACXy3Xq1CmVSoUgiE6nO336dGdn58jIiNfrXVhYmJ+fd7lcXV1dzc3NSQKxWLx///6+vj6CINKYL6UlgQAAb9++3blzJ4/HU6vVV65c+fTp01LXiEajz58/NxgMyfvUaDT37t0Lh8OrBjQxMVFdXQ3DsMFg6OnpwXE8vREAwG636/X6JJNMJrtx40YkElkFIBzHL1y4gCBIVlZWS0vL0NBQNBrN6EWSZHt7u1wuTzLJ5fIHDx4kEomVAo2Ojm7cuJE2FQgEGo3m/Pnzs7OzGe1CodDhw4eZOarT6YaGhlYK9PjxY4FAwPTl8/ktLS3xeDyjY3d3t1QqTU6EYfjMmTNcJtJKXRg/f/5MEAQzkkgkurq6PB5PxtfWaDRu3ryZ+RZbLBaXy5VxIq3UQNFodHHQ7/f7/f6Mjjk5Odu3b2dGvF7vwMDAioB0Oh2fzy7iCoVCoVBkdEQQpLy8nMf715kgiHfv3gEAfh1o7969JSUlrMvU1dVptVoupgUFBawUnJqaYuXAkkqZWSRJ9vb2VlZWisViBEEUCsXRo0fdbjfHxHz58iUzryEIqq2tDYVCXOam3lx5PF5tbe3WrVuHh4cxDNNqtdu2bWMWmPQSCoXMJYMgCIZhGIa5zF1yt4dhWKPRaDQajhCsuayIQCBgIS4biIsAALFYLBgMBgIBv9//8+fPUCgUi8XoXe8/AiII4sePHy6X68OHDyMjIy6Xa25uDsOwcDiM4zhJkuAfMWdxXK9lAJEk6fV6+/v7rVbr4ODg9PQ03aBBECQUClUqVXFxcX5+vlarzcvL8/l8ZrM5Fost61a5AhEE4XQ629vbu7u7v3z5Eo/H6bhIJNLpdCaTqaamxmAwrF+/XiqVCoVCGIZfv36NoujqA1EUNTk5aTabOzo6PB5PchWkUqnJZGpsbKypqVGr1YtL6Iq0VD3AcfzFixdGoxFBkORgBEF27Njx5MkTv9+fppY4HA5WjTh48CDH/TU1UDweN5vNarWaaSoSiU6ePDkxMQEASG+6ykCJRAJFUVaXLhKJLl26hGEYF9NVBnI4HMnujBaPx2tubvb5fFwcVwjEzsdgMHjnzp2pqSlmUK/XX758WaVSpU/HZenv5wFBrILJBrLb7X19fRTjYw1BkKamJmbPtSr6+vXr/fv3KYq6e/cuM84u58+ePWN1YXl5efX19RwLPy0cxzN2P9++fUNRFEVRVpx9mf7+flZEr9cXFhZyp4EgCMMwrt3PIrGBZmZmWJHi4mKxWLws07GxMRzHVwcoEomwIjKZjPvWSDs4HA7qVw/m2ECs1hOCIAzDOLbDtEZHR9+8ecMK0t+KzAhBECRJZgbatGkTK+J0Orl8bNDCcfzhw4c+n2/Lli3M5xoMBlmLSOfZ4n2QDXTkyBHWoNHR0cWZnlIURVmt1o6OjsLCwrNnzzIzz+v1+nw+5sixsTGCIIqKilK4MDU5OVlVVcUaU1NTMz09nb7CAgAGBgYMBoNIJLp9+7bb7WYehkgkks7OzuTgQCCwb98+BEFaW1tZPmwgAIDNZmOVQQRBjh07loYJx3GLxVJWViYQCE6cOIFhWCKRaG1tZT5sk8nkdDoJggiHw2azWSqVlpWVjY+PZwCiKIokyVevXlVXVzPt+Hz+nj17LBZLIBBg7vaRSGR4ePjixYu5ublSqfTcuXPfv3+nf3K73VVVVclM4vF4JSUlTU1N9fX1SqVy3bp1T58+Xdw4pG4/AAAej+fmzZsGg0EoFCaxlEplbW3ttWvXUBRta2u7fv16Q0PDhg0bsrKyKioqUBRlfnzRi1hZWcnsqCAIgmG4qKiora0t5ZlTujNGkiQ9Ho/NZuvt7X3//v3s7Gw4HCYIAgBA7yQIgiiVytLS0kOHDjU0NBQUFLAqFkVRExMTKIparVb6NCc3N3fXrl3Hjx+vqKhggf6NmwYoKRzHFxYWZmZmvF6v1+sNBAKxWEwsFufn5+v1ep1OJ5fL0xRPkiR9Ph/dvahUqpycnDRdLyeg/1Jr7uD8D1AmrTmg1NkeiUR+uaFJL6FQKJFIlgcEALh161ZPT8/vADpw4MDVq1dTVqAlgehqNjg4+DuASktL0xea1EuWnZ2dn5//O4Ay/kv0pzBm0h+gTFpzQH8Bp4gu0MowthIAAAAASUVORK5CYII=|width=48,height=48)"
- },
- "preselect": false,
- "sortText": "00",
- "textEdit": {
- "range": {
- "start": {
- "line": 0,
- "character": 1
- },
- "end": {
- "line": 0,
- "character": 2
- }
- },
- "newText": "b"
- }
- },
- {
- "label": "backslash",
- "kind": 1,
- "detail": "\\, built-in",
- "documentation": {
- "kind": "markdown",
- "value": "![backslash](data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABwAAAA6CAIAAAAsmq7oAAADD0lEQVR4nO2Y3Uv6UBzGv5stsyhCiUTRytJIDTMkRUEqhmnbVTf+o9sygqjAi4RIVqlJKWWl1FB6oyLt/C68K9tb5+YHncudw4fnczjbcxiBEALcg8RO/IN+ha6srKTT6ZeXF5xQSZJ2d3fPzs5wQjc2Nlqt1vb29m+O2lcoy7IWiyWTyTw+PmKDer3eUCgkiuLp6Sk26NDQEMMwT09PW1tb+ncAfRuFQsHhcEQiEUmSvs+qGT3O6dTUVDgcLhQKoijqC9oDOjAwwLLs29vb5ubm5+enHmrP/Ofn5y6XKxgMNhoNPPoA4HA4YrFYuVw+PDzUEbQ3tL+/n2GYTqcjCEK73dZM/Unh8vJydnbW5/PVajU8+gBgs9ni8XilUsnlclqD/gjt6+tjWZYgCI7jPj4+tFFlLG5ububn52dmZiqVCh59ABgfH19dXa3VatlsVlNQOajBYFhfX6coiuf59/d3DVR5kbu7u1AoNDExUSqV8OgDgMVioWn69vZ2f39ffVAFKEmSyWRycHCQ5/nX11e1VEWXZrMZjUZtNpsoinj0AWB0dHRtbe3+/n5nZwep+2wrQwmCSCQSIyMjgiCorG5Vlwmv1xsIBI6OjkqlEjbo8PBwMplUX92qoARB0DTdre6Hhwc8UADweDyLi4vHx8dqqlsttFvdz8/PmUxGubjUv3wnJyd2uz0cDitWt4arpMvlWlpaKhaL+XxefqUGqMlk6la3IAidTkduqXp9hFC5XJ6cnFxYWKjX63j0AcDpdEajUcXq1gY1Go3d6uY4Tq66NekjhKrVqtvtnpubu7q6wqMPAHa7PR6PV6vVg4ODn9ZohlIUxTCMQnVr1UcIXV9f+3y+6enpi4sLPPoAYLVal5eXZapbD9RgMDAMQ1EUx3G9q1uHPkKo0WgEg0Gn01ksFvHoA8DY2BhN0/V6fW9v7/usTihJkqlUymQy8Tzfo7j06SOEJEmKRCJWqzWXy+HRBwCz2ZxIJCRJ4nkeW1KEUDabNZvNfr8fW1IA8Pv9sVjMaDR+eU6gvx8z/wX0H6vA4+khaPAcAAAAAElFTkSuQmCC|width=48,height=48)"
- },
- "preselect": false,
- "sortText": "01",
- "textEdit": {
- "range": {
- "start": {
- "line": 0,
- "character": 1
- },
- "end": {
- "line": 0,
- "character": 2
- }
- },
- "newText": "backslash"
- }
- },
- {
- "label": "badness",
- "kind": 1,
- "detail": "built-in",
- "preselect": false,
- "sortText": "02",
- "textEdit": {
- "range": {
- "start": {
- "line": 0,
- "character": 1
- },
- "end": {
- "line": 0,
- "character": 2
- }
- },
- "newText": "badness"
- }
- },
- {
- "label": "bar",
- "kind": 1,
- "detail": " ̄, built-in",
- "documentation": {
- "kind": "markdown",
- "value": "![bar](data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAC8AAAA6CAIAAACvXpfTAAAHHklEQVR4nO2ZX0xSbxjHORxAkH8FEShCpU7DRI3RNHEul1uzrdRqtpazumrzprV1QReuedFFrbY229ja6kJbK7fanEsrK1saWGoFREA0Y0mioAiNA8HhnPO7YDudH3Dg6K/t14Xfu/fhfZ7zed/3Oc/7vgcAwzDaXyP6/w3wL23QkOvvoqFhJLp16xaLxQL/tM6cOZNIJMgeyshCiSAIgiB/dvAoimb5lZRGq9X29vb+8fe/qqqKTidND2Cj3pBqg4ZcGzTk2qAhF2n1oyIURSEI8vv9gUAgFovl5+fLZDKJRMJgrDPsOt0ikYjFYhkdHZ2YmHC73aFQCEEQJpMpk8n2799/+vRptVoNguBaw665FsMwbDKZDAbDixcvVlZWQBDcsWNHVVWVRCIJBoNWq9Xlcsnl8kuXLp04cYLJZGIY9vXr16GhoaWlpfr6+paWFjabTRqdbDvNKI/Ho9frt27dSqPR6HS6SqXq6+tzu92xWAxFURiGPR7PtWvXZDKZWCweGBhIJBIfP37UarXJvUkoFN6/fz9LfKo0CIKYTKampqbk/DMYjPb2dpvNhiBISk8Yhu/duycWi4uLiycnJ7u6ugAAwAd//vx5FEX/E00ikRgeHi4rK0vGZTAYXV1dCwsLZP1jsZher2cwGI2NjYWFhb/TAgCuXr2a5UG5aRAEefjwoVKpxCO2trZ6vd7sXk6ns6SkhE6nEyeGy+WOjY2tnwZF0adPn27fvh2PqFarP3/+nHMMMAx3d3en5Ghpaanb7V4/jdlsrqysxMMJBILBwcEsC0/Uo0eP8vLyiDStra3RaHSdND6f79ChQ/hUAwDQ1dUFQRAVFAzDZmdnxWIxMWmuXLmS3YWUBobhy5cvs1gsPJxUKjUajRRRMAwbGxvjcrm4O5/PHx8fz+5Cuk9NT08bDIZ4PI5bmpqaampqyPqnCMOw9+/fRyIR3FJUVFRWVpbdKzMNBEF9fX0/fvzALRwO5+jRoxwOhyJNLBZLTiRuUavVW7ZsWQ/N69evR0dHibFKSkr27t1LEYVGo/l8PpvN9vsxdLpOpyOuO1WaaDTa398fDAaJxsbGRqlUSp3G4XAsLCzgTYFAoNVqc3ploLFarS9fviRaOBxOc3Pzms4Jb9++jUajeFOpVJaUlKyZJlnulpeXiUa5XL57927qKNFodGpqirjQNTU1IpFozTSrq6vPnj1LuZ9WV1fLZDLqNF6v1263400QBHU6HZPJXDONy+VyOp3/6kGnNzQ0ZDuUpMluty8uLuLNTZs2UZzaVJqZmZnV1VWihcfjUUlAXBiGmUymX79+4RalUrlt27b10ExPTycSCaJFLpcXFxdTp4Eg6N27d8Skqays3Lx583povnz5kmIpLy8nbjc5tbCwQFxrEAT37NlDJWky0Ph8vhSLWq1O2Yqzy2azEYPw+XyNRkPRN5UGgiBik8lkqtVq6igoihqNxlgshlsyVhoURefm5lJeF1rOGwyXy6WYgEmFw+GZmRli0lRXV6cv9NLS0qlTpwKBAHH3oKXPTcqbLBQKJRIJdRqPx+NyufAmCIJ1dXXpSWO3281mc/qFK5UmeTvBJRAIeDwedRqLxeL3+4nu6ZUGw7CpqSkIgnQ6XQ4alUpFbHI4nJwbL654PP78+XPikUipVKZXh0gkMjExkZeXt2/fvhw0DQ0NxIml/lkUwzCj0Tg6Oko0qlSq9ErjdrutVqtCoUgvqqk09fX1crkcb4ZCoZS3jEwOh0Ov13u9XtwCAEBFRUXK1GIYNjk56fP5tFptUVFRDprS0tLm5mb8ZL68vOzxeHKieDyeCxcuzM7OEucVAADiwJKCIGh4eBgAgAMHDmQoY+lH5Tdv3uA7Np1Ov379evYry/z8/LFjx1gsVltbW0dHBx4ZBMG7d++mdH716pVIJNq5c+e3b9/SQ2WgicfjPT09+AzX1dUtLi5m5EBR1GKxtLS0sFisw4cPu93ux48fCwQCfCQGg4HYPxwOd3Z2giB48eLFjN/3M99gfD7f8ePHk/WAxWL19PSkX6OCwWB/f/+uXbvYbPbJkyfn5+cxDAuFQh0dHfhCd3d3wzCc7A/D8J07d/h8vlqtdjqdGZ9Lep+an5/v7OxMFkM+n3/u3LkPHz74/f7l5WWHwzEwMHDw4EEejyeVSnt7e1dWVnDHT58+1dbWJoEUCsXQ0JDf7//+/fvNmzcLCgokEsmDBw/Sv2zkoMEwLBAI3Lhxo6KigslkgiBYUFCg0Wg0Go1CoWCz2SKR6MiRI+Pj47FYjOiFoqjVam1vb8/Pz6fRaCKRSKPRlJeXczgcpVJ5+/btlP5E5fi2hSDI3NzcyMjIkydPHA7Hz58/QRAsLCzU6XRtbW21tbV4lqQoEAiMjIwMDg6azeZwOCwUChsaGs6ePVtbW5vltL/xrwe5NmjI9XfR/ANs1iTDg+2GBQAAAABJRU5ErkJggg==|width=48,height=48)"
- },
- "preselect": false,
- "sortText": "03",
- "textEdit": {
- "range": {
- "start": {
- "line": 0,
- "character": 1
- },
- "end": {
- "line": 0,
- "character": 2
- }
- },
- "newText": "bar"
- }
- },
- {
- "label": "baselineskip",
- "kind": 1,
- "detail": "built-in",
- "preselect": false,
- "sortText": "04",
- "textEdit": {
- "range": {
- "start": {
- "line": 0,
- "character": 1
- },
- "end": {
- "line": 0,
- "character": 2
- }
- },
- "newText": "baselineskip"
- }
- },
- {
- "label": "baselinestretch",
- "kind": 1,
- "detail": "built-in",
- "preselect": false,
- "sortText": "05",
- "textEdit": {
- "range": {
- "start": {
- "line": 0,
- "character": 1
- },
- "end": {
- "line": 0,
- "character": 2
- }
- },
- "newText": "baselinestretch"
- }
- },
- {
- "label": "batchmode",
- "kind": 1,
- "detail": "built-in",
- "preselect": false,
- "sortText": "06",
- "textEdit": {
- "range": {
- "start": {
- "line": 0,
- "character": 1
- },
- "end": {
- "line": 0,
- "character": 2
- }
- },
- "newText": "batchmode"
- }
- }
- ]
-}
diff --git a/support/texlab/tests/it/snapshots/it__completion__latex__citation.snap b/support/texlab/tests/it/snapshots/it__completion__latex__citation.snap
deleted file mode 100644
index af2249cb0a..0000000000
--- a/support/texlab/tests/it/snapshots/it__completion__latex__citation.snap
+++ /dev/null
@@ -1,54 +0,0 @@
----
-source: tests/it/completion.rs
-assertion_line: 237
-expression: "complete_and_resolve(&server, tex_uri, 3, 6)?"
----
-{
- "isIncomplete": false,
- "items": [
- {
- "label": "bar:2005",
- "kind": 1,
- "preselect": false,
- "sortText": "00 bar:2005 @articlebar:2005",
- "filterText": "bar:2005 @articlebar:2005",
- "textEdit": {
- "range": {
- "start": {
- "line": 3,
- "character": 6
- },
- "end": {
- "line": 3,
- "character": 6
- }
- },
- "newText": "bar:2005"
- }
- },
- {
- "label": "foo:2019",
- "kind": 1,
- "documentation": {
- "kind": "markdown",
- "value": "F. Bar: \"Baz Qux\". (2019)."
- },
- "preselect": false,
- "sortText": "01 foo:2019 @articlefoo:2019 author Foo Bar title Baz Qux year 2019",
- "filterText": "foo:2019 @articlefoo:2019 author Foo Bar title Baz Qux year 2019",
- "textEdit": {
- "range": {
- "start": {
- "line": 3,
- "character": 6
- },
- "end": {
- "line": 3,
- "character": 6
- }
- },
- "newText": "foo:2019"
- }
- }
- ]
-}
diff --git a/support/texlab/tests/it/snapshots/it__completion__latex__citation_after.snap b/support/texlab/tests/it/snapshots/it__completion__latex__citation_after.snap
deleted file mode 100644
index 9d635a36d3..0000000000
--- a/support/texlab/tests/it/snapshots/it__completion__latex__citation_after.snap
+++ /dev/null
@@ -1,9 +0,0 @@
----
-source: tests/it/completion.rs
-assertion_line: 305
-expression: "complete_and_resolve(&server, tex_uri, 3, 7)?"
----
-{
- "isIncomplete": false,
- "items": []
-}
diff --git a/support/texlab/tests/it/snapshots/it__completion__latex__citation_multi_word.snap b/support/texlab/tests/it/snapshots/it__completion__latex__citation_multi_word.snap
deleted file mode 100644
index 94ed4922d6..0000000000
--- a/support/texlab/tests/it/snapshots/it__completion__latex__citation_multi_word.snap
+++ /dev/null
@@ -1,34 +0,0 @@
----
-source: tests/it/completion.rs
-assertion_line: 271
-expression: "complete_and_resolve(&server, tex_uri, 3, 7)?"
----
-{
- "isIncomplete": false,
- "items": [
- {
- "label": "foo",
- "kind": 1,
- "documentation": {
- "kind": "markdown",
- "value": "F. Bar: \"Baz Qux\". (2019)."
- },
- "preselect": false,
- "sortText": "00 foo @articlefoo author Foo Bar title Baz Qux year 2019",
- "filterText": "foo @articlefoo author Foo Bar title Baz Qux year 2019",
- "textEdit": {
- "range": {
- "start": {
- "line": 3,
- "character": 6
- },
- "end": {
- "line": 3,
- "character": 11
- }
- },
- "newText": "foo"
- }
- }
- ]
-}
diff --git a/support/texlab/tests/it/snapshots/it__completion__latex__citation_open_brace.snap b/support/texlab/tests/it/snapshots/it__completion__latex__citation_open_brace.snap
deleted file mode 100644
index 43012267d5..0000000000
--- a/support/texlab/tests/it/snapshots/it__completion__latex__citation_open_brace.snap
+++ /dev/null
@@ -1,34 +0,0 @@
----
-source: tests/it/completion.rs
-assertion_line: 337
-expression: "complete_and_resolve(&server, tex_uri, 3, 9)?"
----
-{
- "isIncomplete": false,
- "items": [
- {
- "label": "FooBar",
- "kind": 1,
- "documentation": {
- "kind": "markdown",
- "value": "F. Bar: \"Baz Qux\". (2019)."
- },
- "preselect": false,
- "sortText": "00 FooBar @articleFooBar author Foo Bar title Baz Qux year 2019",
- "filterText": "FooBar @articleFooBar author Foo Bar title Baz Qux year 2019",
- "textEdit": {
- "range": {
- "start": {
- "line": 3,
- "character": 6
- },
- "end": {
- "line": 3,
- "character": 9
- }
- },
- "newText": "FooBar"
- }
- }
- ]
-}
diff --git a/support/texlab/tests/it/snapshots/it__completion__latex__class_command.snap b/support/texlab/tests/it/snapshots/it__completion__latex__class_command.snap
deleted file mode 100644
index bac91f2943..0000000000
--- a/support/texlab/tests/it/snapshots/it__completion__latex__class_command.snap
+++ /dev/null
@@ -1,150 +0,0 @@
----
-source: tests/it/completion.rs
-assertion_line: 483
-expression: "complete_and_resolve(&server, uri, 2, 5)?"
----
-{
- "isIncomplete": false,
- "items": [
- {
- "label": "chapter",
- "kind": 1,
- "detail": "book.cls",
- "preselect": false,
- "sortText": "00",
- "textEdit": {
- "range": {
- "start": {
- "line": 2,
- "character": 1
- },
- "end": {
- "line": 2,
- "character": 5
- }
- },
- "newText": "chapter"
- }
- },
- {
- "label": "chaptermark",
- "kind": 1,
- "detail": "book.cls",
- "preselect": false,
- "sortText": "01",
- "textEdit": {
- "range": {
- "start": {
- "line": 2,
- "character": 1
- },
- "end": {
- "line": 2,
- "character": 5
- }
- },
- "newText": "chaptermark"
- }
- },
- {
- "label": "chaptername",
- "kind": 1,
- "detail": "book.cls",
- "preselect": false,
- "sortText": "02",
- "textEdit": {
- "range": {
- "start": {
- "line": 2,
- "character": 1
- },
- "end": {
- "line": 2,
- "character": 5
- }
- },
- "newText": "chaptername"
- }
- },
- {
- "label": "thechapter",
- "kind": 1,
- "detail": "book.cls",
- "preselect": false,
- "sortText": "03",
- "textEdit": {
- "range": {
- "start": {
- "line": 2,
- "character": 1
- },
- "end": {
- "line": 2,
- "character": 5
- }
- },
- "newText": "thechapter"
- }
- },
- {
- "label": "scshape",
- "kind": 1,
- "detail": "built-in",
- "preselect": false,
- "sortText": "04",
- "textEdit": {
- "range": {
- "start": {
- "line": 2,
- "character": 1
- },
- "end": {
- "line": 2,
- "character": 5
- }
- },
- "newText": "scshape"
- }
- },
- {
- "label": "fontchardp",
- "kind": 1,
- "detail": "amsmath.sty",
- "preselect": false,
- "sortText": "05",
- "textEdit": {
- "range": {
- "start": {
- "line": 2,
- "character": 1
- },
- "end": {
- "line": 2,
- "character": 5
- }
- },
- "newText": "fontchardp"
- }
- },
- {
- "label": "XeTeXcharglyph",
- "kind": 1,
- "detail": "built-in",
- "preselect": false,
- "sortText": "06",
- "textEdit": {
- "range": {
- "start": {
- "line": 2,
- "character": 1
- },
- "end": {
- "line": 2,
- "character": 5
- }
- },
- "newText": "XeTeXcharglyph"
- }
- }
- ]
-}
diff --git a/support/texlab/tests/it/snapshots/it__completion__latex__class_environment.snap b/support/texlab/tests/it/snapshots/it__completion__latex__class_environment.snap
deleted file mode 100644
index b751033521..0000000000
--- a/support/texlab/tests/it/snapshots/it__completion__latex__class_environment.snap
+++ /dev/null
@@ -1,30 +0,0 @@
----
-source: tests/it/completion.rs
-assertion_line: 506
-expression: "complete_and_resolve(&server, uri, 4, 13)?"
----
-{
- "isIncomplete": false,
- "items": [
- {
- "label": "theindex",
- "kind": 1,
- "detail": "book.cls",
- "preselect": false,
- "sortText": "00",
- "textEdit": {
- "range": {
- "start": {
- "line": 4,
- "character": 7
- },
- "end": {
- "line": 4,
- "character": 13
- }
- },
- "newText": "theindex"
- }
- }
- ]
-}
diff --git a/support/texlab/tests/it/snapshots/it__completion__latex__class_import.snap b/support/texlab/tests/it/snapshots/it__completion__latex__class_import.snap
deleted file mode 100644
index 7d964d6f85..0000000000
--- a/support/texlab/tests/it/snapshots/it__completion__latex__class_import.snap
+++ /dev/null
@@ -1,171 +0,0 @@
----
-source: tests/it/completion.rs
-assertion_line: 569
-expression: "complete_and_resolve(&server, uri, 0, 19)?"
----
-{
- "isIncomplete": false,
- "items": [
- {
- "label": "book",
- "kind": 1,
- "documentation": {
- "kind": "plaintext",
- "value": "LaTeX is a widely-used macro package for TeX, providing many basic document formating commands extended by a wide range of packages. It is a development of Leslie Lamport's LaTeX 2.09, and superseded the older system in June 1994. The basic distribution is catalogued separately, at latex-base; apart from a large set of contributed packages and third-party documentation (elsewhere on the archive), the distribution includes: - a bunch of required packages, which LaTeX authors are \"entitled to assume\" will be present on any system running LaTeX; and - a minimal set of documentation detailing differences from the 'old' version of LaTeX in the areas of user commands, font selection and control, class and package writing, font encodings, configuration options and modification of LaTeX. For downloading details, see the linked catalogue entries above."
- },
- "preselect": false,
- "sortText": "00",
- "textEdit": {
- "range": {
- "start": {
- "line": 0,
- "character": 15
- },
- "end": {
- "line": 0,
- "character": 19
- }
- },
- "newText": "book"
- }
- },
- {
- "label": "bookcover",
- "kind": 1,
- "documentation": {
- "kind": "plaintext",
- "value": "This class helps typesetting book covers and dust jackets."
- },
- "preselect": false,
- "sortText": "01",
- "textEdit": {
- "range": {
- "start": {
- "line": 0,
- "character": 15
- },
- "end": {
- "line": 0,
- "character": 19
- }
- },
- "newText": "bookcover"
- }
- },
- {
- "label": "bookest",
- "kind": 1,
- "documentation": {
- "kind": "plaintext",
- "value": "The class extends the standard book class, in the areas of colour scheme management, document layout, headings and footers, front page layout, and other minor items."
- },
- "preselect": false,
- "sortText": "02",
- "textEdit": {
- "range": {
- "start": {
- "line": 0,
- "character": 15
- },
- "end": {
- "line": 0,
- "character": 19
- }
- },
- "newText": "bookest"
- }
- },
- {
- "label": "bbook",
- "kind": 1,
- "documentation": {
- "kind": "plaintext",
- "value": "The bundle provides class files for writing Bangla and Assamese with LaTeX, and Metafont sources for fonts."
- },
- "preselect": false,
- "sortText": "03",
- "textEdit": {
- "range": {
- "start": {
- "line": 0,
- "character": 15
- },
- "end": {
- "line": 0,
- "character": 19
- }
- },
- "newText": "bbook"
- }
- },
- {
- "label": "basque-book",
- "kind": 1,
- "documentation": {
- "kind": "plaintext",
- "value": "The class is derived from the LaTeX book class. The extensions solve grammatical and numeration issues that occur when book-type documents are written in Basque. The class is useful for writing books, PhD and Master Theses, etc., in Basque."
- },
- "preselect": false,
- "sortText": "04",
- "textEdit": {
- "range": {
- "start": {
- "line": 0,
- "character": 15
- },
- "end": {
- "line": 0,
- "character": 19
- }
- },
- "newText": "basque-book"
- }
- },
- {
- "label": "biditufte-book",
- "kind": 1,
- "documentation": {
- "kind": "plaintext",
- "value": "A convenient interface for typesetting bidirectional texts with plain TeX and LaTeX. The package includes adaptations for use with many other commonly-used packages."
- },
- "preselect": false,
- "sortText": "05",
- "textEdit": {
- "range": {
- "start": {
- "line": 0,
- "character": 15
- },
- "end": {
- "line": 0,
- "character": 19
- }
- },
- "newText": "biditufte-book"
- }
- },
- {
- "label": "caesar_book",
- "kind": 1,
- "documentation": {
- "kind": "plaintext",
- "value": "The package allows typesetting of texts with notes, figures, citations, captions and tables in the margin. This is common (for example) in science text books."
- },
- "preselect": false,
- "sortText": "06",
- "textEdit": {
- "range": {
- "start": {
- "line": 0,
- "character": 15
- },
- "end": {
- "line": 0,
- "character": 19
- }
- },
- "newText": "caesar_book"
- }
- }
- ]
-}
diff --git a/support/texlab/tests/it/snapshots/it__completion__latex__color_model_define_color.snap b/support/texlab/tests/it/snapshots/it__completion__latex__color_model_define_color.snap
deleted file mode 100644
index d65f573d96..0000000000
--- a/support/texlab/tests/it/snapshots/it__completion__latex__color_model_define_color.snap
+++ /dev/null
@@ -1,105 +0,0 @@
----
-source: tests/it/completion.rs
-assertion_line: 373
-expression: "complete_and_resolve(&server, uri, 1, 18)?"
----
-{
- "isIncomplete": false,
- "items": [
- {
- "label": "HTML",
- "kind": 1,
- "preselect": false,
- "sortText": "00",
- "textEdit": {
- "range": {
- "start": {
- "line": 1,
- "character": 18
- },
- "end": {
- "line": 1,
- "character": 18
- }
- },
- "newText": "HTML"
- }
- },
- {
- "label": "RGB",
- "kind": 1,
- "preselect": false,
- "sortText": "01",
- "textEdit": {
- "range": {
- "start": {
- "line": 1,
- "character": 18
- },
- "end": {
- "line": 1,
- "character": 18
- }
- },
- "newText": "RGB"
- }
- },
- {
- "label": "cmyk",
- "kind": 1,
- "preselect": false,
- "sortText": "02",
- "textEdit": {
- "range": {
- "start": {
- "line": 1,
- "character": 18
- },
- "end": {
- "line": 1,
- "character": 18
- }
- },
- "newText": "cmyk"
- }
- },
- {
- "label": "gray",
- "kind": 1,
- "preselect": false,
- "sortText": "03",
- "textEdit": {
- "range": {
- "start": {
- "line": 1,
- "character": 18
- },
- "end": {
- "line": 1,
- "character": 18
- }
- },
- "newText": "gray"
- }
- },
- {
- "label": "rgb",
- "kind": 1,
- "preselect": false,
- "sortText": "04",
- "textEdit": {
- "range": {
- "start": {
- "line": 1,
- "character": 18
- },
- "end": {
- "line": 1,
- "character": 18
- }
- },
- "newText": "rgb"
- }
- }
- ]
-}
diff --git a/support/texlab/tests/it/snapshots/it__completion__latex__color_model_define_color_set.snap b/support/texlab/tests/it/snapshots/it__completion__latex__color_model_define_color_set.snap
deleted file mode 100644
index dd49043a9e..0000000000
--- a/support/texlab/tests/it/snapshots/it__completion__latex__color_model_define_color_set.snap
+++ /dev/null
@@ -1,67 +0,0 @@
----
-source: tests/it/completion.rs
-assertion_line: 391
-expression: "complete_and_resolve(&server, uri, 2, 17)?"
----
-{
- "isIncomplete": false,
- "items": [
- {
- "label": "RGB",
- "kind": 1,
- "preselect": false,
- "sortText": "00",
- "textEdit": {
- "range": {
- "start": {
- "line": 2,
- "character": 16
- },
- "end": {
- "line": 2,
- "character": 17
- }
- },
- "newText": "RGB"
- }
- },
- {
- "label": "rgb",
- "kind": 1,
- "preselect": false,
- "sortText": "01",
- "textEdit": {
- "range": {
- "start": {
- "line": 2,
- "character": 16
- },
- "end": {
- "line": 2,
- "character": 17
- }
- },
- "newText": "rgb"
- }
- },
- {
- "label": "gray",
- "kind": 1,
- "preselect": false,
- "sortText": "02",
- "textEdit": {
- "range": {
- "start": {
- "line": 2,
- "character": 16
- },
- "end": {
- "line": 2,
- "character": 17
- }
- },
- "newText": "gray"
- }
- }
- ]
-}
diff --git a/support/texlab/tests/it/snapshots/it__completion__latex__color_name.snap b/support/texlab/tests/it/snapshots/it__completion__latex__color_name.snap
deleted file mode 100644
index 2b428d0e72..0000000000
--- a/support/texlab/tests/it/snapshots/it__completion__latex__color_name.snap
+++ /dev/null
@@ -1,143 +0,0 @@
----
-source: tests/it/completion.rs
-assertion_line: 355
-expression: "complete_and_resolve(&server, uri, 0, 9)?"
----
-{
- "isIncomplete": false,
- "items": [
- {
- "label": "red",
- "kind": 1,
- "preselect": false,
- "sortText": "00",
- "textEdit": {
- "range": {
- "start": {
- "line": 0,
- "character": 7
- },
- "end": {
- "line": 0,
- "character": 9
- }
- },
- "newText": "red"
- }
- },
- {
- "label": "Red",
- "kind": 1,
- "preselect": false,
- "sortText": "01",
- "textEdit": {
- "range": {
- "start": {
- "line": 0,
- "character": 7
- },
- "end": {
- "line": 0,
- "character": 9
- }
- },
- "newText": "Red"
- }
- },
- {
- "label": "RedOrange",
- "kind": 1,
- "preselect": false,
- "sortText": "02",
- "textEdit": {
- "range": {
- "start": {
- "line": 0,
- "character": 7
- },
- "end": {
- "line": 0,
- "character": 9
- }
- },
- "newText": "RedOrange"
- }
- },
- {
- "label": "RedViolet",
- "kind": 1,
- "preselect": false,
- "sortText": "03",
- "textEdit": {
- "range": {
- "start": {
- "line": 0,
- "character": 7
- },
- "end": {
- "line": 0,
- "character": 9
- }
- },
- "newText": "RedViolet"
- }
- },
- {
- "label": "BrickRed",
- "kind": 1,
- "preselect": false,
- "sortText": "04",
- "textEdit": {
- "range": {
- "start": {
- "line": 0,
- "character": 7
- },
- "end": {
- "line": 0,
- "character": 9
- }
- },
- "newText": "BrickRed"
- }
- },
- {
- "label": "OrangeRed",
- "kind": 1,
- "preselect": false,
- "sortText": "05",
- "textEdit": {
- "range": {
- "start": {
- "line": 0,
- "character": 7
- },
- "end": {
- "line": 0,
- "character": 9
- }
- },
- "newText": "OrangeRed"
- }
- },
- {
- "label": "RubineRed",
- "kind": 1,
- "preselect": false,
- "sortText": "06",
- "textEdit": {
- "range": {
- "start": {
- "line": 0,
- "character": 7
- },
- "end": {
- "line": 0,
- "character": 9
- }
- },
- "newText": "RubineRed"
- }
- }
- ]
-}
diff --git a/support/texlab/tests/it/snapshots/it__completion__latex__empty_document.snap b/support/texlab/tests/it/snapshots/it__completion__latex__empty_document.snap
deleted file mode 100644
index f291fddd8b..0000000000
--- a/support/texlab/tests/it/snapshots/it__completion__latex__empty_document.snap
+++ /dev/null
@@ -1,9 +0,0 @@
----
-source: tests/it/completion.rs
-assertion_line: 194
-expression: "complete_and_resolve(&server, uri, 0, 0)?"
----
-{
- "isIncomplete": false,
- "items": []
-}
diff --git a/support/texlab/tests/it/snapshots/it__completion__latex__kernel_command.snap b/support/texlab/tests/it/snapshots/it__completion__latex__kernel_command.snap
deleted file mode 100644
index 39b89d46d4..0000000000
--- a/support/texlab/tests/it/snapshots/it__completion__latex__kernel_command.snap
+++ /dev/null
@@ -1,30 +0,0 @@
----
-source: tests/it/completion.rs
-assertion_line: 414
-expression: "complete_and_resolve(&server, uri, 0, 2)?"
----
-{
- "isIncomplete": false,
- "items": [
- {
- "label": "documentclass",
- "kind": 1,
- "detail": "built-in",
- "preselect": false,
- "sortText": "00",
- "textEdit": {
- "range": {
- "start": {
- "line": 0,
- "character": 1
- },
- "end": {
- "line": 0,
- "character": 14
- }
- },
- "newText": "documentclass"
- }
- }
- ]
-}
diff --git a/support/texlab/tests/it/snapshots/it__completion__latex__kernel_command_environment.snap b/support/texlab/tests/it/snapshots/it__completion__latex__kernel_command_environment.snap
deleted file mode 100644
index 5e0ea8e44d..0000000000
--- a/support/texlab/tests/it/snapshots/it__completion__latex__kernel_command_environment.snap
+++ /dev/null
@@ -1,30 +0,0 @@
----
-source: tests/it/completion.rs
-assertion_line: 460
-expression: "complete_and_resolve(&server, uri, 6, 10)?"
----
-{
- "isIncomplete": false,
- "items": [
- {
- "label": "document",
- "kind": 1,
- "detail": "built-in",
- "preselect": false,
- "sortText": "00",
- "textEdit": {
- "range": {
- "start": {
- "line": 6,
- "character": 7
- },
- "end": {
- "line": 6,
- "character": 10
- }
- },
- "newText": "document"
- }
- }
- ]
-}
diff --git a/support/texlab/tests/it/snapshots/it__completion__latex__kernel_command_glyph.snap b/support/texlab/tests/it/snapshots/it__completion__latex__kernel_command_glyph.snap
deleted file mode 100644
index 6e7aacacbb..0000000000
--- a/support/texlab/tests/it/snapshots/it__completion__latex__kernel_command_glyph.snap
+++ /dev/null
@@ -1,34 +0,0 @@
----
-source: tests/it/completion.rs
-assertion_line: 437
-expression: "complete_and_resolve(&server, uri, 7, 7)?"
----
-{
- "isIncomplete": false,
- "items": [
- {
- "label": "varepsilon",
- "kind": 1,
- "detail": "ε, built-in",
- "documentation": {
- "kind": "markdown",
- "value": "![varepsilon](data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADMAAAA6CAIAAACSzPa1AAAHu0lEQVR4nO2ZX0hTXxzA77n37p933rmmzmQxYaZmKlOzNKQQJEyJMqgQKn2Q/gjmQ3+ECLEXIxRJkx4CQYJ6SSoffFGaYEgoTW0G/kPMNd1ya5v7d2/bvef+Hm6YLHV/Muvh93nbzrnnfHZ2zvd87zmA4zjknwT92wJb8r9Z5Py7ZvhONRQIBOx2++Li4vz8/PT0tNFoNJvNbrebpmkMw+Li4vbt25eZmZmbm5uZmZmUlCQQCP6sWSAQMJlMo6OjOp1uYmLCaDSura0FAgEI4a+VMQyTSqVqtbq4uLiysvLw4cMkSW7ZNBctHo9Hp9Ndv359//79IpEoot8DAJDJZGVlZX19fV6vd9P2ozGjKGpgYODs2bNyuRwAEOkwb4QkyZqamrm5OQhhUC+AiyTSchw3NzfX3t7+8uVLh8MRVIphmEgkIghCKpUSBCEWizEMgxD6/X6n02m3271e76//MoqiRUVFjx8/zs3N3fh9BGZ+v7+/v//+/ftTU1PrHeA4rlAoUlNTs7Ozs7KyUlNTlUplXFycRCIRCAQYhnEc5/f73W73ly9fxsbGBgcH9Xq90+nc2C8A4MyZM69evQoehnDw+XyPHj1KTExcbys+Pr6ioqKrq2t8fNxutzMME7IRCKHT6RwYGLhw4ULQ3C8rKwuqHJYZRVGtra0ymYx3SkpKunbt2rt379xu96/zIxxcLteLFy9yc3NRFAUAaDSa/v7+iM1Yln327NmePXsQBBEKhRUVFcPDwzRNRyG0EQjh3NxcU1PT7du3379//+uQhzYzGAxpaWkIghAE0djYaLVaf9NpIyzLsiy7aVEIM5qmr169CgAQiUT37t3zeDw7qLU9IcwMBoNKpUIQpKKiwmaz7Y4TT4gdfXR01Gw2EwRRW1urUCjCjC87wnZmEMLJyUmWZZOTk7Va7W4p/SDEmPGBniRJqVS6Kz4/CWHGxzCfz0fT9K74/GQ7MxRFs7OzMQxbWVmZnZ3dNacfvW9ffOzYMZVK5XK5enp63G73NjWDVtbvm4XIHNPS0qqqqtra2l6/fq3Vauvq6iQSCV/EMIzD4TCZTCaTyWKxrK6u+nw+lmVFIpFIJJLL5SqVKj09Xa1WR5q9/SBkXFlaWiopKeFzvbt375pMpuXl5d7e3itXruTl5SUkJIjFYhQNHnsURSUSSUpKyo0bNywWSxTxLHQWxHHc5ORkXV3d2NgYhmE5OTkQwpmZGYqiUBSVyWSJiYl85kMQBIqiDMO43W6z2by0tORwODAMa2tra2hoiHTIQr8HAAC0Wu2DBw9qamqWlpb0ev36qGi12qqqqry8PKVSKZFIUBTlOA5C6PV6p6enu7u7dTodwzA2my1SrbDMGIYZHh5uaWkxm80oiu7du5emabvdDiE0GAyLi4tSqZRPXwEAEEIIIUVRLpeL32TT09NPnToVhVmIf9Pr9XZ3dz98+NBsNickJFy+fLm6utrr9ep0upGRkYWFBbvdTtM0wzB8lgsAAAAIBAKpVKpSqYqLiy9evJiTk/PrRPwtM5fL1dLS0tXVRdP0kSNHmpubjx8/LhQKEQThOO779+8Oh8Nut7vdbo/HEwgEOI7DMIzXksvl8fHxMpksCqcfbLU0PB5PY2OjWCwWCATnz59fWFiIYn39DpubBQKBjo4OgiBwHL906ZLZbN5lLW4rs6GhoeTkZABAeXm5yWTaZSeeTcxsNltZWRmCIBqNRq/X774TT7AZhLCnp0cikQiFwvb29q2S9F0g2Ozbt2+lpaUIghw6dOivTK91gpf0hw8f9Ho9iqLnzp1TKpVRLvidINhsaGhobW1NLpfzu/hfceIJNtPr9RDC5ORktVr9V4TWCTZbXl5GECQ2NjbKpGrnCDZjWRZBEJ/PFwgE/obPT4LN5HI5giBfv361WCx/qMvZ2dnOzs6FhYXIzA4ePAgAsFqtOp2O+wPXKzab7datWzdv3nzz5k2I9oOiyPPnz2NiYhAEycrKmpmZ2dkQRVFUc3OzSCRSKBRDQ0PbVw42MxqN+fn5CIKgKHr69OnPnz/vlJbX6+3o6JDL5TiONzQ0UBQVmRnLsp2dnfzCxDCspKREp9OFbGV7GIaZnZ2tr68nSRIAcOLECaPRGPKpTXb01dXV8vJyPswCAJRKZW1t7eDgoNVqDefIcx2WZZ1O59jYWFNT04EDB/h0vLi42GAwhPP45jntxMRETU2NwWDgPwIASJLMyMgoKCjIz8/XaDTx8fGxsbESiQTHcT5rZVnW7/fTNO3xeKxW6+LiosFgGB8fn56ettlsEEIcx0tLS1tbW/lFFnKtbG7GcdzIyEh9ff3Hjx+DKuA4HhMTQxAESZIEQQgEAhzHIYQsy9I0TVGU2+32er0URfF5Cv8USZLV1dV37tzhT+PCYqvBhBBOTU1VVlaKxeJw29oMoVBYVFTU29vr8/nCnwlcyDNHh8Px9OnTgoKCSP0AAFKp9OjRo0+ePDGbzVEcgYf1jm6xWN6+fdvX1zc+Pm6xWGia3vTCCwCA4zhJkmq1urCw8OTJk4WFhQqFIrqcJYI7FJ/PZzQaP336NDk5OT8/v7Ky4nK5AoGAQCCIiYlJSEhISUnJyMjIzs7WaDSJiYk4/lsXgZHdO+0m/+6d8P9mkfPvmv0HfL2v3IpRQCcAAAAASUVORK5CYII=|width=48,height=48)"
- },
- "preselect": false,
- "sortText": "00",
- "textEdit": {
- "range": {
- "start": {
- "line": 7,
- "character": 1
- },
- "end": {
- "line": 7,
- "character": 7
- }
- },
- "newText": "varepsilon"
- }
- }
- ]
-}
diff --git a/support/texlab/tests/it/snapshots/it__completion__latex__label.snap b/support/texlab/tests/it/snapshots/it__completion__latex__label.snap
deleted file mode 100644
index ffdfa17dd7..0000000000
--- a/support/texlab/tests/it/snapshots/it__completion__latex__label.snap
+++ /dev/null
@@ -1,137 +0,0 @@
----
-source: tests/it/completion.rs
-assertion_line: 699
-expression: "complete_and_resolve(&server, uri, 4, 5)?"
----
-{
- "isIncomplete": false,
- "items": [
- {
- "label": "eq:bar",
- "kind": 1,
- "detail": "Equation (2)",
- "preselect": false,
- "sortText": "00 eq:bar Equation (2)",
- "filterText": "eq:bar Equation (2)",
- "textEdit": {
- "range": {
- "start": {
- "line": 4,
- "character": 5
- },
- "end": {
- "line": 4,
- "character": 5
- }
- },
- "newText": "eq:bar"
- }
- },
- {
- "label": "eq:foo",
- "kind": 1,
- "detail": "Equation (1)",
- "preselect": false,
- "sortText": "01 eq:foo Equation (1)",
- "filterText": "eq:foo Equation (1)",
- "textEdit": {
- "range": {
- "start": {
- "line": 4,
- "character": 5
- },
- "end": {
- "line": 4,
- "character": 5
- }
- },
- "newText": "eq:foo"
- }
- },
- {
- "label": "fig:baz",
- "kind": 1,
- "detail": "Figure 1",
- "documentation": "Baz",
- "preselect": false,
- "sortText": "02 fig:baz Figure 1: Baz",
- "filterText": "fig:baz Figure 1: Baz",
- "textEdit": {
- "range": {
- "start": {
- "line": 4,
- "character": 5
- },
- "end": {
- "line": 4,
- "character": 5
- }
- },
- "newText": "fig:baz"
- }
- },
- {
- "label": "sec:bar",
- "kind": 1,
- "detail": "Section 2 (Bar)",
- "preselect": false,
- "sortText": "03 sec:bar Section 2 (Bar)",
- "filterText": "sec:bar Section 2 (Bar)",
- "textEdit": {
- "range": {
- "start": {
- "line": 4,
- "character": 5
- },
- "end": {
- "line": 4,
- "character": 5
- }
- },
- "newText": "sec:bar"
- }
- },
- {
- "label": "sec:foo",
- "kind": 1,
- "detail": "Section 1 (Foo)",
- "preselect": false,
- "sortText": "04 sec:foo Section 1 (Foo)",
- "filterText": "sec:foo Section 1 (Foo)",
- "textEdit": {
- "range": {
- "start": {
- "line": 4,
- "character": 5
- },
- "end": {
- "line": 4,
- "character": 5
- }
- },
- "newText": "sec:foo"
- }
- },
- {
- "label": "thm:foo",
- "kind": 1,
- "detail": "Lemma 1",
- "preselect": false,
- "sortText": "05 thm:foo Lemma 1",
- "filterText": "thm:foo Lemma 1",
- "textEdit": {
- "range": {
- "start": {
- "line": 4,
- "character": 5
- },
- "end": {
- "line": 4,
- "character": 5
- }
- },
- "newText": "thm:foo"
- }
- }
- ]
-}
diff --git a/support/texlab/tests/it/snapshots/it__completion__latex__multi_line_key.snap b/support/texlab/tests/it/snapshots/it__completion__latex__multi_line_key.snap
deleted file mode 100644
index a3258523bd..0000000000
--- a/support/texlab/tests/it/snapshots/it__completion__latex__multi_line_key.snap
+++ /dev/null
@@ -1,50 +0,0 @@
----
-source: tests/it/completion.rs
-assertion_line: 814
-expression: "complete_and_resolve(&server, uri, 0, 11)?"
----
-{
- "isIncomplete": false,
- "items": [
- {
- "label": "verbatim",
- "kind": 1,
- "detail": "built-in",
- "preselect": false,
- "sortText": "00",
- "textEdit": {
- "range": {
- "start": {
- "line": 0,
- "character": 7
- },
- "end": {
- "line": 0,
- "character": 11
- }
- },
- "newText": "verbatim"
- }
- },
- {
- "label": "verbatim*",
- "kind": 1,
- "detail": "built-in",
- "preselect": false,
- "sortText": "01",
- "textEdit": {
- "range": {
- "start": {
- "line": 0,
- "character": 7
- },
- "end": {
- "line": 0,
- "character": 11
- }
- },
- "newText": "verbatim*"
- }
- }
- ]
-}
diff --git a/support/texlab/tests/it/snapshots/it__completion__latex__package_command.snap b/support/texlab/tests/it/snapshots/it__completion__latex__package_command.snap
deleted file mode 100644
index 011038f894..0000000000
--- a/support/texlab/tests/it/snapshots/it__completion__latex__package_command.snap
+++ /dev/null
@@ -1,34 +0,0 @@
----
-source: tests/it/completion.rs
-assertion_line: 529
-expression: "complete_and_resolve(&server, uri, 3, 7)?"
----
-{
- "isIncomplete": false,
- "items": [
- {
- "label": "varDelta",
- "kind": 1,
- "detail": "amsmath.sty",
- "documentation": {
- "kind": "markdown",
- "value": "![varDelta](data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADoAAAA4CAIAAAAjEXx0AAAF60lEQVR4nO2ab0gTfxzHb0PvNjfERqXOqWyIjaRCUUzc0FUoJaWooEUQPSiIIaFIiaKGYE96IIlECyrBCltqjSwVI9AHJiJapmu1NGkYkXP/0bndnx4Y8u1st+/Nbf5+4Ovh3efzude+9952dxuHoijk/wN3pwXYsasbSnZ1/TE/P3/69GmxWHz9+nWv18uumQovFovl3LlzXC4XQZC0tLSlpSVW7WFdXa/Xe/fu3d7eXpIkEQQxmUxGo5HVhPDpUhQ1ODjY1ta2vr6+scXlck1OTrKeEh7m5uaOHDlCO3pZWZnb7YYfEibdlZWV8vJyLpfL4XBAXblcbjKZ4OeEIwwej6ejo+Ply5cKheLAgQPgrqWlpS9fvsCPCrkuRVH9/f3t7e0ymaytrS0vLw/cyzq+ITv/f5iZmUlLSxOJRFqtliCIzs7OyMhIUKCkpAQ+vqHV/fXrV3FxMYZhTU1NG07T09P79+8HdVNTU79//w45MIS6bre7oaEBRdHS0lKz2byx0WKxHD16FNQVCATDw8OQM0OlSxBEd3f3nj17Dh8+PDs7u7kdx/ErV66AuhwO5+bNm5BjQ6U7NTUll8v37dun0+lIkgR3dXV1RUREgMZnzpxZW1uDGRsS3Z8/f546dYrH47W2tno8HtreDx8+xMbGgropKSmLi4swk4Ovu7a2du3aNRRFKysrLRbL1gKr1ZqTk0OL79DQEMzwIOsSBNHV1RUTE5ORkWEwGHzVqNVqWnxbWlpomQmH7sTEREpKSlxc3MDAAMPhHz16RPv0LSoqWl1d9Ts/mLo/fvwoKCjg8/m3bt3aGlmQmZmZuLg4UFcmky0sLPg9RNB0V1dXq6urURS9cOGCzWZjLrZarbm5uaBuVFTU69ev/R4lOLoEQTx48CA6Ojo7O3t+fh6mvqqqihbfGzdu+I1vcHTHxsakUqlYLH7z5g3MO4aiqCdPnqAoChqfPHnSb3yDoGsymVQqlUAgaG9v93q9kF2zs7Px8fGgrlQq9XtmtqvrcrnUajWKopcuXXI4HPCNNptNoVCAunw+v7+/n7lrW7o4jms0GqFQqFAoIL+WNiEI4urVq7T4NjY2MmdpW7qjo6NJSUlJSUkjIyMBtHd3d9PiW1hY6HK5GFoC111cXFQqlUKhUKPR4DgewIS5uTlafJOTk41GI0NLgLpOp/Py5csoiqrVaub1YMButyuVSlCXx+PpdDqGlkB0cRzv6OgQCAQqlYrVfSwNgiCqq6uRv6mvr2eIL2tdkiTfvn0rkUhkMtnY2FjArhtotVpafE+cOOF0On3Vs9ZdWFjIycmJjo5++PAhQRDbs6X0en1CQgKom5iY+PnzZ1/17HQdDsfFixcxDKupqYG5gPKL3W7Pz88HdTEMe/78ua96Fs8ZcBy/f//+06dP8/Pza2tr+Xw+fK8vhEJhZmYmuGV9fX18fJzy9YsJ5DKQJDk0NBQfH5+amjo5Obn9dd2kp6cHwzBQ6dixY77iC6trNBqzsrJiYmIeP368/ciCfPr0SSKRgLoSicTXnQiUrs1mO3/+PIZhdXV1kLes8DgcDpVKBepiGNbT0/PPYv/Z9Xq9Go2mt7e3oKCgpqaGx+NB5hISX/HdeGRNh/mlkyT56tWr2NjYgwcPvn//PrjruklfXx8tvnl5eXa7fWulH12DwZCeni4SiZ49ewZ53R0ABoMhMTER1BWLxXq9fmslk67FYqmoqODxeM3NzayecbPF6XQeP34c1EVRVKvVbq30mV2Px3Pnzh2dTldUVFRVVUU7WcElKioqKysLfLDu8XjevXv3j/j+8+WSJPnixYu9e/ceOnTo48ePROjp6+ujvYmVSqXVaqWJRdD1EQRBEL1e39jYaDabExISbt++TftBIRQsLy9Tf3+Tff369du3b+np6X/VbV1as9lcWloaBkVmUBS9d+8ezY2u63a7m5qaaBd1O8XZs2f96HZ2dopEop32/INUKvWjK5fLdzwGG3A4HIlEQtPjUL4u1f6T7P6fIZTs6oaS3/oaUpPRFnIuAAAAAElFTkSuQmCC|width=48,height=48)"
- },
- "preselect": false,
- "sortText": "00",
- "textEdit": {
- "range": {
- "start": {
- "line": 3,
- "character": 1
- },
- "end": {
- "line": 3,
- "character": 7
- }
- },
- "newText": "varDelta"
- }
- }
- ]
-}
diff --git a/support/texlab/tests/it/snapshots/it__completion__latex__package_environment.snap b/support/texlab/tests/it/snapshots/it__completion__latex__package_environment.snap
deleted file mode 100644
index 048cff4986..0000000000
--- a/support/texlab/tests/it/snapshots/it__completion__latex__package_environment.snap
+++ /dev/null
@@ -1,150 +0,0 @@
----
-source: tests/it/completion.rs
-assertion_line: 552
-expression: "complete_and_resolve(&server, uri, 5, 6)?"
----
-{
- "isIncomplete": false,
- "items": [
- {
- "label": "align",
- "kind": 1,
- "detail": "amsmath.sty",
- "preselect": false,
- "sortText": "00",
- "textEdit": {
- "range": {
- "start": {
- "line": 5,
- "character": 5
- },
- "end": {
- "line": 5,
- "character": 9
- }
- },
- "newText": "align"
- }
- },
- {
- "label": "align*",
- "kind": 1,
- "detail": "amsmath.sty",
- "preselect": false,
- "sortText": "01",
- "textEdit": {
- "range": {
- "start": {
- "line": 5,
- "character": 5
- },
- "end": {
- "line": 5,
- "character": 9
- }
- },
- "newText": "align*"
- }
- },
- {
- "label": "alignat",
- "kind": 1,
- "detail": "amsmath.sty",
- "preselect": false,
- "sortText": "02",
- "textEdit": {
- "range": {
- "start": {
- "line": 5,
- "character": 5
- },
- "end": {
- "line": 5,
- "character": 9
- }
- },
- "newText": "alignat"
- }
- },
- {
- "label": "alignat*",
- "kind": 1,
- "detail": "amsmath.sty",
- "preselect": false,
- "sortText": "03",
- "textEdit": {
- "range": {
- "start": {
- "line": 5,
- "character": 5
- },
- "end": {
- "line": 5,
- "character": 9
- }
- },
- "newText": "alignat*"
- }
- },
- {
- "label": "aligned",
- "kind": 1,
- "detail": "amsmath.sty",
- "preselect": false,
- "sortText": "04",
- "textEdit": {
- "range": {
- "start": {
- "line": 5,
- "character": 5
- },
- "end": {
- "line": 5,
- "character": 9
- }
- },
- "newText": "aligned"
- }
- },
- {
- "label": "alignedat",
- "kind": 1,
- "detail": "amsmath.sty",
- "preselect": false,
- "sortText": "05",
- "textEdit": {
- "range": {
- "start": {
- "line": 5,
- "character": 5
- },
- "end": {
- "line": 5,
- "character": 9
- }
- },
- "newText": "alignedat"
- }
- },
- {
- "label": "flalign",
- "kind": 1,
- "detail": "amsmath.sty",
- "preselect": false,
- "sortText": "06",
- "textEdit": {
- "range": {
- "start": {
- "line": 5,
- "character": 5
- },
- "end": {
- "line": 5,
- "character": 9
- }
- },
- "newText": "flalign"
- }
- }
- ]
-}
diff --git a/support/texlab/tests/it/snapshots/it__completion__latex__package_import.snap b/support/texlab/tests/it/snapshots/it__completion__latex__package_import.snap
deleted file mode 100644
index 4b45166b80..0000000000
--- a/support/texlab/tests/it/snapshots/it__completion__latex__package_import.snap
+++ /dev/null
@@ -1,102 +0,0 @@
----
-source: tests/it/completion.rs
-assertion_line: 586
-expression: "complete_and_resolve(&server, uri, 1, 15)?"
----
-{
- "isIncomplete": false,
- "items": [
- {
- "label": "amsmath",
- "kind": 1,
- "documentation": {
- "kind": "plaintext",
- "value": "The package provides the principal packages in the AMS-LaTeX distribution. It adapts for use in LaTeX most of the mathematical features found in AMS-TeX; it is highly recommended as an adjunct to serious mathematical typesetting in LaTeX. When amsmath is loaded, AMS-LaTeX packages amsbsy (for bold symbols), amsopn (for operator names) and amstext (for text embedded in mathematics) are also loaded. amsmath is part of the LaTeX required distribution; however, several contributed packages add still further to its appeal; examples are empheq, which provides functions for decorating and highlighting mathematics, and ntheorem, for specifying theorem (and similar) definitions."
- },
- "preselect": false,
- "sortText": "00",
- "textEdit": {
- "range": {
- "start": {
- "line": 1,
- "character": 12
- },
- "end": {
- "line": 1,
- "character": 19
- }
- },
- "newText": "amsmath"
- }
- },
- {
- "label": "lwarp-amsmath",
- "kind": 1,
- "documentation": {
- "kind": "plaintext",
- "value": "This package converts LaTeX to HTML by using LaTeX to process the user's document and generate HTML tags. External utility programs are only used for the final conversion of text and images. Math may be represented by SVG files or MathJax. Hundreds of LaTeX packages are supported, and their load order is automatically verified. Documents may be produced by LaTeX, LuaLaTeX, XeLaTeX, and by several CJK engines, classes, and packages. A texlua script automates compilation, index, glossary, and batch image processing, and also supports latexmk. Configuration is semi-automatic at the first manual compile. Support files are self-generated. Print and HTML versions of each document may coexist. Assistance is provided for HTML import into EPUB conversion software and word processors. Requirements include the commonly-available Poppler utilities, and Perl. Detailed installation instructions are included for each of the major operating systems and TeX distributions. A quick-start tutorial is provided."
- },
- "preselect": false,
- "sortText": "01",
- "textEdit": {
- "range": {
- "start": {
- "line": 1,
- "character": 12
- },
- "end": {
- "line": 1,
- "character": 19
- }
- },
- "newText": "lwarp-amsmath"
- }
- },
- {
- "label": "simurgh-amsmath",
- "kind": 1,
- "documentation": {
- "kind": "plaintext",
- "value": "The package provides an automatic and unified interface for Parsi typesetting in LaTeX, using the LuaTeX engine. The project to produce this system is dedicated to Ferdowsi The Great."
- },
- "preselect": false,
- "sortText": "02",
- "textEdit": {
- "range": {
- "start": {
- "line": 1,
- "character": 12
- },
- "end": {
- "line": 1,
- "character": 19
- }
- },
- "newText": "simurgh-amsmath"
- }
- },
- {
- "label": "onlyamsmath",
- "kind": 1,
- "documentation": {
- "kind": "plaintext",
- "value": "This package inhibits the usage of plain TeX and (on demand) of standard LaTeX mathematics environments. This is useful for class writers who want to encourage their users to use the environments provided by the amsmath package."
- },
- "preselect": false,
- "sortText": "03",
- "textEdit": {
- "range": {
- "start": {
- "line": 1,
- "character": 12
- },
- "end": {
- "line": 1,
- "character": 19
- }
- },
- "newText": "onlyamsmath"
- }
- }
- ]
-}
diff --git a/support/texlab/tests/it/snapshots/it__completion__latex__pgf_library.snap b/support/texlab/tests/it/snapshots/it__completion__latex__pgf_library.snap
deleted file mode 100644
index 23713c6a9e..0000000000
--- a/support/texlab/tests/it/snapshots/it__completion__latex__pgf_library.snap
+++ /dev/null
@@ -1,143 +0,0 @@
----
-source: tests/it/completion.rs
-assertion_line: 753
-expression: "complete_and_resolve(&server, uri, 1, 15)?"
----
-{
- "isIncomplete": false,
- "items": [
- {
- "label": "arrows",
- "kind": 1,
- "preselect": false,
- "sortText": "00",
- "textEdit": {
- "range": {
- "start": {
- "line": 1,
- "character": 15
- },
- "end": {
- "line": 1,
- "character": 15
- }
- },
- "newText": "arrows"
- }
- },
- {
- "label": "arrows.meta",
- "kind": 1,
- "preselect": false,
- "sortText": "01",
- "textEdit": {
- "range": {
- "start": {
- "line": 1,
- "character": 15
- },
- "end": {
- "line": 1,
- "character": 15
- }
- },
- "newText": "arrows.meta"
- }
- },
- {
- "label": "arrows.spaced",
- "kind": 1,
- "preselect": false,
- "sortText": "02",
- "textEdit": {
- "range": {
- "start": {
- "line": 1,
- "character": 15
- },
- "end": {
- "line": 1,
- "character": 15
- }
- },
- "newText": "arrows.spaced"
- }
- },
- {
- "label": "curvilinear",
- "kind": 1,
- "preselect": false,
- "sortText": "03",
- "textEdit": {
- "range": {
- "start": {
- "line": 1,
- "character": 15
- },
- "end": {
- "line": 1,
- "character": 15
- }
- },
- "newText": "curvilinear"
- }
- },
- {
- "label": "datavisualization.barcharts",
- "kind": 1,
- "preselect": false,
- "sortText": "04",
- "textEdit": {
- "range": {
- "start": {
- "line": 1,
- "character": 15
- },
- "end": {
- "line": 1,
- "character": 15
- }
- },
- "newText": "datavisualization.barcharts"
- }
- },
- {
- "label": "datavisualization.formats.functions",
- "kind": 1,
- "preselect": false,
- "sortText": "05",
- "textEdit": {
- "range": {
- "start": {
- "line": 1,
- "character": 15
- },
- "end": {
- "line": 1,
- "character": 15
- }
- },
- "newText": "datavisualization.formats.functions"
- }
- },
- {
- "label": "datavisualization.polar",
- "kind": 1,
- "preselect": false,
- "sortText": "06",
- "textEdit": {
- "range": {
- "start": {
- "line": 1,
- "character": 15
- },
- "end": {
- "line": 1,
- "character": 15
- }
- },
- "newText": "datavisualization.polar"
- }
- }
- ]
-}
diff --git a/support/texlab/tests/it/snapshots/it__completion__latex__preselect_environment.snap b/support/texlab/tests/it/snapshots/it__completion__latex__preselect_environment.snap
deleted file mode 100644
index 29d6f5bac6..0000000000
--- a/support/texlab/tests/it/snapshots/it__completion__latex__preselect_environment.snap
+++ /dev/null
@@ -1,150 +0,0 @@
----
-source: tests/it/completion.rs
-assertion_line: 716
-expression: "complete_and_resolve(&server, uri, 1, 5)?"
----
-{
- "isIncomplete": false,
- "items": [
- {
- "label": "document",
- "kind": 1,
- "detail": "built-in",
- "preselect": true,
- "sortText": "00",
- "textEdit": {
- "range": {
- "start": {
- "line": 1,
- "character": 5
- },
- "end": {
- "line": 1,
- "character": 5
- }
- },
- "newText": "document"
- }
- },
- {
- "label": "abstract",
- "kind": 1,
- "detail": "built-in",
- "preselect": false,
- "sortText": "01",
- "textEdit": {
- "range": {
- "start": {
- "line": 1,
- "character": 5
- },
- "end": {
- "line": 1,
- "character": 5
- }
- },
- "newText": "abstract"
- }
- },
- {
- "label": "array",
- "kind": 1,
- "detail": "built-in",
- "preselect": false,
- "sortText": "02",
- "textEdit": {
- "range": {
- "start": {
- "line": 1,
- "character": 5
- },
- "end": {
- "line": 1,
- "character": 5
- }
- },
- "newText": "array"
- }
- },
- {
- "label": "center",
- "kind": 1,
- "detail": "built-in",
- "preselect": false,
- "sortText": "03",
- "textEdit": {
- "range": {
- "start": {
- "line": 1,
- "character": 5
- },
- "end": {
- "line": 1,
- "character": 5
- }
- },
- "newText": "center"
- }
- },
- {
- "label": "csname",
- "kind": 1,
- "detail": "built-in",
- "preselect": false,
- "sortText": "04",
- "textEdit": {
- "range": {
- "start": {
- "line": 1,
- "character": 5
- },
- "end": {
- "line": 1,
- "character": 5
- }
- },
- "newText": "csname"
- }
- },
- {
- "label": "description",
- "kind": 1,
- "detail": "built-in",
- "preselect": false,
- "sortText": "05",
- "textEdit": {
- "range": {
- "start": {
- "line": 1,
- "character": 5
- },
- "end": {
- "line": 1,
- "character": 5
- }
- },
- "newText": "description"
- }
- },
- {
- "label": "displaymath",
- "kind": 1,
- "detail": "built-in",
- "preselect": false,
- "sortText": "06",
- "textEdit": {
- "range": {
- "start": {
- "line": 1,
- "character": 5
- },
- "end": {
- "line": 1,
- "character": 5
- }
- },
- "newText": "displaymath"
- }
- }
- ]
-}
diff --git a/support/texlab/tests/it/snapshots/it__completion__latex__theorem_environment.snap b/support/texlab/tests/it/snapshots/it__completion__latex__theorem_environment.snap
deleted file mode 100644
index 766d6fe526..0000000000
--- a/support/texlab/tests/it/snapshots/it__completion__latex__theorem_environment.snap
+++ /dev/null
@@ -1,130 +0,0 @@
----
-source: tests/it/completion.rs
-assertion_line: 735
-expression: "complete_and_resolve(&server, uri, 3, 8)?"
----
-{
- "isIncomplete": false,
- "items": [
- {
- "label": "figure",
- "kind": 1,
- "detail": "built-in",
- "preselect": false,
- "sortText": "00",
- "textEdit": {
- "range": {
- "start": {
- "line": 3,
- "character": 7
- },
- "end": {
- "line": 3,
- "character": 8
- }
- },
- "newText": "figure"
- }
- },
- {
- "label": "filecontents",
- "kind": 1,
- "detail": "built-in",
- "preselect": false,
- "sortText": "01",
- "textEdit": {
- "range": {
- "start": {
- "line": 3,
- "character": 7
- },
- "end": {
- "line": 3,
- "character": 8
- }
- },
- "newText": "filecontents"
- }
- },
- {
- "label": "flushleft",
- "kind": 1,
- "detail": "built-in",
- "preselect": false,
- "sortText": "02",
- "textEdit": {
- "range": {
- "start": {
- "line": 3,
- "character": 7
- },
- "end": {
- "line": 3,
- "character": 8
- }
- },
- "newText": "flushleft"
- }
- },
- {
- "label": "flushright",
- "kind": 1,
- "detail": "built-in",
- "preselect": false,
- "sortText": "03",
- "textEdit": {
- "range": {
- "start": {
- "line": 3,
- "character": 7
- },
- "end": {
- "line": 3,
- "character": 8
- }
- },
- "newText": "flushright"
- }
- },
- {
- "label": "foo",
- "kind": 1,
- "detail": "user-defined",
- "preselect": false,
- "sortText": "04",
- "textEdit": {
- "range": {
- "start": {
- "line": 3,
- "character": 7
- },
- "end": {
- "line": 3,
- "character": 8
- }
- },
- "newText": "foo"
- }
- },
- {
- "label": "proof",
- "kind": 1,
- "detail": "amsthm.sty",
- "preselect": false,
- "sortText": "05",
- "textEdit": {
- "range": {
- "start": {
- "line": 3,
- "character": 7
- },
- "end": {
- "line": 3,
- "character": 8
- }
- },
- "newText": "proof"
- }
- }
- ]
-}
diff --git a/support/texlab/tests/it/snapshots/it__completion__latex__user_command.snap b/support/texlab/tests/it/snapshots/it__completion__latex__user_command.snap
deleted file mode 100644
index 09efd12c52..0000000000
--- a/support/texlab/tests/it/snapshots/it__completion__latex__user_command.snap
+++ /dev/null
@@ -1,30 +0,0 @@
----
-source: tests/it/completion.rs
-assertion_line: 773
-expression: "complete_and_resolve(&server, uri, 1, 3)?"
----
-{
- "isIncomplete": false,
- "items": [
- {
- "label": "foobar",
- "kind": 1,
- "detail": "user-defined",
- "preselect": false,
- "sortText": "00",
- "textEdit": {
- "range": {
- "start": {
- "line": 1,
- "character": 1
- },
- "end": {
- "line": 1,
- "character": 6
- }
- },
- "newText": "foobar"
- }
- }
- ]
-}
diff --git a/support/texlab/tests/it/snapshots/it__completion__latex__user_environment.snap b/support/texlab/tests/it/snapshots/it__completion__latex__user_environment.snap
deleted file mode 100644
index 8e3e866d5f..0000000000
--- a/support/texlab/tests/it/snapshots/it__completion__latex__user_environment.snap
+++ /dev/null
@@ -1,50 +0,0 @@
----
-source: tests/it/completion.rs
-assertion_line: 793
-expression: "complete_and_resolve(&server, uri, 4, 8)?"
----
-{
- "isIncomplete": false,
- "items": [
- {
- "label": "foo",
- "kind": 1,
- "detail": "user-defined",
- "preselect": false,
- "sortText": "00",
- "textEdit": {
- "range": {
- "start": {
- "line": 4,
- "character": 7
- },
- "end": {
- "line": 4,
- "character": 9
- }
- },
- "newText": "foo"
- }
- },
- {
- "label": "filecontents",
- "kind": 1,
- "detail": "built-in",
- "preselect": false,
- "sortText": "01",
- "textEdit": {
- "range": {
- "start": {
- "line": 4,
- "character": 7
- },
- "end": {
- "line": 4,
- "character": 9
- }
- },
- "newText": "filecontents"
- }
- }
- ]
-}
diff --git a/support/texlab/tests/it/snapshots/it__hover__empty_bibtex_document.snap b/support/texlab/tests/it/snapshots/it__hover__empty_bibtex_document.snap
deleted file mode 100644
index 0b36355e00..0000000000
--- a/support/texlab/tests/it/snapshots/it__hover__empty_bibtex_document.snap
+++ /dev/null
@@ -1,6 +0,0 @@
----
-source: tests/it/hover.rs
-assertion_line: 12
-expression: "server.hover(uri, 0, 0)?"
----
-null
diff --git a/support/texlab/tests/it/snapshots/it__hover__empty_labtex_document.snap b/support/texlab/tests/it/snapshots/it__hover__empty_labtex_document.snap
deleted file mode 100644
index c653b05832..0000000000
--- a/support/texlab/tests/it/snapshots/it__hover__empty_labtex_document.snap
+++ /dev/null
@@ -1,6 +0,0 @@
----
-source: tests/it/hover.rs
-assertion_line: 21
-expression: "server.hover(uri, 0, 0)?"
----
-null
diff --git a/support/texlab/tests/it/snapshots/it__hover__label_theorem_child_file.snap b/support/texlab/tests/it/snapshots/it__hover__label_theorem_child_file.snap
deleted file mode 100644
index 6bc9b28a75..0000000000
--- a/support/texlab/tests/it/snapshots/it__hover__label_theorem_child_file.snap
+++ /dev/null
@@ -1,21 +0,0 @@
----
-source: tests/it/hover.rs
-assertion_line: 51
-expression: "server.hover(uri, 3, 8)?"
----
-{
- "contents": {
- "kind": "plaintext",
- "value": "Lemma"
- },
- "range": {
- "start": {
- "line": 3,
- "character": 5
- },
- "end": {
- "line": 3,
- "character": 12
- }
- }
-}
diff --git a/support/texlab/tests/it/snapshots/it__hover__label_theorem_child_file_mumber.snap b/support/texlab/tests/it/snapshots/it__hover__label_theorem_child_file_mumber.snap
deleted file mode 100644
index b7515e7d43..0000000000
--- a/support/texlab/tests/it/snapshots/it__hover__label_theorem_child_file_mumber.snap
+++ /dev/null
@@ -1,21 +0,0 @@
----
-source: tests/it/hover.rs
-assertion_line: 87
-expression: "server.hover(uri, 3, 8)?"
----
-{
- "contents": {
- "kind": "plaintext",
- "value": "Lemma 1 (Foo)"
- },
- "range": {
- "start": {
- "line": 3,
- "character": 5
- },
- "end": {
- "line": 3,
- "character": 12
- }
- }
-}
diff --git a/support/texlab/tests/it/snapshots/it__issues__510_completion_with_unmatched_braces.snap b/support/texlab/tests/it/snapshots/it__issues__510_completion_with_unmatched_braces.snap
deleted file mode 100644
index 3895881165..0000000000
--- a/support/texlab/tests/it/snapshots/it__issues__510_completion_with_unmatched_braces.snap
+++ /dev/null
@@ -1,57 +0,0 @@
----
-source: tests/it/issues.rs
-assertion_line: 58
-expression: "server.complete(uri, 1, 7)?"
----
-CompletionList {
- is_incomplete: false,
- items: [
- CompletionItem {
- label: "eq:foo",
- kind: Some(
- Text,
- ),
- detail: None,
- documentation: None,
- deprecated: None,
- preselect: Some(
- false,
- ),
- sort_text: Some(
- "00 eq:foo",
- ),
- filter_text: Some(
- "eq:foo",
- ),
- insert_text: None,
- insert_text_format: None,
- insert_text_mode: None,
- text_edit: Some(
- Edit(
- TextEdit {
- range: Range {
- start: Position {
- line: 1,
- character: 5,
- },
- end: Position {
- line: 1,
- character: 7,
- },
- },
- new_text: "eq:foo",
- },
- ),
- ),
- additional_text_edits: None,
- command: None,
- commit_characters: None,
- data: Some(
- String(
- "label",
- ),
- ),
- tags: None,
- },
- ],
-}
diff --git a/support/texlab/tests/it/workspace_symbol.rs b/support/texlab/tests/it/workspace_symbol.rs
deleted file mode 100644
index 4083b32933..0000000000
--- a/support/texlab/tests/it/workspace_symbol.rs
+++ /dev/null
@@ -1,119 +0,0 @@
-use anyhow::Result;
-use insta::assert_json_snapshot;
-use lsp_types::{ClientCapabilities, SymbolInformation, Url};
-
-use crate::common::ServerTester;
-
-fn run(query: &str) -> Result<Vec<SymbolInformation>> {
- let server = ServerTester::launch_new_instance()?;
- server.initialize(ClientCapabilities::default(), None)?;
- let uri = Url::parse("http://www.example.com/main.tex")?;
- server.open_memory(
- uri,
- r#"
- \documentclass{article}
- \usepackage{caption}
- \usepackage{amsmath}
- \usepackage{amsthm}
-
- \begin{document}
-
- \section{Foo}\label{sec:foo}
-
- \begin{equation}\label{eq:foo}
- Foo
- \end{equation}
-
- \section{Bar}\label{sec:bar}
-
- \begin{figure}
- Bar
- \caption{Bar}
- \label{fig:bar}
- \end{figure}
-
- \section{Baz}\label{sec:baz}
-
- \begin{enumerate}
- \item\label{itm:foo} Foo
- \item\label{itm:bar} Bar
- \item\label{itm:baz} Baz
- \end{enumerate}
-
- \section{Qux}\label{sec:qux}
-
- \newtheorem{lemma}{Lemma}
-
- \begin{lemma}[Qux]\label{thm:qux}
- Qux
- \end{lemma}
-
- \end{document}
- "#,
- "latex",
- )?;
- server.open_memory(
- Url::parse("http://www.example.com/main.aux")?,
- r#"
- \relax
- \@writefile{lof}{\contentsline {figure}{\numberline {1}{\ignorespaces Bar\relax }}{1}\protected@file@percent }
- \providecommand*\caption@xref[2]{\@setref\relax\@undefined{#1}}
- \newlabel{fig:bar}{{1}{1}}
- \@writefile{toc}{\contentsline {section}{\numberline {1}Foo}{1}\protected@file@percent }
- \newlabel{sec:foo}{{1}{1}}
- \newlabel{eq:foo}{{1}{1}}
- \@writefile{toc}{\contentsline {section}{\numberline {2}Bar}{1}\protected@file@percent }
- \newlabel{sec:bar}{{2}{1}}
- \@writefile{toc}{\contentsline {section}{\numberline {3}Baz}{1}\protected@file@percent }
- \newlabel{sec:baz}{{3}{1}}
- \newlabel{itm:foo}{{1}{1}}
- \newlabel{itm:bar}{{2}{1}}
- \newlabel{itm:baz}{{3}{1}}
- \@writefile{toc}{\contentsline {section}{\numberline {4}Qux}{1}\protected@file@percent }
- \newlabel{sec:qux}{{4}{1}}
- \newlabel{thm:qux}{{1}{1}}
- "#,
- "latex",
- )?;
- server.open_memory(
- Url::parse("http://www.example.com/main.bib")?,
- r#"
- @article{foo,}
-
- @string{bar = "bar"}
- "#,
- "bibtex",
- )?;
-
- server.find_workspace_symbols(query)
-}
-
-#[test]
-fn test_filter_type_section() -> Result<()> {
- assert_json_snapshot!(run("section")?);
- Ok(())
-}
-
-#[test]
-fn test_filter_type_figure() -> Result<()> {
- assert_json_snapshot!(run("figure")?);
- Ok(())
-}
-
-#[test]
-fn test_filter_type_item() -> Result<()> {
- assert_json_snapshot!(run("item")?);
- Ok(())
-}
-
-#[test]
-fn test_filter_type_math() -> Result<()> {
- assert_json_snapshot!(run("math")?);
- Ok(())
-}
-
-#[test]
-fn test_filter_bibtex() -> Result<()> {
- assert_json_snapshot!(run("bibtex")?);
- Ok(())
-}
diff --git a/support/texlab/texlab.pdf b/support/texlab/texlab.pdf
index 4c9134ec2c..68e68c312d 100644
--- a/support/texlab/texlab.pdf
+++ b/support/texlab/texlab.pdf
Binary files differ
diff --git a/support/texlab/texlab.tex b/support/texlab/texlab.tex
index 7faff8b122..632325bbc5 100644
--- a/support/texlab/texlab.tex
+++ b/support/texlab/texlab.tex
@@ -72,7 +72,7 @@ There are various ways to install TexLab:
\subsection{Options}
\begin{itemize}
- \item \texttt{--log-file <FILE>} WRite the logging output to \texttt{FILE}
+ \item \texttt{--log-file <FILE>} Write the logging output to \texttt{FILE}
\end{itemize}
\end{document} \ No newline at end of file