xbsl 0.16.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. xbsl-0.16.0/LICENSE +21 -0
  2. xbsl-0.16.0/PKG-INFO +445 -0
  3. xbsl-0.16.0/README.md +415 -0
  4. xbsl-0.16.0/pyproject.toml +58 -0
  5. xbsl-0.16.0/setup.cfg +4 -0
  6. xbsl-0.16.0/tests/test_alias.py +100 -0
  7. xbsl-0.16.0/tests/test_baseline.py +214 -0
  8. xbsl-0.16.0/tests/test_cli.py +105 -0
  9. xbsl-0.16.0/tests/test_codeclimate.py +116 -0
  10. xbsl-0.16.0/tests/test_corpus.py +31 -0
  11. xbsl-0.16.0/tests/test_dataset.py +27 -0
  12. xbsl-0.16.0/tests/test_docs.py +133 -0
  13. xbsl-0.16.0/tests/test_extract_docs.py +134 -0
  14. xbsl-0.16.0/tests/test_extract_stdlib.py +112 -0
  15. xbsl-0.16.0/tests/test_fixer.py +145 -0
  16. xbsl-0.16.0/tests/test_i18n.py +151 -0
  17. xbsl-0.16.0/tests/test_index.py +265 -0
  18. xbsl-0.16.0/tests/test_language.py +20 -0
  19. xbsl-0.16.0/tests/test_lexer.py +42 -0
  20. xbsl-0.16.0/tests/test_lsp.py +31 -0
  21. xbsl-0.16.0/tests/test_lsp_nav.py +451 -0
  22. xbsl-0.16.0/tests/test_mcp.py +41 -0
  23. xbsl-0.16.0/tests/test_meta_surfaces.py +169 -0
  24. xbsl-0.16.0/tests/test_plugins.py +175 -0
  25. xbsl-0.16.0/tests/test_report.py +55 -0
  26. xbsl-0.16.0/tests/test_rule_choice_list.py +124 -0
  27. xbsl-0.16.0/tests/test_rule_dynlist_fields.py +150 -0
  28. xbsl-0.16.0/tests/test_rule_enum_nullable.py +158 -0
  29. xbsl-0.16.0/tests/test_rule_environment.py +346 -0
  30. xbsl-0.16.0/tests/test_rule_local_visibility.py +201 -0
  31. xbsl-0.16.0/tests/test_rule_naming.py +446 -0
  32. xbsl-0.16.0/tests/test_rule_ns_objects.py +235 -0
  33. xbsl-0.16.0/tests/test_rule_project.py +85 -0
  34. xbsl-0.16.0/tests/test_rule_query_in_composite.py +198 -0
  35. xbsl-0.16.0/tests/test_rule_query_tables.py +110 -0
  36. xbsl-0.16.0/tests/test_rule_ref_fields.py +157 -0
  37. xbsl-0.16.0/tests/test_rule_reserved.py +257 -0
  38. xbsl-0.16.0/tests/test_rule_size_stretch.py +166 -0
  39. xbsl-0.16.0/tests/test_rule_unused_methods.py +197 -0
  40. xbsl-0.16.0/tests/test_rule_yaml_imports.py +191 -0
  41. xbsl-0.16.0/tests/test_rules.py +664 -0
  42. xbsl-0.16.0/tests/test_scaffold.py +401 -0
  43. xbsl-0.16.0/tests/test_severity_overrides.py +127 -0
  44. xbsl-0.16.0/tests/test_smoke.py +20 -0
  45. xbsl-0.16.0/tests/test_style_rules.py +407 -0
  46. xbsl-0.16.0/xbsl/__init__.py +3 -0
  47. xbsl-0.16.0/xbsl/__main__.py +4 -0
  48. xbsl-0.16.0/xbsl/baseline.py +185 -0
  49. xbsl-0.16.0/xbsl/cli.py +498 -0
  50. xbsl-0.16.0/xbsl/dataset.py +162 -0
  51. xbsl-0.16.0/xbsl/diagnostics.py +51 -0
  52. xbsl-0.16.0/xbsl/docs.py +168 -0
  53. xbsl-0.16.0/xbsl/engine.py +274 -0
  54. xbsl-0.16.0/xbsl/fixer.py +85 -0
  55. xbsl-0.16.0/xbsl/i18n.py +164 -0
  56. xbsl-0.16.0/xbsl/indexer.py +391 -0
  57. xbsl-0.16.0/xbsl/lexer.py +222 -0
  58. xbsl-0.16.0/xbsl/lsp.py +695 -0
  59. xbsl-0.16.0/xbsl/lsp_nav.py +493 -0
  60. xbsl-0.16.0/xbsl/mcp_server.py +313 -0
  61. xbsl-0.16.0/xbsl/plugins.py +127 -0
  62. xbsl-0.16.0/xbsl/report.py +110 -0
  63. xbsl-0.16.0/xbsl/rules/__init__.py +45 -0
  64. xbsl-0.16.0/xbsl/rules/_syntax.py +595 -0
  65. xbsl-0.16.0/xbsl/rules/choice_list.py +162 -0
  66. xbsl-0.16.0/xbsl/rules/code_structure.py +223 -0
  67. xbsl-0.16.0/xbsl/rules/dynlist_fields.py +212 -0
  68. xbsl-0.16.0/xbsl/rules/enum_nullable.py +156 -0
  69. xbsl-0.16.0/xbsl/rules/enum_values.py +187 -0
  70. xbsl-0.16.0/xbsl/rules/environment.py +314 -0
  71. xbsl-0.16.0/xbsl/rules/handlers.py +90 -0
  72. xbsl-0.16.0/xbsl/rules/local_visibility.py +259 -0
  73. xbsl-0.16.0/xbsl/rules/locals_usage.py +174 -0
  74. xbsl-0.16.0/xbsl/rules/naming.py +657 -0
  75. xbsl-0.16.0/xbsl/rules/ns_objects.py +193 -0
  76. xbsl-0.16.0/xbsl/rules/project.py +155 -0
  77. xbsl-0.16.0/xbsl/rules/queries.py +322 -0
  78. xbsl-0.16.0/xbsl/rules/ref_fields.py +168 -0
  79. xbsl-0.16.0/xbsl/rules/reserved_names.py +277 -0
  80. xbsl-0.16.0/xbsl/rules/semantics.py +443 -0
  81. xbsl-0.16.0/xbsl/rules/size_stretch.py +141 -0
  82. xbsl-0.16.0/xbsl/rules/structure.py +48 -0
  83. xbsl-0.16.0/xbsl/rules/style_conditions.py +148 -0
  84. xbsl-0.16.0/xbsl/rules/style_layout.py +182 -0
  85. xbsl-0.16.0/xbsl/rules/style_naming.py +250 -0
  86. xbsl-0.16.0/xbsl/rules/style_strings.py +184 -0
  87. xbsl-0.16.0/xbsl/rules/style_types.py +251 -0
  88. xbsl-0.16.0/xbsl/rules/typography.py +136 -0
  89. xbsl-0.16.0/xbsl/rules/unused_methods.py +158 -0
  90. xbsl-0.16.0/xbsl/rules/whitespace.py +73 -0
  91. xbsl-0.16.0/xbsl/rules/yaml_imports.py +161 -0
  92. xbsl-0.16.0/xbsl/rules/yaml_properties.py +99 -0
  93. xbsl-0.16.0/xbsl/rules/yaml_schema.py +201 -0
  94. xbsl-0.16.0/xbsl/rules/yaml_types.py +210 -0
  95. xbsl-0.16.0/xbsl/scaffold.py +1547 -0
  96. xbsl-0.16.0/xbsl/web.py +488 -0
  97. xbsl-0.16.0/xbsl.egg-info/PKG-INFO +445 -0
  98. xbsl-0.16.0/xbsl.egg-info/SOURCES.txt +101 -0
  99. xbsl-0.16.0/xbsl.egg-info/dependency_links.txt +1 -0
  100. xbsl-0.16.0/xbsl.egg-info/entry_points.txt +9 -0
  101. xbsl-0.16.0/xbsl.egg-info/requires.txt +14 -0
  102. xbsl-0.16.0/xbsl.egg-info/top_level.txt +2 -0
  103. xbsl-0.16.0/xbsllint/__init__.py +51 -0
xbsl-0.16.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 xbsl-lint contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
xbsl-0.16.0/PKG-INFO ADDED
@@ -0,0 +1,445 @@
1
+ Metadata-Version: 2.4
2
+ Name: xbsl
3
+ Version: 0.16.0
4
+ Summary: Инструментарий XBSL (1С:Элемент): линтер, LSP, документация, индекс проекта, скаффолдинг метаданных
5
+ Author: xbsl contributors
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/keyfire/xbsl
8
+ Project-URL: Repository, https://github.com/keyfire/xbsl
9
+ Project-URL: Issues, https://github.com/keyfire/xbsl/issues
10
+ Keywords: 1c,1c-element,xbsl,linter,lsp,scaffolding,static-analysis
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Natural Language :: Russian
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Topic :: Software Development :: Quality Assurance
15
+ Classifier: Operating System :: OS Independent
16
+ Requires-Python: >=3.10
17
+ Description-Content-Type: text/markdown
18
+ License-File: LICENSE
19
+ Requires-Dist: PyYAML>=6.0
20
+ Provides-Extra: dev
21
+ Requires-Dist: pytest>=7; extra == "dev"
22
+ Requires-Dist: pymorphy3>=2.0; extra == "dev"
23
+ Provides-Extra: mcp
24
+ Requires-Dist: mcp>=1.2; extra == "mcp"
25
+ Provides-Extra: lsp
26
+ Requires-Dist: pygls<2,>=1.3; extra == "lsp"
27
+ Provides-Extra: morph
28
+ Requires-Dist: pymorphy3>=2.0; extra == "morph"
29
+ Dynamic: license-file
30
+
31
+ # xbsl
32
+
33
+ **English** · [Русский](https://github.com/keyfire/xbsl/blob/main/README.ru.md)
34
+
35
+ ![CI](https://github.com/keyfire/xbsl/actions/workflows/ci.yml/badge.svg)
36
+
37
+ The XBSL (1C:Element) toolkit: a linter with autofixes, an LSP server, a project index,
38
+ platform documentation search, metadata scaffolding and an MCP server for AI agents.
39
+ It works on `Name.yaml` (element description) and `Name.xbsl` (code module) pairs –
40
+ before the server-side compilation that happens on deploy.
41
+
42
+ > Before 0.16 the project was named **xbsl-lint** (the `xbsllint` package). The old names
43
+ > keep working: the `xbsllint*` commands are aliases of the new ones, `import xbsllint`
44
+ > returns the `xbsl` modules, and both spellings of the environment variables and
45
+ > entry-point groups are honored.
46
+
47
+ > Not affiliated with 1C. "1C:Element", "1C:Fresh" and related names are trademarks of their
48
+ > respective owners. Language data is generated from your own distribution. See [NOTICE](https://github.com/keyfire/xbsl/blob/main/NOTICE).
49
+
50
+ Development notes and updates (in Russian): the [1C × AI: engineering workshop](https://t.me/ceh_1c_ai) Telegram channel.
51
+
52
+ ## Why
53
+
54
+ 1C:Element has no external tooling: the only code check is the server-side compilation on deploy –
55
+ it is slow and knows nothing about project conventions. xbsl gives fast local feedback, catches
56
+ what the compiler does not check at all, and takes over the metadata mechanics – creating
57
+ objects, attributes and forms.
58
+
59
+ ## Step 1: generate the language data
60
+
61
+ The linter relies on language tables (bilingual keywords, operators), an stdlib type catalog, and
62
+ the configuration metamodel (element properties). XBSL is built on Eclipse Xtext + ANTLR; these are
63
+ extracted from **your** 1C:Element distribution (the `InternalBsl.g` grammar, the documentation, and
64
+ the `.xcore` metamodel) and are NOT bundled in this repository. Generate them locally:
65
+
66
+ ```sh
67
+ python tools/extract_grammar.py --dist "<path to the 1C:Element distribution>"
68
+ python tools/extract_stdlib.py --dist "<path to the 1C:Element distribution>"
69
+ python tools/extract_metamodel.py --dist "<path to the 1C:Element distribution>"
70
+ ```
71
+
72
+ The scripts auto-detect the platform version and place the data under
73
+ `xbsl/data/element/<version>/` (this folder is gitignored). Without the data, the linter and
74
+ the tests will tell you to generate it. Pass `--data-dir` (or set `XBSL_DATA_DIR`) to write the
75
+ data somewhere else – for instance into a private package that ships it, see
76
+ [Extending](#extending-your-own-rules-and-data).
77
+
78
+ ## Step 2: install and run
79
+
80
+ ```sh
81
+ pip install xbsl # or, from a clone: pip install -e .
82
+ xbsl path/to/sources # or: python -m xbsl path/to/sources
83
+ ```
84
+
85
+ The extractors from step 1 ship with the repository, not with the PyPI package – clone the
86
+ repository to generate the data.
87
+
88
+ Flags: `--list-rules`, `--where` (data root, source and versions), `--select`/`--enable`/`--ignore` (by rule id, rule group – the part of the id
89
+ before `/` – or tier letter), `--fix`, `--baseline`/`--write-baseline`, `--element-version`,
90
+ `--data-dir`, `--lang`, `--format text|json|codeclimate`.
91
+ `--fix` repairs the mechanical findings in place – trailing whitespace, typography characters
92
+ (em dash → en dash, `…` → `...`, curly quotes and comment guillemets → straight), and mixed
93
+ newlines (normalized to the dominant style) – then reports whatever is left. It only applies
94
+ unambiguous edits and only for rules active in the run (so `--fix --enable typography` also pays
95
+ down the em-dash/guillemets debt); anything needing judgment is never touched.
96
+ For editor integration, `--stdin --filename NAME` checks a single buffer read from stdin (per-file
97
+ rules only); the JSON payload (`{diagnostics, summary}`) is the same one the MCP server returns.
98
+ `xbsl --index PATH` dumps a JSON index of the project to stdout instead of linting – the
99
+ objects (with tabular sections, module-declared local types and the member families for dot
100
+ completion), the method declarations with their annotations and the named form components, with
101
+ POSIX paths relative to the root and 1-based lines – for go-to-definition and completion in
102
+ editors.
103
+ `--format codeclimate` emits a GitLab Code Quality report (Code Climate issues) with paths relative
104
+ to the current directory – run it from the repository root and save the output as the
105
+ `codequality` artifact.
106
+
107
+ ## Output language
108
+
109
+ Rule titles and diagnostic messages come in Russian and English. The language is picked by
110
+ `--lang ru|en` > the `XBSL_LANG` env var > the system locale > Russian. Type names, keywords
111
+ and other XBSL text inside a message are never translated – only the wording around them. The MCP
112
+ server and the web panel follow the same setting (the web panel also has an in-page RU/EN toggle).
113
+
114
+ ## Use in CI
115
+
116
+ `xbsl` exits non-zero only when a run produces an **error-severity** finding, so it works as a
117
+ pipeline gate as-is – warnings and `info` do not fail the build. The one prerequisite is the
118
+ language data (see [Step 1](#step-1-generate-the-language-data)): generate it in the job (the
119
+ extractors ship with the repository, so check the repo out), or depend on a package that ships the
120
+ data via the `xbsl.data` entry point (see [Extending](#extending-your-own-rules-and-data)) and
121
+ just `pip install` it.
122
+
123
+ ### GitHub Actions
124
+
125
+ ```yaml
126
+ lint:
127
+ runs-on: ubuntu-latest
128
+ steps:
129
+ - uses: actions/checkout@v4
130
+ - uses: actions/setup-python@v5
131
+ with: { python-version: "3.12" }
132
+ - run: pip install xbsl
133
+ # generate the data from your 1C:Element distribution (or install a package that ships it):
134
+ - run: |
135
+ python tools/extract_grammar.py --dist "$ELEMENT_DIST"
136
+ python tools/extract_stdlib.py --dist "$ELEMENT_DIST"
137
+ python tools/extract_metamodel.py --dist "$ELEMENT_DIST"
138
+ - run: xbsl e1c/ # fails the job on any error-severity finding
139
+ ```
140
+
141
+ ### GitLab CI (Code Quality widget)
142
+
143
+ `--format codeclimate` writes a Code Climate report that GitLab renders inline on the merge request.
144
+ Run it from the repository root and save the output as the `codequality` report. The command still
145
+ returns non-zero on error-severity findings, so `artifacts.when: always` keeps the report even when
146
+ the job gates the pipeline (drop the gate with a trailing `|| true` if you want the widget only):
147
+
148
+ ```yaml
149
+ lint:
150
+ script:
151
+ - pip install xbsl
152
+ - xbsl --format codeclimate e1c/ > gl-code-quality-report.json
153
+ artifacts:
154
+ when: always
155
+ reports:
156
+ codequality: gl-code-quality-report.json
157
+ ```
158
+
159
+ ## Rule tiers
160
+
161
+ - **A. Structure and YAML** – `.xbsl`/`.yaml` pairing, schema validity, `Ид` as a UUID,
162
+ `Ид` uniqueness, `Имя` matching the file name.
163
+ - **B. Text and conventions** – typography (en dash, straight quotes),
164
+ encoding/BOM/newlines/trailing whitespace, indentation and line length.
165
+ - **C. Code structure** – balance of blocks and `;`, brackets, unused local and loop variables,
166
+ a structure reference field that must be `обз`, plus the platform's code style conventions
167
+ (the `style/` group, see below).
168
+ - **D. Semantics** – against platform data and the project itself: types, enumeration values,
169
+ cross-file consistency (see below).
170
+
171
+ The type rules of tier D cover every type position in code (`новый`, `как` casts, annotations,
172
+ signatures) and every `Тип:` value in yaml (unions `А|Б|?`, generics, nullable): the root must
173
+ be a known type – stdlib, a project object or a module-declared local type – and a dotted chain
174
+ rooted at a project object must stay within the family that object generates: the derived types
175
+ extracted from the distribution docs (`Ссылка`, `Объект`, `СоздатьОбъект`, the automatic
176
+ forms...), its tabular sections and module structures. Namespace-qualified references
177
+ (`Справочник.X.Ссылка`) also check that the object exists under that kind, and the values of
178
+ project enumerations are verified both in code and in yaml bindings.
179
+
180
+ The cross-file rules of tier D catch what the compiler reports late or not at all: a yaml
181
+ handler missing from the paired module, a foreign-subsystem type used without an `Импорт:`
182
+ entry, a dynamic list typed by the automatic list form that misses an attribute of its object,
183
+ a cross-component `Компоненты.X.Метод()` call to a method without a visibility annotation,
184
+ environment mismatches (`@НаСервере` called from a client handler without `@ДоступноСКлиента`,
185
+ a client-only module used from an HTTP service), reserved names (`Тип`/`type` as a field or
186
+ parameter, a component property named like a built-in one), methods that nothing references,
187
+ and top-level yaml properties against the configuration metamodel. The `query/` group
188
+ parses `Запрос{ ... }` blocks and verifies the tables of `ИЗ`/`СОЕДИНЕНИЕ` against the
189
+ project objects and their tabular sections; a block with constructs outside the supported
190
+ subset (temporary tables, unions, subqueries) is skipped whole rather than guessed.
191
+
192
+ ## Queries: `IN` with a subquery over a composite type (rule `query/in-subquery-composite`)
193
+
194
+ A platform standard: `IN` with a subquery over an expression of a composite type is implemented
195
+ inefficiently on most DBMSs, so the condition is written with `EXISTS` instead. The rule is a
196
+ warning – the standard is mandatory:
197
+
198
+ ```
199
+ WHERE T.Value IN (SELECT F.Value FROM Filters AS F) // warning
200
+ WHERE EXISTS (SELECT 1 FROM Filters AS F WHERE F.Value = T.Value) // this way
201
+ ```
202
+
203
+ A type counts as composite when the yaml spells two or more alternatives (`Строка|Число|?`): the
204
+ `?` is not a type but the admissibility of `Неопределено`, and `Массив<Строка|Число>` is not
205
+ composite either. Only a field whose type is known for sure is questioned: `Alias.Field` or
206
+ `Table.Field`, where the alias is unambiguous within the block and the field is found in the
207
+ table's yaml; a list of values (`IN (1, 2, &Codes)`) is not what the standard is about. Both
208
+ spellings of the query language are understood (`В`/`IN`, `НЕ`/`NOT`, `ВЫБРАТЬ`/`SELECT`).
209
+
210
+ ## Project properties (the `project/` rules)
211
+
212
+ Three rules from the standard "Filling in the project properties": `Поставщик` and `Имя` are
213
+ identifiers built from the presentations (every word capitalized: `КабинетСотрудника`,
214
+ `НовыеЭлементарныеТехнологии`); `Представление` and `ПредставлениеПоставщика` are filled in – the
215
+ official name of the project and of the company that developed it; `Версия` is three numbers
216
+ `A.B.C` (semantic versioning), not `1.0`.
217
+
218
+ ## Names of project elements (the `naming/` rules)
219
+
220
+ Twelve rules from the platform standard "Names of project elements" – it is mandatory in new code,
221
+ so all of them are warnings. They read the descriptions (`.yaml`): the name of the element itself
222
+ and the names of its attributes, dimensions, resources, tabular sections and enumeration values.
223
+
224
+ The number of a name is checked against the kind: catalogs, documents, registers and tabular
225
+ sections are named in the plural, enumerations and structures in the singular (`naming/number`).
226
+ This is morphology, not a guess by the ending: `Номенклатура` is singular and the standard allows
227
+ it, while `Программы` and `Акции` without the case read as a genitive singular. Needs the `[morph]`
228
+ extra (`pip install "xbsl[morph]"`); without it the rule stays silent.
229
+
230
+ The rest: the letter `ё` and underscores in names, an abbreviation written as one word (`Ндс`, not
231
+ `НДС`), an English term as the original (`Xml`, not `Хмл`), `Вид` rather than `Тип` for
232
+ enumerations, the kind inside its own name (`ОтчетЗависшиеЗадачи`), filler words (`Управление`,
233
+ `Менеджер`), an environment suffix on a common module (`ОбменДаннымиКлиентИСервер` – the
234
+ environment is a property, not a name), a boolean attribute named by a negation (`НетОшибок`
235
+ instead of `Успешно`), an empty `Представление`, and the prefixes required for certain kinds
236
+ (`КлючДоступа`, `ПравоНа`, `Навигация`).
237
+
238
+ ## Code style conventions (the `style/` rules)
239
+
240
+ Twenty-one rules that follow the platform documentation ("Code style conventions" and "Language
241
+ idioms"): layout and expression wrapping, naming, type descriptions and signatures, collection
242
+ literals, string interpolation, and checks of boolean values and `Неопределено`.
243
+
244
+ Rules that clean code already satisfies are enabled by default (`warning`) – they guard against
245
+ regressions. Rules that typically fire on accumulated legacy debt are `info` and disabled; enable
246
+ them to measure the debt and pay it down:
247
+
248
+ ```sh
249
+ xbsl path/to/sources --select style # ONLY these rules (replaces the default set)
250
+ xbsl path/to/sources --enable style # the default set PLUS these
251
+ xbsl path/to/sources --ignore style # the default set minus these
252
+ ```
253
+
254
+ `--select`, `--enable` and `--ignore` accept a rule id, a group (the part before `/`) or a tier
255
+ letter, repeated or comma-separated. `--select` narrows to exactly the given rules; `--enable`
256
+ switches on off-by-default rules on top of the defaults.
257
+
258
+ `Запрос{ ... }` blocks (the query DSL) and string literals (HTML/CSS/SVG in web views) are
259
+ excluded from these checks. Not covered, and left to the author and review: indentation being a
260
+ multiple of four, collection idioms, `Строки.Соединить()` for bulk concatenation, the `?.` / `??`
261
+ idioms, and `выбор` instead of an `иначе если` chain.
262
+
263
+ ## Baseline: adopt a rule on a legacy codebase
264
+
265
+ To enable a rule over code that already violates it without drowning in legacy findings, freeze the
266
+ current findings into a baseline and hold only new code to the rule:
267
+
268
+ ```sh
269
+ xbsl e1c/app --enable style --write-baseline baseline.json # freeze the debt once
270
+ xbsl e1c/app --enable style --baseline baseline.json # only NEW findings surface
271
+ ```
272
+
273
+ A finding's identity is `(file, rule, message)` with an allowed count, so moving a line keeps its
274
+ finding suppressed while a genuinely new violation surfaces. The summary reports how many findings
275
+ the baseline suppressed and how many of its entries are now stale (debt paid down) – a signal to
276
+ rewrite the file. Paths are stored relative to the baseline file, so commit it at the repository
277
+ root and run the linter from anywhere.
278
+
279
+ The same file also records point exclusions with their reasons: an entry's value is either a
280
+ bare count or `{"count": N, "reason": "..."}` – the reason says why the code is right on
281
+ purpose. Reasons are written by the "Exclude the finding" lightbulb action of the
282
+ [VS Code extension](https://github.com/keyfire/xbsl/blob/main/editors/vscode/README.md#excluding-a-finding-the-baseline) (or by hand);
283
+ `--write-baseline` keeps the reasons of the identities that survive a rewrite. The LSP server
284
+ accepts the same `--baseline FILE` flag, so exclusions disappear in editors too. The identity
285
+ includes the message text: write and check the baseline under the same output language.
286
+
287
+ ## Metadata scaffolding
288
+
289
+ The toolkit takes over the metadata mechanics: UUIDs, indentation, precise yaml insertions,
290
+ duplicate checks and section/kind compatibility. The same operations are exposed through the
291
+ CLI (subcommands, JSON output), MCP (the `meta_*` tools for agents) and LSP (the `xbsl/meta*`
292
+ custom requests that power the VS Code metadata tree).
293
+
294
+ ```sh
295
+ xbsl new-project . vendor App # Проект.yaml + Проект.xbsl + a subsystem
296
+ xbsl new-object vendor/App/Основное Справочник Товары
297
+ xbsl add-field vendor/App/Основное/Товары.yaml реквизит Цвет --type Строка
298
+ xbsl add-form . --name Товары # object + list forms, registered
299
+ xbsl new-object ... HttpСервис Каталог --routes "GET /, POST /, GET /{id}"
300
+ xbsl add-route .../Каталог.yaml "DELETE /{id}" # url template + handler stub
301
+ xbsl add-subsystem vendor/App Задачи
302
+ xbsl object-info . --name Товары # fields, tabulars, forms, namespace
303
+ xbsl project-info . # projects, subsystems, objects by kind
304
+ ```
305
+
306
+ Forms are generated with real content: input fields per attribute (including the standard
307
+ Наименование / Номер / Дата and hierarchy support), dynamic-list columns, tabular-section
308
+ tables, a report form with parameters; the form is registered in the owner's `Интерфейс`
309
+ section. `--dry-run` prints the changes (with full file texts) without writing – this is how
310
+ the VS Code extension applies them through its own undo-friendly edits.
311
+
312
+ ## Extending: your own rules, data and severities
313
+
314
+ Three entry point groups let a separate package extend the linter without forking it. This exists
315
+ for teams whose rules or language data cannot be published: keep those in a private package that
316
+ depends on `xbsl`.
317
+
318
+ ```toml
319
+ # pyproject.toml of your package
320
+ dependencies = ["xbsl>=0.16"]
321
+
322
+ [project.entry-points."xbsl.rules"]
323
+ myproject = "myproject.rules" # importing the module runs its @rule decorators
324
+
325
+ [project.entry-points."xbsl.data"]
326
+ myproject = "myproject:data_root" # a path, or a callable returning one
327
+
328
+ [project.entry-points."xbsl.severity"]
329
+ myproject = "myproject:severity_overrides" # {rule id: "error"|"warning"|"info"|"off"}
330
+ ```
331
+
332
+ Packages that declared the groups under the pre-rename name (`xbsllint.rules`/`xbsllint.data`/
333
+ `xbsllint.severity`) keep working: the legacy groups are scanned after the new ones.
334
+
335
+ The severity dict (or a zero-argument callable returning one) raises or lowers the default level
336
+ of any rule – built-in or plugin – for every run in this installation: a project may treat, say,
337
+ `style/abbreviation-case` as a warning while the published default stays info. `"off"` removes a
338
+ rule from the default set (an explicit `--select`/`--enable` still turns it on, at its base level).
339
+
340
+ Install the package and the CLI, the MCP server and the web UI all pick everything up – no flags,
341
+ no config file. A failing entry point raises instead of warning: a linter that silently drops a
342
+ rule stays green in CI and guarantees nothing; an override naming an unknown rule id or level
343
+ raises for the same reason. `XBSL_NO_PLUGINS=1` ignores every external package (built-in
344
+ rules, bundled data and default severities only).
345
+
346
+ ## LSP server (experimental)
347
+
348
+ `xbsl-lsp` (the `[lsp]` extra: `pip install "xbsl[lsp]"`) runs the linter as a
349
+ long-living Language Server over stdio: live per-file diagnostics as you type, project-wide
350
+ diagnostics on save, go to definition, completion and hover over a resident project index,
351
+ and quick-fix code actions - without paying the interpreter start-up cost per call. Flags:
352
+ `--project-root` (the sources root relative to the workspace folder), `--select`/`--ignore`/
353
+ `--enable`, `--data-dir`. Any LSP-capable editor (VS Code, Neovim, JetBrains) can spawn it.
354
+
355
+ ## Documentation (searching the Element reference)
356
+
357
+ `tools/extract_docs.py` extracts the Element reference from a distribution (the server-with-IDE
358
+ `.car`) into a `docs.sqlite` next to the language data: the stdlib pages (a type, its methods,
359
+ properties, parameters) with cleaned HTML, a full-text index (SQLite FTS5, from the standard
360
+ library) and canonical links back to the primary source (`https://1cmycloud.com/docs/help/...`,
361
+ taken from the distribution's `sitemap.xml`). Page images are stored alongside. The 1C reference is
362
+ copyrighted, so the database is not shipped in the package – you generate it from your own
363
+ distribution, like the language data (step 1).
364
+
365
+ ```sh
366
+ python tools/extract_docs.py --dist "$ELEMENT_DIST"
367
+ ```
368
+
369
+ The runtime API `xbsl.docs` (`search`, `page`, `tree`, `for_symbol`, `asset`) reads
370
+ `docs.sqlite`; with no database the search is simply empty. It powers the MCP tools (below) and –
371
+ later – the reference panel in the VS Code extension.
372
+
373
+ ## MCP server
374
+
375
+ A thin adapter over the same core: an agent (e.g. Claude Code) can call the checks as tools and
376
+ receive structured diagnostics.
377
+
378
+ ```sh
379
+ pip install -e ".[mcp]"
380
+ claude mcp add xbsl -- xbsl-mcp
381
+ ```
382
+
383
+ Tools: `lint_paths(paths)`, `lint_source(filename, content)`, `list_rules()`; documentation search –
384
+ `docs_search(query)`, `docs_page(id)`, `docs_symbol(name)` (needs the `docs.sqlite` database, see
385
+ above); metadata scaffolding – `meta_new_project`, `meta_new_object`, `meta_add_field`,
386
+ `meta_add_route`, `meta_add_form`, `meta_add_subsystem`, `meta_object_info`, `meta_project_info`.
387
+ Every writing `meta_*` tool applies the changes and returns the lint of the written files in the
388
+ same response – creation and validation in one round trip. The core and the CLI do not require
389
+ `mcp` – it lives only in the `[mcp]` extra.
390
+
391
+ ## Web interface
392
+
393
+ A local page: point it at a project folder and see the diagnostics. Standard library only (no
394
+ external dependencies), binds to `127.0.0.1` only.
395
+
396
+ ```sh
397
+ xbsl-web # then open http://127.0.0.1:8771/
398
+ ```
399
+
400
+ Per-tier rule toggles, a data-version selector, severity/text filters, dark/light theme; clicking
401
+ a diagnostic opens the file in VS Code (`vscode://`).
402
+
403
+ ## Editor support (VS Code)
404
+
405
+ A VS Code extension in [`editors/vscode`](editors/vscode) gives `.xbsl` syntax highlighting,
406
+ live diagnostics as you type (`--stdin`), workspace diagnostics on save (a full linter run in
407
+ the background brings the project-scope rules into the editor), index-based go-to-definition
408
+ and completion across the project (`xbsl --index`), a form preview with a properties
409
+ panel, and a deploy button powered by [elemctl](https://github.com/keyfire/elemctl). It is
410
+ published on the [Marketplace](https://marketplace.visualstudio.com/items?itemName=keyfire.xbsl)
411
+ and [Open VSX](https://open-vsx.org/extension/keyfire/xbsl); its
412
+ [README](editors/vscode/README.md) covers settings, behavior and requirements. See also the
413
+ companion [XBSL Debug](https://marketplace.visualstudio.com/items?itemName=keyfire.xbsl-debug)
414
+ extension from the [elemctl](https://github.com/keyfire/elemctl) project.
415
+
416
+ ## Element versions
417
+
418
+ The data is versioned by platform version:
419
+
420
+ ```
421
+ xbsl/data/element/
422
+ index.json # { available: [...], default: "<version>" }
423
+ <version>/{language.json, stdlib.json, metamodel.json}
424
+ ```
425
+
426
+ Pick a version with `--element-version` / the `XBSL_ELEMENT_VERSION` env var / the index
427
+ `default`; `--version` shows what is available. Add a new version by re-running the extractors with
428
+ a new `--dist`.
429
+
430
+ The data root itself is resolved in this order: `--data-dir` > `XBSL_DATA_DIR` > a root supplied
431
+ by an installed `xbsl.data` entry point > `xbsl/data/element` inside the package.
432
+
433
+ ## Tests
434
+
435
+ ```sh
436
+ pip install -e ".[dev]"
437
+ pytest
438
+ ```
439
+
440
+ Data-dependent tests are skipped automatically when the data has not been generated.
441
+
442
+ ## License
443
+
444
+ MIT – see [LICENSE](https://github.com/keyfire/xbsl/blob/main/LICENSE). Trademarks and data provenance – [NOTICE](https://github.com/keyfire/xbsl/blob/main/NOTICE).
445
+ How to add a rule – [CONTRIBUTING.md](https://github.com/keyfire/xbsl/blob/main/CONTRIBUTING.md).