Skip to content

Commit

Permalink
add warnings for migrations with prints
Browse files Browse the repository at this point in the history
  • Loading branch information
jsanchez556 committed Aug 23, 2024
1 parent 5c27bae commit c1f9d91
Show file tree
Hide file tree
Showing 7 changed files with 111 additions and 1 deletion.
1 change: 1 addition & 0 deletions 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 Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ dojo-lang = { path = "crates/dojo-lang" }
dojo-test-utils = { path = "crates/dojo-test-utils" }
dojo-types = { path = "crates/dojo-types" }
dojo-world = { path = "crates/dojo-world" }
dunce = "1"

# dojo-world
topological-sort = "0.2"
Expand Down
1 change: 1 addition & 0 deletions crates/dojo-lang/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ thiserror.workspace = true
toml.workspace = true
tracing.workspace = true
url.workspace = true
dunce.workspace = true

[dev-dependencies]
assert_fs.workspace = true
Expand Down
54 changes: 53 additions & 1 deletion crates/dojo-lang/src/compiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use std::ops::DerefMut;
use anyhow::{anyhow, Context, Result};
use cairo_lang_compiler::db::RootDatabase;
use cairo_lang_defs::db::DefsGroup;
use cairo_lang_defs::ids::{ModuleId, ModuleItemId, TopLevelLanguageElementId};
use cairo_lang_defs::ids::{ModuleId, ModuleItemId, NamedLanguageElementId, TopLevelLanguageElementId};
use cairo_lang_filesystem::db::FilesGroup;
use cairo_lang_filesystem::ids::{CrateId, CrateLongId};
use cairo_lang_formatter::format_string;
Expand All @@ -16,9 +16,11 @@ use cairo_lang_starknet::compile::compile_prepared_db;
use cairo_lang_starknet::contract::{find_contracts, ContractDeclaration};
use cairo_lang_starknet::plugin::aux_data::StarkNetContractAuxData;
use cairo_lang_starknet_classes::abi;
use cairo_lang_starknet_classes::allowed_libfuncs::{ ListSelector, AllowedLibfuncsError };
use cairo_lang_starknet_classes::contract_class::ContractClass;
use cairo_lang_utils::UpcastMut;
use camino::Utf8PathBuf;
use indoc::formatdoc;
use convert_case::{Case, Casing};
use dojo_world::contracts::naming;
use dojo_world::manifest::{
Expand All @@ -42,6 +44,7 @@ use tracing::{debug, trace, trace_span};
use crate::inline_macros::utils::{SYSTEM_READS, SYSTEM_WRITES};
use crate::plugin::{ComputedValuesAuxData, DojoAuxData, Model};
use crate::semantics::utils::find_module_rw;
use crate::scarb_internal::serdex::RelativeUtf8PathBuf;

const CAIRO_PATH_SEPARATOR: &str = "::";

Expand All @@ -57,12 +60,21 @@ pub struct DojoCompiler;
#[derive(Debug, Default, Serialize, Deserialize)]
#[serde(rename_all = "kebab-case")]
pub struct Props {
pub allowed_libfuncs_deny: bool,
pub allowed_libfuncs_list: Option<SerdeListSelector>,
pub build_external_contracts: Option<Vec<ContractSelector>>,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ContractSelector(String);

#[derive(Debug, Serialize, Deserialize)]
#[serde(untagged, rename_all = "kebab-case")]
pub enum SerdeListSelector {
Name { name: String },
Path { path: RelativeUtf8PathBuf },
}

impl ContractSelector {
fn package(&self) -> PackageName {
let parts = self.0.split_once(CAIRO_PATH_SEPARATOR).unwrap_or((self.0.as_str(), ""));
Expand Down Expand Up @@ -131,8 +143,37 @@ impl Compiler for DojoCompiler {
};

let mut compiled_classes: HashMap<String, (Felt, ContractClass)> = HashMap::new();
let list_selector = get_allowed_libfuncs_list(&props, &unit);

for (decl, class) in zip(contracts, classes) {
match class.validate_version_compatible(list_selector.clone()) {
Ok(()) => {},
Err(AllowedLibfuncsError::UnsupportedLibfunc {
invalid_libfunc,
allowed_libfuncs_list_name,
}) => {
let contract_name = decl.submodule_id.name(db.upcast_mut());
let diagnostic = formatdoc! {r#"
Contract `{contract_name}` include `{invalid_libfunc}` function that is not allowed in the libfuncs list `{allowed_libfuncs_list_name}`.
Please locate and remove this function from contract `{contract_name}` to ensure compatibility.
"#};

if props.allowed_libfuncs_deny {
ws.config().ui().error(diagnostic);
} else {
ws.config().ui().warn(diagnostic);
}
},
Err(e) => {
return Err(e).with_context(|| {
format!(
"Failed to check allowed libfuncs for contract: {contract_name}",
contract_name = decl.submodule_id.name(db.upcast_mut())
)
})
}
}

// note that the qualified path is in snake case while
// the `full_path()` method of StructId uses the original struct name case.
// (see in `get_dojo_model_artifacts`)
Expand All @@ -157,6 +198,17 @@ impl Compiler for DojoCompiler {
}
}

fn get_allowed_libfuncs_list(props: &Props, unit: &CairoCompilationUnit) -> ListSelector {
match &props.allowed_libfuncs_list {
Some(SerdeListSelector::Name { name }) => ListSelector::ListName(name.clone()),
Some(SerdeListSelector::Path { path }) => {
let path = path.relative_to_file(unit.main_component().package.manifest_path()).unwrap_or_default();
ListSelector::ListFile(path.into_string())
}
None => Default::default(),
}
}

fn compute_class_hash_of_contract_class(class: &ContractClass) -> Result<Felt> {
let class_str = serde_json::to_string(&class)?;
let sierra_class = serde_json::from_str::<SierraClass>(&class_str)
Expand Down
32 changes: 32 additions & 0 deletions crates/dojo-lang/src/scarb_internal/fsx.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
use std::path::{Path, PathBuf};

use anyhow::{anyhow, Context, Result};
use camino::Utf8PathBuf;

/// Equivalent to [`fs::canonicalize`] with better error messages.
///
/// Uses [`dunce`] to generate more familiar paths on Windows.
pub fn canonicalize(p: impl AsRef<Path>) -> Result<PathBuf> {
return inner(p.as_ref());

fn inner(p: &Path) -> Result<PathBuf> {
dunce::canonicalize(p)
.with_context(|| format!("failed to get absolute path of `{}`", p.display()))
}
}

/// Equivalent to [`fs::canonicalize`], but for Utf-8 paths, with better error messages.
pub fn canonicalize_utf8(p: impl AsRef<Path>) -> Result<Utf8PathBuf> {
canonicalize(p)?.try_into_utf8()
}

pub trait PathBufUtf8Ext {
fn try_into_utf8(self) -> Result<Utf8PathBuf>;
}

impl PathBufUtf8Ext for PathBuf {
fn try_into_utf8(self) -> Result<Utf8PathBuf> {
Utf8PathBuf::from_path_buf(self)
.map_err(|path| anyhow!("path `{}` is not UTF-8 encoded", path.display()))
}
}
3 changes: 3 additions & 0 deletions crates/dojo-lang/src/scarb_internal/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -331,3 +331,6 @@ pub fn cfg_set_from_component(

Ok(cfg_set)
}

pub mod serdex;
pub mod fsx;
20 changes: 20 additions & 0 deletions crates/dojo-lang/src/scarb_internal/serdex.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
use anyhow::Result;
use camino::{Utf8Path, Utf8PathBuf};
use serde::{Deserialize, Serialize};

use crate::scarb_internal::fsx;

#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)]
#[serde(transparent)]
pub struct RelativeUtf8PathBuf(Utf8PathBuf);

impl RelativeUtf8PathBuf {
pub fn relative_to_directory(&self, root: &Utf8Path) -> Result<Utf8PathBuf> {
fsx::canonicalize_utf8(root.join(&self.0))
}

pub fn relative_to_file(&self, file: &Utf8Path) -> Result<Utf8PathBuf> {
let root = file.parent().expect("Expected file path to not be `/`.");
self.relative_to_directory(root)
}
}

0 comments on commit c1f9d91

Please sign in to comment.