diff --git a/crates/cairo-lang-doc/src/documentable_formatter.rs b/crates/cairo-lang-doc/src/documentable_formatter.rs index 77639dbf251..8866e68d5eb 100644 --- a/crates/cairo-lang-doc/src/documentable_formatter.rs +++ b/crates/cairo-lang-doc/src/documentable_formatter.rs @@ -26,7 +26,7 @@ use salsa::Database; use crate::documentable_item::DocumentableItemId; use crate::helpers::{ - extract_and_format, format_resolver_generic_params, get_generic_params, + format_generic_arg, format_resolver_generic_params, format_type, get_generic_params, get_struct_attributes_syntax, get_syntactic_evaluation, get_syntactic_visibility, resolve_type, }; use crate::location_links::{LocationLink, format_signature}; @@ -151,7 +151,6 @@ impl<'db> HirFormatter<'db> { full_path: &String, ) -> Result<(), SignatureError> { self.write_str(prefix.unwrap_or_default())?; - let formatted_element_type = element_type.format(self.db); if let TypeLongId::Tuple(vec_types) = element_type.long(self.db) { self.write_str("(")?; @@ -160,22 +159,15 @@ impl<'db> HirFormatter<'db> { self.write_type(None, *t, if count == 1 { None } else { Some(", ") }, full_path)?; count -= 1; } - self.write_str(")")?; - } else if is_the_same_root(full_path, &formatted_element_type) { - let documentable_id = resolve_type(self.db, element_type); - match documentable_id { - Some(documentable_id) => { - let start_offset = self.buf.len(); - self.write_str(&extract_and_format(&formatted_element_type))?; - let end_offset = self.buf.len(); - self.add_location_link(start_offset, end_offset, documentable_id); - } - None => { - self.write_str(&extract_and_format(&formatted_element_type))?; - } + if vec_types.len() == 1 { + self.write_str(",")?; } + self.write_str(")")?; } else { - self.write_str(&extract_and_format(&formatted_element_type))?; + let documentable_id = is_the_same_root(full_path, &element_type.format(self.db)) + .then(|| resolve_type(self.db, element_type)) + .flatten(); + self.write_link(&format_type(self.db, element_type), documentable_id)?; } self.hir_write(postfix.unwrap_or_default()) } @@ -184,19 +176,15 @@ impl<'db> HirFormatter<'db> { /// buf. fn write_link( &mut self, - name: String, + name: &str, documentable_id: Option>, ) -> fmt::Result { - match documentable_id { - Some(documentable_id) => { - let start_offset = self.buf.len(); - self.write_str(&name)?; - let end_offset = self.buf.len(); - self.add_location_link(start_offset, end_offset, documentable_id); - Ok(()) - } - None => self.write_str(&extract_and_format(&name)), + let start_offset = self.buf.len(); + self.write_str(name)?; + if let Some(documentable_id) = documentable_id { + self.add_location_link(start_offset, self.buf.len(), documentable_id); } + Ok(()) } /// Applies extra formatting to item signature. @@ -464,7 +452,7 @@ impl<'db> HirDisplay<'db> for TraitConstantId<'db> { f, "const {}: {};", trait_const_full_signature.name.long(f.db), - extract_and_format(&return_type.format(f.db)), + format_type(f.db, return_type), )?; f.format(); @@ -578,7 +566,7 @@ impl<'db> HirDisplay<'db> for ExternFunctionId<'db> { write!( f, "{}{}", - extract_and_format(&type_id.format(f.db)), + format_type(f.db, *type_id), if count == 1 { ")".to_string() } else { ", ".to_string() } )?; count -= 1; @@ -709,7 +697,7 @@ fn write_generic_args<'db>( } for arg in &generic_args { let documentable_id = resolve_generic_arg(*arg, f.db); - let _ = f.write_link(extract_and_format(&arg.format(f.db)), documentable_id); + let _ = f.write_link(&format_generic_arg(f.db, *arg), documentable_id); let _ = f.write_str(if count == 1 { ">" } else { ", " }); count -= 1; } diff --git a/crates/cairo-lang-doc/src/helpers.rs b/crates/cairo-lang-doc/src/helpers.rs index 7e9c1fdf10a..ca35143be31 100644 --- a/crates/cairo-lang-doc/src/helpers.rs +++ b/crates/cairo-lang-doc/src/helpers.rs @@ -3,13 +3,20 @@ use std::fmt; use cairo_lang_defs::ids::TraitItemId::Function; use cairo_lang_defs::ids::{ GenericImplItemId, GenericItemId, GenericKind, GenericModuleItemId, GenericParamId, - GenericTraitItemId, ImplItemId, LookupItemId, ModuleId, ModuleItemId, TraitItemId, + GenericTraitItemId, ImplItemId, LookupItemId, ModuleId, ModuleItemId, NamedLanguageElementId, + TraitItemId, }; use cairo_lang_semantic::expr::inference::InferenceId; +use cairo_lang_semantic::items::constant::{ConstValue, ConstValueId}; use cairo_lang_semantic::items::functions::GenericFunctionId; -use cairo_lang_semantic::items::generics::GenericParamSemantic; +use cairo_lang_semantic::items::generics::{ + GenericArgumentId, GenericParamImpl, GenericParamSemantic, +}; +use cairo_lang_semantic::items::imp::{ImplId, ImplLongId}; +use cairo_lang_semantic::items::trt::ConcreteTraitId; use cairo_lang_semantic::items::us::UseSemantic; use cairo_lang_semantic::items::visibility::Visibility; +use cairo_lang_semantic::types::ImplTypeId; use cairo_lang_semantic::{ConcreteTypeId, GenericParam, TypeId, TypeLongId}; use cairo_lang_syntax::attribute::structured::Attribute; use cairo_lang_syntax::node::kind::SyntaxKind; @@ -42,49 +49,62 @@ pub fn get_generic_params<'db>( buff.push_str("const "); buff.push_str(&extract_and_format(param_const.id.format(db).long(db))); } - GenericParam::Impl(param_impl) => { - let name = extract_and_format(param_impl.id.format(db).long(db)); - match param_impl.concrete_trait { - Ok(concrete_trait) => { - let documentable_id = - DocumentableItemId::from(LookupItemId::ModuleItem( - ModuleItemId::Trait(concrete_trait.trait_id(db)), - )); - if name.starts_with("+") { - location_links.push(LocationLink::new( - buff.len(), - buff.len() + name.len(), - documentable_id, - 0, - )); - buff.push_str(&name); - } else { - buff.push_str(&format!("impl {name}: ")); + GenericParam::Impl(param_impl) => match param_impl.concrete_trait { + Ok(concrete_trait) => { + let documentable_id = DocumentableItemId::from(LookupItemId::ModuleItem( + ModuleItemId::Trait(concrete_trait.trait_id(db)), + )); + if let Some(name) = param_impl.id.name(db) { + buff.push_str(&format!("impl {}: ", name.long(db))); - let concrete_trait_name = concrete_trait.name(db).long(db); - let concrete_trait_generic_args = concrete_trait - .generic_args(db) - .iter() - .map(|arg| extract_and_format(&arg.format(db))) - .join(", "); + let concrete_trait_name = concrete_trait.name(db).long(db); + let concrete_trait_generic_args = concrete_trait + .generic_args(db) + .iter() + .map(|arg| format_generic_arg(db, *arg)) + .join(", "); - location_links.push(LocationLink::new( - buff.len(), - buff.len() + concrete_trait_name.len(), - documentable_id, - 0, - )); - buff.push_str(concrete_trait_name); + location_links.push(LocationLink::new( + buff.len(), + buff.len() + concrete_trait_name.len(), + documentable_id, + 0, + )); + buff.push_str(concrete_trait_name); - if !concrete_trait_generic_args.is_empty() { - buff.push_str(&format!("<{concrete_trait_generic_args}>")); - } + if !concrete_trait_generic_args.is_empty() { + buff.push_str(&format!("<{concrete_trait_generic_args}>")); } + } else { + let bound = + format_anonymous_impl_param(db, "+", param_impl, concrete_trait); + location_links.push(LocationLink::new( + buff.len(), + buff.len() + bound.len(), + documentable_id, + 0, + )); + buff.push_str(&bound); } - Err(_) => buff.push_str(&name), } - } - GenericParam::NegImpl(_) => buff.push_str(crate::documentable_formatter::MISSING), + Err(_) => buff.push_str(param_impl.id.format(db).long(db)), + }, + GenericParam::NegImpl(param_neg_impl) => match param_neg_impl.concrete_trait { + Ok(concrete_trait) => { + let bound = + format_anonymous_impl_param(db, "-", param_neg_impl, concrete_trait); + location_links.push(LocationLink::new( + buff.len(), + buff.len() + bound.len(), + DocumentableItemId::from(LookupItemId::ModuleItem( + ModuleItemId::Trait(concrete_trait.trait_id(db)), + )), + 0, + )); + buff.push_str(&bound); + } + Err(_) => buff.push_str(param_neg_impl.id.format(db).long(db)), + }, } } buff.push('>'); @@ -136,7 +156,7 @@ pub fn get_syntactic_visibility(semantic_visibility: &Visibility) -> &str { /// Formats the full paths of complex types. For example, input "Result" results in output "Result". -pub(crate) fn extract_and_format(input: &str) -> String { +fn extract_and_format(input: &str) -> String { let delimiters = [',', '<', '>', '(', ')', '[', ']', '@']; let mut output = String::new(); let mut slice_start = 0; @@ -162,6 +182,177 @@ pub(crate) fn extract_and_format(input: &str) -> String { output } +/// Formats an anonymous impl param, as in `+Shape`, `-Drop` or +/// `+FnOnce[Output: U]`. +/// +/// An anonymous param is spelled by the bound it imposes, so it keeps the `+` or `-` the source +/// writes it with. This is what separates it from an impl *argument*, which is spelled `_`. +/// +/// The text spells the trait as written, which may be a full path, and shortening it takes the `::` +/// of an associated type in the trait's arguments for a path separator and drops the qualifier. +fn format_anonymous_impl_param<'db>( + db: &'db dyn Database, + sign: &str, + param_impl: &GenericParamImpl<'db>, + concrete_trait: ConcreteTraitId<'db>, +) -> String { + let bound = format!("{sign}{}", format_concrete_trait(db, concrete_trait, false)); + if param_impl.type_constraints.is_empty() { + return bound; + } + let constraints = param_impl + .type_constraints + .iter() + .map(|(trait_type, type_id)| { + format!("{}: {}", trait_type.name(db).long(db), format_type(db, *type_id)) + }) + .join(", "); + format!("{bound}[{constraints}]") +} + +/// Formats a [`TypeId`] for signature documentation. +/// +/// Full paths are shortened to the item's name (for example `core::felt252` results in `felt252`), +/// except for associated types, which keep the impl qualifier they are accessed through (for +/// example `Self::Item`), as an associated type name on its own does not identify a type. +pub(crate) fn format_type<'db>(db: &'db dyn Database, type_id: TypeId<'db>) -> String { + match type_id.long(db) { + TypeLongId::ImplType(impl_type_id) => format_impl_type(db, impl_type_id), + TypeLongId::Snapshot(inner_type_id) => format!("@{}", format_type(db, *inner_type_id)), + TypeLongId::Tuple(inner_type_ids) => { + let inner = inner_type_ids.iter().map(|ty| format_type(db, *ty)).join(", "); + // A single element tuple requires a trailing comma, to tell it apart from a + // parenthesized type. + if inner_type_ids.len() == 1 { format!("({inner},)") } else { format!("({inner})") } + } + TypeLongId::FixedSizeArray { type_id, size } => { + format!("[{}; {}]", format_type(db, *type_id), format_const_value(db, *size)) + } + TypeLongId::Concrete(concrete_type_id) => { + let name = concrete_type_id.generic_type(db).name(db).long(db); + let generic_args = concrete_type_id.generic_args(db); + if generic_args.is_empty() { + name.to_string() + } else { + let generic_args = + generic_args.iter().map(|arg| format_generic_arg(db, *arg)).join(", "); + format!("{name}<{generic_args}>") + } + } + // None of these can contain a nested type, so shortening the flattened text is enough. + TypeLongId::GenericParameter(_) + | TypeLongId::Var(_) + | TypeLongId::NumericLiteral(_) + | TypeLongId::Coupon(_) + | TypeLongId::Closure(_) + | TypeLongId::Missing(_) => extract_and_format(&type_id.format(db)), + } +} + +/// Formats a [`GenericArgumentId`] for signature documentation. +pub(crate) fn format_generic_arg<'db>( + db: &'db dyn Database, + generic_arg: GenericArgumentId<'db>, +) -> String { + match generic_arg { + GenericArgumentId::Type(type_id) => format_type(db, type_id), + GenericArgumentId::Constant(value) => format_const_value(db, value), + // An impl argument is written when it has a name - the source can pass one explicitly, as + // in `bar::()` - and `_` when it is inferred and has none to write. An impl *param* + // is a bound instead, and keeps its `+` or `-`. + GenericArgumentId::Impl(impl_id) => { + format_impl_name(db, impl_id).unwrap_or_else(|| "_".to_string()) + } + // A negative impl is never written in argument position. + GenericArgumentId::NegImpl(_) => "_".to_string(), + } +} + +/// Formats a [`ConcreteTraitId`] for signature documentation, as its name followed by its generic +/// arguments - for example `AssocTrait`. +fn format_concrete_trait<'db>( + db: &'db dyn Database, + concrete_trait: ConcreteTraitId<'db>, + add_turbofish: bool, +) -> String { + let name = concrete_trait.name(db).long(db); + let generic_args = concrete_trait.generic_args(db); + if generic_args.is_empty() { + return name.to_string(); + } + let generic_args = generic_args.iter().map(|arg| format_generic_arg(db, *arg)).format(", "); + let turbofish = if add_turbofish { "::" } else { "" }; + format!("{name}{turbofish}<{generic_args}>") +} + +/// Formats the name an [`ImplId`] is written with - for example `Self`, `CircleShape` or +/// `S::Inner`. Returns [`None`] for an impl the source cannot name: an anonymous impl param, an +/// inference variable, and a generated impl. +/// +/// The name comes from the impl's semantic data rather than from shortening [`ImplLongId::name`], +/// which is a full path for some variants and a debug representation for others. Shortening the +/// whole `::` string is not an option either - it would take the `::` for a path +/// separator and drop the qualifier, which is the very bug this avoids. +fn format_impl_name<'db>(db: &'db dyn Database, impl_id: ImplId<'db>) -> Option { + match impl_id.long(db) { + // The trait's own impl is written `Self`. + ImplLongId::SelfImpl(_) => Some("Self".to_string()), + // A concrete impl, or a named impl param, is written with its own name, which + // [`ImplLongId::name`] gives as the bare item name. + ImplLongId::Concrete(_) => Some(impl_id.long(db).name(db)), + ImplLongId::GenericParameter(param) if param.name(db).is_some() => { + Some(impl_id.long(db).name(db)) + } + // An impl item of another impl is written through the impl holding it, so it is nameable + // only as long as that one is. + ImplLongId::ImplImpl(impl_impl) => { + let outer = format_impl_name(db, impl_impl.impl_id())?; + Some(format!("{outer}::{}", impl_impl.trait_impl_id().name(db).long(db))) + } + ImplLongId::GenericParameter(_) | ImplLongId::ImplVar(_) | ImplLongId::GeneratedImpl(_) => { + None + } + } +} + +/// Formats an [`ImplId`] as the qualifier an associated item is accessed through. +/// +/// An impl with no name of its own still has to be qualified with something, or the associated +/// item's name would not identify it. Its trait is used instead, as in `AssocTrait::::Item`, +/// which is how the source reaches the item too. +fn format_impl<'db>(db: &'db dyn Database, impl_id: ImplId<'db>) -> String { + format_impl_name(db, impl_id).unwrap_or_else(|| { + impl_id + .concrete_trait(db) + .map(|concrete_trait| format_concrete_trait(db, concrete_trait, true)) + .unwrap_or_else(|_| crate::documentable_formatter::MISSING.to_string()) + }) +} + +/// Formats an associated type, qualified by the impl it is accessed through. For example, input +/// `core::iter::traits::iterator::Iterator::::Item` results in output `Self::Item`. +fn format_impl_type<'db>(db: &'db dyn Database, impl_type_id: &ImplTypeId<'db>) -> String { + format!("{}::{}", format_impl(db, impl_type_id.impl_id()), impl_type_id.ty().name(db).long(db)) +} + +/// Formats a [`ConstValueId`] for signature documentation, as reached through a fixed size array's +/// length. +/// +/// An associated const keeps the impl qualifier it is accessed through, for the same reason an +/// associated type does - `SIZE` on its own does not identify a const. A length is a `usize`, so +/// the remaining spellings a value can take there are a literal, a const generic param, an +/// inference variable and a missing value, all of which are already short. +fn format_const_value<'db>(db: &'db dyn Database, value: ConstValueId<'db>) -> String { + match value.long(db) { + ConstValue::ImplConstant(impl_constant) => format!( + "{}::{}", + format_impl(db, impl_constant.impl_id()), + impl_constant.trait_constant_id().name(db).long(db) + ), + _ => value.format(db), + } +} + /// Formats a single type path. For example, input "core::felt252" results in output "felt252". fn format_final_part(slice: &str) -> String { let mut parts = slice.rsplit("::"); @@ -189,44 +380,42 @@ pub fn format_resolver_generic_params<'db>( params .iter() .map(|param| { - if matches!(param.kind(db), GenericKind::Impl) { - let param_formatted = param.format(db); - if param_formatted.long(db).starts_with("+") { - param_formatted.long(db).to_string() - } else { - match db.generic_param_semantic(*param) { - Ok(generic_param) => match generic_param { - GenericParam::Impl(generic_param_impl) => { - match generic_param_impl.concrete_trait { - Ok(concrete_trait) => { - let generic_args = concrete_trait.generic_args(db); - format!( - "impl {}: {}{}", - param_formatted.long(db), - concrete_trait.name(db).long(db), - if generic_args.is_empty() { - "".to_string() - } else { - format!( - "<{}>", - generic_args - .iter() - .map(|arg| arg.format(db)) - .join(", "), - ) - } - ) - } - Err(_) => param_formatted.long(db).to_string(), - } - } - _ => param_formatted.long(db).to_string(), - }, - Err(_) => param_formatted.long(db).to_string(), + // Only an impl param has a bound to spell; a type or const param is its name. + let semantic = match param.kind(db) { + GenericKind::Impl | GenericKind::NegImpl => { + db.generic_param_semantic(*param).ok() + } + GenericKind::Type | GenericKind::Const => None, + }; + match semantic { + Some(GenericParam::Impl(param_impl)) => { + match (param_impl.concrete_trait, param.name(db)) { + (Ok(concrete_trait), Some(name)) => format!( + "impl {}: {}", + name.long(db), + format_concrete_trait(db, concrete_trait, false), + ), + (Ok(concrete_trait), None) => format_anonymous_impl_param( + db, + "+", + ¶m_impl, + concrete_trait, + ), + (Err(_), _) => param.format(db).long(db).to_string(), + } + } + Some(GenericParam::NegImpl(param_impl)) => { + match param_impl.concrete_trait { + Ok(concrete_trait) => format_anonymous_impl_param( + db, + "-", + ¶m_impl, + concrete_trait, + ), + Err(_) => param.format(db).long(db).to_string(), } } - } else { - param.format(db).long(db).to_string() + _ => param.format(db).long(db).to_string(), } }) .join(", ") diff --git a/crates/cairo-lang-doc/src/tests/test-data/comment_markers.txt b/crates/cairo-lang-doc/src/tests/test-data/comment_markers.txt index 95d5ce5c991..c4bc6b3f700 100644 --- a/crates/cairo-lang-doc/src/tests/test-data/comment_markers.txt +++ b/crates/cairo-lang-doc/src/tests/test-data/comment_markers.txt @@ -8,7 +8,7 @@ documentation_test_runner hello = "src" //! > cairo_code -trait T { +trait Mapper { ///////////////////////////////////////////////////////////////////////// // Transforming contained values ///////////////////////////////////////////////////////////////////////// @@ -39,16 +39,14 @@ trait T { //! > Item documentation tokens #1 //! > Item signature #2 -trait T +trait Mapper //! > Item documentation #2 //! > Item documentation tokens #2 //! > Item signature #3 -fn map, +core::ops::FnOnce[Output: U]>( - self: Option, f: F, -) -> Option +fn map, +FnOnce[Output: U]>(self: Option, f: F) -> Option //! > Item documentation #3 Maps an `Option` to `Option` by applying a function to a contained value (if `Some`) diff --git a/crates/cairo-lang-doc/src/tests/test-data/signature.txt b/crates/cairo-lang-doc/src/tests/test-data/signature.txt index e24de9ffbd1..3e02c5fe893 100644 --- a/crates/cairo-lang-doc/src/tests/test-data/signature.txt +++ b/crates/cairo-lang-doc/src/tests/test-data/signature.txt @@ -33,6 +33,7 @@ trait Shape { type ShapePair; fn area(self: T) -> u32; + fn pair(self: T) -> Self::ShapePair; } struct Circle { @@ -45,6 +46,7 @@ impl CircleShape of Shape { fn area(self: Circle) -> u32 { 3 * self.radius * self.radius } + fn pair(self: Circle) -> Self::ShapePair {} } @@ -57,6 +59,10 @@ struct B { impl BCopy, +Copy> of Copy>; +impl ATraitImpl of ATrait {} + +fn nameable_impl_arg(b: B) -> B {} + pub extern type bytes31; pub extern type Pedersen; @@ -114,6 +120,59 @@ struct StructLeadingImplParam<+CTrait, T> { value: T, } +trait AssocTrait { + const ASSOC_CONST: Self::Item; + const SIZE: usize; + type Item; + type Other; + + fn assoc_in_param_and_return(self: T, other: Self::Other) -> Self::Other; + fn assoc_nested_in_generic(self: T) -> Option; + fn assoc_in_tuple(self: T) -> (Self::Item, Self::Other); + fn assoc_in_snapshot(self: T) -> @Self::Item; + fn assoc_const_array_size(self: T) -> [bool; Self::SIZE]; +} + +trait OuterAssoc { + impl Nested: AssocTrait; + + fn impl_impl_assoc(x: Self::Nested::Item) -> Self::Nested::Item; +} + +fn impl_impl_of_impl_param>(x: O::Nested::Item) -> O::Nested::Item {} + +fn assoc_of_impl_params, impl U: AssocTrait>( + first: S::Item, second: U::Item, +) -> (S::Item, U::Item) {} + +fn snapshot_param(a: @Circle) -> @Circle {} + +fn concrete_impl_bound>(circle: Circle) -> u32 {} + +fn anon_assoc_qualified>(x: T) -> AssocTrait::::Item {} + +fn assoc_in_anon_bound, +Shape>(x: T) {} + +fn neg_impl_param>(x: T) {} + +struct NegImplStruct> { + value: T, +} + +struct ConstGenericStruct { + value: felt252, +} + +fn assoc_const_generic_arg>() -> ConstGenericStruct {} + +fn one_tuple(a: felt252) -> (felt252,) {} + +fn nested_one_tuple(a: felt252) -> Option<(felt252,)> {} + +struct AssocBoundStruct, impl V: Shape> { + value: T, +} + //! > Item signature #1 //! > Item documentation #1 @@ -214,153 +273,181 @@ fn area(self: T) -> u32 //! > Item documentation tokens #13 //! > Item signature #14 -struct Circle { - radius: u32, -} +fn pair(self: T) -> Self::ShapePair //! > Item documentation #14 //! > Item documentation tokens #14 //! > Item signature #15 -radius: u32 +struct Circle { + radius: u32, +} //! > Item documentation #15 //! > Item documentation tokens #15 //! > Item signature #16 -impl CircleShape of Shape; +radius: u32 //! > Item documentation #16 //! > Item documentation tokens #16 //! > Item signature #17 -type ShapePair = (Circle, Circle); +impl CircleShape of Shape; //! > Item documentation #17 //! > Item documentation tokens #17 //! > Item signature #18 -const SHAPE_CONST: felt252 = 'xyz'; +type ShapePair = (Circle, Circle); //! > Item documentation #18 //! > Item documentation tokens #18 //! > Item signature #19 -fn area(self: Circle) -> u32 +const SHAPE_CONST: felt252 = 'xyz'; //! > Item documentation #19 //! > Item documentation tokens #19 //! > Item signature #20 -trait ATrait +fn area(self: Circle) -> u32 //! > Item documentation #20 //! > Item documentation tokens #20 //! > Item signature #21 -struct B { - t: T, - g: G, -} +fn pair(self: Circle) -> (Circle, Circle) //! > Item documentation #21 //! > Item documentation tokens #21 //! > Item signature #22 -t: T +trait ATrait //! > Item documentation #22 //! > Item documentation tokens #22 //! > Item signature #23 -g: G +struct B { + t: T, + g: G, +} //! > Item documentation #23 //! > Item documentation tokens #23 //! > Item signature #24 -impl BCopy, +Copy> of Copy>; +t: T //! > Item documentation #24 //! > Item documentation tokens #24 //! > Item signature #25 -pub extern type bytes31; +g: G //! > Item documentation #25 //! > Item documentation tokens #25 //! > Item signature #26 -pub extern type Pedersen; +impl BCopy, +Copy> of Copy>; //! > Item documentation #26 //! > Item documentation tokens #26 //! > Item signature #27 -pub extern fn pedersen(a: felt252, b: felt252) -> felt252 implicits(Pedersen) nopanic; +impl ATraitImpl of ATrait; //! > Item documentation #27 //! > Item documentation tokens #27 //! > Item signature #28 -fn this_function_has_a_very_long_signature( - and_contains_a_linked_parameter: Circle, - lorem: felt252, - ipsum: felt252, - and_another_linked_parameter_in_the_middle: Circle, - dolor: felt252, - sit: felt252, - amet: felt252, - yet_another_linked_parameter_at_the_end: Circle, -) -> Circle +fn nameable_impl_arg(b: B) -> B //! > Item documentation #28 //! > Item documentation tokens #28 //! > Item signature #29 -fn test_fixed_size_array(param: [u32; 8]) -> [u32; 8] +pub extern type bytes31; //! > Item documentation #29 //! > Item documentation tokens #29 //! > Item signature #30 -trait TestTrait +pub extern type Pedersen; //! > Item documentation #30 //! > Item documentation tokens #30 //! > Item signature #31 -trait TestTraitWithoutGenerics +pub extern fn pedersen(a: felt252, b: felt252) -> felt252 implicits(Pedersen) nopanic; //! > Item documentation #31 //! > Item documentation tokens #31 //! > Item signature #32 -impl TestTraitImpl of TestTrait; +fn this_function_has_a_very_long_signature( + and_contains_a_linked_parameter: Circle, + lorem: felt252, + ipsum: felt252, + and_another_linked_parameter_in_the_middle: Circle, + dolor: felt252, + sit: felt252, + amet: felt252, + yet_another_linked_parameter_at_the_end: Circle, +) -> Circle //! > Item documentation #32 //! > Item documentation tokens #32 //! > Item signature #33 +fn test_fixed_size_array(param: [u32; 8]) -> [u32; 8] + +//! > Item documentation #33 + +//! > Item documentation tokens #33 + +//! > Item signature #34 +trait TestTrait + +//! > Item documentation #34 + +//! > Item documentation tokens #34 + +//! > Item signature #35 +trait TestTraitWithoutGenerics + +//! > Item documentation #35 + +//! > Item documentation tokens #35 + +//! > Item signature #36 +impl TestTraitImpl of TestTrait; + +//! > Item documentation #36 + +//! > Item documentation tokens #36 + +//! > Item signature #37 macro count_idents { ($x:ident) => { ... }; ($x:ident, $y:ident) => { ... }; @@ -370,47 +457,251 @@ macro count_idents { (abc {$x:ident, (abc $y:ident) }) => { ... }; } -//! > Item documentation #33 +//! > Item documentation #37 -//! > Item documentation tokens #33 +//! > Item documentation tokens #37 -//! > Item signature #34 +//! > Item signature #38 macro matcher_star { ($($x:expr), *) => { ... }; } -//! > Item documentation #34 +//! > Item documentation #38 -//! > Item documentation tokens #34 +//! > Item documentation tokens #38 -//! > Item signature #35 +//! > Item signature #39 macro square_brackets_redundant_whitespace { [$x:ident] => { ... }; } -//! > Item documentation #35 +//! > Item documentation #39 -//! > Item documentation tokens #35 +//! > Item documentation tokens #39 -//! > Item signature #36 +//! > Item signature #40 trait CTrait -//! > Item documentation #36 +//! > Item documentation #40 -//! > Item documentation tokens #36 +//! > Item documentation tokens #40 -//! > Item signature #37 +//! > Item signature #41 struct StructLeadingImplParam<+CTrait, T> { value: T, } -//! > Item documentation #37 +//! > Item documentation #41 -//! > Item documentation tokens #37 +//! > Item documentation tokens #41 -//! > Item signature #38 +//! > Item signature #42 value: T -//! > Item documentation #38 +//! > Item documentation #42 -//! > Item documentation tokens #38 +//! > Item documentation tokens #42 + +//! > Item signature #43 +trait AssocTrait + +//! > Item documentation #43 + +//! > Item documentation tokens #43 + +//! > Item signature #44 +const ASSOC_CONST: Self::Item; + +//! > Item documentation #44 + +//! > Item documentation tokens #44 + +//! > Item signature #45 +const SIZE: u32; + +//! > Item documentation #45 + +//! > Item documentation tokens #45 + +//! > Item signature #46 +type Item; + +//! > Item documentation #46 + +//! > Item documentation tokens #46 + +//! > Item signature #47 +type Other; + +//! > Item documentation #47 + +//! > Item documentation tokens #47 + +//! > Item signature #48 +fn assoc_in_param_and_return(self: T, other: Self::Other) -> Self::Other + +//! > Item documentation #48 + +//! > Item documentation tokens #48 + +//! > Item signature #49 +fn assoc_nested_in_generic(self: T) -> Option + +//! > Item documentation #49 + +//! > Item documentation tokens #49 + +//! > Item signature #50 +fn assoc_in_tuple(self: T) -> (Self::Item, Self::Other) + +//! > Item documentation #50 + +//! > Item documentation tokens #50 + +//! > Item signature #51 +fn assoc_in_snapshot(self: T) -> @Self::Item + +//! > Item documentation #51 + +//! > Item documentation tokens #51 + +//! > Item signature #52 +fn assoc_const_array_size(self: T) -> [bool; Self::SIZE] + +//! > Item documentation #52 + +//! > Item documentation tokens #52 + +//! > Item signature #53 +trait OuterAssoc + +//! > Item documentation #53 + +//! > Item documentation tokens #53 + +//! > Item signature #54 +fn impl_impl_assoc(x: Self::Nested::Item) -> Self::Nested::Item + +//! > Item documentation #54 + +//! > Item documentation tokens #54 + +//! > Item signature #55 +fn impl_impl_of_impl_param>(x: O::Nested::Item) -> O::Nested::Item + +//! > Item documentation #55 + +//! > Item documentation tokens #55 + +//! > Item signature #56 +fn assoc_of_impl_params, impl U: AssocTrait>( + first: S::Item, second: U::Item, +) -> (S::Item, U::Item) + +//! > Item documentation #56 + +//! > Item documentation tokens #56 + +//! > Item signature #57 +fn snapshot_param(a: @Circle) -> @Circle + +//! > Item documentation #57 + +//! > Item documentation tokens #57 + +//! > Item signature #58 +fn concrete_impl_bound>(circle: Circle) -> u32 + +//! > Item documentation #58 + +//! > Item documentation tokens #58 + +//! > Item signature #59 +fn anon_assoc_qualified>(x: T) -> AssocTrait::::Item + +//! > Item documentation #59 + +//! > Item documentation tokens #59 + +//! > Item signature #60 +fn assoc_in_anon_bound, +Shape>(x: T) + +//! > Item documentation #60 + +//! > Item documentation tokens #60 + +//! > Item signature #61 +fn neg_impl_param>(x: T) + +//! > Item documentation #61 + +//! > Item documentation tokens #61 + +//! > Item signature #62 +struct NegImplStruct> { + value: T, +} + +//! > Item documentation #62 + +//! > Item documentation tokens #62 + +//! > Item signature #63 +value: T + +//! > Item documentation #63 + +//! > Item documentation tokens #63 + +//! > Item signature #64 +struct ConstGenericStruct { + value: felt252, +} + +//! > Item documentation #64 + +//! > Item documentation tokens #64 + +//! > Item signature #65 +value: felt252 + +//! > Item documentation #65 + +//! > Item documentation tokens #65 + +//! > Item signature #66 +fn assoc_const_generic_arg>() -> ConstGenericStruct + +//! > Item documentation #66 + +//! > Item documentation tokens #66 + +//! > Item signature #67 +fn one_tuple(a: felt252) -> (felt252,) + +//! > Item documentation #67 + +//! > Item documentation tokens #67 + +//! > Item signature #68 +fn nested_one_tuple(a: felt252) -> Option<(felt252,)> + +//! > Item documentation #68 + +//! > Item documentation tokens #68 + +//! > Item signature #69 +struct AssocBoundStruct, impl V: Shape> { + value: T, +} + +//! > Item documentation #69 + +//! > Item documentation tokens #69 + +//! > Item signature #70 +value: T + +//! > Item documentation #70 + +//! > Item documentation tokens #70