diff --git a/Cargo.lock b/Cargo.lock index 8ba7afa7..a076a7af 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -235,10 +235,8 @@ dependencies = [ "num-bigint", "num-traits", "pretty", - "proc-macro2 1.0.81", "rand", "serde", - "syn 2.0.60", "test-generator", "thiserror", "toml", diff --git a/rust/candid_parser/Cargo.toml b/rust/candid_parser/Cargo.toml index d580434e..2630d651 100644 --- a/rust/candid_parser/Cargo.toml +++ b/rust/candid_parser/Cargo.toml @@ -34,9 +34,6 @@ convert_case = "0.6" handlebars = "5.1" toml = { version = "0.8", default-features = false, features = ["parse"] } -syn = { version = "2.0", features = ["full", "visit", "extra-traits"] } -proc-macro2 = { version = "1.0", features = ["span-locations"] } - arbitrary = { workspace = true, optional = true } fake = { version = "2.4", optional = true } rand = { version = "0.8", optional = true } diff --git a/rust/candid_parser/src/bindings/rust.rs b/rust/candid_parser/src/bindings/rust.rs index aecd5e87..d136b631 100644 --- a/rust/candid_parser/src/bindings/rust.rs +++ b/rust/candid_parser/src/bindings/rust.rs @@ -772,203 +772,6 @@ fn nominalize_all(env: &TypeEnv, actor: &Option) -> (TypeEnv, Option .map(|ty| nominalize(&mut res, &mut vec![], ty)); (res, actor) } -pub fn check_rust(source: &str, candid: &Output) { - use codespan_reporting::{ - files::SimpleFile, - term::{self, termcolor::StandardStream}, - }; - let rust = get_endpoint_from_rust_source(source); - let diags = diff_did_and_rust(candid, &rust); - let writer = StandardStream::stderr(term::termcolor::ColorChoice::Auto); - let config = term::Config::default(); - let file = SimpleFile::new("rust code", source); - for diag in diags { - term::emit(&mut writer.lock(), &config, &file, &diag).unwrap(); - } -} -fn get_endpoint_from_rust_source(source: &str) -> Vec { - use syn::visit::{self, Visit}; - use syn::{ImplItemFn, ItemFn}; - struct FnVisitor(Vec); - impl<'ast> Visit<'ast> for FnVisitor { - fn visit_item_fn(&mut self, node: &'ast ItemFn) { - if let Some(m) = get_cdk_function(&node.attrs, &node.sig) { - self.0.push(m); - } - // handle nested functions - visit::visit_item_fn(self, node); - } - fn visit_impl_item_fn(&mut self, node: &'ast ImplItemFn) { - if let Some(m) = get_cdk_function(&node.attrs, &node.sig) { - self.0.push(m); - } - // handle nested functions - visit::visit_impl_item_fn(self, node); - } - } - let ast = syn::parse_file(source).unwrap(); - let mut visitor = FnVisitor(Vec::new()); - visitor.visit_file(&ast); - for m in &visitor.0 { - m.debug_print(source); - } - visitor.0 -} -struct CDKMethod { - func_name: syn::Ident, - export_name: Option<(String, syn::Meta)>, - composite: Option, - mode: syn::Ident, - args: Vec, - rets: Vec, -} -impl CDKMethod { - fn debug_print(&self, source: &str) { - use syn::spanned::Spanned; - println!("{} {}", self.func_name, self.mode); - if let Some((_, meta)) = &self.export_name { - let range = meta.span().byte_range(); - println!(" export {}", &source[range]); - } - if let Some(composite) = &self.composite { - let range = composite.span().byte_range(); - println!(" composite {}", &source[range]); - } - for arg in &self.args { - let range = arg.span().byte_range(); - println!(" arg {}", &source[range]); - } - for ret in &self.rets { - let range = ret.span().byte_range(); - println!(" ret {}", &source[range]); - } - } -} -use codespan_reporting::diagnostic::Diagnostic; -fn diff_did_and_rust(candid: &Output, rust: &[CDKMethod]) -> Vec> { - use codespan_reporting::diagnostic::Label; - use syn::spanned::Spanned; - let mut res = Vec::new(); - let rust: BTreeMap<_, _> = rust - .iter() - .map(|m| { - let name = m - .export_name - .as_ref() - .map(|x| x.0.clone()) - .unwrap_or(m.func_name.to_string()); - (name, m) - }) - .collect(); - for m in &candid.methods { - let diag = Diagnostic::error() - .with_message(format!("Error with Candid method {}", m.original_name)); - let mut labels = Vec::new(); - let mut notes = Vec::new(); - if let Some(func) = rust.get(&m.original_name) { - if m.original_name == m.name { - } else { - if let Some((name, meta)) = &func.export_name { - if *name != m.original_name { - labels - .push(Label::primary((), meta.span().byte_range()).with_message( - format!("expect {}", m.original_name.escape_debug()), - )); - } - } else { - labels.push( - Label::primary((), func.mode.span().byte_range()).with_message(format!( - "missing (name = \"{}\")", - m.original_name.escape_debug() - )), - ); - } - } - let args = func.args.iter().zip(m.args.iter().map(|x| &x.1)); - for (rust_arg, candid_arg) in args { - let parsed_candid_arg: syn::Type = syn::parse_str(candid_arg).unwrap(); - if parsed_candid_arg != *rust_arg { - labels.push( - Label::primary((), rust_arg.span().byte_range()) - .with_message(format!("expect type: {}", candid_arg)), - ); - } - } - } else { - notes.push(format!( - "method \"{}\" missing from Rust code", - m.original_name - )); - } - res.push(diag.with_labels(labels).with_notes(notes)); - } - res -} -fn get_cdk_function(attrs: &[syn::Attribute], sig: &syn::Signature) -> Option { - use syn::parse::Parser; - use syn::{Expr, ExprLit, FnArg, Lit, Meta, ReturnType}; - let func_name = sig.ident.clone(); - let mut mode = None; - let mut export_name = None; - let mut composite = None; - for attr in attrs { - let attr_name = &attr.meta.path().segments.last().unwrap().ident; - if attr_name != "update" && attr_name != "query" && attr_name != "init" { - continue; - } - mode = Some(attr_name.clone()); - if let Meta::List(list) = &attr.meta { - let nested = syn::punctuated::Punctuated::::parse_terminated - .parse2(list.tokens.clone()) - .unwrap(); - for meta in nested { - if let Meta::NameValue(ref m) = meta { - if m.path.is_ident("name") { - if let Expr::Lit(ExprLit { - lit: Lit::Str(name), - .. - }) = &m.value - { - export_name = Some((name.value(), meta)); - } - } else if m.path.is_ident("composite") { - if let Expr::Lit(ExprLit { - lit: Lit::Bool(b), .. - }) = &m.value - { - if b.value { - composite = Some(meta); - } - } - } - } - } - } - } - let args = sig - .inputs - .iter() - .filter_map(|arg| match arg { - FnArg::Receiver(_) => None, - FnArg::Typed(pat) => Some(*pat.ty.clone()), - }) - .collect(); - let rets = match &sig.output { - ReturnType::Default => Vec::new(), - ReturnType::Type(_, ty) => match ty.as_ref() { - syn::Type::Tuple(ty) => ty.elems.iter().map(|t| (*t).clone()).collect(), - _ => vec![*ty.clone()], - }, - }; - mode.map(|mode| CDKMethod { - func_name, - export_name, - composite, - args, - rets, - mode, - }) -} fn get_hbs() -> handlebars::Handlebars<'static> { use handlebars::*; let mut hbs = Handlebars::new(); diff --git a/tools/didc/src/main.rs b/tools/didc/src/main.rs index ee2c9116..c0b59198 100644 --- a/tools/didc/src/main.rs +++ b/tools/didc/src/main.rs @@ -216,22 +216,13 @@ fn main() -> Result<()> { "did" => candid_parser::pretty::candid::compile(&env, &actor), "mo" => candid_parser::bindings::motoko::compile(&env, &actor), "rs" => { - use candid_parser::bindings::rust::{ - check_rust, compile, emit_bindgen, Config, ExternalConfig, - }; + use candid_parser::bindings::rust::{compile, Config, ExternalConfig}; let external = configs .get_subtable(&["external".to_string(), "rust".to_string()]) .map(|x| x.clone().try_into().unwrap()) .unwrap_or(ExternalConfig::default()); let config = Config::new(configs); - if let Some(file) = external.0.get("output_file") { - let (output, _) = emit_bindgen(&config, &env, &actor); - let file = std::fs::read_to_string(file).unwrap(); - check_rust(&file, &output); - String::new() - } else { - compile(&config, &env, &actor, external) - } + compile(&config, &env, &actor, external) } "rs-agent" | "rs-stub" => { use candid_parser::bindings::rust::{compile, Config, ExternalConfig};