Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Split up TypeRefExt::cs_type_string #3893

Merged
6 changes: 2 additions & 4 deletions tools/slicec-cs/src/builders.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,9 +142,7 @@ impl ContainerBuilder {

pub fn add_fields(&mut self, fields: &[&Field]) -> &mut Self {
for field in fields {
let type_string = field
.data_type()
.cs_type_string(&field.namespace(), TypeContext::Field, false);
let type_string = field.data_type().field_type_string(&field.namespace(), false);

self.add_field(
&field.field_name(),
Expand Down Expand Up @@ -338,7 +336,7 @@ impl FunctionBuilder {
};

for (index, parameter) in parameters.iter().enumerate() {
let parameter_type = parameter.cs_type_string(&operation.namespace(), context, false);
let parameter_type = parameter.cs_type_string(&operation.namespace(), context);
let parameter_name = parameter.parameter_name();

let default_value = if context == TypeContext::OutgoingParam && (index >= trailing_optional_parameters_index) {
Expand Down
48 changes: 17 additions & 31 deletions tools/slicec-cs/src/decoding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use crate::slicec_ext::*;
use convert_case::Case;
use slicec::code_block::CodeBlock;
use slicec::grammar::*;
use slicec::utils::code_gen_util::{get_bit_sequence_size, TypeContext};
use slicec::utils::code_gen_util::get_bit_sequence_size;

/// Compute how many bits are needed to decode the provided members, and if more than 0 bits are needed,
/// this generates code that creates a new `BitSequenceReader` with the necessary capacity.
Expand All @@ -26,9 +26,7 @@ pub fn decode_fields(fields: &[&Field], encoding: Encoding) -> CodeBlock {
let mut code = CodeBlock::default();
initialize_bit_sequence_reader_for(fields, &mut code, encoding);

let action = |field_name, field_value| {
writeln!(code, "this.{field_name} = {field_value};")
};
let action = |field_name, field_value| writeln!(code, "this.{field_name} = {field_value};");

decode_fields_core(fields, encoding, action);
code
Expand Down Expand Up @@ -75,7 +73,7 @@ pub fn default_activator(encoding: Encoding) -> &'static str {
fn decode_member(member: &impl Member, namespace: &str, encoding: Encoding) -> CodeBlock {
let mut code = CodeBlock::default();
let data_type = member.data_type();
let type_string = data_type.cs_type_string(namespace, TypeContext::IncomingParam, true);
let type_string = data_type.field_type_string(namespace, true);

if data_type.is_optional {
match data_type.concrete_type() {
Expand Down Expand Up @@ -173,14 +171,10 @@ fn decode_dictionary(dictionary_ref: &TypeRef<Dictionary>, namespace: &str, enco
// decode value
let mut decode_value = decode_func(value_type, namespace, encoding);
if matches!(value_type.concrete_type(), Types::Sequence(_) | Types::Dictionary(_)) {
write!(
decode_value,
" as {}",
value_type.cs_type_string(namespace, TypeContext::Field, true),
);
write!(decode_value, " as {}", value_type.field_type_string(namespace, true));
}

let dictionary_type = dictionary_ref.cs_type_string(namespace, TypeContext::IncomingParam, true);
let dictionary_type = dictionary_ref.incoming_parameter_type_string(namespace, true);
let decode_key = decode_key.indent();
let decode_value = decode_value.indent();

Expand Down Expand Up @@ -231,23 +225,19 @@ fn decode_sequence(sequence_ref: &TypeRef<Sequence>, namespace: &str, encoding:
if !has_cs_type_attribute && matches!(element_type.concrete_type(), Types::Sequence(_)) {
// For nested sequences we want to cast Foo[][] returned by DecodeSequence to IList<Foo>[]
// used in the request and response decode methods.
write!(
code,
"({}[])",
element_type.cs_type_string(namespace, TypeContext::Field, false),
);
write!(code, "({}[])", element_type.field_type_string(namespace, false));
};

if has_cs_type_attribute {
let sequence_type = sequence_ref.cs_type_string(namespace, TypeContext::IncomingParam, true);
let sequence_type = sequence_ref.incoming_parameter_type_string(namespace, true);

let arg: Option<String> = match element_type.concrete_type() {
Types::Primitive(primitive) if primitive.fixed_wire_size().is_some() && !element_type.is_optional => {
// We always read an array even when mapped to a collection, as it's expected to be
// faster than decoding the collection elements one by one.
Some(format!(
"decoder.DecodeSequence<{}>({})",
element_type.cs_type_string(namespace, TypeContext::IncomingParam, true),
element_type.incoming_parameter_type_string(namespace, true),
if matches!(primitive, Primitive::Bool) {
"checkElement: SliceDecoder.CheckBoolValue"
} else {
Expand All @@ -265,14 +255,14 @@ fn decode_sequence(sequence_ref: &TypeRef<Sequence>, namespace: &str, encoding:
if enum_def.is_unchecked {
Some(format!(
"decoder.DecodeSequence<{}>()",
element_type.cs_type_string(namespace, TypeContext::IncomingParam, true),
element_type.incoming_parameter_type_string(namespace, true),
))
} else {
Some(format!(
"\
decoder.DecodeSequence(
({enum_type_name} e) => _ = {underlying_extensions_class}.As{name}(({underlying_type})e))",
enum_type_name = element_type.cs_type_string(namespace, TypeContext::IncomingParam, false),
enum_type_name = element_type.incoming_parameter_type_string(namespace, false),
underlying_extensions_class = enum_def.escape_scoped_identifier_with_suffix(
&format!(
"{}Extensions",
Expand Down Expand Up @@ -332,7 +322,7 @@ decoder.DecodeSequenceOfOptionals(
write!(
code,
"decoder.DecodeSequence<{}>({})",
element_type.cs_type_string(namespace, TypeContext::IncomingParam, true),
element_type.incoming_parameter_type_string(namespace, true),
if matches!(primitive, Primitive::Bool) {
"checkElement: SliceDecoder.CheckBoolValue"
} else {
Expand All @@ -345,15 +335,15 @@ decoder.DecodeSequenceOfOptionals(
write!(
code,
"decoder.DecodeSequence<{}>()",
element_type.cs_type_string(namespace, TypeContext::IncomingParam, true),
element_type.incoming_parameter_type_string(namespace, true),
)
} else {
write!(
code,
"\
decoder.DecodeSequence(
({enum_type} e) => _ = {underlying_extensions_class}.As{name}(({underlying_type})e))",
enum_type = element_type.cs_type_string(namespace, TypeContext::IncomingParam, false),
enum_type = element_type.incoming_parameter_type_string(namespace, false),
underlying_extensions_class = enum_def.escape_scoped_identifier_with_suffix(
&format!(
"{}Extensions",
Expand Down Expand Up @@ -400,11 +390,7 @@ fn decode_result_field(type_ref: &TypeRef, namespace: &str, encoding: Encoding)

// TODO: it's lame to have to do this here. We should provide a better API.
if matches!(type_ref.concrete_type(), Types::Sequence(_) | Types::Dictionary(_)) {
write!(
decode_func,
" as {}",
type_ref.cs_type_string(namespace, TypeContext::Field, false),
);
write!(decode_func, " as {}", type_ref.field_type_string(namespace, false));
}

if type_ref.is_optional {
Expand All @@ -427,7 +413,7 @@ pub fn decode_func(type_ref: &TypeRef, namespace: &str, encoding: Encoding) -> C

fn decode_func_body(type_ref: &TypeRef, namespace: &str, encoding: Encoding) -> CodeBlock {
let mut code = CodeBlock::default();
let type_name = type_ref.cs_type_string(namespace, TypeContext::IncomingParam, true);
let type_name = type_ref.incoming_parameter_type_string(namespace, true);

// When we decode the type, we decode it as a non-optional.
// If the type is supposed to be optional, we cast it after decoding.
Expand Down Expand Up @@ -503,7 +489,7 @@ pub fn decode_operation(operation: &Operation, dispatch: bool) -> CodeBlock {
// For optional value types we have to use the full type as the compiler cannot
// disambiguate between null and the actual value type.
let param_type_string = match param_type.is_optional && param_type.is_value_type() {
true => param_type.cs_type_string(&namespace, TypeContext::IncomingParam, false),
true => param_type.incoming_parameter_type_string(&namespace, false),
false => "var".to_owned(),
};

Expand All @@ -530,7 +516,7 @@ pub fn decode_operation_stream(
) -> CodeBlock {
let cs_encoding = encoding.to_cs_encoding();
let param_type = stream_member.data_type();
let param_type_str = param_type.cs_type_string(namespace, TypeContext::IncomingParam, false);
let param_type_str = param_type.incoming_parameter_type_string(namespace, false);
let fixed_wire_size = param_type.fixed_wire_size();

match param_type.concrete_type() {
Expand Down
15 changes: 12 additions & 3 deletions tools/slicec-cs/src/encoding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ fn encode_tagged_type(
let null_check = if read_only_memory {
format!("{param}.Span != null")
} else {
let unwrapped_type = data_type.cs_type_string(namespace, type_context, true);
let unwrapped_type = get_type_string(data_type, namespace, type_context, true);
format!("{param} is {unwrapped_type} {unwrapped_name}")
};

Expand Down Expand Up @@ -332,7 +332,7 @@ fn encode_action(
) -> CodeBlock {
CodeBlock::from(format!(
"(ref SliceEncoder encoder, {value_type} value) => {encode_action_body}",
value_type = type_ref.cs_type_string(namespace, type_context, is_tagged),
value_type = get_type_string(type_ref, namespace, type_context, is_tagged),
encode_action_body = encode_action_body(type_ref, type_context, namespace, encoding, is_tagged),
))
}
Expand Down Expand Up @@ -457,7 +457,7 @@ fn encode_type_with_bit_sequence_optimization(
namespace: &str,
encoding: Encoding,
) -> CodeBlock {
let value_type = type_ref.cs_type_string(namespace, type_context, false);
let value_type = get_type_string(type_ref, namespace, type_context, false);
if type_ref.is_optional {
CodeBlock::from(format!(
"\
Expand Down Expand Up @@ -549,3 +549,12 @@ int startPos_ = encoder_.EncodedByteCount;",
)
.into()
}

// TODO temporary bridging code while cleaning up the type_string functions.
fn get_type_string(type_ref: &TypeRef, namespace: &str, context: TypeContext, ignore_optional: bool) -> String {
match context {
TypeContext::OutgoingParam => type_ref.outgoing_parameter_type_string(namespace, ignore_optional),
TypeContext::Field => type_ref.field_type_string(namespace, ignore_optional),
TypeContext::IncomingParam => unreachable!(),
}
}
3 changes: 1 addition & 2 deletions tools/slicec-cs/src/generators/class_generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ use crate::member_util::*;
use crate::slicec_ext::*;
use slicec::code_block::CodeBlock;
use slicec::grammar::{Class, Encoding, Field};
use slicec::utils::code_gen_util::TypeContext;

pub fn generate_class(class_def: &Class) -> CodeBlock {
let class_name = class_def.escape_identifier();
Expand Down Expand Up @@ -129,7 +128,7 @@ fn constructor(

for field in base_fields.iter().chain(fields.iter()) {
builder.add_parameter(
&field.data_type.cs_type_string(namespace, TypeContext::Field, false),
&field.data_type.field_type_string(namespace, false),
&field.parameter_name(),
None,
field.formatted_doc_comment_summary(),
Expand Down
6 changes: 3 additions & 3 deletions tools/slicec-cs/src/generators/dispatch_generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ fn request_class(interface_def: &Interface) -> CodeBlock {
},
&format!(
"global::System.Threading.Tasks.ValueTask<{}>",
&parameters.to_tuple_type(namespace, TypeContext::IncomingParam, false),
&parameters.to_tuple_type(namespace, TypeContext::IncomingParam),
),
&operation.escape_identifier_with_prefix_and_suffix("Decode", "Async"),
function_type,
Expand Down Expand Up @@ -192,7 +192,7 @@ fn response_class(interface_def: &Interface) -> CodeBlock {
match non_streamed_returns.as_slice() {
[param] => {
builder.add_parameter(
&param.cs_type_string(namespace, TypeContext::OutgoingParam, false),
&param.cs_type_string(namespace, TypeContext::OutgoingParam),
"returnValue",
None,
Some("The operation return value.".to_owned()),
Expand All @@ -201,7 +201,7 @@ fn response_class(interface_def: &Interface) -> CodeBlock {
_ => {
for param in &non_streamed_returns {
builder.add_parameter(
&param.cs_type_string(namespace, TypeContext::OutgoingParam, false),
&param.cs_type_string(namespace, TypeContext::OutgoingParam),
&param.parameter_name(),
None,
param.formatted_param_doc_comment(),
Expand Down
3 changes: 1 addition & 2 deletions tools/slicec-cs/src/generators/exception_generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ use crate::member_util::*;
use crate::slicec_ext::*;
use slicec::code_block::CodeBlock;
use slicec::grammar::{Encoding, Exception, Member};
use slicec::utils::code_gen_util::TypeContext;

pub fn generate_exception(exception_def: &Exception) -> CodeBlock {
let exception_name = exception_def.escape_identifier();
Expand Down Expand Up @@ -144,7 +143,7 @@ fn one_shot_constructor(exception_def: &Exception) -> CodeBlock {

for field in &all_fields {
ctor_builder.add_parameter(
&field.data_type().cs_type_string(namespace, TypeContext::Field, false),
&field.data_type().field_type_string(namespace, false),
field.parameter_name().as_str(),
None,
field.formatted_doc_comment_summary(),
Expand Down
6 changes: 3 additions & 3 deletions tools/slicec-cs/src/generators/proxy_generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,7 @@ if ({features_parameter}?.Get<IceRpc.Features.ICompressFeature>() is null)
invocation_builder.add_argument(
FunctionCallBuilder::new(format!(
"{stream_parameter_name}.ToPipeReader<{}>",
stream_type.cs_type_string(namespace, TypeContext::OutgoingParam, false),
stream_type.outgoing_parameter_type_string(namespace, false),
))
.use_semicolon(false)
.add_argument(encode_stream_parameter(stream_type, namespace, operation.encoding).indent())
Expand Down Expand Up @@ -486,7 +486,7 @@ fn request_class(interface_def: &Interface) -> CodeBlock {

for param in &params {
builder.add_parameter(
&param.cs_type_string(namespace, TypeContext::OutgoingParam, false),
&param.cs_type_string(namespace, TypeContext::OutgoingParam),
&param.parameter_name(),
None,
param.formatted_param_doc_comment(),
Expand Down Expand Up @@ -554,7 +554,7 @@ fn response_class(interface_def: &Interface) -> CodeBlock {
} else {
format!(
"global::System.Threading.Tasks.ValueTask<{}>",
members.to_tuple_type(namespace, TypeContext::IncomingParam, false),
members.to_tuple_type(namespace, TypeContext::IncomingParam),
)
};

Expand Down
3 changes: 1 addition & 2 deletions tools/slicec-cs/src/generators/struct_generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ use crate::member_util::*;
use crate::slicec_ext::{CommentExt, EntityExt, MemberExt, TypeRefExt};
use slicec::code_block::CodeBlock;
use slicec::grammar::*;
use slicec::utils::code_gen_util::*;

pub fn generate_struct(struct_def: &Struct) -> CodeBlock {
let escaped_identifier = struct_def.escape_identifier();
Expand Down Expand Up @@ -54,7 +53,7 @@ pub fn generate_struct(struct_def: &Struct) -> CodeBlock {

for field in &fields {
main_constructor.add_parameter(
&field.data_type().cs_type_string(&namespace, TypeContext::Field, false),
&field.data_type().field_type_string(&namespace, false),
field.parameter_name().as_str(),
None,
field.formatted_doc_comment_summary(),
Expand Down
5 changes: 1 addition & 4 deletions tools/slicec-cs/src/member_util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ use crate::comments::CommentTag;
use crate::slicec_ext::*;
use slicec::code_block::CodeBlock;
use slicec::grammar::{Contained, Field, Member};
use slicec::utils::code_gen_util::TypeContext;

/// Takes a list of members and sorts them in the following order: [required members][tagged members]
/// Required members are left in the provided order. Tagged members are sorted so tag values are in increasing order.
Expand All @@ -23,9 +22,7 @@ pub fn escape_parameter_name(parameters: &[&impl Member], name: &str) -> String
}

pub fn field_declaration(field: &Field) -> String {
let type_string = field
.data_type()
.cs_type_string(&field.namespace(), TypeContext::Field, false);
let type_string = field.data_type().field_type_string(&field.namespace(), false);
let mut prelude = CodeBlock::default();

if let Some(summary) = field.formatted_doc_comment_summary() {
Expand Down
20 changes: 13 additions & 7 deletions tools/slicec-cs/src/slicec_ext/member_ext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,16 +63,22 @@ impl FieldExt for Field {
}

pub trait ParameterExt {
fn cs_type_string(&self, namespace: &str, context: TypeContext, ignore_optional: bool) -> String;
fn cs_type_string(&self, namespace: &str, context: TypeContext) -> String;

/// Returns the message of the `@param` tag corresponding to this parameter from the operation it's part of.
/// If the operation has no doc comment, or a matching `@param` tag, this returns `None`.
fn formatted_param_doc_comment(&self) -> Option<String>;
}

impl ParameterExt for Parameter {
fn cs_type_string(&self, namespace: &str, context: TypeContext, ignore_optional: bool) -> String {
let type_str = self.data_type().cs_type_string(namespace, context, ignore_optional);
fn cs_type_string(&self, namespace: &str, context: TypeContext) -> String {
// TODO this can be further simplified.
let type_str = match context {
TypeContext::OutgoingParam => self.data_type().outgoing_parameter_type_string(namespace, false),
TypeContext::IncomingParam => self.data_type().incoming_parameter_type_string(namespace, false),
TypeContext::Field => unreachable!(),
};

if self.is_streamed {
if type_str == "byte" {
"global::System.IO.Pipelines.PipeReader".to_owned()
Expand All @@ -99,7 +105,7 @@ impl ParameterExt for Parameter {

pub trait ParameterSliceExt {
fn to_argument_tuple(&self, prefix: &str) -> String;
fn to_tuple_type(&self, namespace: &str, context: TypeContext, ignore_optional: bool) -> String;
fn to_tuple_type(&self, namespace: &str, context: TypeContext) -> String;
}

impl ParameterSliceExt for [&Parameter] {
Expand All @@ -117,14 +123,14 @@ impl ParameterSliceExt for [&Parameter] {
}
}

fn to_tuple_type(&self, namespace: &str, context: TypeContext, ignore_optional: bool) -> String {
fn to_tuple_type(&self, namespace: &str, context: TypeContext) -> String {
match self {
[] => panic!("tuple type with no members"),
[member] => member.cs_type_string(namespace, context, ignore_optional),
[member] => member.cs_type_string(namespace, context),
_ => format!(
"({})",
self.iter()
.map(|m| m.cs_type_string(namespace, context, ignore_optional) + " " + &m.field_name())
.map(|m| m.cs_type_string(namespace, context) + " " + &m.field_name())
.collect::<Vec<String>>()
.join(", "),
),
Expand Down
Loading
Loading