|
4 | 4 | initialization options.
|
5 | 5 | """
|
6 | 6 |
|
7 |
| -from typing import List, Optional, Pattern, Set |
| 7 | +from dataclasses import dataclass, field |
| 8 | +from typing import Any, List, Optional, Pattern, Set |
8 | 9 |
|
| 10 | +from attrs import fields, has |
| 11 | +from cattrs import Converter |
| 12 | +from cattrs.gen import make_dict_structure_fn, override |
9 | 13 | from lsprotocol.types import MarkupKind
|
10 |
| -from pydantic import BaseModel, ConfigDict, Field |
11 | 14 |
|
12 | 15 | # pylint: disable=missing-class-docstring
|
13 | 16 | # pylint: disable=too-few-public-methods
|
14 | 17 |
|
| 18 | +light_dataclass = dataclass(kw_only=True, eq=False, match_args=False) |
15 | 19 |
|
16 |
| -def snake_to_camel(string: str) -> str: |
17 |
| - """Convert from snake_case to camelCase.""" |
18 |
| - return "".join( |
19 |
| - word.capitalize() if idx > 0 else word |
20 |
| - for idx, word in enumerate(string.split("_")) |
21 |
| - ) |
22 | 20 |
|
23 |
| - |
24 |
| -class Model(BaseModel): |
25 |
| - model_config = ConfigDict(alias_generator=snake_to_camel) |
26 |
| - |
27 |
| - |
28 |
| -class CodeAction(Model): |
| 21 | +@light_dataclass |
| 22 | +class CodeAction: |
29 | 23 | name_extract_variable: str = "jls_extract_var"
|
30 | 24 | name_extract_function: str = "jls_extract_def"
|
31 | 25 |
|
32 | 26 |
|
33 |
| -class Completion(Model): |
| 27 | +@light_dataclass |
| 28 | +class Completion: |
34 | 29 | disable_snippets: bool = False
|
35 | 30 | resolve_eagerly: bool = False
|
36 |
| - ignore_patterns: List[Pattern[str]] = [] |
| 31 | + ignore_patterns: List[Pattern[str]] = field(default_factory=list) |
37 | 32 |
|
38 | 33 |
|
39 |
| -class Diagnostics(Model): |
| 34 | +@light_dataclass |
| 35 | +class Diagnostics: |
40 | 36 | enable: bool = True
|
41 | 37 | did_open: bool = True
|
42 | 38 | did_save: bool = True
|
43 | 39 | did_change: bool = True
|
44 | 40 |
|
45 | 41 |
|
46 |
| -class HoverDisableOptions(Model): |
| 42 | +@light_dataclass |
| 43 | +class HoverDisableOptions: |
47 | 44 | all: bool = False
|
48 |
| - names: Set[str] = set() |
49 |
| - full_names: Set[str] = set() |
| 45 | + names: Set[str] = field(default_factory=set) |
| 46 | + full_names: Set[str] = field(default_factory=set) |
50 | 47 |
|
51 | 48 |
|
52 |
| -class HoverDisable(Model): |
| 49 | +@light_dataclass |
| 50 | +class HoverDisable: |
53 | 51 | """All Attributes have _ appended to avoid syntax conflicts.
|
54 | 52 |
|
55 | 53 | For example, the keyword class would have required a special case.
|
56 | 54 | To get around this, I decided it's simpler to always assume an
|
57 | 55 | underscore at the end.
|
58 | 56 | """
|
59 | 57 |
|
60 |
| - keyword_: HoverDisableOptions = Field( |
61 |
| - default=HoverDisableOptions(), alias="keyword" |
62 |
| - ) |
63 |
| - module_: HoverDisableOptions = Field( |
64 |
| - default=HoverDisableOptions(), alias="module" |
65 |
| - ) |
66 |
| - class_: HoverDisableOptions = Field( |
67 |
| - default=HoverDisableOptions(), alias="class" |
68 |
| - ) |
69 |
| - instance_: HoverDisableOptions = Field( |
70 |
| - default=HoverDisableOptions(), alias="instance" |
71 |
| - ) |
72 |
| - function_: HoverDisableOptions = Field( |
73 |
| - default=HoverDisableOptions(), alias="function" |
74 |
| - ) |
75 |
| - param_: HoverDisableOptions = Field( |
76 |
| - default=HoverDisableOptions(), alias="param" |
77 |
| - ) |
78 |
| - path_: HoverDisableOptions = Field( |
79 |
| - default=HoverDisableOptions(), alias="path" |
80 |
| - ) |
81 |
| - property_: HoverDisableOptions = Field( |
82 |
| - default=HoverDisableOptions(), alias="property" |
83 |
| - ) |
84 |
| - statement_: HoverDisableOptions = Field( |
85 |
| - default=HoverDisableOptions(), alias="statement" |
| 58 | + keyword_: HoverDisableOptions = field(default_factory=HoverDisableOptions) |
| 59 | + module_: HoverDisableOptions = field(default_factory=HoverDisableOptions) |
| 60 | + class_: HoverDisableOptions = field(default_factory=HoverDisableOptions) |
| 61 | + instance_: HoverDisableOptions = field(default_factory=HoverDisableOptions) |
| 62 | + function_: HoverDisableOptions = field(default_factory=HoverDisableOptions) |
| 63 | + param_: HoverDisableOptions = field(default_factory=HoverDisableOptions) |
| 64 | + path_: HoverDisableOptions = field(default_factory=HoverDisableOptions) |
| 65 | + property_: HoverDisableOptions = field(default_factory=HoverDisableOptions) |
| 66 | + statement_: HoverDisableOptions = field( |
| 67 | + default_factory=HoverDisableOptions |
86 | 68 | )
|
87 | 69 |
|
88 | 70 |
|
89 |
| -class Hover(Model): |
| 71 | +@light_dataclass |
| 72 | +class Hover: |
90 | 73 | enable: bool = True
|
91 |
| - disable: HoverDisable = HoverDisable() |
| 74 | + disable: HoverDisable = field(default_factory=HoverDisable) |
92 | 75 |
|
93 | 76 |
|
94 |
| -class JediSettings(Model): |
95 |
| - auto_import_modules: List[str] = [] |
| 77 | +@light_dataclass |
| 78 | +class JediSettings: |
| 79 | + auto_import_modules: List[str] = field(default_factory=list) |
96 | 80 | case_insensitive_completion: bool = True
|
97 | 81 | debug: bool = False
|
98 | 82 |
|
99 | 83 |
|
100 |
| -class Symbols(Model): |
101 |
| - ignore_folders: List[str] = [".nox", ".tox", ".venv", "__pycache__"] |
| 84 | +@light_dataclass |
| 85 | +class Symbols: |
| 86 | + ignore_folders: List[str] = field( |
| 87 | + default_factory=lambda: [".nox", ".tox", ".venv", "__pycache__"] |
| 88 | + ) |
102 | 89 | max_symbols: int = 20
|
103 | 90 |
|
104 | 91 |
|
105 |
| -class Workspace(Model): |
| 92 | +@light_dataclass |
| 93 | +class Workspace: |
106 | 94 | environment_path: Optional[str] = None
|
107 |
| - extra_paths: List[str] = [] |
108 |
| - symbols: Symbols = Symbols() |
| 95 | + extra_paths: List[str] = field(default_factory=list) |
| 96 | + symbols: Symbols = field(default_factory=Symbols) |
109 | 97 |
|
110 | 98 |
|
111 |
| -class InitializationOptions(Model): |
112 |
| - code_action: CodeAction = CodeAction() |
113 |
| - completion: Completion = Completion() |
114 |
| - diagnostics: Diagnostics = Diagnostics() |
115 |
| - hover: Hover = Hover() |
116 |
| - jedi_settings: JediSettings = JediSettings() |
| 99 | +@light_dataclass |
| 100 | +class InitializationOptions: |
| 101 | + code_action: CodeAction = field(default_factory=CodeAction) |
| 102 | + completion: Completion = field(default_factory=Completion) |
| 103 | + diagnostics: Diagnostics = field(default_factory=Diagnostics) |
| 104 | + hover: Hover = field(default_factory=Hover) |
| 105 | + jedi_settings: JediSettings = field(default_factory=JediSettings) |
117 | 106 | markup_kind_preferred: Optional[MarkupKind] = None
|
118 |
| - workspace: Workspace = Workspace() |
| 107 | + workspace: Workspace = field(default_factory=Workspace) |
| 108 | + |
| 109 | + |
| 110 | +initialization_options_converter = Converter() |
| 111 | + |
| 112 | +WEIRD_NAMES = { |
| 113 | + "keyword_": "keyword", |
| 114 | + "module_": "module", |
| 115 | + "class_": "class", |
| 116 | + "instance_": "instance", |
| 117 | + "function_": "function", |
| 118 | + "param_": "param", |
| 119 | + "path_": "path", |
| 120 | + "property_": "property", |
| 121 | + "statement_ ": "statement", |
| 122 | +} |
| 123 | + |
| 124 | + |
| 125 | +def convert_class_keys(string: str) -> str: |
| 126 | + """Convert from snake_case to camelCase. |
| 127 | +
|
| 128 | + Also handles random special cases for keywords. |
| 129 | + """ |
| 130 | + if string in WEIRD_NAMES: |
| 131 | + return WEIRD_NAMES[string] |
| 132 | + return "".join( |
| 133 | + word.capitalize() if idx > 0 else word |
| 134 | + for idx, word in enumerate(string.split("_")) |
| 135 | + ) |
| 136 | + |
| 137 | + |
| 138 | +def structure(cls: type) -> Any: |
| 139 | + """Hook to convert names when marshalling initialization_options.""" |
| 140 | + return make_dict_structure_fn( |
| 141 | + cls, |
| 142 | + initialization_options_converter, |
| 143 | + **{ |
| 144 | + a.name: override(rename=convert_class_keys(a.name)) |
| 145 | + for a in fields(cls) |
| 146 | + } |
| 147 | + ) |
| 148 | + |
| 149 | + |
| 150 | +initialization_options_converter.register_structure_hook_factory( |
| 151 | + has, structure |
| 152 | +) |
0 commit comments