From 5d29b8b0acd4a6c86c683baa96586334217de2bc Mon Sep 17 00:00:00 2001 From: Ori Ziv Date: Sun, 14 Jan 2024 17:32:06 +0200 Subject: [PATCH] Added warnings for bad embeddable impls. commit-id:48280088 --- crates/cairo-lang-starknet/src/analyzer.rs | 77 ++++++++++++++----- .../plugin_test_data/components/diagnostics | 5 ++ .../plugin_test_data/components/embeddable_as | 6 +- .../plugin_test_data/contracts/embedded_impl | 20 +++++ 4 files changed, 88 insertions(+), 20 deletions(-) diff --git a/crates/cairo-lang-starknet/src/analyzer.rs b/crates/cairo-lang-starknet/src/analyzer.rs index 588b37a86fd..5045fbbf2d4 100644 --- a/crates/cairo-lang-starknet/src/analyzer.rs +++ b/crates/cairo-lang-starknet/src/analyzer.rs @@ -1,10 +1,15 @@ use cairo_lang_defs::ids::ModuleId; use cairo_lang_defs::plugin::PluginDiagnostic; use cairo_lang_semantic::db::SemanticGroup; +use cairo_lang_semantic::items::attribute::SemanticQueryAttrs; use cairo_lang_semantic::plugin::AnalyzerPlugin; +use cairo_lang_syntax::attribute::consts::STARKNET_INTERFACE_ATTR; +use cairo_lang_syntax::node::helpers::QueryAttrs; +use cairo_lang_syntax::node::TypedSyntaxNode; use crate::abi::{ABIError, AbiBuilder, BuilderConfig}; use crate::contract::module_contract; +use crate::plugin::consts::EMBEDDABLE_ATTR; /// Plugin to add diagnostics for contracts for bad ABI generation. #[derive(Default, Debug)] @@ -12,26 +17,60 @@ pub struct ABIAnalyzer; impl AnalyzerPlugin for ABIAnalyzer { fn diagnostics(&self, db: &dyn SemanticGroup, module_id: ModuleId) -> Vec { - let Some(contract) = module_contract(db, module_id) else { - return vec![]; - }; - let Ok(abi_builder) = AbiBuilder::from_submodule( - db, - contract.submodule_id, - BuilderConfig { account_contract_validations: true }, - ) else { - return vec![]; - }; let mut diagnostics = vec![]; - for err in abi_builder.errors() { - if !matches!(err, ABIError::SemanticError) { - diagnostics.push(PluginDiagnostic::warning( - err.location(db) - .unwrap_or_else(|| contract.submodule_id.stable_ptr(db.upcast()).untyped()), - format!("Failed to generate ABI: {err}"), - )); - } - } + add_non_starknet_interface_embeddable_diagnostics(db, module_id, &mut diagnostics); + add_abi_diagnostics(db, module_id, &mut diagnostics); diagnostics } } + +/// Add diagnostics for embeddable impls that do not implement a starknet interface. +fn add_non_starknet_interface_embeddable_diagnostics( + db: &dyn SemanticGroup, + module_id: ModuleId, + diagnostics: &mut Vec, +) { + let Ok(impls) = db.module_impls(module_id) else { + return; + }; + for (id, item) in impls.iter() { + if !item.has_attr(db.upcast(), EMBEDDABLE_ATTR) { + continue; + } + let Ok(impl_trait) = db.impl_def_trait(*id) else { continue }; + if !impl_trait.has_attr(db.upcast(), STARKNET_INTERFACE_ATTR).unwrap_or(true) { + diagnostics.push(PluginDiagnostic::warning( + item.stable_ptr().untyped(), + "Impls with the embeddable attribute must implement a starknet interface trait." + .to_string(), + )); + } + } +} + +/// Add diagnostics for ABI generation. +fn add_abi_diagnostics( + db: &dyn SemanticGroup, + module_id: ModuleId, + diagnostics: &mut Vec, +) { + let Some(contract) = module_contract(db, module_id) else { + return; + }; + let Ok(abi_builder) = AbiBuilder::from_submodule( + db, + contract.submodule_id, + BuilderConfig { account_contract_validations: true }, + ) else { + return; + }; + for err in abi_builder.errors() { + if !matches!(err, ABIError::SemanticError) { + diagnostics.push(PluginDiagnostic::warning( + err.location(db) + .unwrap_or_else(|| contract.submodule_id.stable_ptr(db.upcast()).untyped()), + format!("Failed to generate ABI: {err}"), + )); + } + } +} diff --git a/crates/cairo-lang-starknet/src/plugin/plugin_test_data/components/diagnostics b/crates/cairo-lang-starknet/src/plugin/plugin_test_data/components/diagnostics index 6594bb2c5ab..8775075a5aa 100644 --- a/crates/cairo-lang-starknet/src/plugin/plugin_test_data/components/diagnostics +++ b/crates/cairo-lang-starknet/src/plugin/plugin_test_data/components/diagnostics @@ -991,6 +991,11 @@ error: Plugin diagnostic: The first parameter of a function in an #[embeddable_a fn self_of_wrong_type(self: ComponentState) {} ^**********************************^ +warning: Plugin diagnostic: Impls with the embeddable attribute must implement a starknet interface trait. + --> lib.cairo[component]:33:1 +#[starknet::embeddable] +^*********************^ + error: Not all trait items are implemented. Missing: 'no_self', 'self_of_wrong_type'. --> lib.cairo:8:21 #[embeddable_as(MyImpl)] diff --git a/crates/cairo-lang-starknet/src/plugin/plugin_test_data/components/embeddable_as b/crates/cairo-lang-starknet/src/plugin/plugin_test_data/components/embeddable_as index d3daafd3cd3..fcde722db96 100644 --- a/crates/cairo-lang-starknet/src/plugin/plugin_test_data/components/embeddable_as +++ b/crates/cairo-lang-starknet/src/plugin/plugin_test_data/components/embeddable_as @@ -1,7 +1,7 @@ //! > Test `embeddable_as` with Drop. //! > test_runner_name -ExpandContractTestRunner(expect_diagnostics: false) +ExpandContractTestRunner(expect_diagnostics: true) //! > cairo_code #[starknet::component] @@ -149,3 +149,7 @@ pub mod __constructor_MyImpl { } //! > expected_diagnostics +warning: Plugin diagnostic: Impls with the embeddable attribute must implement a starknet interface trait. + --> lib.cairo[component]:33:1 +#[starknet::embeddable] +^*********************^ diff --git a/crates/cairo-lang-starknet/src/plugin/plugin_test_data/contracts/embedded_impl b/crates/cairo-lang-starknet/src/plugin/plugin_test_data/contracts/embedded_impl index 897e8aa86ed..7a9e3f8affd 100644 --- a/crates/cairo-lang-starknet/src/plugin/plugin_test_data/contracts/embedded_impl +++ b/crates/cairo-lang-starknet/src/plugin/plugin_test_data/contracts/embedded_impl @@ -246,6 +246,11 @@ impl EventIsEvent of starknet::Event { } //! > expected_diagnostics +warning: Plugin diagnostic: Impls with the embeddable attribute must implement a starknet interface trait. + --> lib.cairo:1:1 +#[starknet::embeddable] +^*********************^ + warning: Plugin diagnostic: Failed to generate ABI: An embedded impl must be an impl of a trait marked with #[starknet::interface]. --> lib.cairo:17:5 #[abi(embed_v0)] @@ -533,6 +538,16 @@ error: Plugin diagnostic: `embeddable` impls can't have impl generic parameters impl DisallowedPanicDestruct: PanicDestruct ^*********************************************************^ +warning: Plugin diagnostic: Impls with the embeddable attribute must implement a starknet interface trait. + --> lib.cairo:1:1 +#[starknet::embeddable] +^*********************^ + +warning: Plugin diagnostic: Impls with the embeddable attribute must implement a starknet interface trait. + --> lib.cairo:12:1 +#[starknet::embeddable] +^*********************^ + warning: Plugin diagnostic: Failed to generate ABI: An embedded impl must be an impl of a trait marked with #[starknet::interface]. --> lib.cairo:28:5 #[abi(embed_v0)] @@ -730,6 +745,11 @@ impl EventIsEvent of starknet::Event { } //! > expected_diagnostics +warning: Plugin diagnostic: Impls with the embeddable attribute must implement a starknet interface trait. + --> lib.cairo:1:1 +#[starknet::embeddable] +^*********************^ + warning: Plugin diagnostic: Failed to generate ABI: An embedded impl must be an impl of a trait marked with #[starknet::interface]. --> lib.cairo:17:5 #[abi(embed_v0)]