Coverage for src/debputy/lsp/lsp_reference_keyword.py: 95%
49 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 dataclasses
2import textwrap
3from typing import (
4 Optional,
5 Union,
6 Mapping,
7 Sequence,
8 Callable,
9 Iterable,
10 Any,
11 Self,
12 TYPE_CHECKING,
13)
15from debputy.lsp.ref_models.deb822_reference_parse_models import UsageHint
16from debputy.lsp.vendoring._deb822_repro import Deb822ParagraphElement
18if TYPE_CHECKING:
19 from debputy.linting.lint_util import LintState
20 from debputy.lsp.debputy_ls import DebputyLanguageServer
22LSP_DATA_DOMAIN = "debputy-lsp-data"
25def format_comp_item_synopsis_doc(
26 usage_hint: Optional[UsageHint],
27 synopsis_doc: Optional[str],
28 is_deprecated: bool,
29) -> str:
30 if is_deprecated:
31 return (
32 f"[OBSOLETE]: {synopsis_doc}"
33 if synopsis_doc is not None and not synopsis_doc.isspace()
34 else f"[OBSOLETE]"
35 )
36 if usage_hint is not None:
37 return (
38 f"[{usage_hint.upper()}]: {synopsis_doc}"
39 if synopsis_doc is not None and not synopsis_doc.isspace()
40 else f"[{usage_hint.upper()}]"
41 )
42 return synopsis_doc
45@dataclasses.dataclass(slots=True, frozen=True)
46class Keyword:
47 value: str
48 synopsis: Optional[str] = None
49 long_description: Optional[str] = None
50 translation_context: str = ""
51 is_obsolete: bool = False
52 replaced_by: Optional[str] = None
53 is_exclusive: bool = False
54 sort_text: Optional[
55 Union[
56 str,
57 Callable[
58 ["Keyword", "LintState", Sequence[Deb822ParagraphElement], str], str
59 ],
60 ]
61 ] = None
62 usage_hint: Optional[UsageHint] = None
63 can_complete_keyword_in_stanza: Optional[
64 Callable[[Iterable[Deb822ParagraphElement]], bool]
65 ] = None
66 """For keywords in fields that allow multiple keywords, the `is_exclusive` can be
67 used for keywords that cannot be used with other keywords. As an example, the `all`
68 value in `Architecture` of `debian/control` cannot be used with any other architecture.
69 """
71 @property
72 def is_deprecated(self) -> bool:
73 return self.is_obsolete or self.replaced_by is not None
75 def resolve_sort_text(
76 self,
77 lint_state: "LintState",
78 stanza_parts: Sequence[Deb822ParagraphElement],
79 value_being_completed: str,
80 ) -> Optional[str]:
81 sort_text = self.sort_text
82 if sort_text is None:
83 return None
84 if not isinstance(sort_text, str): 84 ↛ 91line 84 didn't jump to line 91 because the condition on line 84 was always true
85 return sort_text(
86 self,
87 lint_state,
88 stanza_parts,
89 value_being_completed,
90 )
91 return sort_text
93 def is_keyword_valid_completion_in_stanza(
94 self,
95 stanza_parts: Sequence[Deb822ParagraphElement],
96 ) -> bool:
97 return (
98 self.can_complete_keyword_in_stanza is None
99 or self.can_complete_keyword_in_stanza(stanza_parts)
100 )
102 def replace(self, **changes: Any) -> "Self":
103 return dataclasses.replace(self, **changes)
105 def synopsis_translated(
106 self, translation_provider: Union["DebputyLanguageServer", "LintState"]
107 ) -> str:
108 return translation_provider.translation(LSP_DATA_DOMAIN).pgettext(
109 self.translation_context,
110 self.synopsis,
111 )
113 def long_description_translated(
114 self, translation_provider: Union["DebputyLanguageServer", "LintState"]
115 ) -> str:
116 return translation_provider.translation(LSP_DATA_DOMAIN).pgettext(
117 self.translation_context,
118 self.long_description,
119 )
122def allowed_values(*values: Union[str, Keyword]) -> Mapping[str, Keyword]:
123 as_keywords = [k if isinstance(k, Keyword) else Keyword(k) for k in values]
124 as_mapping = {k.value: k for k in as_keywords if k.value}
125 # Simple bug check
126 assert len(as_keywords) == len(as_mapping)
127 return as_mapping
130# This is the set of styles that `debputy` explicitly supports, which is more narrow than
131# the ones in the config file.
132ALL_PUBLIC_NAMED_STYLES = allowed_values(
133 Keyword(
134 "black",
135 long_description=textwrap.dedent(
136 """\
137 Uncompromising file formatting of Debian packaging files
139 By using it, you agree to cede control over minutiae of hand-formatting. In
140 return, the formatter gives you speed, determinism, and freedom from style
141 discussions about formatting.
143 The `black` style is inspired by the `black` Python code formatter. Like with
144 `black`, the style will evolve over time.
145 """
146 ),
147 ),
148)