Skip to content

Commit 12f6f91

Browse files
(GH-538) Add dsc-lib-jsonschema crate
This change begins the schema canonicalization process by adding a new library crate to contain the helpers for defining canonical and enhanced schemas ergonomically. In this initial phase, the new crate defines: - The `VSCODE_KEYWORDS` constant, enumerating the keywords that VS Code's JSON language server recognizes. - The `idiomaticize_string_enum` transformer for munging the generated schemas for string enums with annotation keywords. - The `idiomaticize_externally_tagged_enum` transformer for munging the generated schemas for externally tagged enums to a more idiomatic and readable representation.
1 parent 997f9c1 commit 12f6f91

File tree

19 files changed

+1700
-0
lines changed

19 files changed

+1700
-0
lines changed

Cargo.lock

Lines changed: 35 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ resolver = "2"
55
members = [
66
"dsc",
77
"lib/dsc-lib",
8+
"lib/dsc-lib-jsonschema",
89
"resources/dscecho",
910
"lib/dsc-lib-osinfo",
1011
"resources/osinfo",
@@ -27,6 +28,7 @@ members = [
2728
default-members = [
2829
"dsc",
2930
"lib/dsc-lib",
31+
"lib/dsc-lib-jsonschema",
3032
"resources/dscecho",
3133
"lib/dsc-lib-osinfo",
3234
"resources/osinfo",
@@ -51,6 +53,7 @@ default-members = [
5153
Windows = [
5254
"dsc",
5355
"lib/dsc-lib",
56+
"lib/dsc-lib-jsonschema",
5457
"resources/dscecho",
5558
"lib/dsc-lib-osinfo",
5659
"resources/osinfo",
@@ -70,6 +73,7 @@ Windows = [
7073
macOS = [
7174
"dsc",
7275
"lib/dsc-lib",
76+
"lib/dsc-lib-jsonschema",
7377
"resources/dscecho",
7478
"lib/dsc-lib-osinfo",
7579
"resources/osinfo",
@@ -86,6 +90,7 @@ macOS = [
8690
Linux = [
8791
"dsc",
8892
"lib/dsc-lib",
93+
"lib/dsc-lib-jsonschema",
8994
"resources/dscecho",
9095
"lib/dsc-lib-osinfo",
9196
"resources/osinfo",
@@ -206,8 +211,13 @@ cc = { version = "1.2" }
206211
# registry, dsc-lib-registry
207212
static_vcruntime = { version = "2.0" }
208213

214+
# test-only dependencies
215+
# dsc-lib-jsonschema
216+
pretty_assertions = { version = "1.4.1" }
217+
209218
# Workspace crates as dependencies
210219
dsc-lib = { path = "lib/dsc-lib" }
220+
dsc-lib-jsonschema = { path = "lib/dsc-lib-jsonschema" }
211221
dsc-lib-osinfo = { path = "lib/dsc-lib-osinfo" }
212222
dsc-lib-security_context = { path = "lib/dsc-lib-security_context" }
213223
tree-sitter-dscexpression = { path = "grammars/tree-sitter-dscexpression" }

build.data.psd1

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,12 @@
244244
)
245245
}
246246
}
247+
@{
248+
Name = 'dsc-lib-jsonschema'
249+
RelativePath = 'lib/dsc-lib-jsonschema'
250+
Kind = 'Library'
251+
IsRust = $true
252+
}
247253
@{
248254
Name = 'dsc-lib'
249255
RelativePath = 'lib/dsc-lib'

build.ps1

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,7 @@ if (!$SkipBuild) {
356356
".",
357357
"grammars/tree-sitter-dscexpression",
358358
"grammars/tree-sitter-ssh-server-config",
359+
"lib/dsc-lib-jsonschema",
359360
"lib/dsc-lib-security_context",
360361
"lib/dsc-lib-osinfo",
361362
"lib/dsc-lib",

lib/dsc-lib-jsonschema/Cargo.toml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
[package]
2+
name = "dsc-lib-jsonschema"
3+
version = "0.0.0" # version stays 0.0.0 until we're ready to publish - should pin to dsc-lib.
4+
edition = "2024"
5+
6+
[lib]
7+
doctest = false # Disable doc tests for compilation speed
8+
9+
[dependencies]
10+
regex = { workspace = true }
11+
rust-i18n = { workspace = true }
12+
schemars = { workspace = true }
13+
serde = { workspace = true }
14+
serde_json = { workspace = true }
15+
tracing = { workspace = true }
16+
17+
[dev-dependencies]
18+
# Helps review complex comparisons, like schemas
19+
pretty_assertions = { workspace = true }
20+
21+
[lints.clippy]
22+
pedantic = { level = "deny" }
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
_version = 1
2+
3+
[transforms.idiomaticize_externally_tagged_enum]
4+
applies_to = "invalid application of idiomaticize_externally_tagged_enum; missing 'oneOf' keyword in transforming schema: %{transforming_schema}"
5+
oneOf_array = "invalid application of idiomaticize_externally_tagged_enum; 'oneOf' isn't an array in transforming schema: %{transforming_schema}"
6+
oneOf_item_as_object = """
7+
invalid application of idiomaticize_externally_tagged_enum; items in 'oneOf' should always be objects, but encountered an invalid item in transforming schema:
8+
9+
invalid item: %{invalid_item}
10+
11+
transforming schema: %{transforming_schema}
12+
"""
13+
oneOf_item_define_type = """
14+
invalid application of idiomaticize_externally_tagged_enum; every entry in oneOf should define the 'type' keyword, but encountered an invalid item in transforming schema:
15+
16+
invalid item: %{invalid_item}
17+
18+
transforming schema: %{transforming_schema}
19+
"""
20+
oneOf_item_type_string = """
21+
invalid application of idiomaticize_externally_tagged_enum; the value for the 'type' keyword should be a string, but was invalid in transforming schema:
22+
23+
invalid item: %{invalid_item}
24+
25+
transforming schema: %{transforming_schema}
26+
"""
27+
oneOf_item_not_object_type = """
28+
invalid application of idiomaticize_externally_tagged_enum; expected type for 'oneOf' entry to be 'object' but was '%{item_data_type}' in transforming schema:
29+
30+
invalid item: %{invalid_item}
31+
32+
transforming schema: %{transforming_schema}
33+
"""
34+
oneOf_item_properties_missing = """
35+
invalid application of idiomaticize_externally_tagged_enum; expected each item in oneOf to define an object with properties, but encountered invalid item in transforming schema:
36+
37+
invalid item: %{invalid_item}
38+
39+
transforming schema: %{transforming_schema}
40+
"""
41+
oneOf_item_properties_not_object = """
42+
invalid application of idiomaticize_externally_tagged_enum; the 'properties' keyword should always be an object, but encountered invalid item in transforming schema:
43+
44+
invalid item: %{invalid_item}
45+
46+
transforming schema: %{transforming_schema}
47+
"""
48+
oneOf_item_properties_entry_not_object = """
49+
invalid application of idiomaticize_externally_tagged_enum; the property '%{name}' in the 'oneOf' item's 'properties' keyword should always be an object, but was something else in transforming schema:
50+
51+
invalid item: %{invalid_item}
52+
53+
transforming schema: %{transforming_schema}
54+
"""
55+
56+
[transforms.idiomaticize_string_enum]
57+
applies_to = "invalid application of idiomaticize_string_enum; missing 'oneOf' keyword in transforming schema: %{transforming_schema}"
58+
oneOf_array = "invalid application of idiomaticize_string_enum; 'oneOf' isn't an array in transforming schema: %{transforming_schema}"
59+
oneOf_item_as_object = """
60+
invalid application of idiomaticize_string_enum; items in 'oneOf' should always be objects, but encountered an invalid item in transforming schema:
61+
62+
invalid item: %{invalid_item}
63+
64+
transforming schema: %{transforming_schema}
65+
"""
66+
oneOf_item_define_type = """
67+
invalid application of idiomaticize_string_enum; every entry in oneOf should define the 'type' keyword, but encountered an invalid item in transforming schema:
68+
69+
invalid item: %{invalid_item}
70+
71+
transforming schema: %{transforming_schema}
72+
"""
73+
oneOf_item_type_string = """
74+
invalid application of idiomaticize_string_enum; the value for the 'type' keyword should be a string, but was invalid in transforming schema:
75+
76+
invalid item: %{invalid_item}
77+
78+
transforming schema: %{transforming_schema}
79+
"""
80+
oneOf_item_not_string_type = """
81+
invalid application of idiomaticize_string_enum; expected type for 'oneOf' entry to be 'string' but was '%{invalid_type}' in transforming schema:
82+
83+
invalid item: %{invalid_item}
84+
85+
transforming schema: %{transforming_schema}
86+
"""
87+
oneOf_item_enum_not_array = """
88+
invalid application of idiomaticize_string_enum; the 'enum' keyword should always be an array, but encountered invalid item in transforming schema:
89+
90+
invalid item: %{invalid_item}
91+
92+
transforming schema: %{transforming_schema}
93+
"""
94+
oneOf_item_enum_item_not_string = """
95+
invalid application of idiomaticize_string_enum; every item in the 'enum' keyword should always be an array of strings, but encountered invalid item in transforming schema:
96+
97+
invalid item: %{invalid_item}
98+
99+
transforming schema: %{transforming_schema}
100+
"""
101+
oneOf_item_const_missing = """
102+
invalid application of idiomaticize_string_enum; documented items in a string enum are generated as subschemas with the 'const' keyword, but encountered invalid item in transforming schema:
103+
104+
invalid item: %{invalid_item}
105+
106+
transforming schema: %{transforming_schema}
107+
"""
108+
oneOf_item_const_not_string = """
109+
invalid application of idiomaticize_string_enum; the value for the 'const' keyword in a string enum should be a string, but encountered invalid item in transforming schema:
110+
111+
invalid item: %{invalid_item}
112+
113+
transforming schema: %{transforming_schema}
114+
"""

lib/dsc-lib-jsonschema/src/lib.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// Licensed under the MIT License.
3+
4+
//! Helper library for working with DSC and JSON Schemas.
5+
6+
use rust_i18n::i18n;
7+
8+
#[macro_use]
9+
pub mod macros;
10+
11+
pub mod vscode;
12+
pub mod transforms;
13+
14+
#[cfg(test)]
15+
mod tests;
16+
17+
// Enable localization for emitted strings
18+
i18n!("locales", fallback = "en-us");
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// Licensed under the MIT License.
3+
4+
//! Defines macros used by the module.
5+
6+
/// Panics with a translated message.
7+
macro_rules! panic_t {
8+
($($all:tt)*) => {
9+
panic!("{}", crate::_rust_i18n_t!($($all)*))
10+
};
11+
}
12+
13+
/// Asserts an expression evaluates to true or panics with a translated message.
14+
macro_rules! assert_t {
15+
($expr:expr, $($tail:tt)*) => {
16+
assert!($expr, "{}", crate::_rust_i18n_t!($($tail)*))
17+
};
18+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// Licensed under the MIT License.
3+
4+
//! Defines unit tests for [`dsc-lib-jsonschema`].
5+
//!
6+
//! Instead of defining tests in each of the module files for the crate, we
7+
//! define them in this module to improve compilation times. The tests in this
8+
//! module are for internal code. Do not define tests for public items in this
9+
//! module. Instead, define those tests in the `tests/integration` folder,
10+
//! which forces usage of the crate as a public API.
11+
//!
12+
//! When you define tests in this module, ensure that you mirror the structure
13+
//! of the modules from the rest of the source tree.
14+
15+
#[cfg(test)] mod transforms;
16+
#[cfg(test)] mod vscode;
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// Licensed under the MIT License.
3+
4+
//! Unit tests for [`dsc-lib-jsonschema::transforms`]

0 commit comments

Comments
 (0)