Rendered from specs/F04-binding.md — edit it there, not here.
F04 — Schema–File Binding
Overview
The extension allows users to associate (bind) a JSON Schema file with one or more data files. Bindings are stored in VS Code's standard json.schemas / yaml.schemas settings entries so both the extension and VS Code's built-in language server recognise them.
User Stories
- As a developer, I want to bind
data/user.jsontoschemas/user.schema.jsonso validation and IntelliSense work without adding$schemato every file. - As a team lead, I want bindings committed in
.vscode/settings.jsonso all team members get them automatically.
Functional Requirements
Binding Command
- F04-FR-01 The command
jsonschema.bindToCurrentFileMUST present a Quick Pick list of all JSON Schema files discovered asynchronously in the open workspace folder(s). - F04-FR-02 The user MUST be prompted to choose a scope: Workspace file (only when a
.code-workspacefile exists), Workspace folder, or User. - F04-FR-03 The binding MUST be written to the appropriate
json.schemas/yaml.schemasVS Code setting at the chosen scope. - F04-FR-04 A YAML data file (
.yaml/.yml) MUST be bound viayaml.schemas; all other supported formats MUST usejson.schemas.
Status Bar
- F04-FR-05 The status bar item MUST be visible whenever a supported data file (JSON, JSONC, JSONL, YAML, YML) is the active editor.
- F04-FR-06 When a schema is bound the status bar item MUST display
$(check) Schema: <basename>and a tooltip showing the full schema path and a hint to click to change or remove.<basename>MUST be start-truncated to a bounded length of ~20 characters (a single leading ellipsis eliding the beginning, keeping the legible end — the distinguishing part and the file extension) when it would otherwise be long, so the item cannot grow unbounded and push other status-bar items off-screen; the full, untruncated name MUST remain visible in the tooltip. - F04-FR-07 When no schema is bound and no native schema is detected (F04-FR-15) the status bar item MUST display
$(circle-slash) Schema: unboundwith a tooltip offering to bind one. - F04-FR-08 Clicking the status bar item MUST execute
jsonschema.bindToCurrentFile. - F04-FR-15 When the file has no explicit binding (neither inline
$schemanor a settings binding) but matches a schema that VS Code resolves natively — an installed extension'scontributes.jsonValidationfileMatch, or a SchemaStore/user-catalog entry (F12) when the catalog is enabled — the status bar item MUST reflect that resolved schema with an informational auto state ($(check) Schema: <name> (auto)) instead of$(circle-slash) unbound, so the bar stays coherent with the validation VS Code already provides. The tooltip MUST explain the schema is provided automatically and that JSON Schema Preview's own features still use an explicit binding (the click target is unchanged, F04-FR-08). Detection MUST be synchronous in the status-bar refresh path (extension contributions are in-memory; the catalog is read from its existing cache); the catalog MAY be warmed once per session in the background, reusing F12's fetch under its existingjsonschema.catalogconfig gate — it introduces no new network category beyond the catalog fetch F12 already makes. An explicit binding (F04-FR-06) always takes precedence over the auto state.
Context and Explorer Menus
- F04-FR-09 The Bind Schema… entry MUST appear in the editor context menu for supported data files.
- F04-FR-10 The Bind Schema… entry MUST appear in the Explorer context menu for files with extensions
.json,.jsonc,.jsonl,.yaml,.yml.
Local Cache Redirection
- F04-FR-11 When a schema is cached locally (see F08) the binding that previously pointed at the remote URL MUST be updated to point at the local cache path.
Legacy Cleanup
- F04-FR-12 On startup the extension MUST silently clean up any session-scoped temporary bindings written by older versions of the extension.
Local Schema Path Resolution
- F04-FR-13 When the picked schema is a local file, the stored
url/$schemavalue MUST be a./-prefixed relative path only for WorkspaceFolder scope and only when the schema file lives in the same workspace folder as the data file being bound. In every other case the value MUST be the absolute file system path, because:- a relative
urlis resolved against the data file's workspace folder (both by VS Code's language servers reading the folder's.vscode/settings.jsonand by this extension's own validator), so a path made relative to a different workspace folder of a multi-root workspace would silently resolve inside the wrong project; - relative
json.schemas/yaml.schemasurlresolution is documented as unreliable once the setting is defined outside a single folder's own.vscode/settings.json(see microsoft/vscode#156006, #181187, #92348), which previously caused schema loading to silently fail for Workspace-scoped bindings; and - User (Global) settings apply machine-wide and have no single workspace folder to resolve a relative path against.
- When the picked schema file is outside the workspace entirely, the absolute path MUST be used regardless of scope (pre-existing behaviour).
- a relative
Reading Back a Binding
- F04-FR-14 Any code that determines whether the active document has a bound schema (the status bar, the validator, F08's cache auto-revalidation) MUST resolve
json.schemas/yaml.schemasthe same way VS Code itself does for that document: scoped to the document's own resource (so a WorkspaceFolder-scoped entry written in a different folder's.vscode/settings.jsonis correctly excluded), and checked against every scope that can hold a binding for that document — Global, Workspace, and the document's own WorkspaceFolder — since a workspace can contain bindings written at different scopes for different files simultaneously. Matching MUST try both path forms a binding can be stored in (plain folder-relative, from WorkspaceFolder/Global scope, and workspace-root-relative with a folder-name prefix, from Workspace scope in a multi-root workspace — see F04-FR-13 andrelFileForTarget), since which form applies depends on which scope produced the entry, not on which scope is being read.
Acceptance Criteria
- Binding
person-valid.jsontoperson.schema.jsonat Workspace scope adds an entry to.vscode/settings.jsonunderjson.schemas. - The status bar shows
$(check) Schema: person.schema.jsonafter binding. - After removal the status bar reverts to
$(circle-slash) Schema: unbound. - Binding a local schema at Workspace or User scope stores the absolute file system path; binding the same schema at WorkspaceFolder scope stores a
./-relative path instead (F04-FR-13). - In a multi-root workspace, binding a schema that lives in a different workspace folder than the data file stores the absolute path at every scope — never a
./-relative path that would resolve inside the data file's own folder (F04-FR-13). - In a multi-root workspace with two folders, a WorkspaceFolder-scoped binding written in folder A is recognised by the status bar and validator for files in folder A, and does not leak into folder B; a Workspace-scoped binding (folder-prefixed
fileMatch) is recognised for the file it names regardless of which folder is currently active (F04-FR-14).
Requirement traceability
Status of each requirement in specs/traceability.json. Test coverage is auto-discovered from [ID] tags in test titles and is not listed here.
| Requirement | Status | Implementation | Note |
|---|---|---|---|
F04-FR-01 | implemented | src/SchemaBindingManager.ts | Quick Pick of discovered schemas (unit-tested) |
F04-FR-02 | implemented | src/SchemaBindingManager.ts | scope selection (unit-tested) |
F04-FR-03 | implemented | src/SchemaBindingManager.ts | writes json.schemas/yaml.schemas (unit-tested) |
F04-FR-04 | implemented | src/SchemaBindingManager.ts | YAML via yaml.schemas (unit-tested) |
F04-FR-05 | implemented | src/SchemaBindingManager.ts | status-bar visibility (unit-tested) |
F04-FR-06 | implemented | src/SchemaBindingManager.ts, src/statusBarFormat.ts | bound display; long basenames start-truncated (~20 chars, keeping the end/extension) via truncateStart (statusBarFormat.ts), full name kept in the tooltip — unit-tested (pure helper + status-bar label/tooltip) |
F04-FR-07 | implemented | src/SchemaBindingManager.ts | unbound display (unit-tested) |
F04-FR-08 | manual | src/SchemaBindingManager.ts | VS Code API-bound; verified by manual / E2E testing |
F04-FR-09 | implemented | package.json | editor/context Bind Schema for data langs, !isJsonSchema |
F04-FR-10 | implemented | package.json | explorer/context Bind Schema for .json/.jsonc/.jsonl/.yaml/.yml |
F04-FR-11 | manual | src/SchemaBindingManager.ts | VS Code API-bound; verified by manual / E2E testing |
F04-FR-12 | manual | src/SchemaBindingManager.ts | VS Code API-bound; verified by manual / E2E testing |
F04-FR-13 | implemented | src/SchemaBindingManager.ts | resolveLocalSchemaRef(): relative only for WorkspaceFolder/Inline scope AND only when the schema is in the same workspace folder as the data file; absolute otherwise (Workspace/Global scope, schema outside the workspace, or schema in a different folder of a multi-root workspace). |
F04-FR-14 | implemented | src/SchemaBindingManager.ts | findBoundSchemaPath resolves scoped to doc.uri and unions Global/Workspace/WorkspaceFolder, matching both folder-relative and workspace-prefixed path forms |
F04-FR-15 | implemented | src/nativeSchema.ts, src/SchemaBindingManager.ts, src/SchemaCatalogManager.ts | status bar shows an auto state when VS Code resolves a schema natively (jsonValidation or SchemaStore catalog) instead of unbound |