Skip to content

Commit

Permalink
Return type replacement of self is now generalised so that any refere…
Browse files Browse the repository at this point in the history
…nce to self is replaced.

Fixes #28
  • Loading branch information
BrynCooke committed May 6, 2022
1 parent 956aca1 commit edc48b0
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 10 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## 0.1.11 - 2022-05-06
[#39](https://github.com/BrynCooke/buildstructor/issues/39)
Visibility of builder now matches the visibility of the constructor.

[#28](https://github.com/BrynCooke/buildstructor/issues/28)
Generalize replacing of self in return type.

## 0.1.10 - 2022-05-04
[#30](https://github.com/BrynCooke/buildstructor/issues/30)
The original token stream is output if there are compile errors.
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ If your type does not conform to these patterns then you can use a type alias to

#### Naming

Use the plural form in your constructor argument and `buildstructor` will automatically try to figure out the singular form for individual entry. For isntance:
Use the plural form in your constructor argument and `buildstructor` will automatically try to figure out the singular form for individual entry. For instance:

`addresses` => `address`

Expand Down
2 changes: 1 addition & 1 deletion src/buildstructor/codegen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ pub fn codegen(ir: Ir) -> Result<TokenStream> {
}
}

pub struct __Required<T> {
pub struct __Required<T> {
_phantom: std::marker::PhantomData<T>,
}
pub struct __Optional<T> {
Expand Down
32 changes: 24 additions & 8 deletions src/buildstructor/lower.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ use quote::{format_ident, quote};
use std::default::Default;
use syn::punctuated::Punctuated;
use syn::{
Expr, ExprField, FnArg, GenericArgument, GenericParam, Generics, Index, Member, Pat, Result,
ReturnType, Type, TypeParam, TypeTuple, VisRestricted, Visibility,
Expr, ExprField, FnArg, GenericArgument, GenericParam, Generics, Index, Member, Pat,
PathArguments, Result, ReturnType, Type, TypeParam, TypeTuple, VisRestricted, Visibility,
};
use try_match::try_match;

Expand Down Expand Up @@ -68,7 +68,7 @@ pub fn lower(model: ConstrutorModel) -> Result<Ir> {
builder_method_name: builder_method_name(&model),
builder_fields: builder_fields(&model),
constructor_name: format_ident!("{}Constructor", model.ident.to_string()),
return_type: builder_return_type(model.output, model.ident),
return_type: builder_return_type(model.output, &model.ident),
is_async: model.is_async,
generics: model.generics,
builder_generics: Ir::builder_generics(),
Expand All @@ -89,16 +89,32 @@ fn builder_vilibility(vis: &Visibility) -> Visibility {
}
}

fn builder_return_type(mut return_type: ReturnType, target: Ident) -> ReturnType {
fn builder_return_type(mut return_type: ReturnType, target: &Ident) -> ReturnType {
if let ReturnType::Type(_, ty) = &mut return_type {
let self_type = Box::new(Type::Path(format_ident!("Self").to_type_path()));
if ty == &self_type {
*ty = Box::new(Type::Path(target.to_type_path()));
}
replace_self(ty, target);
}
return_type
}

fn replace_self(ty: &mut Type, target: &Ident) {
let self_type = format_ident!("Self").to_type_path();
if let Type::Path(path) = ty {
if path == &self_type {
*path = target.to_type_path();
} else {
for segment in path.path.segments.iter_mut() {
if let PathArguments::AngleBracketed(args) = &mut segment.arguments {
for mut arg in args.args.iter_mut() {
if let GenericArgument::Type(ty) = &mut arg {
replace_self(ty, target);
}
}
}
}
}
}
}

fn builder_fields(model: &ConstrutorModel) -> Vec<BuilderField> {
model
.args
Expand Down
8 changes: 8 additions & 0 deletions tests/buildstructor/pass/fallible.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,16 @@ impl Foo {
fn new(simple: usize) -> Result<Foo, String> {
Ok(Self { simple })
}
fn self_new(simple: usize) -> Result<Self, String> {
Ok(Self { simple })
}
fn deep_self_new(simple: usize) -> Result<Result<Self, String>, String> {
Ok(Ok(Self { simple }))
}
}

fn main() {
let _ = Foo::builder().simple(2).build().is_ok();
let _ = Foo::self_builder().simple(2).build().is_ok();
let _ = Foo::deep_self_builder().simple(2).build().is_ok();
}

0 comments on commit edc48b0

Please sign in to comment.