diff --git a/Cargo.lock b/Cargo.lock index 9a77734..0316ffd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -196,7 +196,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -399,7 +399,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6d2301688392eb071b0bf1a37be05c469d3cc4dbbd95df672fe28ab021e6a096" dependencies = [ "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -498,7 +498,7 @@ dependencies = [ "base64 0.13.1", "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -849,7 +849,7 @@ dependencies = [ "proc-macro2", "quote", "regex-syntax", - "syn", + "syn 1.0.109", ] [[package]] @@ -1182,7 +1182,7 @@ dependencies = [ "proc-macro-error-attr", "proc-macro2", "quote", - "syn", + "syn 1.0.109", "version_check", ] @@ -1363,7 +1363,7 @@ checksum = "8218eaf5d960e3c478a1b0f129fa888dd3d8d22eb3de097e9af14c1ab4438024" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -1421,7 +1421,7 @@ checksum = "d7e29c4601e36bcec74a223228dce795f4cd3616341a4af93520ca1a837c087d" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -1621,7 +1621,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -1635,6 +1635,17 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "syn" +version = "2.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79d9531f94112cfc3e4c8f5f02cb2b58f72c97b7efd85f70203cc6d8efda5927" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "syntect" version = "5.0.0" @@ -1724,26 +1735,27 @@ dependencies = [ "pretty_assertions", "serde", "serde_json", + "thiserror", ] [[package]] name = "thiserror" -version = "1.0.39" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5ab016db510546d856297882807df8da66a16fb8c4101cb8b30054b0d5b2d9c" +checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.39" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5420d42e90af0c38c3290abcca25b9b3bdf379fc9f55c528f53a269d9c9a267e" +checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.12", ] [[package]] @@ -1952,7 +1964,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn", + "syn 1.0.109", "wasm-bindgen-shared", ] @@ -1974,7 +1986,7 @@ checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", "wasm-bindgen-backend", "wasm-bindgen-shared", ] diff --git a/tf-ncl/Cargo.toml b/tf-ncl/Cargo.toml index 9c41887..213706b 100644 --- a/tf-ncl/Cargo.toml +++ b/tf-ncl/Cargo.toml @@ -12,6 +12,7 @@ serde = { version = "1.0", features = ["derive"] } nickel-lang = "0.3.1" pretty = "0.11" codespan = "0.11.1" +thiserror = "1.0.40" [dev-dependencies] pretty_assertions = "1.3" diff --git a/tf-ncl/src/intermediate.rs b/tf-ncl/src/intermediate.rs index 7300e83..11c13e4 100644 --- a/tf-ncl/src/intermediate.rs +++ b/tf-ncl/src/intermediate.rs @@ -144,12 +144,17 @@ pub struct SplitSchema { pub core_schema: GoSchema, } -#[derive(Debug)] +#[derive(thiserror::Error, Debug)] pub enum SplittingError { + #[error("leftover top-level computed fields found")] LeftoverComputedFields, + #[error("Missing top-level block {field}")] MissingBlock { field: &'static str }, + #[error("expected {field} to be an object")] ExpectedObject { field: &'static str }, + #[error("expected {field} to be a list of objects")] ExpectedListOfObjects { field: String }, + #[error("missing provider {provider}")] MissingProvider { provider: String }, } @@ -199,17 +204,23 @@ impl GoSchema { return Err(SplittingError::LeftoverComputedFields); } + let resource = self + .schema + .remove("resource") + .ok_or(SplittingError::MissingBlock { field: "resource" })?; + + let data = self + .schema + .remove("data") + .ok_or(SplittingError::MissingBlock { field: "data" })?; + Ok(SplitSchema { - resources: self - .schema - .remove("resource") - .ok_or(SplittingError::MissingBlock { field: "resource" })? + resources: resource + .clone() .into_object_content() .ok_or(SplittingError::ExpectedObject { field: "resource" })?, - data_sources: self - .schema - .remove("data") - .ok_or(SplittingError::MissingBlock { field: "data" })? + data_sources: data + .clone() .into_object_content() .ok_or(SplittingError::ExpectedObject { field: "data" })?, provider_schema: self @@ -226,7 +237,33 @@ impl GoSchema { .ok_or(SplittingError::ExpectedListOfObjects { field: format!("provider.{}", provider.as_ref()), })?, - core_schema: self, + core_schema: { + self.schema.insert( + String::from("resource"), + Attribute { + description: resource.description, + optional: true, + computed: false, + type_: Type::Object { + open: true, + content: HashMap::new(), + }, + }, + ); + self.schema.insert( + String::from("data"), + Attribute { + description: data.description, + optional: true, + computed: false, + type_: Type::Object { + open: true, + content: HashMap::new(), + }, + }, + ); + self + }, }) } } diff --git a/tf-ncl/src/main.rs b/tf-ncl/src/main.rs index e8ba37f..e4bdc1a 100644 --- a/tf-ncl/src/main.rs +++ b/tf-ncl/src/main.rs @@ -89,21 +89,22 @@ impl<'a, 'b> fmt::Display for Display<'a, 'b> { fn main() -> anyhow::Result<()> { let opts = Args::parse(); - // let providers = get_providers(&opts)?; let go_schema = get_schema(&opts)?.push_down_computed_fields(); - let split_schema = dbg!(go_schema.split_for_provider("github")); + let split_schema = dbg!(go_schema.split_for_provider("github")?); - Ok(()) + let mut schema_terms = HashMap::from([( + PathBuf::from("core.nix"), + split_schema.core_schema.as_nickel_term(), + )]); + split_schema.as_nickel(&mut schema_terms); - // let doc: RenderableSchema = go_schema.with_providers(providers).into(); + let doc = RenderableSchema { + schemas: schema_terms + .into_iter() + .map(|(k, v)| (k, v.pretty(&BoxAllocator).into_doc())) + .collect(), + }; - // let doc = RenderableSchema { - // schemas: schema_docs - // .into_iter() - // .map(|(k, v)| (k, v.pretty(&BoxAllocator).into_doc())) - // .collect(), - // }; - - // doc.render(&opts.output_directory) + doc.render(&opts.output_directory) } diff --git a/tf-ncl/src/nickel.rs b/tf-ncl/src/nickel.rs index f3cd7e6..f695625 100644 --- a/tf-ncl/src/nickel.rs +++ b/tf-ncl/src/nickel.rs @@ -2,7 +2,7 @@ use std::collections::HashMap; use std::path::PathBuf; use std::rc::Rc; -use crate::intermediate::{self, FieldDescriptor, GoSchema, Providers, WithProviders}; +use crate::intermediate::{self, FieldDescriptor, GoSchema, Providers, SplitSchema, WithProviders}; use crate::nickel_builder::{self as builder, Types}; use crate::terraform::{TFProviderSchema, TFSchema}; use nickel_lang::term::array::{Array, ArrayAttrs}; @@ -37,16 +37,50 @@ impl AsNickel for TFProviderSchema { } } +impl AsNickel for SplitSchema { + fn as_nickel(&self, schemas: &mut HashMap) { + schemas.extend(self.resources.iter().map(|(resource, schema)| { + match &schema.type_ { + intermediate::Type::Dictionary { + inner, + prefix: _, + computed_fields: _, + } => match inner.as_ref() { + intermediate::Type::Object { open, content } => ( + PathBuf::new() + .join("resource") + .join(resource) + .with_extension("ncl"), + as_nickel_record(content).set_open(*open).build(), + ), + _ => unimplemented!(), + }, + _ => unimplemented!(), + } + })); + + schemas.extend(self.data_sources.iter().map(|(data_source, schema)| { + ( + PathBuf::new() + .join("data") + .join(data_source) + .with_extension("ncl"), + schema + .as_nickel_field(builder::Field::name(data_source)) + .with_record(builder::Record::new()) + .build(), + ) + })); + } +} + pub trait AsNickelTerm { fn as_nickel_term(&self) -> RichTerm; } -impl AsNickelTerm for WithProviders { +impl AsNickelTerm for GoSchema { fn as_nickel_term(&self) -> RichTerm { - as_nickel_record(&self.data.schema) - .path(["terraform", "required_providers"]) - .value(self.providers.as_nickel_term()) - .build() + as_nickel_record(&self.schema).build() } }