Skip to content

Commit

Permalink
Introduced the new per-crate plugin logic
Browse files Browse the repository at this point in the history
  • Loading branch information
integraledelebesgue committed Dec 20, 2024
1 parent 6546837 commit b8ddb6c
Show file tree
Hide file tree
Showing 10 changed files with 125 additions and 53 deletions.
3 changes: 3 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

29 changes: 25 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,10 @@ expect-test = "1.5"
flate2 = { version = "1.0.35", default-features = false, features = ["zlib"] }
fs4 = { version = "0.7", features = ["tokio"] }
fs_extra = "1"
futures = { version = "0.3", default-features = false, features = ["std", "async-await"] }
futures = { version = "0.3", default-features = false, features = [
"std",
"async-await",
] }
gix = ">=0.55"
gix-path = "0.10"
glob = "0.3"
Expand All @@ -109,7 +112,14 @@ proc-macro2 = "1"
quote = "1"
ra_ap_toolchain = "0.0.218"
redb = "2.3.0"
reqwest = { version = "0.11", features = ["gzip", "brotli", "deflate", "json", "stream", "multipart"], default-features = false }
reqwest = { version = "0.11", features = [
"gzip",
"brotli",
"deflate",
"json",
"stream",
"multipart",
], default-features = false }
salsa = { package = "rust-analyzer-salsa", version = "0.17.0-pre.6" }
semver = { version = "1", features = ["serde"] }
serde = { version = "1", features = ["serde_derive"] }
Expand All @@ -130,7 +140,14 @@ tempfile = "3"
test-case = "3"
thiserror = "2"
time = "0.3"
tokio = { version = "1", features = ["macros", "io-util", "process", "rt", "rt-multi-thread", "sync"] }
tokio = { version = "1", features = [
"macros",
"io-util",
"process",
"rt",
"rt-multi-thread",
"sync",
] }
toml = "0.8"
toml_edit = { version = "0.22", features = ["serde"] }
tower-http = { version = "0.4", features = ["fs"] }
Expand All @@ -141,7 +158,11 @@ typed-builder = ">=0.17"
url = { version = "2", features = ["serde"] }
walkdir = "2"
which = "7"
windows-sys = { version = "0.59", features = ["Win32_Foundation", "Win32_System", "Win32_System_Console"] }
windows-sys = { version = "0.59", features = [
"Win32_Foundation",
"Win32_System",
"Win32_System_Console",
] }
xshell = "0.2"
xxhash-rust = { version = "0.8", features = ["xxh3"] }
zip = { version = "0.6", default-features = false, features = ["deflate"] }
Expand Down
17 changes: 8 additions & 9 deletions extensions/scarb-doc/src/db.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use cairo_lang_compiler::project::{update_crate_roots_from_project_config, ProjectConfig};
use cairo_lang_defs::db::{try_ext_as_virtual_impl, DefsDatabase, DefsGroup};
use cairo_lang_defs::db::{init_defs_group, try_ext_as_virtual_impl, DefsDatabase, DefsGroup};
use cairo_lang_doc::db::{DocDatabase, DocGroup};
use cairo_lang_filesystem::cfg::{Cfg, CfgSet};
use cairo_lang_filesystem::db::{
Expand All @@ -8,7 +8,9 @@ use cairo_lang_filesystem::db::{
use cairo_lang_filesystem::ids::VirtualFile;
use cairo_lang_lowering::db::{LoweringDatabase, LoweringGroup};
use cairo_lang_parser::db::{ParserDatabase, ParserGroup};
use cairo_lang_semantic::db::{SemanticDatabase, SemanticGroup};
use cairo_lang_semantic::db::{
init_semantic_group, PluginSuiteInput, SemanticDatabase, SemanticGroup,
};
use cairo_lang_semantic::inline_macros::get_default_plugin_suite;
use cairo_lang_semantic::plugin::PluginSuite;
use cairo_lang_starknet::starknet_plugin_suite;
Expand Down Expand Up @@ -44,10 +46,13 @@ impl ScarbDocDatabase {
};

init_files_group(&mut db);
init_defs_group(&mut db);
init_semantic_group(&mut db);

db.set_cfg_set(Self::initial_cfg_set().into());

db.apply_plugin_suite(plugin_suite);
let interned_plugin_suite = db.intern_plugin_suite(plugin_suite);
db.set_default_plugins_from_suite(interned_plugin_suite);

if let Some(config) = project_config {
db.apply_project_config(config);
Expand All @@ -60,12 +65,6 @@ impl ScarbDocDatabase {
CfgSet::from_iter([Cfg::name("doc")])
}

fn apply_plugin_suite(&mut self, plugin_suite: PluginSuite) {
self.set_macro_plugins(plugin_suite.plugins);
self.set_inline_macro_plugins(plugin_suite.inline_macro_plugins.into());
self.set_analyzer_plugins(plugin_suite.analyzer_plugins);
}

fn apply_project_config(&mut self, config: ProjectConfig) {
update_crate_roots_from_project_config(self, &config);
}
Expand Down
18 changes: 14 additions & 4 deletions scarb/src/compiler/compilers/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ use anyhow::{Context, Result};
use cairo_lang_compiler::db::RootDatabase;
use cairo_lang_compiler::CompilerConfig;
use cairo_lang_defs::db::DefsGroup;
use cairo_lang_defs::plugin::MacroPlugin;
use cairo_lang_filesystem::db::FilesGroup;
use cairo_lang_filesystem::ids::CrateLongId;
use cairo_lang_sierra::program::VersionedProgram;
use cairo_lang_sierra_to_casm::compiler::SierraToCasmConfig;
use cairo_lang_sierra_to_casm::metadata::{calc_metadata, calc_metadata_ap_change_only};
Expand Down Expand Up @@ -145,15 +148,22 @@ fn validate_compiler_config(
unit: &CairoCompilationUnit,
ws: &Workspace<'_>,
) {
let main_component = unit.main_component();
let main_crate_id = db.intern_crate(CrateLongId::Real {
name: main_component.target_name(),
discriminator: main_component.id.to_discriminator(),
});

// Generally, lib target compilation should be driven by a certain objective (e.g. cairo-run,
// test framework, etc.), expressed by the plugin set with executables definition.
// This does not apply to debug build (expressed by `replace_ids` flag),
// which is a goal by itself.
// See starkware-libs/cairo#5440 for more context.
let executable_plugin = db
.macro_plugins()
.iter()
.any(|plugin| !plugin.executable_attributes().is_empty());
let executable_plugin = db.crate_macro_plugins(main_crate_id).iter().any(|&plugin| {
!db.lookup_intern_macro_plugin(plugin)
.executable_attributes()
.is_empty()
});
if !executable_plugin && !compiler_config.replace_ids {
ws.config().ui().warn(formatdoc! {r#"
artefacts produced by this build may be hard to utilize due to the build configuration
Expand Down
15 changes: 10 additions & 5 deletions scarb/src/compiler/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,13 +58,13 @@ fn load_plugins(
let package_id = plugin_info.package.id;
let plugin = ws.config().cairo_plugins().fetch(package_id)?;
let instance = plugin.instantiate()?;
builder.with_plugin_suite(instance.plugin_suite());
builder.with_default_plugin_suite(instance.plugin_suite());
} else {
proc_macros.register(plugin_info.package.clone(), ws.config())?;
}
}
let macro_host = Arc::new(proc_macros.into_plugin()?);
builder.with_plugin_suite(ProcMacroHostPlugin::build_plugin_suite(macro_host.clone()));
builder.with_default_plugin_suite(ProcMacroHostPlugin::build_plugin_suite(macro_host.clone()));
Ok(macro_host)
}

Expand Down Expand Up @@ -198,10 +198,15 @@ fn build_project_config(unit: &CairoCompilationUnit) -> Result<ProjectConfig> {
Ok(project_config)
}

pub(crate) fn has_starknet_plugin(db: &RootDatabase) -> bool {
db.macro_plugins()
pub(crate) fn has_starknet_plugin(db: &RootDatabase, component: &CompilationUnitComponent) -> bool {
let crate_id = db.intern_crate(CrateLongId::Real {
name: component.target_name(),
discriminator: component.id.to_discriminator(),
});

db.crate_macro_plugins(crate_id)
.iter()
.any(|plugin| is_starknet_plugin(&**plugin))
.any(|&plugin| is_starknet_plugin(&db.lookup_intern_macro_plugin(plugin)))
}

fn is_starknet_plugin(plugin: &dyn MacroPlugin) -> bool {
Expand Down
2 changes: 1 addition & 1 deletion scarb/src/ops/compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ fn check_starknet_dependency(
// I think we can get away with emitting false positives for users who write raw contracts
// without using Starknet code generators. Such people shouldn't do what they do 😁
if unit.main_component().target_kind() == TargetKind::STARKNET_CONTRACT
&& !has_starknet_plugin(db)
&& !has_starknet_plugin(db, unit.main_component())
{
ws.config().ui().warn(formatdoc! {
r#"
Expand Down
67 changes: 42 additions & 25 deletions scarb/src/ops/proc_macro_server/methods/defined_macros.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
use std::sync::Arc;

use anyhow::Result;
use cairo_lang_utils::ordered_hash_map::OrderedHashMap;
use itertools::Itertools;
use scarb_proc_macro_server_types::methods::defined_macros::{
DefinedMacros, DefinedMacrosResponse,
DefinedMacros, DefinedMacrosCrateInfo, DefinedMacrosResponse,
};

use super::Handler;
Expand All @@ -13,37 +15,52 @@ impl Handler for DefinedMacros {
proc_macro_host: Arc<ProcMacroHost>,
_params: Self::Params,
) -> Result<Self::Response> {
let mut response = proc_macro_host
let crate_macro_info = proc_macro_host
.macros()
.iter()
.map(|e| DefinedMacrosResponse {
attributes: e.declared_attributes(),
inline_macros: e.inline_macros(),
derives: e.declared_derives(),
executables: e.executable_attributes(),
})
.reduce(|mut acc, defined_macros| {
acc.attributes.extend(defined_macros.attributes);
acc.inline_macros.extend(defined_macros.inline_macros);
acc.derives.extend(defined_macros.derives);
acc.executables.extend(defined_macros.executables);
.map(|macro_instance| {
let attributes = macro_instance
.declared_attributes()
.into_iter()
.sorted()
.dedup()
.collect();

acc
})
.unwrap_or_default();
let inline_macros = macro_instance
.inline_macros()
.into_iter()
.sorted()
.dedup()
.collect();

response.attributes.sort();
response.attributes.dedup();
let derives = macro_instance
.declared_attributes()
.into_iter()
.sorted()
.dedup()
.collect();

response.inline_macros.sort();
response.inline_macros.dedup();
let executables = macro_instance
.executable_attributes()
.into_iter()
.sorted()
.dedup()
.collect();

response.derives.sort();
response.derives.dedup();
let package_name = macro_instance.package_id().name.to_smol_str();

response.executables.sort();
response.executables.dedup();
(
package_name,
DefinedMacrosCrateInfo {
attributes,
inline_macros,
derives,
executables,
},
)
})
.collect::<OrderedHashMap<_, _>>();

Ok(response)
Ok(DefinedMacrosResponse { crate_macro_info })
}
}
14 changes: 10 additions & 4 deletions scarb/tests/proc_macro_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,17 @@ fn defined_macros() {
let response = proc_macro_server
.request_and_wait::<DefinedMacros>(DefinedMacrosParams {})
.unwrap();
let response = response.crate_macro_info;

assert_eq!(response.attributes, vec!["some".to_string()]);
assert_eq!(response.derives, vec!["some_derive".to_string()]);
assert_eq!(response.inline_macros, vec!["inline_some".to_string()]);
assert_eq!(response.executables, vec!["some_executable".to_string()]);
let packages = response.keys().collect::<Vec<_>>();
assert_eq!(packages.len(), 1);
assert_eq!(packages[0], "test_package");

let crate_macros = &response["test_package"];
assert_eq!(&crate_macros.attributes, &["some".to_string()]);
assert_eq!(&crate_macros.derives, &["some_derive".to_string()]);
assert_eq!(&crate_macros.inline_macros, &["inline_some".to_string()]);
assert_eq!(&crate_macros.executables, &["some_executable".to_string()]);
}

#[test]
Expand Down
3 changes: 3 additions & 0 deletions utils/scarb-proc-macro-server-types/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,8 @@ repository.workspace = true

[dependencies]
cairo-lang-macro = { version = "0.1", features = ["serde"] }
cairo-lang-semantic.workspace = true
cairo-lang-utils.workspace = true
serde.workspace = true
serde_json.workspace = true
smol_str.workspace = true
Original file line number Diff line number Diff line change
@@ -1,11 +1,19 @@
use super::Method;
use cairo_lang_utils::ordered_hash_map::OrderedHashMap;
use serde::{Deserialize, Serialize};
use smol_str::SmolStr;

/// Response structure containing a mapping from package names to the information about the macros they use.
#[derive(Debug, Default, Serialize, Deserialize)]
pub struct DefinedMacrosResponse {
pub crate_macro_info: OrderedHashMap<SmolStr, DefinedMacrosCrateInfo>,
}

/// Response structure containing lists of all defined macros supported.
///
/// Details the types of macros that can be expanded, such as attributes, inline macros, and derives.
#[derive(Debug, Default, Serialize, Deserialize)]
pub struct DefinedMacrosResponse {
pub struct DefinedMacrosCrateInfo {
/// List of attribute macro names available.
pub attributes: Vec<String>,
/// List of inline macro names available.
Expand Down

0 comments on commit b8ddb6c

Please sign in to comment.