Fix methods returning Self

Rewrite any instance of `Self` to the name of the class

Closes #137
This commit is contained in:
Alex Crichton 2018-04-19 18:43:16 -07:00
parent 542b3a28eb
commit c6f7d3dfd5
3 changed files with 56 additions and 9 deletions

View File

@ -14,5 +14,5 @@ Backend code generation of the wasm-bindgen tool
quote = '0.5'
proc-macro2 = { version = "0.3", features = ["nightly"] }
wasm-bindgen-shared = { path = "../shared", version = "=0.2.4" }
syn = { version = '0.13', features = ['full', 'visit'] }
syn = { version = '0.13', features = ['full', 'visit-mut'] }
serde_json = "1.0"

View File

@ -179,12 +179,13 @@ impl Program {
},
_ => panic!("unsupported self type in impl"),
};
for mut item in item.items.iter_mut() {
self.push_impl_item(name, &mut item);
for item in item.items.iter_mut() {
self.push_impl_item(name, item);
}
}
fn push_impl_item(&mut self, class: syn::Ident, item: &mut syn::ImplItem) {
replace_self(class, item);
let method = match item {
syn::ImplItem::Const(_) => panic!("const definitions aren't supported"),
syn::ImplItem::Type(_) => panic!("type definitions in impls aren't supported"),
@ -458,7 +459,7 @@ impl Function {
pub fn from_decl(
name: syn::Ident,
decl: Box<syn::FnDecl>,
mut decl: Box<syn::FnDecl>,
attrs: Vec<syn::Attribute>,
opts: BindgenAttrs,
vis: syn::Visibility,
@ -471,7 +472,7 @@ impl Function {
panic!("can't bindgen functions with lifetime or type parameters")
}
assert_no_lifetimes(&decl);
assert_no_lifetimes(&mut decl);
let mut mutable = None;
let arguments = decl.inputs
@ -928,15 +929,29 @@ fn term<'a>(cursor: syn::buffer::Cursor<'a>, name: &str) -> syn::synom::PResult<
syn::parse_error()
}
fn assert_no_lifetimes(decl: &syn::FnDecl) {
fn assert_no_lifetimes(decl: &mut syn::FnDecl) {
struct Walk;
impl<'ast> syn::visit::Visit<'ast> for Walk {
fn visit_lifetime(&mut self, _i: &'ast syn::Lifetime) {
impl<'ast> syn::visit_mut::VisitMut for Walk {
fn visit_lifetime_mut(&mut self, _i: &mut syn::Lifetime) {
panic!("it is currently not sound to use lifetimes in function \
signatures");
}
}
syn::visit::Visit::visit_fn_decl(&mut Walk, decl);
syn::visit_mut::VisitMut::visit_fn_decl_mut(&mut Walk, decl);
}
fn replace_self(name: syn::Ident, item: &mut syn::ImplItem) {
struct Walk(syn::Ident);
impl syn::visit_mut::VisitMut for Walk {
fn visit_ident_mut(&mut self, i: &mut syn::Ident) {
if i.as_ref() == "Self" {
*i = self.0;
}
}
}
syn::visit_mut::VisitMut::visit_impl_item_mut(&mut Walk(name), item);
}

View File

@ -526,3 +526,35 @@ fn public_fields() {
"#)
.test();
}
#[test]
fn using_self() {
project()
.debug(false)
.file("src/lib.rs", r#"
#![feature(proc_macro, wasm_custom_section, wasm_import_module)]
extern crate wasm_bindgen;
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub struct Foo {
}
#[wasm_bindgen]
impl Foo {
pub fn new() -> Self {
Foo {}
}
}
"#)
.file("test.ts", r#"
import { Foo } from "./out";
export function test() {
Foo.new().free();
}
"#)
.test();
}