Линтер исходников 1С:Элемент (пары .yaml/.xbsl)
Project description
xbsl-lint
English · Русский
A linter for 1C:Element sources — it checks Name.yaml (element description) and Name.xbsl
(code module) pairs before the server-side compilation that happens on deploy.
Not affiliated with 1C. "1C:Element", "1C:Fresh" and related names are trademarks of their respective owners. Language data is generated from your own distribution. See NOTICE.
Why
1C:Element has no external linter: the only code check is the server-side compilation on deploy — it is slow and knows nothing about project conventions. xbsl-lint gives fast local feedback and catches what the compiler does not check at all.
Step 1: generate the language data
The linter relies on language tables (bilingual keywords, operators), an stdlib type catalog, and
the configuration metamodel (element properties). XBSL is built on Eclipse Xtext + ANTLR; these are
extracted from your 1C:Element distribution (the InternalBsl.g grammar, the documentation, and
the .xcore metamodel) and are NOT bundled in this repository. Generate them locally:
python tools/extract_grammar.py --dist "<path to the 1C:Element distribution>"
python tools/extract_stdlib.py --dist "<path to the 1C:Element distribution>"
python tools/extract_metamodel.py --dist "<path to the 1C:Element distribution>"
The scripts auto-detect the platform version and place the data under
xbsllint/data/element/<version>/ (this folder is gitignored). Without the data, the linter and
the tests will tell you to generate it. Pass --data-dir (or set XBSLLINT_DATA_DIR) to write the
data somewhere else – for instance into a private package that ships it, see
Extending.
Step 2: install and run
pip install xbsllint # or, from a clone: pip install -e .
xbsllint path/to/sources # or: python -m xbsllint path/to/sources
The extractors from step 1 ship with the repository, not with the PyPI package — clone the repository to generate the data.
Flags: --list-rules, --select/--enable/--ignore (by rule id, rule group — the part of the id
before / — or tier letter), --fix, --baseline/--write-baseline, --element-version,
--data-dir, --lang, --format text|json|codeclimate.
--fix repairs the mechanical findings in place — trailing whitespace, typography characters
(em dash → en dash, … → ..., curly quotes and comment guillemets → straight), and mixed
newlines (normalized to the dominant style) — then reports whatever is left. It only applies
unambiguous edits and only for rules active in the run (so --fix --enable typography also pays
down the em-dash/guillemets debt); anything needing judgment is never touched.
For editor integration, --stdin --filename NAME checks a single buffer read from stdin (per-file
rules only); the JSON payload ({diagnostics, summary}) is the same one the MCP server returns.
xbsllint --index PATH dumps a JSON index of the project to stdout instead of linting – the
objects (with tabular sections, module-declared local types and the member families for dot
completion), the method declarations with their annotations and the named form components, with
POSIX paths relative to the root and 1-based lines – for go-to-definition and completion in
editors.
--format codeclimate emits a GitLab Code Quality report (Code Climate issues) with paths relative
to the current directory — run it from the repository root and save the output as the
codequality artifact.
Output language
Rule titles and diagnostic messages come in Russian and English. The language is picked by
--lang ru|en > the XBSLLINT_LANG env var > the system locale > Russian. Type names, keywords
and other XBSL text inside a message are never translated — only the wording around them. The MCP
server and the web panel follow the same setting (the web panel also has an in-page RU/EN toggle).
Rule tiers
- A. Structure and YAML —
.xbsl/.yamlpairing, schema validity,Идas a UUID,Идuniqueness,Имяmatching the file name. - B. Text and conventions — typography (en dash, straight quotes), encoding/BOM/newlines/trailing whitespace, indentation and line length.
- C. Code structure — balance of blocks and
;, brackets, unused local and loop variables, a structure reference field that must beобз, plus the platform's code style conventions (thestyle/group, see below). - D. Semantics — against platform data and the project itself: types, enumeration values, cross-file consistency (see below).
The type rules of tier D cover every type position in code (новый, как casts, annotations,
signatures) and every Тип: value in yaml (unions А|Б|?, generics, nullable): the root must
be a known type — stdlib, a project object or a module-declared local type — and a dotted chain
rooted at a project object must stay within the family that object generates: the derived types
extracted from the distribution docs (Ссылка, Объект, СоздатьОбъект, the automatic
forms...), its tabular sections and module structures. Namespace-qualified references
(Справочник.X.Ссылка) also check that the object exists under that kind, and the values of
project enumerations are verified both in code and in yaml bindings.
The cross-file rules of tier D catch what the compiler reports late or not at all: a yaml
handler missing from the paired module, a foreign-subsystem type used without an Импорт:
entry, a dynamic list typed by the automatic list form that misses an attribute of its object,
a cross-component Компоненты.X.Метод() call to a method without a visibility annotation,
environment mismatches (@НаСервере called from a client handler without @ДоступноСКлиента,
a client-only module used from an HTTP service), reserved names (Тип/type as a field or
parameter, a component property named like a built-in one), methods that nothing references,
and top-level yaml properties against the configuration metamodel.
Code style conventions (the style/ rules)
Twenty-one rules that follow the platform documentation ("Code style conventions" and "Language
idioms"): layout and expression wrapping, naming, type descriptions and signatures, collection
literals, string interpolation, and checks of boolean values and Неопределено.
Rules that clean code already satisfies are enabled by default (warning) — they guard against
regressions. Rules that typically fire on accumulated legacy debt are info and disabled; enable
them to measure the debt and pay it down:
xbsllint path/to/sources --select style # ONLY these rules (replaces the default set)
xbsllint path/to/sources --enable style # the default set PLUS these
xbsllint path/to/sources --ignore style # the default set minus these
--select, --enable and --ignore accept a rule id, a group (the part before /) or a tier
letter, repeated or comma-separated. --select narrows to exactly the given rules; --enable
switches on off-by-default rules on top of the defaults.
Запрос{ ... } blocks (the query DSL) and string literals (HTML/CSS/SVG in web views) are
excluded from these checks. Not covered, and left to the author and review: indentation being a
multiple of four, collection idioms, Строки.Соединить() for bulk concatenation, the ?. / ??
idioms, and выбор instead of an иначе если chain.
Baseline: adopt a rule on a legacy codebase
To enable a rule over code that already violates it without drowning in legacy findings, freeze the current findings into a baseline and hold only new code to the rule:
xbsllint e1c/site --enable style --write-baseline baseline.json # freeze the debt once
xbsllint e1c/site --enable style --baseline baseline.json # only NEW findings surface
A finding's identity is (file, rule, message) with an allowed count, so moving a line keeps its
finding suppressed while a genuinely new violation surfaces. The summary reports how many findings
the baseline suppressed and how many of its entries are now stale (debt paid down) — a signal to
rewrite the file. Paths are stored relative to the baseline file, so commit it at the repository
root and run the linter from anywhere.
Extending: your own rules and data
Two entry point groups let a separate package extend the linter without forking it. This exists for
teams whose rules or language data cannot be published: keep those in a private package that depends
on xbsllint.
# pyproject.toml of your package
dependencies = ["xbsllint>=0.3"]
[project.entry-points."xbsllint.rules"]
myproject = "myproject.rules" # importing the module runs its @rule decorators
[project.entry-points."xbsllint.data"]
myproject = "myproject:data_root" # a path, or a callable returning one
Install the package and the CLI, the MCP server and the web UI all pick both up – no flags, no
config file. A failing entry point raises instead of warning: a linter that silently drops a rule
stays green in CI and guarantees nothing. XBSLLINT_NO_PLUGINS=1 ignores every external package
(built-in rules and bundled data only).
MCP server
A thin adapter over the same core: an agent (e.g. Claude Code) can call the checks as tools and receive structured diagnostics.
pip install -e ".[mcp]"
claude mcp add xbsllint -- xbsllint-mcp
Tools: lint_paths(paths), lint_source(filename, content), list_rules(). The core and the CLI
do not require mcp — it lives only in the [mcp] extra.
Web interface
A local page: point it at a project folder and see the diagnostics. Standard library only (no
external dependencies), binds to 127.0.0.1 only.
xbsllint-web # then open http://127.0.0.1:8771/
Per-tier rule toggles, a data-version selector, severity/text filters, dark/light theme; clicking
a diagnostic opens the file in VS Code (vscode://).
Editor support (VS Code)
A VS Code extension in editors/vscode gives .xbsl syntax highlighting,
live diagnostics as you type (--stdin), workspace diagnostics on save (a full linter run in
the background brings the project-scope rules into the editor), and index-based go-to-definition
and completion across the project (xbsllint --index). Build the .vsix with
npm install && npm run package in that folder; its README covers
settings, behavior and requirements.
Element versions
The data is versioned by platform version:
xbsllint/data/element/
index.json # { available: [...], default: "<version>" }
<version>/{language.json, stdlib.json, metamodel.json}
Pick a version with --element-version / the XBSLLINT_ELEMENT_VERSION env var / the index
default; --version shows what is available. Add a new version by re-running the extractors with
a new --dist.
The data root itself is resolved in this order: --data-dir > XBSLLINT_DATA_DIR > a root supplied
by an installed xbsllint.data entry point > xbsllint/data/element inside the package.
Tests
pip install -e ".[dev]"
pytest
Data-dependent tests are skipped automatically when the data has not been generated.
License
MIT — see LICENSE. Trademarks and data provenance — NOTICE. How to add a rule — CONTRIBUTING.md.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file xbsllint-0.7.0.tar.gz.
File metadata
- Download URL: xbsllint-0.7.0.tar.gz
- Upload date:
- Size: 146.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
481817d2d26b57bd92b00661cb938a0106f3ffac64383ee989ee906135826e7a
|
|
| MD5 |
6d30f1bf263ee3adee8f2c8edd00b98e
|
|
| BLAKE2b-256 |
8fd29f0c6d120c153265d2589c237776b8935385dba89dbf7c0f97804b25a355
|
File details
Details for the file xbsllint-0.7.0-py3-none-any.whl.
File metadata
- Download URL: xbsllint-0.7.0-py3-none-any.whl
- Upload date:
- Size: 132.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
40857cec1e5ac90dc4f533de7840b63b9cc34e0d16e4e8e331721eb8578b6d8d
|
|
| MD5 |
7be6fa23f8197469db15134d9a15e9a2
|
|
| BLAKE2b-256 |
1b525222275ae58994f816aa7e0d254311f50e68740d20e9d9452186af4a529e
|