scale_typegen/typegen/
error.rs1use std::collections::HashSet;
2
3use proc_macro2::Span;
4use quote::ToTokens;
5
6#[derive(Debug, thiserror::Error)]
8#[non_exhaustive]
9pub enum TypegenError {
10 #[error("Could not parse into a syn type: {0}")]
12 SynParseError(#[from] syn::Error),
13 #[error("Fields should either be all named or all unnamed, make sure you are providing a valid metadata: {0}")]
15 InvalidFields(String),
16 #[error("A type in the metadata was invalid: {0}")]
18 InvalidType(String),
19 #[error("Could not generate a type that contains a compact type, because the Compact type path is not set in the settings.")]
21 CompactPathNone,
22 #[error("Could not generate a type that contains a bit sequence, because the DecodedBits type path is not set in the settings.")]
24 DecodedBitsPathNone,
25 #[error("Could not find type with ID {0} in the type registry.")]
27 TypeNotFound(u32),
28 #[error("Type substitution error: {0}")]
30 InvalidSubstitute(#[from] TypeSubstitutionError),
31 #[error("Settings do not fit the given type registry: {0}")]
33 SettingsValidation(SettingsValidationError),
34 #[error("There are two types with the the same type path {0} but different structure. Use `scale_typegen::utils::ensure_unique_type_paths` on your `PortableRegistry` before, to avoid this error.")]
37 DuplicateTypePath(String),
38 #[error("PortableRegistry entry has incorrect type_id. expected type_id: {expected_ty_id}, got: {given_ty_id}.\nDefinition of the type: {ty_def}.\nThis can happen if registry was modified with calls to `::retain()` in older versions of scale-info. Try generating a new metadata to fix this.")]
40 RegistryTypeIdsInvalid {
41 given_ty_id: u32,
43 expected_ty_id: u32,
45 ty_def: String,
47 },
48}
49
50#[derive(Debug, thiserror::Error)]
52pub struct TypeSubstitutionError {
53 pub span: Span,
55 pub kind: TypeSubstitutionErrorKind,
57}
58
59impl std::fmt::Display for TypeSubstitutionError {
60 fn fmt(
61 &self,
62 f: &mut scale_info::prelude::fmt::Formatter<'_>,
63 ) -> scale_info::prelude::fmt::Result {
64 f.write_fmt(format_args!("{}", self.kind))
65 }
66}
67
68#[derive(Debug, thiserror::Error)]
70#[non_exhaustive]
71pub enum TypeSubstitutionErrorKind {
72 #[error("`substitute_type(with = <path>)` must be a path prefixed with 'crate::' or '::'")]
74 ExpectedAbsolutePath,
75 #[error("Substitute types must have a valid path.")]
77 EmptySubstitutePath,
78 #[error("Expected the from/to type generics to have the form 'Foo<A,B,C..>'.")]
80 ExpectedAngleBracketGenerics,
81 #[error("Expected an ident like 'Foo' or 'A' to mark a type to be substituted.")]
83 InvalidFromType,
84 #[error("Expected an ident like 'Foo' or an absolute concrete path like '::path::to::Bar' for the substitute type.")]
86 InvalidToType,
87 #[error("Cannot find matching param on 'from' type.")]
89 NoMatchingFromType,
90}
91
92#[derive(Debug, thiserror::Error, Default, PartialEq, Eq)]
94pub struct SettingsValidationError {
95 pub derives_for_unknown_types: Vec<(syn::Path, HashSet<syn::Path>)>,
97 pub attributes_for_unknown_types: Vec<(syn::Path, HashSet<syn::Attribute>)>,
99 pub substitutes_for_unknown_types: Vec<(syn::Path, syn::Path)>,
101}
102
103impl std::fmt::Display for SettingsValidationError {
104 fn fmt(
105 &self,
106 f: &mut scale_info::prelude::fmt::Formatter<'_>,
107 ) -> scale_info::prelude::fmt::Result {
108 fn display_one(e: &impl ToTokens) -> String {
109 e.to_token_stream().to_string().replace(' ', "")
110 }
111
112 fn display_many(set: &HashSet<impl ToTokens>) -> String {
113 set.iter()
114 .map(|e| display_one(e))
115 .collect::<Vec<_>>()
116 .join(", ")
117 }
118
119 writeln!(f, "Settings validation error:")?;
120
121 if !self.derives_for_unknown_types.is_empty() {
122 writeln!(f, " Derives for unknown types:")?;
123 for (path, derives) in &self.derives_for_unknown_types {
124 writeln!(
125 f,
126 " {} (Derives: {})",
127 display_one(path),
128 display_many(derives)
129 )?;
130 }
131 }
132
133 if !self.attributes_for_unknown_types.is_empty() {
134 writeln!(f, " Attributes for unknown types:")?;
135 for (path, attributes) in &self.attributes_for_unknown_types {
136 writeln!(
137 f,
138 " {} (Attributes: {})",
139 display_one(path),
140 display_many(attributes)
141 )?;
142 }
143 }
144
145 if !self.substitutes_for_unknown_types.is_empty() {
146 writeln!(f, " Substitutes for unknown types:")?;
147 for (original, substitute) in &self.substitutes_for_unknown_types {
148 writeln!(
149 f,
150 " {} (Substitute: {})",
151 display_one(original),
152 display_one(substitute),
153 )?;
154 }
155 }
156
157 Ok(())
158 }
159}
160
161impl SettingsValidationError {
162 pub(crate) fn is_empty(&self) -> bool {
163 self.derives_for_unknown_types.is_empty()
164 && self.attributes_for_unknown_types.is_empty()
165 && self.substitutes_for_unknown_types.is_empty()
166 }
167}