Repository: oxidecomputer/typify
Pull request #542 (2024-04-01 13:52:21)

Bump clap from 4.5.3 to 4.5.4
Bumps [clap](https://github.com/clap-rs/clap) from 4.5.3 to 4.5.4.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a href="https://github.com/clap-rs/clap/releases">clap's releases</a>.</em></p>
<blockquote>
<h2>v4.5.4</h2>
<h2>[4.5.4] - 2024-03-25</h2>
<h3>Fixes</h3>
<ul>
<li><em>(derive)</em> Allow non-literal <code>#[arg(id)]</code> attributes again</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a href="https://github.com/clap-rs/clap/blob/master/CHANGELOG.md">clap's changelog</a>.</em></p>
<blockquote>
<h2>[4.5.4] - 2024-03-25</h2>
<h3>Fixes</h3>
<ul>
<li><em>(derive)</em> Allow non-literal <code>#[arg(id)]</code> attributes again</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a href="https://github.com/clap-rs/clap/commit/5e4facf76fb38e04edba6cb1ab67d4f2b1ec8550"><code>5e4facf</code></a> chore: Release</li>
<li><a href="https://github.com/clap-rs/clap/commit/8880b0a5da1160892187c4b372881c9a5e2280c2"><code>8880b0a</code></a> docs: Update changelog</li>
<li><a href="https://github.com/clap-rs/clap/commit/132b5dded50e3e4341931f4894ccb2746196c741"><code>132b5dd</code></a> Merge pull request <a href="https://redirect.github.com/clap-rs/clap/issues/5425">#5425</a> from epage/lit</li>
<li><a href="https://github.com/clap-rs/clap/commit/df915fefefba42493290c4f7c4ac627807e9ebd4"><code>df915fe</code></a> fix(derive): Re-allow expressions for id's</li>
<li><a href="https://github.com/clap-rs/clap/commit/8eab48fa3c9d6a40128c601b2520d33c7b3e6c2a"><code>8eab48f</code></a> refactor(derive): Make it easier to work with 'Name'</li>
<li><a href="https://github.com/clap-rs/clap/commit/be73195ecfe8a082783765f87036ce9ecf1ce7c8"><code>be73195</code></a> refactor(derive): Clarify tests</li>
<li><a href="https://github.com/clap-rs/clap/commit/024089bb602ee6f55ab1fd8494a20eb9b21c6b5e"><code>024089b</code></a> Merge pull request <a href="https://redirect.github.com/clap-rs/clap/issues/5415">#5415</a> from Pi-Cla/patch-1</li>
<li><a href="https://github.com/clap-rs/clap/commit/3b35dba1600ff84e6207668d9cba11276fa1c5b5"><code>3b35dba</code></a> docs: Add mention of nushell to clap_complete README</li>
<li><a href="https://github.com/clap-rs/clap/commit/58469d1669fa1e05080263fb38b12fb2d7b78180"><code>58469d1</code></a> Merge pull request <a href="https://redirect.github.com/clap-rs/clap/issues/5405">#5405</a> from epage/docs</li>
<li><a href="https://github.com/clap-rs/clap/commit/655d8295a7f2e8a4c655a11ba578636428a3c9ac"><code>655d829</code></a> docs(derive): Fix ToC links within tutorial chapters</li>
<li>See full diff in <a href="https://github.com/clap-rs/clap/compare/v4.5.3...v4.5.4">compare view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=clap&package-manager=cargo&previous-version=4.5.3&new-version=4.5.4)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)


</details>


Patch:
diff --git a/Cargo.lock b/Cargo.lock
index 13b5f90..a5a21ed 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -221,9 +221,9 @@ dependencies = [
 
 [[package]]
 name = "clap"
-version = "4.5.3"
+version = "4.5.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "949626d00e063efc93b6dca932419ceb5432f99769911c0b995f7e884c778813"
+checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0"
 dependencies = [
  "clap_builder",
  "clap_derive",
@@ -243,9 +243,9 @@ dependencies = [
 
 [[package]]
 name = "clap_derive"
-version = "4.5.3"
+version = "4.5.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "90239a040c80f5e14809ca132ddc4176ab33d5e17e49691793296e3fcb34d72f"
+checksum = "528131438037fd55894f62d6e9f068b8f45ac57ffa77517819645d10aed04f64"
 dependencies = [
  "heck 0.5.0",
  "proc-macro2",
diff --git a/cargo-typify/Cargo.toml b/cargo-typify/Cargo.toml
index 4aef1ed..5da943a 100644
--- a/cargo-typify/Cargo.toml
+++ b/cargo-typify/Cargo.toml
@@ -14,7 +14,7 @@ default-run = "cargo-typify"
 [dependencies]
 typify = { version = "0.0.16", path = "../typify" }
 
-clap = { version = "4.5.3", features = ["derive"] }
+clap = { version = "4.5.4", features = ["derive"] }
 color-eyre = "0.6"
 env_logger = "0.10"
 rustfmt-wrapper = "0.2.1"
diff --git a/typify-impl/src/value.rs b/typify-impl/src/value.rs
index 3e20f10..2c38ef2 100644
--- a/typify-impl/src/value.rs
+++ b/typify-impl/src/value.rs
@@ -377,6 +377,25 @@ fn value_for_struct_props(
 ) -> Option<Vec<TokenStream>> {
     let map = value.as_object()?;
 
+    let direct_props = properties.iter().filter_map(|prop| {
+        let name = match &prop.rename {
+            StructPropertyRename::None => &prop.name,
+            StructPropertyRename::Rename(rename) => rename,
+            StructPropertyRename::Flatten => return None,
+        };
+
+        let name_ident = format_ident!("{}", &prop.name);
+
+        if let Some(value) = map.get(name) {
+            let type_entry = type_space.id_to_entry.get(&prop.type_id).unwrap();
+            let prop_value = type_entry.output_value(type_space, value, scope)?;
+
+            Some(quote! { #name_ident: #prop_value })
+        } else {
+            Some(quote! { #name_ident: Default::default() })
+        }
+    });
+
     let prop_map = properties
         .iter()
         .filter_map(|prop| {
@@ -390,17 +409,6 @@ fn value_for_struct_props(
         })
         .collect::<BTreeMap<_, _>>();
 
-    let direct_props = map.iter().filter_map(|(name, value)| {
-        // It's okay if the property isn't in the prop_map... it must be part
-        // of one of the flattened properties.
-        let prop = prop_map.get(name)?;
-        let type_entry = type_space.id_to_entry.get(&prop.type_id).unwrap();
-        let prop_value = type_entry.output_value(type_space, value, scope)?;
-        let name_ident = format_ident!("{}", name);
-
-        Some(quote! { #name_ident: #prop_value })
-    });
-
     let extra_value = serde_json::Value::Object(
         map.clone()
             .into_iter()
@@ -622,7 +630,8 @@ mod tests {
                     super::Test {
                         a: "aaaa".to_string(),
                         b: 7_u32,
-                        c: Some("cccc".to_string())
+                        c: Some("cccc".to_string()),
+                        d: Default::default()
                     }
                 }
                 .to_string()
@@ -663,7 +672,8 @@ mod tests {
                     Test {
                         a: "aaaa".to_string(),
                         b: 7_u32,
-                        c: Some("cccc".to_string())
+                        c: Some("cccc".to_string()),
+                        d: Default::default()
                     }
                 }
                 .to_string()


Test patch:
diff --git a/typify/tests/schemas/types-with-defaults.json b/typify/tests/schemas/types-with-defaults.json
index c230306..7b7d18f 100644
--- a/typify/tests/schemas/types-with-defaults.json
+++ b/typify/tests/schemas/types-with-defaults.json
@@ -29,6 +29,27 @@
         }
       }
     },
+    "OuterThing": {
+      "type": "object",
+      "properties": {
+        "thing": {
+          "type": "object",
+          "title": "ThingWithDefaults",
+          "properties": {
+            "a": {
+              "type": "string"
+            },
+            "type": {
+              "type": "string"
+            }
+          },
+          "additionalProperties": false,
+          "default": {
+            "type": "bee"
+          }
+        }
+      }
+    },
     "Doodad": {
       "type": "object",
       "properties": {
diff --git a/typify/tests/schemas/types-with-defaults.rs b/typify/tests/schemas/types-with-defaults.rs
index 471fe0d..17d1749 100644
--- a/typify/tests/schemas/types-with-defaults.rs
+++ b/typify/tests/schemas/types-with-defaults.rs
@@ -53,6 +53,44 @@ impl From<&Doodad> for Doodad {
         value.clone()
     }
 }
+#[doc = "OuterThing"]
+#[doc = r""]
+#[doc = r" <details><summary>JSON schema</summary>"]
+#[doc = r""]
+#[doc = r" ```json"]
+#[doc = "{"]
+#[doc = "  \"type\": \"object\","]
+#[doc = "  \"properties\": {"]
+#[doc = "    \"thing\": {"]
+#[doc = "      \"title\": \"ThingWithDefaults\","]
+#[doc = "      \"default\": {"]
+#[doc = "        \"type\": \"bee\""]
+#[doc = "      },"]
+#[doc = "      \"type\": \"object\","]
+#[doc = "      \"properties\": {"]
+#[doc = "        \"a\": {"]
+#[doc = "          \"type\": \"string\""]
+#[doc = "        },"]
+#[doc = "        \"type\": {"]
+#[doc = "          \"type\": \"string\""]
+#[doc = "        }"]
+#[doc = "      },"]
+#[doc = "      \"additionalProperties\": false"]
+#[doc = "    }"]
+#[doc = "  }"]
+#[doc = "}"]
+#[doc = r" ```"]
+#[doc = r" </details>"]
+#[derive(Clone, Debug, Deserialize, Serialize)]
+pub struct OuterThing {
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub thing: Option<ThingWithDefaults>,
+}
+impl From<&OuterThing> for OuterThing {
+    fn from(value: &OuterThing) -> Self {
+        value.clone()
+    }
+}
 #[doc = "TestBed"]
 #[doc = r""]
 #[doc = r" <details><summary>JSON schema</summary>"]
@@ -99,6 +137,50 @@ impl From<&TestBed> for TestBed {
         value.clone()
     }
 }
+#[doc = "ThingWithDefaults"]
+#[doc = r""]
+#[doc = r" <details><summary>JSON schema</summary>"]
+#[doc = r""]
+#[doc = r" ```json"]
+#[doc = "{"]
+#[doc = "  \"title\": \"ThingWithDefaults\","]
+#[doc = "  \"default\": {"]
+#[doc = "    \"type\": \"bee\""]
+#[doc = "  },"]
+#[doc = "  \"type\": \"object\","]
+#[doc = "  \"properties\": {"]
+#[doc = "    \"a\": {"]
+#[doc = "      \"type\": \"string\""]
+#[doc = "    },"]
+#[doc = "    \"type\": {"]
+#[doc = "      \"type\": \"string\""]
+#[doc = "    }"]
+#[doc = "  },"]
+#[doc = "  \"additionalProperties\": false"]
+#[doc = "}"]
+#[doc = r" ```"]
+#[doc = r" </details>"]
+#[derive(Clone, Debug, Deserialize, Serialize)]
+#[serde(deny_unknown_fields)]
+pub struct ThingWithDefaults {
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub a: Option<String>,
+    #[serde(rename = "type", default, skip_serializing_if = "Option::is_none")]
+    pub type_: Option<String>,
+}
+impl From<&ThingWithDefaults> for ThingWithDefaults {
+    fn from(value: &ThingWithDefaults) -> Self {
+        value.clone()
+    }
+}
+impl Default for ThingWithDefaults {
+    fn default() -> Self {
+        ThingWithDefaults {
+            a: Default::default(),
+            type_: Some("bee".to_string()),
+        }
+    }
+}
 #[doc = r" Generation of default values for serde."]
 pub mod defaults {
     pub(super) fn doodad_when() -> chrono::DateTime<chrono::offset::Utc> {