Coverage for src/debputy/lsp/languages/lsp_debian_copyright.py: 82%
70 statements
« prev ^ index » next coverage.py v7.8.2, created at 2025-09-07 09:27 +0000
« prev ^ index » next coverage.py v7.8.2, created at 2025-09-07 09:27 +0000
1import re
2from typing import (
3 Union,
4 Sequence,
5 Optional,
6 List,
7)
9from debputy.linting.lint_util import LintState, with_range_in_continuous_parts
10from debputy.lsp.debputy_ls import DebputyLanguageServer
11from debputy.lsp.lsp_debian_control_reference_data import (
12 Dep5FileMetadata,
13)
14from debputy.lsp.lsp_features import (
15 lint_diagnostics,
16 lsp_completer,
17 lsp_hover,
18 lsp_standard_handler,
19 lsp_folding_ranges,
20 lsp_semantic_tokens_full,
21 lsp_will_save_wait_until,
22 lsp_format_document,
23 SecondaryLanguage,
24 LanguageDispatchRule,
25 lsp_cli_reformat_document,
26)
27from debputy.lsp.lsp_generic_deb822 import (
28 deb822_completer,
29 deb822_hover,
30 deb822_folding_ranges,
31 deb822_semantic_tokens_full,
32 deb822_format_file,
33 scan_for_syntax_errors_and_token_level_diagnostics,
34)
35from debputy.lsp.vendoring._deb822_repro import (
36 Deb822FileElement,
37 Deb822ParagraphElement,
38)
39from debputy.lsprotocol.types import (
40 CompletionItem,
41 CompletionList,
42 CompletionParams,
43 HoverParams,
44 Hover,
45 TEXT_DOCUMENT_CODE_ACTION,
46 SemanticTokens,
47 SemanticTokensParams,
48 FoldingRangeParams,
49 FoldingRange,
50 WillSaveTextDocumentParams,
51 TextEdit,
52 DocumentFormattingParams,
53)
55try:
56 from debputy.lsp.vendoring._deb822_repro.locatable import (
57 Position as TEPosition,
58 Range as TERange,
59 )
61 from pygls.server import LanguageServer
62 from pygls.workspace import TextDocument
63except ImportError:
64 pass
67_CONTAINS_SPACE_OR_COLON = re.compile(r"[\s:]")
69_DISPATCH_RULE = LanguageDispatchRule.new_rule(
70 "debian/copyright",
71 None,
72 "debian/copyright",
73 [
74 # emacs's name
75 SecondaryLanguage("debian-copyright"),
76 # vim's name
77 SecondaryLanguage("debcopyright"),
78 ],
79)
81_DEP5_FILE_METADATA = Dep5FileMetadata()
83lsp_standard_handler(_DISPATCH_RULE, TEXT_DOCUMENT_CODE_ACTION)
86@lsp_hover(_DISPATCH_RULE)
87def _debian_copyright_hover(
88 ls: "DebputyLanguageServer",
89 params: HoverParams,
90) -> Optional[Hover]:
91 return deb822_hover(ls, params, _DEP5_FILE_METADATA)
94@lsp_completer(_DISPATCH_RULE)
95def _debian_copyright_completions(
96 ls: "DebputyLanguageServer",
97 params: CompletionParams,
98) -> Optional[Union[CompletionList, Sequence[CompletionItem]]]:
99 return deb822_completer(ls, params, _DEP5_FILE_METADATA)
102@lsp_folding_ranges(_DISPATCH_RULE)
103def _debian_copyright_folding_ranges(
104 ls: "DebputyLanguageServer",
105 params: FoldingRangeParams,
106) -> Optional[Sequence[FoldingRange]]:
107 return deb822_folding_ranges(ls, params, _DEP5_FILE_METADATA)
110@lint_diagnostics(_DISPATCH_RULE)
111async def _lint_debian_copyright(lint_state: LintState) -> None:
112 deb822_file = lint_state.parsed_deb822_file_content
114 if not _DEP5_FILE_METADATA.file_metadata_applies_to_file(deb822_file):
115 return
117 first_error = await scan_for_syntax_errors_and_token_level_diagnostics(
118 deb822_file,
119 lint_state,
120 )
121 header_stanza, files_stanza, _ = _DEP5_FILE_METADATA.stanza_types()
122 stanza_no = 0
124 async for stanza_range, stanza in lint_state.slow_iter(
125 with_range_in_continuous_parts(deb822_file.iter_parts())
126 ):
127 if not isinstance(stanza, Deb822ParagraphElement):
128 continue
129 stanza_position = stanza_range.start_pos
130 if stanza_position.line_position >= first_error: 130 ↛ 131line 130 didn't jump to line 131 because the condition on line 130 was never true
131 break
132 stanza_no += 1
133 is_files_or_license_stanza = stanza_no != 1
134 if is_files_or_license_stanza:
135 stanza_metadata = _DEP5_FILE_METADATA.classify_stanza(
136 stanza,
137 stanza_no,
138 )
139 other_stanza_metadata = header_stanza
140 other_stanza_name = "Header"
141 elif "Format" in stanza: 141 ↛ 146line 141 didn't jump to line 146 because the condition on line 141 was always true
142 stanza_metadata = header_stanza
143 other_stanza_metadata = files_stanza
144 other_stanza_name = "Files/License"
145 else:
146 break
148 await stanza_metadata.stanza_diagnostics(
149 deb822_file,
150 stanza,
151 stanza_position,
152 lint_state,
153 confusable_with_stanza_name=other_stanza_name,
154 confusable_with_stanza_metadata=other_stanza_metadata,
155 )
158@lsp_will_save_wait_until(_DISPATCH_RULE)
159def _debian_copyright_on_save_formatting(
160 ls: "DebputyLanguageServer",
161 params: WillSaveTextDocumentParams,
162) -> Optional[Sequence[TextEdit]]:
163 doc = ls.workspace.get_text_document(params.text_document.uri)
164 lint_state = ls.lint_state(doc)
165 return deb822_format_file(lint_state, _DEP5_FILE_METADATA)
168@lsp_cli_reformat_document(_DISPATCH_RULE)
169def _reformat_debian_copyright(
170 lint_state: LintState,
171) -> Optional[Sequence[TextEdit]]:
172 return deb822_format_file(lint_state, _DEP5_FILE_METADATA)
175@lsp_format_document(_DISPATCH_RULE)
176def _debian_copyright_format_document(
177 ls: "DebputyLanguageServer",
178 params: DocumentFormattingParams,
179) -> Optional[Sequence[TextEdit]]:
180 doc = ls.workspace.get_text_document(params.text_document.uri)
181 lint_state = ls.lint_state(doc)
182 return deb822_format_file(lint_state, _DEP5_FILE_METADATA)
185@lsp_semantic_tokens_full(_DISPATCH_RULE)
186async def _debian_copyright_semantic_tokens_full(
187 ls: "DebputyLanguageServer",
188 request: SemanticTokensParams,
189) -> Optional[SemanticTokens]:
190 return await deb822_semantic_tokens_full(
191 ls,
192 request,
193 _DEP5_FILE_METADATA,
194 )