Skip to content
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

Add skip_typescript attribute to prevent .d.ts emit #2016

Merged
merged 2 commits into from
Mar 3, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions crates/backend/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,7 @@ pub struct Function {
pub rust_attrs: Vec<syn::Attribute>,
pub rust_vis: syn::Visibility,
pub r#async: bool,
pub generate_typescript: bool,
}

#[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq, Eq))]
Expand All @@ -231,6 +232,7 @@ pub struct Struct {
pub fields: Vec<StructField>,
pub comments: Vec<String>,
pub is_inspectable: bool,
pub generate_typescript: bool,
}

#[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq, Eq))]
Expand All @@ -243,6 +245,7 @@ pub struct StructField {
pub getter: Ident,
pub setter: Ident,
pub comments: Vec<String>,
pub generate_typescript: bool,
}

#[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq, Eq))]
Expand All @@ -252,6 +255,7 @@ pub struct Enum {
pub variants: Vec<Variant>,
pub comments: Vec<String>,
pub hole: u32,
pub generate_typescript: bool,
}

#[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq, Eq))]
Expand Down
4 changes: 4 additions & 0 deletions crates/backend/src/encode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ fn shared_function<'a>(func: &'a ast::Function, _intern: &'a Interner) -> Functi
Function {
arg_names,
name: &func.name,
generate_typescript: func.generate_typescript,
}
}

Expand All @@ -218,6 +219,7 @@ fn shared_enum<'a>(e: &'a ast::Enum, intern: &'a Interner) -> Enum<'a> {
.map(|v| shared_variant(v, intern))
.collect(),
comments: e.comments.iter().map(|s| &**s).collect(),
generate_typescript: e.generate_typescript,
}
}

Expand Down Expand Up @@ -307,6 +309,7 @@ fn shared_struct<'a>(s: &'a ast::Struct, intern: &'a Interner) -> Struct<'a> {
.collect(),
comments: s.comments.iter().map(|s| &**s).collect(),
is_inspectable: s.is_inspectable,
generate_typescript: s.generate_typescript,
}
}

Expand All @@ -318,6 +321,7 @@ fn shared_struct_field<'a>(s: &'a ast::StructField, intern: &'a Interner) -> Str
},
readonly: s.readonly,
comments: s.comments.iter().map(|s| &**s).collect(),
generate_typescript: s.generate_typescript,
}
}

Expand Down
130 changes: 82 additions & 48 deletions crates/cli-support/src/js/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,17 +111,16 @@ impl<'a> Context<'a> {
&mut self,
export_name: &str,
contents: &str,
comments: Option<String>,
comments: Option<&str>,
) -> Result<(), Error> {
let definition_name = generate_identifier(export_name, &mut self.defined_identifiers);
if contents.starts_with("class") && definition_name != export_name {
bail!("cannot shadow already defined class `{}`", export_name);
}

let contents = contents.trim();
if let Some(ref c) = comments {
if let Some(c) = comments {
self.globals.push_str(c);
self.typescript.push_str(c);
}
let global = match self.config.mode {
OutputMode::Node {
Expand Down Expand Up @@ -804,7 +803,7 @@ impl<'a> Context<'a> {
dst.push_str("}\n");
ts_dst.push_str("}\n");

self.export(&name, &dst, Some(class.comments.clone()))?;
self.export(&name, &dst, Some(&class.comments))?;
self.typescript.push_str(&ts_dst);

Ok(())
Expand Down Expand Up @@ -2153,41 +2152,58 @@ impl<'a> Context<'a> {
// on what's being exported.
match kind {
Kind::Export(export) => {
let ts_sig = match export.generate_typescript {
true => Some(ts_sig.as_str()),
false => None,
};

let docs = format_doc_comments(&export.comments, Some(js_doc));
match &export.kind {
AuxExportKind::Function(name) => {
self.export(&name, &format!("function{}", code), Some(docs))?;
if let Some(ts_sig) = ts_sig {
self.typescript.push_str(&docs);
self.typescript.push_str("export function ");
self.typescript.push_str(&name);
self.typescript.push_str(ts_sig);
self.typescript.push_str(";\n");
}
self.export(&name, &format!("function{}", code), Some(&docs))?;
self.globals.push_str("\n");
self.typescript.push_str("export function ");
self.typescript.push_str(&name);
self.typescript.push_str(&ts_sig);
self.typescript.push_str(";\n");
}
AuxExportKind::Constructor(class) => {
let exported = require_class(&mut self.exported_classes, class);
if exported.has_constructor {
bail!("found duplicate constructor for class `{}`", class);
}
exported.has_constructor = true;
exported.push(&docs, "constructor", "", &code, &ts_sig);
exported.push(&docs, "constructor", "", &code, ts_sig);
}
AuxExportKind::Getter { class, field } => {
let ret_ty = ts_ret_ty.unwrap();
let ret_ty = match export.generate_typescript {
true => match &ts_ret_ty {
Some(s) => Some(s.as_str()),
_ => None,
},
false => None,
};
let exported = require_class(&mut self.exported_classes, class);
exported.push_getter(&docs, field, &code, &ret_ty);
exported.push_getter(&docs, field, &code, ret_ty);
}
AuxExportKind::Setter { class, field } => {
let arg_ty = ts_arg_tys[0].clone();
let arg_ty = match export.generate_typescript {
true => Some(ts_arg_tys[0].as_str()),
false => None,
};
let exported = require_class(&mut self.exported_classes, class);
exported.push_setter(&docs, field, &code, &arg_ty, might_be_optional_field);
exported.push_setter(&docs, field, &code, arg_ty, might_be_optional_field);
}
AuxExportKind::StaticFunction { class, name } => {
let exported = require_class(&mut self.exported_classes, class);
exported.push(&docs, name, "static ", &code, &ts_sig);
exported.push(&docs, name, "static ", &code, ts_sig);
}
AuxExportKind::Method { class, name, .. } => {
let exported = require_class(&mut self.exported_classes, class);
exported.push(&docs, name, "", &code, &ts_sig);
exported.push(&docs, name, "", &code, ts_sig);
}
}
}
Expand Down Expand Up @@ -2865,19 +2881,27 @@ impl<'a> Context<'a> {
}

fn generate_enum(&mut self, enum_: &AuxEnum) -> Result<(), Error> {
let docs = format_doc_comments(&enum_.comments, None);
let mut variants = String::new();

self.typescript
.push_str(&format!("export enum {} {{", enum_.name));
if enum_.generate_typescript {
self.typescript.push_str(&docs);
self.typescript
.push_str(&format!("export enum {} {{", enum_.name));
}
for (name, value) in enum_.variants.iter() {
variants.push_str(&format!("{}:{},", name, value));
self.typescript.push_str(&format!("\n {},", name));
if enum_.generate_typescript {
self.typescript.push_str(&format!("\n {},", name));
}
}
if enum_.generate_typescript {
self.typescript.push_str("\n}\n");
}
self.typescript.push_str("\n}\n");
self.export(
&enum_.name,
&format!("Object.freeze({{ {} }})", variants),
Some(format_doc_comments(&enum_.comments, None)),
Some(&docs),
)?;

Ok(())
Expand Down Expand Up @@ -3163,24 +3187,36 @@ fn require_class<'a>(
}

impl ExportedClass {
fn push(&mut self, docs: &str, function_name: &str, function_prefix: &str, js: &str, ts: &str) {
fn push(
&mut self,
docs: &str,
function_name: &str,
function_prefix: &str,
js: &str,
ts: Option<&str>,
) {
self.contents.push_str(docs);
self.contents.push_str(function_prefix);
self.contents.push_str(function_name);
self.contents.push_str(js);
self.contents.push_str("\n");
self.typescript.push_str(docs);
self.typescript.push_str(" ");
self.typescript.push_str(function_prefix);
self.typescript.push_str(function_name);
self.typescript.push_str(ts);
self.typescript.push_str(";\n");
if let Some(ts) = ts {
self.typescript.push_str(docs);
self.typescript.push_str(" ");
self.typescript.push_str(function_prefix);
self.typescript.push_str(function_name);
self.typescript.push_str(ts);
self.typescript.push_str(";\n");
}
}

/// Used for adding a getter to a class, mainly to ensure that TypeScript
/// generation is handled specially.
fn push_getter(&mut self, docs: &str, field: &str, js: &str, ret_ty: &str) {
self.push_accessor(docs, field, js, "get ", ret_ty);
fn push_getter(&mut self, docs: &str, field: &str, js: &str, ret_ty: Option<&str>) {
self.push_accessor(docs, field, js, "get ");
if let Some(ret_ty) = ret_ty {
self.push_accessor_ts(field, ret_ty);
}
self.readable_properties.push(field.to_string());
}

Expand All @@ -3191,28 +3227,18 @@ impl ExportedClass {
docs: &str,
field: &str,
js: &str,
ret_ty: &str,
ret_ty: Option<&str>,
might_be_optional_field: bool,
) {
let (has_setter, is_optional) = self.push_accessor(docs, field, js, "set ", ret_ty);
*has_setter = true;
*is_optional = might_be_optional_field;
self.push_accessor(docs, field, js, "set ");
if let Some(ret_ty) = ret_ty {
let (has_setter, is_optional) = self.push_accessor_ts(field, ret_ty);
*has_setter = true;
*is_optional = might_be_optional_field;
}
}

fn push_accessor(
&mut self,
docs: &str,
field: &str,
js: &str,
prefix: &str,
ret_ty: &str,
) -> (&mut bool, &mut bool) {
self.contents.push_str(docs);
self.contents.push_str(prefix);
self.contents.push_str(field);
self.contents.push_str(js);
self.contents.push_str("\n");

fn push_accessor_ts(&mut self, field: &str, ret_ty: &str) -> (&mut bool, &mut bool) {
let (ty, has_setter, is_optional) = self
.typescript_fields
.entry(field.to_string())
Expand All @@ -3221,6 +3247,14 @@ impl ExportedClass {
*ty = ret_ty.to_string();
(has_setter, is_optional)
}

fn push_accessor(&mut self, docs: &str, field: &str, js: &str, prefix: &str) {
self.contents.push_str(docs);
self.contents.push_str(prefix);
self.contents.push_str(field);
self.contents.push_str(js);
self.contents.push_str("\n");
}
}

#[test]
Expand Down
6 changes: 6 additions & 0 deletions crates/cli-support/src/wit/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -454,6 +454,7 @@ impl<'a> Context<'a> {
comments: concatenate_comments(&export.comments),
arg_names: Some(export.function.arg_names),
kind,
generate_typescript: export.function.generate_typescript,
},
);
Ok(())
Expand Down Expand Up @@ -767,6 +768,7 @@ impl<'a> Context<'a> {
.iter()
.map(|v| (v.name.to_string(), v.value))
.collect(),
generate_typescript: enum_.generate_typescript,
};
self.aux.enums.push(aux);
Ok(())
Expand Down Expand Up @@ -799,6 +801,7 @@ impl<'a> Context<'a> {
class: struct_.name.to_string(),
field: field.name.to_string(),
},
generate_typescript: field.generate_typescript,
},
);

Expand All @@ -824,13 +827,15 @@ impl<'a> Context<'a> {
class: struct_.name.to_string(),
field: field.name.to_string(),
},
generate_typescript: field.generate_typescript,
},
);
}
let aux = AuxStruct {
name: struct_.name.to_string(),
comments: concatenate_comments(&struct_.comments),
is_inspectable: struct_.is_inspectable,
generate_typescript: struct_.generate_typescript,
};
self.aux.structs.push(aux);

Expand Down Expand Up @@ -1048,6 +1053,7 @@ impl<'a> Context<'a> {
comments: String::new(),
arg_names: None,
kind,
generate_typescript: true,
};
assert!(self.aux.export_map.insert(id, export).is_none());
}
Expand Down
7 changes: 7 additions & 0 deletions crates/cli-support/src/wit/nonstandard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ pub struct AuxExport {
pub arg_names: Option<Vec<String>>,
/// What kind of function this is and where it shows up
pub kind: AuxExportKind,
/// Whether typescript bindings should be generated for this export.
pub generate_typescript: bool,
}

/// All possible kinds of exports from a wasm module.
Expand Down Expand Up @@ -131,7 +133,10 @@ pub struct AuxEnum {
/// The copied Rust comments to forward to JS
pub comments: String,
/// A list of variants with their name and value
/// and whether typescript bindings should be generated for each variant
pub variants: Vec<(String, u32)>,
/// Whether typescript bindings should be generated for this enum.
pub generate_typescript: bool,
}

#[derive(Debug)]
Expand All @@ -142,6 +147,8 @@ pub struct AuxStruct {
pub comments: String,
/// Whether to generate helper methods for inspecting the class
pub is_inspectable: bool,
/// Whether typescript bindings should be generated for this struct.
pub generate_typescript: bool,
}

/// All possible types of imports that can be imported by a wasm module.
Expand Down
Loading