From ebbf0d5103d6ad91480995791d2aca63be936e81 Mon Sep 17 00:00:00 2001 From: Shadaj Laddad Date: Thu, 22 Jul 2021 16:04:07 -0700 Subject: [PATCH] Add support for imports --- core/src/ast/modules.rs | 46 +++++++++++++++++++++++++++++++++-------- core/src/ast/types.rs | 14 ++++++++++++- example/src/other.rs | 8 ++++--- tool/src/main.rs | 2 -- 4 files changed, 55 insertions(+), 15 deletions(-) diff --git a/core/src/ast/modules.rs b/core/src/ast/modules.rs index 33b998de5..599a6ecd7 100644 --- a/core/src/ast/modules.rs +++ b/core/src/ast/modules.rs @@ -2,13 +2,14 @@ use serde::{Deserialize, Serialize}; use std::collections::HashMap; use quote::ToTokens; -use syn::{ImplItem, Item, ItemMod}; +use syn::{ImplItem, Item, ItemMod, UseTree}; use super::{CustomType, Method, ModSymbol, OpaqueStruct, Path, Struct, TypeName}; #[derive(Clone, Serialize, Deserialize, Debug)] pub struct Module { pub name: String, + pub imports: Vec<(Path, String)>, pub declared_types: HashMap, pub sub_modules: Vec, } @@ -35,6 +36,11 @@ impl Module { fn insert_all_types(&self, in_path: Path, out: &mut HashMap>) { let mut mod_symbols = HashMap::new(); + + self.imports.iter().for_each(|(path, name)| { + mod_symbols.insert(name.clone(), ModSymbol::Alias(path.clone())); + }); + self.declared_types.iter().for_each(|(k, v)| { if mod_symbols .insert(k.clone(), ModSymbol::CustomType(v.clone())) @@ -47,10 +53,7 @@ impl Module { let path_to_self = in_path.sub_path(self.name.clone()); self.sub_modules.iter().for_each(|m| { m.insert_all_types(path_to_self.clone(), out); - mod_symbols.insert( - m.name.clone(), - ModSymbol::Alias(path_to_self.sub_path(m.name.clone())), - ); + mod_symbols.insert(m.name.clone(), ModSymbol::SubModule(m.name.clone())); }); out.insert(path_to_self, mod_symbols); @@ -59,6 +62,7 @@ impl Module { pub fn from_syn(input: &ItemMod, force_analyze: bool) -> Module { let mut custom_types_by_name = HashMap::new(); let mut sub_modules = Vec::new(); + let mut imports = Vec::new(); let analyze_types = force_analyze || input @@ -73,6 +77,9 @@ impl Module { .1 .iter() .for_each(|a| match a { + Item::Use(u) => { + extract_imports(&Path::empty(), &u.tree, &mut imports); + } Item::Struct(strct) => { if analyze_types { if strct @@ -130,12 +137,36 @@ impl Module { Module { name: input.ident.to_string(), + imports, declared_types: custom_types_by_name, sub_modules, } } } +fn extract_imports(base_path: &Path, use_tree: &UseTree, out: &mut Vec<(Path, String)>) { + match use_tree { + UseTree::Name(name) => out.push(( + base_path.sub_path(name.ident.to_string()), + name.ident.to_string(), + )), + UseTree::Path(path) => { + extract_imports(&base_path.sub_path(path.ident.to_string()), &path.tree, out) + } + UseTree::Glob(_) => todo!("Glob imports are not yet supported"), + UseTree::Group(group) => { + group + .items + .iter() + .for_each(|i| extract_imports(base_path, &i, out)); + } + UseTree::Rename(rename) => out.push(( + base_path.sub_path(rename.ident.to_string()), + rename.rename.to_string(), + )), + } +} + #[derive(Clone, Debug)] pub struct File { pub modules: HashMap, @@ -163,10 +194,7 @@ impl File { self.modules.values().for_each(|m| { m.insert_all_types(Path::empty(), &mut out); - top_symbols.insert( - m.name.clone(), - ModSymbol::Alias(Path::empty().sub_path(m.name.clone())), - ); + top_symbols.insert(m.name.clone(), ModSymbol::SubModule(m.name.clone())); }); out.insert(Path::empty(), top_symbols); diff --git a/core/src/ast/types.rs b/core/src/ast/types.rs index 3b61286a2..861664281 100644 --- a/core/src/ast/types.rs +++ b/core/src/ast/types.rs @@ -75,6 +75,8 @@ impl CustomType { pub enum ModSymbol { /// A symbol that is a pointer to another path. Alias(Path), + /// A symbol that is a submodule. + SubModule(String), /// A symbol that is a custom type. CustomType(CustomType), } @@ -187,7 +189,17 @@ impl TypeName { "super" => cur_path = cur_path.get_super(), o => match env.get(&cur_path).and_then(|env| env.get(o)) { - Some(ModSymbol::Alias(p)) => cur_path = p.clone(), + Some(ModSymbol::Alias(p)) => { + let mut remaining_elements: Vec = + local_path.elements.iter().skip(i + 1).cloned().collect(); + let mut new_path = p.elements.clone(); + new_path.append(&mut remaining_elements); + return TypeName::Named(Path { elements: new_path }) + .resolve_with_path(&cur_path.clone(), env); + } + Some(ModSymbol::SubModule(name)) => { + cur_path.elements.push(name.clone()); + } Some(ModSymbol::CustomType(t)) => { if i == local_path.elements.len() - 1 { return (cur_path, t); diff --git a/example/src/other.rs b/example/src/other.rs index 3f966256e..8df35d20a 100644 --- a/example/src/other.rs +++ b/example/src/other.rs @@ -12,6 +12,8 @@ mod ffi { use icu_provider::serde::SerdeDeDataProvider; use writeable::Writeable; + use crate::fixed_decimal::ffi::ICU4XFixedDecimal; + #[diplomat::opaque] /// An ICU4X Locale, capable of representing strings like `"en-US"`. /// See [the Rust docs](https://unicode-org.github.io/icu4x-docs/doc/icu/locid/struct.Locale.html) for more information. @@ -38,7 +40,7 @@ mod ffi { } #[diplomat::opaque] - /// An ICU4X Fixed Decimal Format object, capable of formatting a [`crate::fixed_decimal::ffi::ICU4XFixedDecimal`] as a string. + /// An ICU4X Fixed Decimal Format object, capable of formatting a [`ICU4XFixedDecimal`] as a string. /// See [the Rust docs](https://unicode-org.github.io/icu4x-docs/doc/icu/decimal/struct.FixedDecimalFormat.html) for more information. pub struct ICU4XFixedDecimalFormat(pub FixedDecimalFormat<'static, 'static>); @@ -106,10 +108,10 @@ mod ffi { } } - /// Formats a [`crate::fixed_decimal::ffi::ICU4XFixedDecimal`] to a string. See [the Rust docs](https://unicode-org.github.io/icu4x-docs/doc/icu/decimal/struct.FixedDecimalFormat.html#method.format) for more information. + /// Formats a [`ICU4XFixedDecimal`] to a string. See [the Rust docs](https://unicode-org.github.io/icu4x-docs/doc/icu/decimal/struct.FixedDecimalFormat.html#method.format) for more information. fn format_write( &self, - value: &crate::fixed_decimal::ffi::ICU4XFixedDecimal, + value: &ICU4XFixedDecimal, write: &mut diplomat_runtime::DiplomatWriteable, ) { self.0.format(&value.0).write_to(write).unwrap(); diff --git a/tool/src/main.rs b/tool/src/main.rs index 1de4dfb23..ef268d7cf 100644 --- a/tool/src/main.rs +++ b/tool/src/main.rs @@ -28,8 +28,6 @@ fn main() -> std::io::Result<()> { panic!(); } - dbg!(&env); - let args: Vec = env::args().collect(); let target = args[1].as_str();