constructor-boilerplate
One tree of constructors is built by hand at many sites.
- Group
- Opportunities
- Runs
- Runs under ur report:
ur report --rule constructor-boilerplate - Level
- note
- Reads
- Every file
- Fix
- None: the smart constructor's name and where it lives are a design choice
Why
These sites build the same nest of constructors, such as a struct literal or a call of a type's or variant's path around others, and differ only in the arguments they pass, the holes the finding shows. A literal every site writes the same stays in the shape. A smart constructor that takes the holes as arguments would build the tree once. It reads every language whose grammar states its shapes in a Shapes.rsc; an advisory rule that ur report runs.
The fix, as Ur suggests it: write a smart constructor that takes the holes as arguments, and call it at each site.
For agents
Before writing out a nest of constructors again, look for a function that builds it and call that, or write one.
Example
src/errors.rsuse crate::http::{Body, CachePolicy, Response, Status};
pub fn not_found(path: &str) -> Response {
Response {
status: Status::NotFound,
body: Body::Text(format!("no page at {path}")),
cache: CachePolicy::NoStore,
}
}
pub fn unauthorized(realm: &str) -> Response {
Response {
status: Status::Unauthorized,
body: Body::Text(format!("sign in to {realm} to continue")),
cache: CachePolicy::NoStore,
}
}
pub fn too_large(limit: usize) -> Response {
Response {
status: Status::PayloadTooLarge,
body: Body::Text(format!("uploads are limited to {limit} bytes")),
cache: CachePolicy::NoStore,
}
}
pub fn unavailable(seconds: u64) -> Response {
Response {
status: Status::ServiceUnavailable,
body: Body::Text(format!("try again in {seconds} seconds")),
cache: CachePolicy::NoStore,
}
}
$ ur report --rule constructor-boilerplate
opportunity[constructor-boilerplate]: 4 sites build `Response { status: $, body: Body::Text(format!($)), cache: CachePolicy::NoStore }` with only its holes different (saves about 12 lines)
--> ./src/errors.rs:4:5-8 builds `Response { status: $, body: Body::Text(format!($)), cache: CachePolicy::NoStore }`
--> ./src/errors.rs:12:5-16 builds `Response { status: $, body: Body::Text(format!($)), cache: CachePolicy::NoStore }`
--> ./src/errors.rs:20:5-24 builds `Response { status: $, body: Body::Text(format!($)), cache: CachePolicy::NoStore }`
--> ./src/errors.rs:28:5-32 builds `Response { status: $, body: Body::Text(format!($)), cache: CachePolicy::NoStore }`
= hint: write a smart constructor that takes the holes as arguments, and call it at each site
1 opportunity saving about 12 lines in all