Skip to content

Commit

Permalink
resolve props types
Browse files Browse the repository at this point in the history
  • Loading branch information
g-plane committed Jan 31, 2024
1 parent f57244e commit cacb9ff
Show file tree
Hide file tree
Showing 80 changed files with 2,382 additions and 7 deletions.
36 changes: 35 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions visitor/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ repository = "https://github.com/g-plane/swc-plugin-vue-jsx"
edition = "2021"

[dependencies]
ahash = "0.8"
bitflags = "2.4"
css_dataset = "0.3"
indexmap = "2.1"
Expand Down
108 changes: 108 additions & 0 deletions visitor/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use ahash::AHashMap;
use directive::{is_directive, parse_directive, Directive, NormalDirective};
use indexmap::IndexSet;
pub use options::{Options, Regex};
Expand All @@ -18,6 +19,7 @@ use swc_core::{
mod directive;
mod options;
mod patch_flags;
mod resolve_type;
mod slot_flag;
mod util;

Expand All @@ -38,7 +40,10 @@ where
options: Options,
vue_imports: BTreeMap<&'static str, Ident>,
transform_on_helper: Option<Ident>,

define_component: Option<SyntaxContext>,
interfaces: AHashMap<(JsWord, SyntaxContext), TsInterfaceDecl>,
type_aliases: AHashMap<(JsWord, SyntaxContext), TsType>,

unresolved_mark: Mark,
comments: Option<C>,
Expand All @@ -62,7 +67,10 @@ where
options,
vue_imports: Default::default(),
transform_on_helper: None,

define_component: None,
interfaces: Default::default(),
type_aliases: Default::default(),

unresolved_mark,
comments,
Expand Down Expand Up @@ -1100,6 +1108,17 @@ where
elems
}
}

fn is_define_component_call(&self, CallExpr { callee, .. }: &CallExpr) -> bool {
callee
.as_expr()
.and_then(|expr| expr.as_ident())
.and_then(|ident| {
self.define_component
.map(|ctxt| ctxt == ident.span.ctxt() && ident.sym == "defineComponent")
})
.unwrap_or_default()
}
}

impl<C> VisitMut for VueJsxTransformVisitor<C>
Expand Down Expand Up @@ -1356,4 +1375,93 @@ where
self.define_component = Some(ctxt);
}
}

fn visit_mut_ts_interface_decl(&mut self, ts_interface_decl: &mut TsInterfaceDecl) {
ts_interface_decl.visit_mut_children_with(self);
if self.options.resolve_type {
let key = (
ts_interface_decl.id.sym.clone(),
ts_interface_decl.id.span.ctxt(),
);
if let Some(interface) = self.interfaces.get_mut(&key) {
interface
.body
.body
.extend_from_slice(&ts_interface_decl.body.body);
} else {
self.interfaces.insert(key, ts_interface_decl.clone());
}
}
}

fn visit_mut_ts_type_alias_decl(&mut self, ts_type_alias_decl: &mut TsTypeAliasDecl) {
ts_type_alias_decl.visit_mut_children_with(self);
if self.options.resolve_type {
self.type_aliases.insert(
(
ts_type_alias_decl.id.sym.clone(),
ts_type_alias_decl.id.span.ctxt(),
),
(*ts_type_alias_decl.type_ann).clone(),
);
}
}

fn visit_mut_call_expr(&mut self, call_expr: &mut CallExpr) {
call_expr.visit_mut_children_with(self);

if !self.options.resolve_type {
return;
}

if !self.is_define_component_call(call_expr) {
return;
}

let Some((maybe_setup, args)) = call_expr.args.split_first_mut() else {
return;
};

match args.first_mut().map(|arg| &mut *arg.expr) {
Some(Expr::Object(object)) => {
if !object.props.iter().any(|prop| {
prop.as_prop()
.and_then(|prop| prop.as_key_value())
.and_then(|key_value| key_value.key.as_ident())
.map(|ident| ident.sym == "props")
.unwrap_or_default()
}) {
if let Some(prop_types) = self.extract_props_type(maybe_setup) {
object
.props
.push(PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp {
key: PropName::Ident(quote_ident!("props")),
value: Box::new(Expr::Object(prop_types)),
}))));
}
}
}
None => {
let mut props = vec![];

if let Some(prop_types) = self.extract_props_type(maybe_setup) {
props.push(PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp {
key: PropName::Ident(quote_ident!("props")),
value: Box::new(Expr::Object(prop_types)),
}))));
}

if !props.is_empty() {
call_expr.args.push(ExprOrSpread {
expr: Box::new(Expr::Object(ObjectLit {
props,
span: DUMMY_SP,
})),
spread: None,
});
}
}
_ => {}
}
}
}
3 changes: 3 additions & 0 deletions visitor/src/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ pub struct Options {
pub enable_object_slots: bool,

pub pragma: Option<String>,

pub resolve_type: bool,
}

impl Default for Options {
Expand All @@ -31,6 +33,7 @@ impl Default for Options {
merge_props: true,
enable_object_slots: true,
pragma: None,
resolve_type: false,
}
}
}
Expand Down
Loading

0 comments on commit cacb9ff

Please sign in to comment.