-
Notifications
You must be signed in to change notification settings - Fork 117
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
Proof of concept, argument to export_to
other than &'static str
#347
base: main
Are you sure you want to change the base?
Conversation
Hey, thanks for opening this PR! Is there a real use-case behind this feature, or is this more of a "it'd be really cool if this worked" kind of thing? I do think there are some advantages of keeping the directory structure static. For more exotic usecases (like custom build scripts), there's |
Hi NyxCode! It's not that providing a real-life example is difficult, One general downside of using a
|
Looks like we're talking about two different aspects here. Honestly, I didn’t even consider any side effects while implementing this PR; my approach was "Just trust the trait and make sure The only purpose of this PR is to challenge the type of input for the Especially after the latest releases, users (myself included) can now write multiple types to the same file. a) Copy and paste the new path to each of my three objects, recompile, and run test again. However, if the path is defined as lets say an environment variable, all I need to do is:
So yes, the arguments might look cooler, but there's more than that. Typically, for a group of objects, we define shared variable instead of hard-coding values. The compiler only checks these variables, and in the case of a
|
This looks really interesting! 2 questions though:
|
macros/src/path.rs
Outdated
#[ts(export_to = MY_STATIC_PATH)] | ||
#[ts(export_to = crate::MY_STATIC_PATH)] | ||
|
||
Note: This option is available for Rust 1.7.0 and higher! |
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 feels like a typo, did you really mean 1.7.0? The MSRV for ts-rs
is 1.63.0, so this note is not needed if you really did mean 1.7.0
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's not a typo std::sync::OnceLock is stabilised in Rust 1.70.0, probably available 1.63. nightly only.
The idiomatic way is to check the Rust version, but #[cfg(version(..))]) isn't stabilised as well.
The worst-case scenario is a compile-time error, informing the user that std::sync::OnceLock
is only available in nightly.
Additionally, since ts-rs
currently depends on lazy_static
, there's a good chance that this dependency will be dropped in favour of the standard library types increasing the MSRV and making this issue less relevant over time.
not sure what to do with it it's up to you really.
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.
So you meant 1.70.0 right?
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.
of course 1.70 )))
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.
And the code says 1.7... you're missing a zero
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.
That's right, it is a typo )))
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.
Alright, in that case, we can just change the MSRV to 1.70.0 and we don't have to worry about it
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.
Formatting feels weird, can you run cargo +nightly fmt
?
macros/src/path.rs
Outdated
let msg = | ||
"expected arguments for 'export_to': | ||
|
||
1) string literal | ||
#[ts(export_to = \"my/path\")] | ||
|
||
2) static or constant variable name | ||
|
||
#[ts(export_to = MY_STATIC_PATH)] | ||
#[ts(export_to = crate::MY_STATIC_PATH)] | ||
|
||
Note: This option is available for Rust 1.7.0 and higher! | ||
|
||
3) function name of a `Fn(&'static str) -> Option<&'static str>` | ||
|
||
#[ts(export_to = get_path)] | ||
#[ts(export_to = crate::get_path)] | ||
|
||
Note: This option overrides the original `TS::output_path` logic`! | ||
|
||
4) environment variable name | ||
|
||
#[ts(export_to = env(\"MY_ENV_VAR_PATH\"))] | ||
|
||
Note: This option is for environment variables defined in the '.cargo/config.toml' file only, accessible through the `env!` macro! | ||
"; |
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 message should be a module level const
to avoid having a massive string literal inside the function. This makes the function more difficult to read
macros/src/path.rs
Outdated
3) function name of a `Fn(&'static str) -> Option<&'static str>` | ||
|
||
#[ts(export_to = get_path)] | ||
#[ts(export_to = crate::get_path)] | ||
|
||
Note: This option overrides the original `TS::output_path` logic`! |
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'm not really sure if we should allow users to override TS::output_path
, this may lead to way too many footguns
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.
things that may go wrong with this option:
- If the path is a directory:
a) for existing directory, the test will panic with CannotBeExported.
b) will write into a file with no extension. - Anytime the function returns None, the test will panic with CannotBeExported.
Also I've found a way to propagate the error the correct message
and exact span if the provided function is of a different than required type,
by asigning first as a function pointer and then use the pointer to invoke the function:
fn output_path() -> Option<&'static std::path::Path> {
let path: fn(&'static str) -> Option<&'static str> = crate::get_path_fn;
Some(std::path::Path::new(path("ObjC")?))
}
it is precise!
Hi @gustavo-shigueo ! One more thing to consider is documenting the type options. The ts-rs documentation is already quite dense with terms, and adding more might make it harder for users to remember any. Plus the fact that macros are really bad when it comes to documenting. I propose to introduce an easy to remeber notation like this Bassically a quick reminder. Compared to crate documentation this could be more efficient as the information is provided at the right place and time. |
macros/src/path.rs
Outdated
// static or const | ||
if is_screaming_snake_case(&last.to_string()) { | ||
return Ok(CustomPath::Static(path)); | ||
} | ||
|
||
// function | ||
if is_snake_case(&last.to_string()) { | ||
return Ok(CustomPath::Fn(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.
Another reason I don't really like allowing a function path here is that there is no reliable way to differentiate between a function name and a const/static name. Sure, clippy will complain if a const isn't in SCREAMING_SNAKE_CASE, but it doesn't prevent the code from compiling
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've triyed this scenario on the new design (I've mentioned above, assignment to a function pointer ) and it looks like
it will not compile, which is not bad, this means that the macro is limited to
Rust naming conventions. As long as the mistake is excluded we are ok.
so for lower case static the error will be :
expected fn pointer `fn(&'static str) -> std::option::Option<&'static str>`
found reference `&'static str`
That may not be necessary, the error message you've written already seems to serve that purpose quite well, so if we make sure to display it for any syntax error in |
export_to
other than &'static str
Before too much effort is put into this, i think we should answer the question if we really want this feature. |
I see, I do kinda like the idea of allowing As for the complexity, it would go way down if only static/const were added, but I'm also not sure it'd be worth it |
Sorry for the delay, I can't actively includ myself in conversation right now ( will be back in couple of days). Think of other proposition, I'll write later some arguments in favour of keeping all variants of |
This PR was initiated to demonstrate the possible use of different types for the Naming types, modules, and variables is always important, and the right names often emerge as the project evolves. Therefore, having a flexible approach to renaming both the types of arguments and the values of those arguments is a common and necessary practice for programmers. Since I didn't have a clear initial objective for this PR, I think it would be helpful to summarize my proposition in one clear statement. Allowed Types:
In my opinion, using a typed path is safer for various reasons. Limiting the crate to the use of The current PR aims to assist in two major ways:
The crate's responsibility is limited to two general cases:
Note: This point is base for
Additionally, I believe that restricting the number of variants, whatever they may be, lacks sufficient justification. Since there isn't a universally efficient approach, any type restriction is often unnecessary. The type of the path itself isn't likely to cause bugs; rather, it's the type value that could lead to issues, which is entirely the user's responsibility. Consider either accepting I've made my point, from here, it's up to you to decide what is acceptable so we can move forward with more precise code, some tests, and ensure that the PR aligns with project requirements. |
…dded some simple test to prevent it.
There was a bug, it wasn't working for the environment variables, after refactoring. 😅 |
Hi there,
and thank you for this crate!
In addition to a
'static str
as the argument toexport_to
attributewe could use the following types :
.cargo/config.toml
#[ts(export_to = env("CONFIG_ENV_VAR_PATH"))]
TS::output_path
method generated for the type:Fn(&'static str) -> Option<&'static str>
) that will override the standardTS::output_path
method logic.example:
the argument is an identifier or a path to our function
TS::output_path
method generated for the ( ts nameObjB
):const
andstatic
namesagain as identifier or path
TS::output_path
method generated for the type:All options are reactive, modifying the source of argument value
will make
TS
export to the new path without need to recompile.Thinking about the most efficient or correct way to handle paths can be overwhelming, as there's no universally right way to do it! My proposition is to allow users to manage paths using methods already established by the programming community: constants, statics, and environment variables. Unfortunately, due to Rust's limitations for Derive macros and the 'test' runtime, this is currently restricted to those defined in
.cargo/config.toml
.