config: generate & check schema for configuration automatically#413
config: generate & check schema for configuration automatically#413
Conversation
|
Update:
Based on the discussion with @aviatesk, the ideal system we want to achieve is as follows:
Steps 1 and 2 have already been achieved. To achieve step 3, there are still some remaining issues. First, the However, this is easy problem, since it can be worked around by inlining references. The biggest remaining task is support for default values. I plan to implement a straightforward API for registering default values, such as: In some cases, such as the After that is done, I think it will be ready to merge once we finalize a small interface for how and where to define description and other data, and update the devdocs accordingly. |
aviatesk
left a comment
There was a problem hiding this comment.
This is a great change. Really appreciate you working on this.
Your approach for default values sounds good too.
Just one thing to keep in mind: I will merge #415, so we'll need to update things like diagnostic descriptions. (Apologies for making schema changes while this PR was in progress.)
Anyway, just let me know when you think it's good to go, and I think we can merge it directly.
|
I think it will take a few days to implement features related to default values, so please feel free to update the configuration structures as you like :) Additional note: It would be nice if we could generate descriptions from docstrings, but unfortunately Configurations.jl does not seem to retain docstrings for individual fields. As we discussed before, this may require creating a separate package tailored for this purpose. |
|
Yeah, we need some macro hacks to preserve field docs information (just realized this when I were writing Anyway, the current
And I understand that jetls-client/package.json (or part of it) will be generated from |
Yes, that’s correct. |
|
Yes, this kind of information for developers should go to DEVELOPMENT.md. |
22649ea to
d4b6ce2
Compare
|
UPDATE: Struct2JSONSchema.jl now supports features such as setting default values easily. Remaining tasks:
|
|
Great progress. Let me know if you need a new review round. |
d4b6ce2 to
4f63561
Compare
|
Support for updating As shown below, schema_pr_demo.movThere is still one point that needs discussion.
Once this point is decided, I will write the developer documentation, review description and some implementations, and then it should be ready to merge. |
923d39a to
8407664
Compare
|
Automatically updating package.json with bots or actions is one idea, but I'm concerned that it might make the operational policy a bit complicated. Since config updates don't happen very frequently, it might be fine to force devs to update package.json whenever we make changes to configuration using the update script in ./scripts? And, on the jetls-client side, we would set up CI that verfies whether the currently checked-in package.json is consistent with the current JETLS configuration schema. |
7ccd404 to
b1dc704
Compare
|
Taking your feedback into account, I changed the setup as follows.
I also rewrote 1. Description updatesFor example, the description of 2. Added fieldsFields such as |
Thanks 👍 |
scripts/schema/update-pkg-json.jl
Outdated
| else | ||
| settings["properties"] = expected_props | ||
| open(package_json_path, "w") do io | ||
| write(io, JSON.json(package_json, 2)) |
There was a problem hiding this comment.
Should we use OrderedDict or similar technique to ensure stable output? Or does JSON.jl already handle that functionality? I kinda want the output to be deterministic and ideally sorted alphabetically in terms of JSON's key order.
There was a problem hiding this comment.
As you pointed out, it seems necessary to make it deterministic.
Since computation time and implementation are not an issue, explicitly sorting the results before generating the output should be sufficient. I’ll add that.
scripts/schema/generate.jl
Outdated
| include("lib.jl") | ||
|
|
||
| gen_ctx = SchemaContext() | ||
| setup_ctx!(gen_ctx) | ||
|
|
||
| schema = generate_schema(JETLS.JETLSConfig; ctx = gen_ctx) | ||
|
|
||
| schemafile_path = joinpath(@__DIR__, "..", "..", "jetls-config.schema.json") | ||
| open(schemafile_path, "w") do io | ||
| write(io, JSON.json(schema.doc, 2)) | ||
| end | ||
|
|
There was a problem hiding this comment.
I'm thinking of adding a --check option to this script as well.
The reason is, I want to add a feature like jetls schema to the main JETLS.jl app, so that JETLS can output the schema itself. For this, I'm thinking we could check in the JSON schema directly into the JETLS.jl git checkout, similar to package.json for jetls-client. The idea is that JETLS would then include_dependency the schema file and use it for the jetls schema app output.
Some editors can get JSON schemas directly from language server extensions and use them for autocompletion (zed-industries/zed#48334). While editors might be able to pull schemas from a remote source, I think outputting it locally would be the best solution for consistency.
Moving back to the original point, for CI, similar to package.json, we could check if the currently checked-in schema is consistent with the JETLS state.
|
Great job. Can we generate a similar schema for |
| completion = "Completion configuration. See [Completion configuration](https://aviatesk.github.io/JETLS.jl/release/configuration/#config/completion)." | ||
| code_lens = "Code lens configuration. See [Code lens configuration](https://aviatesk.github.io/JETLS.jl/release/configuration/#config/code_lens)." | ||
| inlay_hint = "Inlay hint configuration. See [Inlay hint configuration](https://aviatesk.github.io/JETLS.jl/release/configuration/#config/inlay_hint)." | ||
| initialization_options = "Static initialization options that are set once at server startup and require a server restart to take effect. See [Initialization options](https://aviatesk.github.io/JETLS.jl/release/launching/#init-options)." |
There was a problem hiding this comment.
I don't think the schema for JETLSConfig (, which basically corresponds to what handled by workspace/configuration) should not contain anything about initialization_options, since they are just different ways to configure the server.
There was a problem hiding this comment.
On second thought, maybe description.toml itself should be as is, as the single source for all descriptions of dynamic settings (workspace/configuration) and initialization options. Rather, JETLS should output three types of schemas, and CI should probably validate each of them:
- Schema for dynamic settings
- Schema for initialization options
- Schema for
.JETLSConfig.toml(schema of dynamic settings + initialization options)
Co-Authored-By: Claude <claude@users.noreply.github.com>
Co-Authored-By: Claude <claude@users.noreply.github.com>
Co-Authored-By: Claude <claude@users.noreply.github.com>
Co-Authored-By: Claude <claude@users.noreply.github.com>
Co-Authored-By: Claude <claude@users.noreply.github.com>
Add `jetls schema` CLI subcommand that prints JSON schema files from `schemas/` directory to stdout. Supports `--settings`, `--init-options`, and `--config-toml` flags. Add process-based tests in `test/app/test_jetls_schema.jl` that spawn `julia -m JETLS schema` subprocesses, matching the existing pattern for `test_jetls_check.jl` and `test_jetls_serve.jl`. Add a reusable `check-schemas.yml` workflow that verifies schema files are up to date by running `generate.jl --check`. This is called from both `JETLS.jl.yml` and `release.yml`. Also update `JETLS.jl.yml` path triggers to include `schemas/**` and `scripts/schema/**`, update `prepare-release.sh` checklist.
e6407a3 to
e00ded3
Compare
- Add `jetls schema` command entry to `launching.md` and link to the new JSON Schema section in `configuration.md` - Add `analysis_overrides` initialization option reference to `launching.md` - Add `## JSON Schema` section to `configuration.md` listing the three schema files (`config-toml.schema.json`, `settings.schema.json`, `init-options.schema.json`) with download links, and a `jetls schema` CLI usage example - Update CHANGELOG `## Unreleased` with Added entries for `jetls schema` CLI and the schema generation infrastructure - Upload schema files as GitHub Release assets in `release.yml`
|
Working beautifully. Thanks so much for your work on this, @abap34 ! |


Summary
As the configuration has grown more complex, it has become increasingly difficult for users to write correct configuration files without tool support. This PR adds JSON Schema generation for the configuration to support user.
The schema is automatically generated at release time and published as a release asset, enabling:
jetls-schema-demo.mov
Implementation details
For this feature, I developed Struct2JSONSchema.jl, which generates JSON Schemas without requiring any modifications to existing struct definitions. This approach is well-suited for projects like this one, where schema generation is optional and should remain decoupled from the core codebase.
A new script
scripts/schema/generate.jluses Struct2JSONSchema.jl to generate a JSON Schema from theJETLSConfigstruct definition.Users can reference the schema in their editor configuration:
Notes
Struct2JSONSchema.jl is not yet registered in the Julia package registry, so the release workflow currently references it directly from GitHub. Once it is registered, this will be switched to using the registry version. It would be also reasonable choice to wait for that registration before merging this PR. (This is why this PR is draft)registered.Try it now
For testing purposes, a temporary schema is currently hosted at https://www.abap34.com/jetls-config.schema.json. You can try it by either:
.JETLSConfig.toml:#:schema https://www.abap34.com/jetls-config.schema.jsonTasks