Coverage for src/debputy/lsp/lsp_debian_tests_control.py: 70%
78 statements
« prev ^ index » next coverage.py v7.6.0, created at 2025-01-27 13:59 +0000
« prev ^ index » next coverage.py v7.6.0, created at 2025-01-27 13:59 +0000
1import re
2from typing import (
3 Union,
4 Sequence,
5 Tuple,
6 Optional,
7 List,
8 Dict,
9)
11from debputy.linting.lint_util import LintState
12from debputy.lsp.debputy_ls import DebputyLanguageServer
13from debputy.lsp.lsp_debian_control_reference_data import (
14 Deb822KnownField,
15 DTestsCtrlFileMetadata,
16 StanzaMetadata,
17)
18from debputy.lsp.lsp_features import (
19 lint_diagnostics,
20 lsp_completer,
21 lsp_hover,
22 lsp_standard_handler,
23 lsp_folding_ranges,
24 lsp_semantic_tokens_full,
25 lsp_will_save_wait_until,
26 lsp_format_document,
27 SecondaryLanguage,
28 LanguageDispatchRule,
29)
30from debputy.lsp.lsp_generic_deb822 import (
31 deb822_completer,
32 deb822_hover,
33 deb822_folding_ranges,
34 deb822_semantic_tokens_full,
35 deb822_token_iter,
36 deb822_format_file,
37)
38from debputy.lsp.quickfixes import (
39 propose_correct_text_quick_fix,
40)
41from debputy.lsp.vendoring._deb822_repro import (
42 Deb822FileElement,
43 Deb822ParagraphElement,
44)
45from debputy.lsp.vendoring._deb822_repro.parsing import (
46 Deb822KeyValuePairElement,
47)
48from debputy.lsprotocol.types import (
49 Range,
50 CompletionItem,
51 CompletionList,
52 CompletionParams,
53 DiagnosticRelatedInformation,
54 Location,
55 HoverParams,
56 Hover,
57 TEXT_DOCUMENT_CODE_ACTION,
58 SemanticTokens,
59 SemanticTokensParams,
60 FoldingRangeParams,
61 FoldingRange,
62 WillSaveTextDocumentParams,
63 TextEdit,
64 DocumentFormattingParams,
65)
66from debputy.util import detect_possible_typo
68try:
69 from debputy.lsp.vendoring._deb822_repro.locatable import (
70 Position as TEPosition,
71 Range as TERange,
72 START_POSITION,
73 )
75 from pygls.server import LanguageServer
76 from pygls.workspace import TextDocument
77except ImportError:
78 pass
81_CONTAINS_SPACE_OR_COLON = re.compile(r"[\s:]")
82_DISPATCH_RULE = LanguageDispatchRule.new_rule(
83 "debian/tests/control",
84 "debian/tests/control",
85 [
86 # emacs's name - from elpa-dpkg-dev-el (>> 37.11)
87 SecondaryLanguage("debian-autopkgtest-control-mode"),
88 # Likely to be vim's name if it had support
89 SecondaryLanguage("debtestscontrol"),
90 ],
91)
93_DTESTS_CTRL_FILE_METADATA = DTestsCtrlFileMetadata()
95lsp_standard_handler(_DISPATCH_RULE, TEXT_DOCUMENT_CODE_ACTION)
98@lsp_hover(_DISPATCH_RULE)
99def debian_tests_control_hover(
100 ls: "DebputyLanguageServer",
101 params: HoverParams,
102) -> Optional[Hover]:
103 return deb822_hover(ls, params, _DTESTS_CTRL_FILE_METADATA)
106@lsp_completer(_DISPATCH_RULE)
107def debian_tests_control_completions(
108 ls: "DebputyLanguageServer",
109 params: CompletionParams,
110) -> Optional[Union[CompletionList, Sequence[CompletionItem]]]:
111 return deb822_completer(ls, params, _DTESTS_CTRL_FILE_METADATA)
114@lsp_folding_ranges(_DISPATCH_RULE)
115def debian_tests_control_folding_ranges(
116 ls: "DebputyLanguageServer",
117 params: FoldingRangeParams,
118) -> Optional[Sequence[FoldingRange]]:
119 return deb822_folding_ranges(ls, params, _DTESTS_CTRL_FILE_METADATA)
122def _scan_for_syntax_errors_and_token_level_diagnostics(
123 deb822_file: Deb822FileElement,
124 lint_state: LintState,
125) -> int:
126 first_error = len(lint_state.lines) + 1
127 spell_checker = lint_state.spellchecker()
128 for (
129 token,
130 start_line,
131 start_offset,
132 end_line,
133 end_offset,
134 ) in deb822_token_iter(deb822_file.iter_tokens()):
135 if token.is_error: 135 ↛ 136line 135 didn't jump to line 136 because the condition on line 135 was never true
136 first_error = min(first_error, start_line)
137 start_pos = TEPosition(
138 start_line,
139 start_offset,
140 )
141 end_pos = TEPosition(
142 end_line,
143 end_offset,
144 )
145 token_range = TERange.between(start_pos, end_pos)
146 lint_state.emit_diagnostic(
147 token_range,
148 "Syntax error",
149 "error",
150 "debputy",
151 )
152 elif token.is_comment: 152 ↛ 153line 152 didn't jump to line 153 because the condition on line 152 was never true
153 for word, col_pos, end_col_pos in spell_checker.iter_words(token.text):
154 corrections = spell_checker.provide_corrections_for(word)
155 if not corrections:
156 continue
157 start_pos = TEPosition(
158 start_line,
159 col_pos,
160 )
161 end_pos = TEPosition(
162 start_line,
163 end_col_pos,
164 )
165 word_range = TERange.between(start_pos, end_pos)
166 lint_state.emit_diagnostic(
167 word_range,
168 f'Spelling "{word}"',
169 "spelling",
170 "debputy",
171 quickfixes=[propose_correct_text_quick_fix(c) for c in corrections],
172 enable_non_interactive_auto_fix=False,
173 )
174 return first_error
177@lint_diagnostics(_DISPATCH_RULE)
178def _lint_debian_tests_control(lint_state: LintState) -> None:
179 doc_reference = lint_state.doc_uri
180 deb822_file = lint_state.parsed_deb822_file_content
182 first_error = _scan_for_syntax_errors_and_token_level_diagnostics(
183 deb822_file,
184 lint_state,
185 )
187 paragraphs = list(deb822_file)
189 for paragraph_no, paragraph in enumerate(paragraphs, start=1):
190 paragraph_pos = paragraph.position_in_file()
191 if paragraph_pos.line_position >= first_error: 191 ↛ 192line 191 didn't jump to line 192 because the condition on line 191 was never true
192 break
193 stanza_metadata = _DTESTS_CTRL_FILE_METADATA.classify_stanza(
194 paragraph,
195 paragraph_no,
196 )
197 stanza_metadata.stanza_diagnostics(
198 deb822_file,
199 paragraph,
200 paragraph_pos,
201 doc_reference,
202 lint_state,
203 )
206@lsp_will_save_wait_until(_DISPATCH_RULE)
207def _debian_tests_control_on_save_formatting(
208 ls: "DebputyLanguageServer",
209 params: WillSaveTextDocumentParams,
210) -> Optional[Sequence[TextEdit]]:
211 doc = ls.workspace.get_text_document(params.text_document.uri)
212 lint_state = ls.lint_state(doc)
213 return deb822_format_file(lint_state, _DTESTS_CTRL_FILE_METADATA)
216def _reformat_debian_tests_control(
217 lint_state: LintState,
218) -> Optional[Sequence[TextEdit]]:
219 return deb822_format_file(lint_state, _DTESTS_CTRL_FILE_METADATA)
222@lsp_format_document(_DISPATCH_RULE)
223def _debian_tests_control_on_save_formatting(
224 ls: "DebputyLanguageServer",
225 params: DocumentFormattingParams,
226) -> Optional[Sequence[TextEdit]]:
227 doc = ls.workspace.get_text_document(params.text_document.uri)
228 lint_state = ls.lint_state(doc)
229 return deb822_format_file(lint_state, _DTESTS_CTRL_FILE_METADATA)
232@lsp_semantic_tokens_full(_DISPATCH_RULE)
233def _debian_tests_control_semantic_tokens_full(
234 ls: "DebputyLanguageServer",
235 request: SemanticTokensParams,
236) -> Optional[SemanticTokens]:
237 return deb822_semantic_tokens_full(
238 ls,
239 request,
240 _DTESTS_CTRL_FILE_METADATA,
241 )