Skip to content

Commit

Permalink
crate::Error for services (#497)
Browse files Browse the repository at this point in the history
  • Loading branch information
ctaggart authored Nov 8, 2021
1 parent 1db35c6 commit e6b2138
Show file tree
Hide file tree
Showing 1,587 changed files with 531,535 additions and 306,323 deletions.
3 changes: 1 addition & 2 deletions services/autorust/codegen/examples/gen_mgmt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ const SKIP_SERVICES: &[&str] = &[
"m365securityandcompliance", // can't find privateLinkServicesForO365ManagementActivityAPI.json
"marketplace",
"mixedreality", // TODO #83 AccountKeyRegenerateRequest not generated
"powerplatform", // https://github.com/Azure/azure-rest-api-specs/pull/11580 incorrect ref & duplicate Operations_List
"service-map", // Ident "Ref:machine"
"servicefabric", // https://github.com/Azure/azure-rest-api-specs/pull/11581 allOf mistakes and duplicate Operations_List
"servicefabricmanagedclusters",
Expand All @@ -32,7 +31,6 @@ const SKIP_SERVICE_TAGS: &[(&str, &str)] = &[
("consumption", "package-2018-03"), // defines get_balances_by_billing_account twice
("consumption", "package-2019-11"), // ReservationRecommendationDetails_Get has a path and query param both named "scope"
("consumption", "package-2021-05"),
("cosmos-db", "package-2021-06"), // duplicate tag https://github.com/Azure/azure-rest-api-specs/issues/14996
("databricks", "package-2021-04-01-preview"), // duplicate tag https://github.com/Azure/azure-rest-api-specs/issues/14995
// datamigration, same error for all
// SchemaNotFound MigrateSqlServerSqlDbTask.json ValidationStatus, but may be buried
Expand All @@ -43,6 +41,7 @@ const SKIP_SERVICE_TAGS: &[(&str, &str)] = &[
("datamigration", "package-2017-11-15-preview"),
("datamigration", "package-2021-06"),
("deploymentmanager", "package-2018-09-01-preview"), // identifiers are bound more than once in param list. https://github.com/Azure/azure-sdk-for-rust/issues/415
("iothub", "package-preview-2021-07"), // duplicate tag https://github.com/Azure/azure-rest-api-specs/issues/16692
("mediaservices", "package-2019-05-preview"), // invalid unicode character of a dash instead of a hyphen https://github.com/Azure/azure-rest-api-specs/pull/11576
("marketplace", "package-2020-01-01"),
("marketplace", "package-2020-12-01"),
Expand Down
125 changes: 77 additions & 48 deletions services/autorust/codegen/src/codegen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ pub enum Error {
PropertyName(#[source] crate::identifier::Error),
#[error("creating name for module: {0}")]
ModuleName(#[source] crate::identifier::Error),
#[error("creating name for enum variant: {0}")]
EnumVariantName(#[source] crate::identifier::Error),
#[error("creating name for enum {property}: {source}")]
EnumName {
source: crate::identifier::Error,
Expand Down Expand Up @@ -117,13 +119,6 @@ pub enum Error {
StatusCode(#[from] crate::status_codes::Error),
}

/// Whether or not to pass a type is a reference.
#[derive(Copy, Clone)]
pub enum AsReference {
True,
False,
}

pub fn is_vec(ts: &TokenStream) -> bool {
ts.to_string().starts_with("Vec <")
}
Expand Down Expand Up @@ -181,70 +176,104 @@ pub fn enum_values_as_strings(values: &[Value]) -> Vec<&str> {
.collect()
}

pub fn get_type_name_for_schema(schema: &SchemaCommon, as_ref: AsReference) -> Result<TokenStream, Error> {
if let Some(schema_type) = &schema.type_ {
pub enum TypeName {
Reference(String),
Array(Box<TypeName>),
Value,
Bytes,
Int32,
Int64,
Float32,
Float64,
Boolean,
String,
}

impl TypeName {
pub fn to_token_stream(&self, as_ref: bool, qualify_models: bool) -> Result<TokenStream, Error> {
Ok(match self {
TypeName::Reference(name) => {
let idt = ident(&name.to_camel_case()).map_err(Error::TypeNameForSchemaRef)?;
let idt = if qualify_models {
quote! { models::#idt }
} else {
idt
};
match as_ref {
true => quote! { &#idt },
false => idt,
}
}
TypeName::Array(vec_items_typ) => {
let vec_items_typ = vec_items_typ.to_token_stream(as_ref, qualify_models)?;
match as_ref {
true => quote! { &[#vec_items_typ] },
false => quote! { Vec<#vec_items_typ> },
}
}
TypeName::Value => match as_ref {
true => quote! { &serde_json::Value },
false => quote! { serde_json::Value },
},
TypeName::Bytes => quote! { bytes::Bytes },
TypeName::Int32 => quote! { i32 },
TypeName::Int64 => quote! { i64 },
TypeName::Float32 => quote! { f32 },
TypeName::Float64 => quote! { f64 },
TypeName::Boolean => quote! { bool },
TypeName::String => match as_ref {
true => quote! { &str },
false => quote! { String },
},
})
}
}

pub fn get_type_name_for_schema(schema: &SchemaCommon) -> Result<TypeName, Error> {
Ok(if let Some(schema_type) = &schema.type_ {
let format = schema.format.as_deref();
let ts = match schema_type {
match schema_type {
DataType::Array => {
let items = get_schema_array_items(schema)?;
let vec_items_typ = get_type_name_for_schema_ref(items, as_ref)?;
match as_ref {
AsReference::True => quote! { &[#vec_items_typ] },
AsReference::False => quote! { Vec<#vec_items_typ> },
}
let vec_items_typ = get_type_name_for_schema_ref(items)?;
TypeName::Array(Box::new(vec_items_typ))
}
DataType::Integer => {
if format == Some("int32") {
quote! { i32 }
TypeName::Int32
} else {
quote! { i64 }
TypeName::Int64
}
}
DataType::Number => {
if format == Some("float") {
quote! { f32 }
TypeName::Float32
} else {
quote! { f64 }
TypeName::Float64
}
}
DataType::String => match as_ref {
AsReference::True => quote! { &str },
AsReference::False => quote! { String },
},
DataType::Boolean => quote! { bool },
DataType::Object => match as_ref {
AsReference::True => quote! { &serde_json::Value },
AsReference::False => quote! { serde_json::Value },
},
DataType::File => {
quote! { bytes::Bytes }
}
};
Ok(ts)
DataType::String => TypeName::String,
DataType::Boolean => TypeName::Boolean,
DataType::Object => TypeName::Value,
DataType::File => TypeName::Bytes,
}
} else {
// eprintln!(
// "WARN unknown type in get_type_name_for_schema, description {:?}",
// schema.description
// );
match as_ref {
AsReference::True => Ok(quote! { &serde_json::Value }),
AsReference::False => Ok(quote! { serde_json::Value }),
}
}
TypeName::Value
})
}

pub fn get_type_name_for_schema_ref(schema: &ReferenceOr<Schema>, as_ref: AsReference) -> Result<TokenStream, Error> {
match schema {
pub fn get_type_name_for_schema_ref(schema: &ReferenceOr<Schema>) -> Result<TypeName, Error> {
Ok(match schema {
ReferenceOr::Reference { reference, .. } => {
let name = &reference.name.as_ref().ok_or(Error::NoNameForRef)?;
let idt = ident(&name.to_camel_case()).map_err(Error::TypeNameForSchemaRef)?;
match as_ref {
AsReference::True => Ok(quote! { &#idt }),
AsReference::False => Ok(quote! { #idt }),
}
let name = reference.name.as_ref().ok_or(Error::NoNameForRef)?;
TypeName::Reference(name.to_owned())
}
ReferenceOr::Item(schema) => get_type_name_for_schema(&schema.common, as_ref),
}
ReferenceOr::Item(schema) => get_type_name_for_schema(&schema.common)?,
})
}

pub fn create_mod(api_version: &str) -> TokenStream {
Expand Down
17 changes: 10 additions & 7 deletions services/autorust/codegen/src/codegen_models.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::{
codegen::{
create_generated_by_header, enum_values_as_strings, get_schema_array_items, get_type_name_for_schema, get_type_name_for_schema_ref,
is_array, is_basic_type, is_local_enum, is_local_struct, is_vec, require, AsReference, Error,
is_array, is_basic_type, is_local_enum, is_local_struct, is_vec, require, Error,
},
identifier::{ident, CamelCaseIdent},
spec, CodeGen, PropertyName, ResolvedSchema,
Expand Down Expand Up @@ -51,8 +51,8 @@ pub fn create_models(cg: &CodeGen) -> Result<TokenStream, Error> {
}

// any referenced schemas from other files
for (doc_file, doc) in cg.spec.input_docs() {
for reference in openapi::get_api_schema_references(doc) {
for (doc_file, api) in cg.spec.input_docs() {
for reference in openapi::get_api_schema_references(doc_file, api) {
add_schema_refs(cg, &mut all_schemas, doc_file, reference)?;
}
}
Expand Down Expand Up @@ -86,7 +86,7 @@ pub fn create_models(cg: &CodeGen) -> Result<TokenStream, Error> {

fn create_basic_type_alias(property_name: &str, property: &ResolvedSchema) -> Result<(TokenStream, TokenStream), Error> {
let id = ident(&property_name.to_camel_case()).map_err(Error::StructName)?;
let value = get_type_name_for_schema(&property.schema.common, AsReference::False)?;
let value = get_type_name_for_schema(&property.schema.common)?.to_token_stream(false, false)?;
Ok((id, value))
}

Expand Down Expand Up @@ -158,7 +158,7 @@ fn create_enum(
fn create_vec_alias(alias_name: &str, schema: &ResolvedSchema) -> Result<TokenStream, Error> {
let items = get_schema_array_items(&schema.schema.common)?;
let typ = ident(&alias_name.to_camel_case()).map_err(Error::VecAliasName)?;
let items_typ = get_type_name_for_schema_ref(items, AsReference::False)?;
let items_typ = get_type_name_for_schema_ref(items)?.to_token_stream(false, false)?;
Ok(quote! { pub type #typ = Vec<#items_typ>; })
}

Expand All @@ -172,7 +172,7 @@ fn create_struct(cg: &CodeGen, doc_file: &Path, struct_name: &str, schema: &Reso
let required: HashSet<&str> = schema.schema.required.iter().map(String::as_str).collect();

for schema in &schema.schema.all_of {
let type_name = get_type_name_for_schema_ref(schema, AsReference::False)?;
let type_name = get_type_name_for_schema_ref(schema)?.to_token_stream(false, false)?;
let field_name = ident(&type_name.to_string().to_snake_case()).map_err(Error::StructFieldName)?;
props.extend(quote! {
#[serde(flatten)]
Expand Down Expand Up @@ -285,7 +285,10 @@ fn create_struct_field_type(
// println!("creating local struct {:?} {}", tp_name, tps.len());
Ok((tp_name, tps))
} else {
Ok((get_type_name_for_schema(&property.schema.common, AsReference::False)?, Vec::new()))
Ok((
get_type_name_for_schema(&property.schema.common)?.to_token_stream(false, false)?,
Vec::new(),
))
}
}
}
Expand Down
Loading

0 comments on commit e6b2138

Please sign in to comment.