Skip to content

Commit 7ffb5ed

Browse files
authored
Add skip_typescript attribute to prevent .d.ts emit (#2016)
* Add skip_typescript attribute to prevent .d.ts emit * Add guide page for typescript attribute
1 parent 3f4acc4 commit 7ffb5ed

File tree

12 files changed

+227
-56
lines changed

12 files changed

+227
-56
lines changed

Diff for: crates/backend/src/ast.rs

+4
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,7 @@ pub struct Function {
221221
pub rust_attrs: Vec<syn::Attribute>,
222222
pub rust_vis: syn::Visibility,
223223
pub r#async: bool,
224+
pub generate_typescript: bool,
224225
}
225226

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

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

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

257261
#[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq, Eq))]

Diff for: crates/backend/src/encode.rs

+4
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,7 @@ fn shared_function<'a>(func: &'a ast::Function, _intern: &'a Interner) -> Functi
206206
Function {
207207
arg_names,
208208
name: &func.name,
209+
generate_typescript: func.generate_typescript,
209210
}
210211
}
211212

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

@@ -307,6 +309,7 @@ fn shared_struct<'a>(s: &'a ast::Struct, intern: &'a Interner) -> Struct<'a> {
307309
.collect(),
308310
comments: s.comments.iter().map(|s| &**s).collect(),
309311
is_inspectable: s.is_inspectable,
312+
generate_typescript: s.generate_typescript,
310313
}
311314
}
312315

@@ -318,6 +321,7 @@ fn shared_struct_field<'a>(s: &'a ast::StructField, intern: &'a Interner) -> Str
318321
},
319322
readonly: s.readonly,
320323
comments: s.comments.iter().map(|s| &**s).collect(),
324+
generate_typescript: s.generate_typescript,
321325
}
322326
}
323327

Diff for: crates/cli-support/src/js/mod.rs

+82-48
Original file line numberDiff line numberDiff line change
@@ -111,17 +111,16 @@ impl<'a> Context<'a> {
111111
&mut self,
112112
export_name: &str,
113113
contents: &str,
114-
comments: Option<String>,
114+
comments: Option<&str>,
115115
) -> Result<(), Error> {
116116
let definition_name = generate_identifier(export_name, &mut self.defined_identifiers);
117117
if contents.starts_with("class") && definition_name != export_name {
118118
bail!("cannot shadow already defined class `{}`", export_name);
119119
}
120120

121121
let contents = contents.trim();
122-
if let Some(ref c) = comments {
122+
if let Some(c) = comments {
123123
self.globals.push_str(c);
124-
self.typescript.push_str(c);
125124
}
126125
let global = match self.config.mode {
127126
OutputMode::Node {
@@ -804,7 +803,7 @@ impl<'a> Context<'a> {
804803
dst.push_str("}\n");
805804
ts_dst.push_str("}\n");
806805

807-
self.export(&name, &dst, Some(class.comments.clone()))?;
806+
self.export(&name, &dst, Some(&class.comments))?;
808807
self.typescript.push_str(&ts_dst);
809808

810809
Ok(())
@@ -2153,41 +2152,58 @@ impl<'a> Context<'a> {
21532152
// on what's being exported.
21542153
match kind {
21552154
Kind::Export(export) => {
2155+
let ts_sig = match export.generate_typescript {
2156+
true => Some(ts_sig.as_str()),
2157+
false => None,
2158+
};
2159+
21562160
let docs = format_doc_comments(&export.comments, Some(js_doc));
21572161
match &export.kind {
21582162
AuxExportKind::Function(name) => {
2159-
self.export(&name, &format!("function{}", code), Some(docs))?;
2163+
if let Some(ts_sig) = ts_sig {
2164+
self.typescript.push_str(&docs);
2165+
self.typescript.push_str("export function ");
2166+
self.typescript.push_str(&name);
2167+
self.typescript.push_str(ts_sig);
2168+
self.typescript.push_str(";\n");
2169+
}
2170+
self.export(&name, &format!("function{}", code), Some(&docs))?;
21602171
self.globals.push_str("\n");
2161-
self.typescript.push_str("export function ");
2162-
self.typescript.push_str(&name);
2163-
self.typescript.push_str(&ts_sig);
2164-
self.typescript.push_str(";\n");
21652172
}
21662173
AuxExportKind::Constructor(class) => {
21672174
let exported = require_class(&mut self.exported_classes, class);
21682175
if exported.has_constructor {
21692176
bail!("found duplicate constructor for class `{}`", class);
21702177
}
21712178
exported.has_constructor = true;
2172-
exported.push(&docs, "constructor", "", &code, &ts_sig);
2179+
exported.push(&docs, "constructor", "", &code, ts_sig);
21732180
}
21742181
AuxExportKind::Getter { class, field } => {
2175-
let ret_ty = ts_ret_ty.unwrap();
2182+
let ret_ty = match export.generate_typescript {
2183+
true => match &ts_ret_ty {
2184+
Some(s) => Some(s.as_str()),
2185+
_ => None,
2186+
},
2187+
false => None,
2188+
};
21762189
let exported = require_class(&mut self.exported_classes, class);
2177-
exported.push_getter(&docs, field, &code, &ret_ty);
2190+
exported.push_getter(&docs, field, &code, ret_ty);
21782191
}
21792192
AuxExportKind::Setter { class, field } => {
2180-
let arg_ty = ts_arg_tys[0].clone();
2193+
let arg_ty = match export.generate_typescript {
2194+
true => Some(ts_arg_tys[0].as_str()),
2195+
false => None,
2196+
};
21812197
let exported = require_class(&mut self.exported_classes, class);
2182-
exported.push_setter(&docs, field, &code, &arg_ty, might_be_optional_field);
2198+
exported.push_setter(&docs, field, &code, arg_ty, might_be_optional_field);
21832199
}
21842200
AuxExportKind::StaticFunction { class, name } => {
21852201
let exported = require_class(&mut self.exported_classes, class);
2186-
exported.push(&docs, name, "static ", &code, &ts_sig);
2202+
exported.push(&docs, name, "static ", &code, ts_sig);
21872203
}
21882204
AuxExportKind::Method { class, name, .. } => {
21892205
let exported = require_class(&mut self.exported_classes, class);
2190-
exported.push(&docs, name, "", &code, &ts_sig);
2206+
exported.push(&docs, name, "", &code, ts_sig);
21912207
}
21922208
}
21932209
}
@@ -2865,19 +2881,27 @@ impl<'a> Context<'a> {
28652881
}
28662882

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

2870-
self.typescript
2871-
.push_str(&format!("export enum {} {{", enum_.name));
2887+
if enum_.generate_typescript {
2888+
self.typescript.push_str(&docs);
2889+
self.typescript
2890+
.push_str(&format!("export enum {} {{", enum_.name));
2891+
}
28722892
for (name, value) in enum_.variants.iter() {
28732893
variants.push_str(&format!("{}:{},", name, value));
2874-
self.typescript.push_str(&format!("\n {},", name));
2894+
if enum_.generate_typescript {
2895+
self.typescript.push_str(&format!("\n {},", name));
2896+
}
2897+
}
2898+
if enum_.generate_typescript {
2899+
self.typescript.push_str("\n}\n");
28752900
}
2876-
self.typescript.push_str("\n}\n");
28772901
self.export(
28782902
&enum_.name,
28792903
&format!("Object.freeze({{ {} }})", variants),
2880-
Some(format_doc_comments(&enum_.comments, None)),
2904+
Some(&docs),
28812905
)?;
28822906

28832907
Ok(())
@@ -3163,24 +3187,36 @@ fn require_class<'a>(
31633187
}
31643188

31653189
impl ExportedClass {
3166-
fn push(&mut self, docs: &str, function_name: &str, function_prefix: &str, js: &str, ts: &str) {
3190+
fn push(
3191+
&mut self,
3192+
docs: &str,
3193+
function_name: &str,
3194+
function_prefix: &str,
3195+
js: &str,
3196+
ts: Option<&str>,
3197+
) {
31673198
self.contents.push_str(docs);
31683199
self.contents.push_str(function_prefix);
31693200
self.contents.push_str(function_name);
31703201
self.contents.push_str(js);
31713202
self.contents.push_str("\n");
3172-
self.typescript.push_str(docs);
3173-
self.typescript.push_str(" ");
3174-
self.typescript.push_str(function_prefix);
3175-
self.typescript.push_str(function_name);
3176-
self.typescript.push_str(ts);
3177-
self.typescript.push_str(";\n");
3203+
if let Some(ts) = ts {
3204+
self.typescript.push_str(docs);
3205+
self.typescript.push_str(" ");
3206+
self.typescript.push_str(function_prefix);
3207+
self.typescript.push_str(function_name);
3208+
self.typescript.push_str(ts);
3209+
self.typescript.push_str(";\n");
3210+
}
31783211
}
31793212

31803213
/// Used for adding a getter to a class, mainly to ensure that TypeScript
31813214
/// generation is handled specially.
3182-
fn push_getter(&mut self, docs: &str, field: &str, js: &str, ret_ty: &str) {
3183-
self.push_accessor(docs, field, js, "get ", ret_ty);
3215+
fn push_getter(&mut self, docs: &str, field: &str, js: &str, ret_ty: Option<&str>) {
3216+
self.push_accessor(docs, field, js, "get ");
3217+
if let Some(ret_ty) = ret_ty {
3218+
self.push_accessor_ts(field, ret_ty);
3219+
}
31843220
self.readable_properties.push(field.to_string());
31853221
}
31863222

@@ -3191,28 +3227,18 @@ impl ExportedClass {
31913227
docs: &str,
31923228
field: &str,
31933229
js: &str,
3194-
ret_ty: &str,
3230+
ret_ty: Option<&str>,
31953231
might_be_optional_field: bool,
31963232
) {
3197-
let (has_setter, is_optional) = self.push_accessor(docs, field, js, "set ", ret_ty);
3198-
*has_setter = true;
3199-
*is_optional = might_be_optional_field;
3233+
self.push_accessor(docs, field, js, "set ");
3234+
if let Some(ret_ty) = ret_ty {
3235+
let (has_setter, is_optional) = self.push_accessor_ts(field, ret_ty);
3236+
*has_setter = true;
3237+
*is_optional = might_be_optional_field;
3238+
}
32003239
}
32013240

3202-
fn push_accessor(
3203-
&mut self,
3204-
docs: &str,
3205-
field: &str,
3206-
js: &str,
3207-
prefix: &str,
3208-
ret_ty: &str,
3209-
) -> (&mut bool, &mut bool) {
3210-
self.contents.push_str(docs);
3211-
self.contents.push_str(prefix);
3212-
self.contents.push_str(field);
3213-
self.contents.push_str(js);
3214-
self.contents.push_str("\n");
3215-
3241+
fn push_accessor_ts(&mut self, field: &str, ret_ty: &str) -> (&mut bool, &mut bool) {
32163242
let (ty, has_setter, is_optional) = self
32173243
.typescript_fields
32183244
.entry(field.to_string())
@@ -3221,6 +3247,14 @@ impl ExportedClass {
32213247
*ty = ret_ty.to_string();
32223248
(has_setter, is_optional)
32233249
}
3250+
3251+
fn push_accessor(&mut self, docs: &str, field: &str, js: &str, prefix: &str) {
3252+
self.contents.push_str(docs);
3253+
self.contents.push_str(prefix);
3254+
self.contents.push_str(field);
3255+
self.contents.push_str(js);
3256+
self.contents.push_str("\n");
3257+
}
32243258
}
32253259

32263260
#[test]

Diff for: crates/cli-support/src/wit/mod.rs

+6
Original file line numberDiff line numberDiff line change
@@ -454,6 +454,7 @@ impl<'a> Context<'a> {
454454
comments: concatenate_comments(&export.comments),
455455
arg_names: Some(export.function.arg_names),
456456
kind,
457+
generate_typescript: export.function.generate_typescript,
457458
},
458459
);
459460
Ok(())
@@ -767,6 +768,7 @@ impl<'a> Context<'a> {
767768
.iter()
768769
.map(|v| (v.name.to_string(), v.value))
769770
.collect(),
771+
generate_typescript: enum_.generate_typescript,
770772
};
771773
self.aux.enums.push(aux);
772774
Ok(())
@@ -799,6 +801,7 @@ impl<'a> Context<'a> {
799801
class: struct_.name.to_string(),
800802
field: field.name.to_string(),
801803
},
804+
generate_typescript: field.generate_typescript,
802805
},
803806
);
804807

@@ -824,13 +827,15 @@ impl<'a> Context<'a> {
824827
class: struct_.name.to_string(),
825828
field: field.name.to_string(),
826829
},
830+
generate_typescript: field.generate_typescript,
827831
},
828832
);
829833
}
830834
let aux = AuxStruct {
831835
name: struct_.name.to_string(),
832836
comments: concatenate_comments(&struct_.comments),
833837
is_inspectable: struct_.is_inspectable,
838+
generate_typescript: struct_.generate_typescript,
834839
};
835840
self.aux.structs.push(aux);
836841

@@ -1048,6 +1053,7 @@ impl<'a> Context<'a> {
10481053
comments: String::new(),
10491054
arg_names: None,
10501055
kind,
1056+
generate_typescript: true,
10511057
};
10521058
assert!(self.aux.export_map.insert(id, export).is_none());
10531059
}

Diff for: crates/cli-support/src/wit/nonstandard.rs

+7
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@ pub struct AuxExport {
7373
pub arg_names: Option<Vec<String>>,
7474
/// What kind of function this is and where it shows up
7575
pub kind: AuxExportKind,
76+
/// Whether typescript bindings should be generated for this export.
77+
pub generate_typescript: bool,
7678
}
7779

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

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

147154
/// All possible types of imports that can be imported by a wasm module.

0 commit comments

Comments
 (0)