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.
- xbsl-0.16.0/LICENSE +21 -0
- xbsl-0.16.0/PKG-INFO +445 -0
- xbsl-0.16.0/README.md +415 -0
- xbsl-0.16.0/pyproject.toml +58 -0
- xbsl-0.16.0/setup.cfg +4 -0
- xbsl-0.16.0/tests/test_alias.py +100 -0
- xbsl-0.16.0/tests/test_baseline.py +214 -0
- xbsl-0.16.0/tests/test_cli.py +105 -0
- xbsl-0.16.0/tests/test_codeclimate.py +116 -0
- xbsl-0.16.0/tests/test_corpus.py +31 -0
- xbsl-0.16.0/tests/test_dataset.py +27 -0
- xbsl-0.16.0/tests/test_docs.py +133 -0
- xbsl-0.16.0/tests/test_extract_docs.py +134 -0
- xbsl-0.16.0/tests/test_extract_stdlib.py +112 -0
- xbsl-0.16.0/tests/test_fixer.py +145 -0
- xbsl-0.16.0/tests/test_i18n.py +151 -0
- xbsl-0.16.0/tests/test_index.py +265 -0
- xbsl-0.16.0/tests/test_language.py +20 -0
- xbsl-0.16.0/tests/test_lexer.py +42 -0
- xbsl-0.16.0/tests/test_lsp.py +31 -0
- xbsl-0.16.0/tests/test_lsp_nav.py +451 -0
- xbsl-0.16.0/tests/test_mcp.py +41 -0
- xbsl-0.16.0/tests/test_meta_surfaces.py +169 -0
- xbsl-0.16.0/tests/test_plugins.py +175 -0
- xbsl-0.16.0/tests/test_report.py +55 -0
- xbsl-0.16.0/tests/test_rule_choice_list.py +124 -0
- xbsl-0.16.0/tests/test_rule_dynlist_fields.py +150 -0
- xbsl-0.16.0/tests/test_rule_enum_nullable.py +158 -0
- xbsl-0.16.0/tests/test_rule_environment.py +346 -0
- xbsl-0.16.0/tests/test_rule_local_visibility.py +201 -0
- xbsl-0.16.0/tests/test_rule_naming.py +446 -0
- xbsl-0.16.0/tests/test_rule_ns_objects.py +235 -0
- xbsl-0.16.0/tests/test_rule_project.py +85 -0
- xbsl-0.16.0/tests/test_rule_query_in_composite.py +198 -0
- xbsl-0.16.0/tests/test_rule_query_tables.py +110 -0
- xbsl-0.16.0/tests/test_rule_ref_fields.py +157 -0
- xbsl-0.16.0/tests/test_rule_reserved.py +257 -0
- xbsl-0.16.0/tests/test_rule_size_stretch.py +166 -0
- xbsl-0.16.0/tests/test_rule_unused_methods.py +197 -0
- xbsl-0.16.0/tests/test_rule_yaml_imports.py +191 -0
- xbsl-0.16.0/tests/test_rules.py +664 -0
- xbsl-0.16.0/tests/test_scaffold.py +401 -0
- xbsl-0.16.0/tests/test_severity_overrides.py +127 -0
- xbsl-0.16.0/tests/test_smoke.py +20 -0
- xbsl-0.16.0/tests/test_style_rules.py +407 -0
- xbsl-0.16.0/xbsl/__init__.py +3 -0
- xbsl-0.16.0/xbsl/__main__.py +4 -0
- xbsl-0.16.0/xbsl/baseline.py +185 -0
- xbsl-0.16.0/xbsl/cli.py +498 -0
- xbsl-0.16.0/xbsl/dataset.py +162 -0
- xbsl-0.16.0/xbsl/diagnostics.py +51 -0
- xbsl-0.16.0/xbsl/docs.py +168 -0
- xbsl-0.16.0/xbsl/engine.py +274 -0
- xbsl-0.16.0/xbsl/fixer.py +85 -0
- xbsl-0.16.0/xbsl/i18n.py +164 -0
- xbsl-0.16.0/xbsl/indexer.py +391 -0
- xbsl-0.16.0/xbsl/lexer.py +222 -0
- xbsl-0.16.0/xbsl/lsp.py +695 -0
- xbsl-0.16.0/xbsl/lsp_nav.py +493 -0
- xbsl-0.16.0/xbsl/mcp_server.py +313 -0
- xbsl-0.16.0/xbsl/plugins.py +127 -0
- xbsl-0.16.0/xbsl/report.py +110 -0
- xbsl-0.16.0/xbsl/rules/__init__.py +45 -0
- xbsl-0.16.0/xbsl/rules/_syntax.py +595 -0
- xbsl-0.16.0/xbsl/rules/choice_list.py +162 -0
- xbsl-0.16.0/xbsl/rules/code_structure.py +223 -0
- xbsl-0.16.0/xbsl/rules/dynlist_fields.py +212 -0
- xbsl-0.16.0/xbsl/rules/enum_nullable.py +156 -0
- xbsl-0.16.0/xbsl/rules/enum_values.py +187 -0
- xbsl-0.16.0/xbsl/rules/environment.py +314 -0
- xbsl-0.16.0/xbsl/rules/handlers.py +90 -0
- xbsl-0.16.0/xbsl/rules/local_visibility.py +259 -0
- xbsl-0.16.0/xbsl/rules/locals_usage.py +174 -0
- xbsl-0.16.0/xbsl/rules/naming.py +657 -0
- xbsl-0.16.0/xbsl/rules/ns_objects.py +193 -0
- xbsl-0.16.0/xbsl/rules/project.py +155 -0
- xbsl-0.16.0/xbsl/rules/queries.py +322 -0
- xbsl-0.16.0/xbsl/rules/ref_fields.py +168 -0
- xbsl-0.16.0/xbsl/rules/reserved_names.py +277 -0
- xbsl-0.16.0/xbsl/rules/semantics.py +443 -0
- xbsl-0.16.0/xbsl/rules/size_stretch.py +141 -0
- xbsl-0.16.0/xbsl/rules/structure.py +48 -0
- xbsl-0.16.0/xbsl/rules/style_conditions.py +148 -0
- xbsl-0.16.0/xbsl/rules/style_layout.py +182 -0
- xbsl-0.16.0/xbsl/rules/style_naming.py +250 -0
- xbsl-0.16.0/xbsl/rules/style_strings.py +184 -0
- xbsl-0.16.0/xbsl/rules/style_types.py +251 -0
- xbsl-0.16.0/xbsl/rules/typography.py +136 -0
- xbsl-0.16.0/xbsl/rules/unused_methods.py +158 -0
- xbsl-0.16.0/xbsl/rules/whitespace.py +73 -0
- xbsl-0.16.0/xbsl/rules/yaml_imports.py +161 -0
- xbsl-0.16.0/xbsl/rules/yaml_properties.py +99 -0
- xbsl-0.16.0/xbsl/rules/yaml_schema.py +201 -0
- xbsl-0.16.0/xbsl/rules/yaml_types.py +210 -0
- xbsl-0.16.0/xbsl/scaffold.py +1547 -0
- xbsl-0.16.0/xbsl/web.py +488 -0
- xbsl-0.16.0/xbsl.egg-info/PKG-INFO +445 -0
- xbsl-0.16.0/xbsl.egg-info/SOURCES.txt +101 -0
- xbsl-0.16.0/xbsl.egg-info/dependency_links.txt +1 -0
- xbsl-0.16.0/xbsl.egg-info/entry_points.txt +9 -0
- xbsl-0.16.0/xbsl.egg-info/requires.txt +14 -0
- xbsl-0.16.0/xbsl.egg-info/top_level.txt +2 -0
- 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
|
+

|
|
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).
|