Skip to content

Commit

Permalink
fix: allow ref self until sozo can handle starknet contracts (starkwa…
Browse files Browse the repository at this point in the history
…re-libs#1879)

* fix: allow ref self until sozo can handle starknet contracts

* fix: add test for attr extractor function

* fix: ignore IPFS test for now

* fix: remove test expansion test seems not detected by codecov
  • Loading branch information
glihm authored May 1, 2024
1 parent 683620c commit 5d9a8d1
Show file tree
Hide file tree
Showing 4 changed files with 161 additions and 11 deletions.
41 changes: 38 additions & 3 deletions crates/dojo-lang/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,35 @@ use cairo_lang_defs::plugin::{
DynGeneratedFileAuxData, PluginDiagnostic, PluginGeneratedFile, PluginResult,
};
use cairo_lang_diagnostics::Severity;
use cairo_lang_syntax::attribute::structured::{
Attribute, AttributeArg, AttributeArgVariant, AttributeListStructurize,
};
use cairo_lang_syntax::node::ast::MaybeModuleBody;
use cairo_lang_syntax::node::db::SyntaxGroup;
use cairo_lang_syntax::node::{ast, ids, Terminal, TypedSyntaxNode};
use cairo_lang_utils::unordered_hash_map::UnorderedHashMap;
use dojo_types::system::Dependency;

use crate::plugin::{DojoAuxData, SystemAuxData};
use crate::plugin::{DojoAuxData, SystemAuxData, DOJO_CONTRACT_ATTR};

const ALLOW_REF_SELF_ARG: &str = "allow_ref_self";

pub struct DojoContract {
diagnostics: Vec<PluginDiagnostic>,
dependencies: HashMap<smol_str::SmolStr, Dependency>,
do_allow_ref_self: bool,
}

impl DojoContract {
pub fn from_module(db: &dyn SyntaxGroup, module_ast: ast::ItemModule) -> PluginResult {
let name = module_ast.name(db).text(db);
let mut system = DojoContract { diagnostics: vec![], dependencies: HashMap::new() };

let attrs = module_ast.attributes(db).structurize(db);
let dojo_contract_attr = attrs.iter().find(|attr| attr.id.as_str() == DOJO_CONTRACT_ATTR);
let do_allow_ref_self = extract_allow_ref_self(dojo_contract_attr, db).unwrap_or_default();

let mut system =
DojoContract { diagnostics: vec![], dependencies: HashMap::new(), do_allow_ref_self };
let mut has_event = false;
let mut has_storage = false;

Expand Down Expand Up @@ -351,7 +363,7 @@ impl DojoContract {
});
}

if has_ref_self {
if has_ref_self && !self.do_allow_ref_self {
self.diagnostics.push(PluginDiagnostic {
stable_ptr: diagnostic_item,
message: "Functions of dojo::contract cannot have 'ref self' parameter."
Expand Down Expand Up @@ -457,3 +469,26 @@ impl DojoContract {
vec![RewriteNode::Copied(impl_ast.as_syntax_node())]
}
}

/// Extract the allow_ref_self attribute.
pub(crate) fn extract_allow_ref_self(
allow_ref_self_attr: Option<&Attribute>,
db: &dyn SyntaxGroup,
) -> Option<bool> {
let Some(attr) = allow_ref_self_attr else {
return None;
};

#[allow(clippy::collapsible_match)]
match &attr.args[..] {
[AttributeArg { variant: AttributeArgVariant::Unnamed { value, .. }, .. }] => match value {
ast::Expr::Path(path)
if path.as_syntax_node().get_text_without_trivia(db) == ALLOW_REF_SELF_ARG =>
{
Some(true)
}
_ => None,
},
_ => None,
}
}
127 changes: 119 additions & 8 deletions crates/dojo-lang/src/plugin_test_data/system
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,20 @@ trait IFaultyTrait {
fn do_with_attrs(p1: u8) -> u16;
}

#[starknet::interface]
trait IAllowedRefSelf<T> {
fn spawn(ref self: T);
}

#[dojo::contract(allow_ref_self)]
mod ContractAllowedRefSelf {
#[abi(embed_v0)]
impl AllowedImpl of IAllowedRefSelf<ContractState> {
fn spawn(ref self: ContractState) {
}
}
}

#[dojo::interface]
trait INominalTrait {
fn do_no_param();
Expand Down Expand Up @@ -320,32 +334,32 @@ error: Functions of dojo::interface cannot have `ref self` parameter.
^***************************************^

error: Functions of dojo::contract cannot have 'ref self' parameter.
--> test_src/lib.cairo:119:9
--> test_src/lib.cairo:133:9
fn do_with_ref_self(ref self: ContractState) -> felt252 {
^*******************************************************^

error: Only one parameter of type IWorldDispatcher is allowed.
--> test_src/lib.cairo:123:9
--> test_src/lib.cairo:137:9
fn do_with_several_world_dispatchers(
^***********************************^

error: The IWorldDispatcher parameter must be named 'world'.
--> test_src/lib.cairo:131:42
--> test_src/lib.cairo:145:42
fn do_with_world_not_named_world(another_world: IWorldDispatcher) -> felt252 {
^*****************************^

error: The IWorldDispatcher parameter must be named 'world'.
--> test_src/lib.cairo:135:73
--> test_src/lib.cairo:149:73
fn do_with_self_and_world_not_named_world(self: @ContractState, another_world: IWorldDispatcher) -> felt252 {
^*****************************^

error: The IWorldDispatcher parameter must be the first parameter of the function (self excluded).
--> test_src/lib.cairo:139:47
--> test_src/lib.cairo:153:47
fn do_with_world_not_first(vec: Vec2, world: IWorldDispatcher) -> felt252 {
^*********************^

error: The IWorldDispatcher parameter must be the first parameter of the function (self excluded).
--> test_src/lib.cairo:143:78
--> test_src/lib.cairo:157:78
fn do_with_self_and_world_not_first(self: @ContractState, vec: Vec2, world: IWorldDispatcher) -> felt252 {
^*********************^

Expand Down Expand Up @@ -379,6 +393,11 @@ error: Unsupported attribute.
#[my_attr]
^********^

error: Unsupported attribute.
--> test_src/lib.cairo[ContractAllowedRefSelf]:2:17
#[starknet::contract]
^*******************^

error: Unsupported attribute.
--> test_src/lib.cairo[MyFaultyContract]:2:17
#[starknet::contract]
Expand Down Expand Up @@ -599,6 +618,46 @@ error: Unsupported attribute.
#[flat]
^*****^

error: Unknown inline item macro: 'component'.
--> test_src/lib.cairo[ContractAllowedRefSelf]:10:21
component!(path: dojo::components::upgradeable::upgradeable, storage: upgradeable, event: UpgradeableEvent);
^**********************************************************************************************************^

error: Unsupported attribute.
--> test_src/lib.cairo[ContractAllowedRefSelf]:12:21
#[abi(embed_v0)]
^**************^

error: Unsupported attribute.
--> test_src/lib.cairo[ContractAllowedRefSelf]:19:21
#[abi(embed_v0)]
^**************^

error: Unsupported attribute.
--> test_src/lib.cairo[ContractAllowedRefSelf]:26:21
#[abi(embed_v0)]
^**************^

error: Unsupported attribute.
--> test_src/lib.cairo:98:5
#[abi(embed_v0)]
^**************^

error: Unsupported attribute.
--> test_src/lib.cairo[ContractAllowedRefSelf]:35:13
#[event]
^******^

error: Unsupported attribute.
--> test_src/lib.cairo[ContractAllowedRefSelf]:41:13
#[storage]
^********^

error: Unsupported attribute.
--> test_src/lib.cairo[ContractAllowedRefSelf]:44:17
#[substorage(v0)]
^***************^

error: Unknown inline item macro: 'component'.
--> test_src/lib.cairo[MyFaultyContract]:10:21
component!(path: dojo::components::upgradeable::upgradeable, storage: upgradeable, event: UpgradeableEvent);
Expand All @@ -620,7 +679,7 @@ error: Unsupported attribute.
^**************^

error: Unsupported attribute.
--> test_src/lib.cairo:117:5
--> test_src/lib.cairo:131:5
#[abi(embed_v0)]
^**************^

Expand Down Expand Up @@ -660,7 +719,7 @@ error: Unsupported attribute.
^**************^

error: Unsupported attribute.
--> test_src/lib.cairo:158:5
--> test_src/lib.cairo:172:5
#[abi(embed_v0)]
^**************^

Expand Down Expand Up @@ -693,6 +752,11 @@ mod testcomponent2 {
struct Storage {}
}

#[starknet::interface]
trait IAllowedRefSelf<T> {
fn spawn(ref self: T);
}

#[starknet::contract]
mod spawn {
use dojo::world;
Expand Down Expand Up @@ -944,6 +1008,53 @@ impl EventDrop of core::traits::Drop::<Event>;

}

#[starknet::contract]
mod ContractAllowedRefSelf {
use dojo::world;
use dojo::world::IWorldDispatcher;
use dojo::world::IWorldDispatcherTrait;
use dojo::world::IWorldProvider;
use dojo::world::IDojoResourceProvider;

#[abi(embed_v0)]
impl DojoResourceProviderImpl of IDojoResourceProvider<ContractState> {
fn dojo_resource(self: @ContractState) -> felt252 {
'ContractAllowedRefSelf'
}
}

#[abi(embed_v0)]
impl WorldProviderImpl of IWorldProvider<ContractState> {
fn world(self: @ContractState) -> IWorldDispatcher {
self.world_dispatcher.read()
}
}

#[abi(embed_v0)]
impl UpgradableImpl = dojo::components::upgradeable::upgradeable::UpgradableImpl<ContractState>;

#[abi(embed_v0)]
impl AllowedImpl of IAllowedRefSelf<ContractState> {
fn spawn(ref self: ContractState) {
}
}

#[event]
#[derive(Drop, starknet::Event)]
enum Event {
UpgradeableEvent: dojo::components::upgradeable::upgradeable::Event,
}

#[storage]
struct Storage {
world_dispatcher: IWorldDispatcher,
#[substorage(v0)]
upgradeable: dojo::components::upgradeable::upgradeable::Storage,
}
impl EventDrop of core::traits::Drop::<Event>;

}

#[starknet::interface]
trait INominalTrait<TContractState> {
fn do_no_param(self: @TContractState);
Expand Down
2 changes: 2 additions & 0 deletions crates/dojo-world/src/metadata_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ socials.x = "https://x.com/dojostarknet"
assert_eq!(world.socials.unwrap().get("x"), Some(&"https://x.com/dojostarknet".to_string()));
}

// TODO: remove ignore once IPFS node is running.
#[ignore]
#[tokio::test]
async fn world_metadata_hash_and_upload() {
let meta = WorldMetadata {
Expand Down
2 changes: 2 additions & 0 deletions crates/sozo/ops/src/tests/migration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,8 @@ async fn migration_from_remote() {
assert_eq!(local_manifest.models.len(), remote_manifest.models.len());
}

// TODO: remove ignore once IPFS node is running.
#[ignore]
#[tokio::test(flavor = "multi_thread")]
async fn migrate_with_metadata() {
let config = build_full_test_config("../../../examples/spawn-and-move/Scarb.toml", false)
Expand Down

0 comments on commit 5d9a8d1

Please sign in to comment.