-
Notifications
You must be signed in to change notification settings - Fork 0
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
Validate Codegen Settings #11
Conversation
typegen/src/typegen/error.rs
Outdated
impl std::fmt::Display for SettingsValidationError { | ||
fn fmt( | ||
&self, | ||
f: &mut scale_info::prelude::fmt::Formatter<'_>, | ||
) -> scale_info::prelude::fmt::Result { | ||
f.write_fmt(format_args!("{:?}", self)) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if this could be replaced with the thiserror attr on the struct:
#[error = "{:?}"]
But moreover, I think that a proper Display
impl should do better than just debug printing :)
|
||
use super::{error::SettingsValidationError, settings::substitutes::TryIntoSynPath}; | ||
|
||
impl<'a> TypeGenerator<'a> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It feels sortof weird to me to have a separate impl block in a different place from the type; I like being able to quite easily see all of the methods that something exposes in a single impl block (of it different constraints, a few impl blocks next to eachother) next to the type definition.
If you want to keep the validation stuff in one place, then perhaps it's best to make this a freestanding function like the ones below?
I also wonder how useful this function actually is, since it will check everything (and in Subxt at least, some things don't want to be checked). I can imagine that for Subxt we'd prefer to use the functions below? Do you have a use case for this overall one?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you are right, since we want to be very specific about what type paths to check in subxt, maybe this general validation function is not the right approach. :)
About the splitting into different files: It's just my personal style influenced by how you often define extension classes in C# or Dart. But It is probably better to merge it all into one impl
block for people reading the code.
pub trait TryIntoSynPath { | ||
/// Turns the type into a [`syn::Path`]. Returns None for empty paths. | ||
fn syn_path(self) -> Option<syn::Path>; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is cleaner than the PathSegments
stuff I think :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't like it so much that we have to define a new trait for this, but due to the orphan rule, we cannot use TryFrom<T>
for syn::Path
:(
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I thought about that too and realised that you had no other choice! The other half way option would have been to define an enum Path { SynPath(syn::Path), TypeInfoPath(typeinfo::Path) }
and then a From
on that, but I think your approach is cleaner since you only care about getting one of those back!
Generally LGTM! Just a couple of small things! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me; the real test will be how it works in Subxt/subxt-explorer :)
pub substitutes_for_unknown_types: Vec<(syn::Path, syn::Path)>, | ||
} | ||
|
||
impl std::fmt::Display for SettingsValidationError { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit; It would be interesting to see if we could provide alternative types. Since we cannot find type a::b::Ty
, we could inspect the type registry for Ty
and return all valid paths.
Which for an xcm MultiLocation it would return both v2 and v3 entries, which might make things easier during development. Tho, this could probably be a follow-up
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have a feeling that Subxt won't be able to use the function that produces this error, so it may well be that it's not that useful for us actually, and instead we'll lean on those other validation.rs
functions, one of which does provide a list of similar paths
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, the similar_type_paths_in_registry
function can do that, but I have not put it into the SettingsValidationError
, to not bloat it too much. We should definitely do this though from the subxt macro side.
typegen/src/typegen/mod.rs
Outdated
/// | ||
/// # Panics | ||
/// | ||
/// If no type with the given id found in the type registry. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since we are returning a result here, would it be dificult to make this method not panic? Same for below?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point; in most places we just have an error variant to capture "type ID not found" so it's probably good to do that here too for consistency.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh good catch! The docs are out of date, it actually returns an Err(..) if a wrong id was provided.
} | ||
|
||
/// Returns types in the PortableRegistry that share the identifier with the input path. | ||
pub fn similar_type_paths_in_registry( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IIUC, this is only used for testing atm, would changing the code a bit make this more informative?
- registry_contains_type_path ->
Result<(), Vec<syn::Path>>
- if the path is in the registry, return
Ok(())
- when the paths not present, return alternatives with this method
Then we could say if let Err(alternatives) = registry_contains_type_path(..)
and extend the error object with those
Or we could keep registry_contains_type_path
as it is, and call similar_type_paths_in_registry
on false (thinking out loud :D)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or we could keep registry_contains_type_path as it is, and call similar_type_paths_in_registry on false
I am inclined to do this (as currently done in validate_substitutes_and_derives_against_registry
), because it keeps it a bit more decoupled. Ultimately I am not even sure if we will use validate_substitutes_and_derives_against_registry
from the subxt side or if we build some separate logic on top of registry_contains_type_path
and similar_type_paths_in_registry
.
} | ||
|
||
/// Returns types in the PortableRegistry that share the identifier with the input path. | ||
pub fn similar_type_paths_in_registry( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is good for now; eventually we might want to improve it to find paths that are close (to cater for typos) but that would be a reasonable amount of extra work and dependencies
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah yeah, maybe some Levenshtein distance calculations? But should be too much for now.
Looks solid! Nice job here! |
This PR adds functionality to check if the provided type substitute and derive settings are appropriate for a given Type Registry. The validation incrementally builds up an error type that is then returned, containing all the type paths for which special settings were defined, but that do not exist in the metadata.
There is also a function
similar_type_paths_in_registry
to suggest similar type paths that the user might have meant instead.