Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Store plugins in the Crate structure #209

Merged
merged 1 commit into from
Feb 21, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion src/project/crate_data.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use std::collections::HashSet;
use std::path::PathBuf;

use cairo_lang_defs::db::DefsGroup;
Expand All @@ -10,6 +11,7 @@ use cairo_lang_filesystem::ids::{CrateId, CrateLongId, Directory};
use cairo_lang_utils::{Intern, LookupIntern};
use smol_str::SmolStr;

use super::builtin_plugins::BuiltinPlugin;
use crate::lang::db::AnalysisDatabase;

/// A complete set of information needed to set up a real crate in the analysis database.
Expand All @@ -36,6 +38,10 @@ pub struct Crate {

/// Crate settings.
pub settings: CrateSettings,

/// Built-in plugins required by the crate.
#[allow(dead_code)] // TODO: remove. The field is used later in the stack
pub builtin_plugins: HashSet<BuiltinPlugin>,
}

impl Crate {
Expand All @@ -61,6 +67,9 @@ impl Crate {
if let Some(file_stems) = &self.custom_main_file_stems {
inject_virtual_wrapper_lib(db, crate_id, file_stems);
}

// TODO (later in the stack): Construct the plugin suite
// from builtin_plugins and set as an override for the crate.
}

/// Construct a [`Crate`] from data already applied to the [`AnalysisDatabase`].
Expand All @@ -79,7 +88,11 @@ impl Crate {

let custom_main_file_stems = extract_custom_file_stems(db, crate_id);

Some(Self { name, discriminator, root, custom_main_file_stems, settings })
// TODO (later in the stack): Extract plugins associated with this crate
// from db and store it in this set.
let builtin_plugins = HashSet::default();

Some(Self { name, discriminator, root, custom_main_file_stems, settings, builtin_plugins })
}

/// States whether this is the `core` crate.
Expand Down
67 changes: 65 additions & 2 deletions src/project/scarb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,13 @@ use cairo_lang_filesystem::db::{
};
use itertools::Itertools;
use scarb_metadata::{
CompilationUnitComponentDependencyMetadata, CompilationUnitComponentId, Metadata,
PackageMetadata,
CompilationUnitCairoPluginMetadata, CompilationUnitComponentDependencyMetadata,
CompilationUnitComponentId, Metadata, PackageMetadata,
};
use smol_str::ToSmolStr;
use tracing::{debug, error, warn};

use super::builtin_plugins::BuiltinPlugin;
use super::manifest_registry::member_config::MemberConfig;
use crate::lang::db::AnalysisDatabase;
use crate::project::crate_data::Crate;
Expand Down Expand Up @@ -183,12 +184,53 @@ pub fn extract_crates(metadata: &Metadata) -> Vec<Crate> {

let custom_main_file_stems = (file_stem != "lib").then_some(vec![file_stem.into()]);

let plugin_dependencies = component
.dependencies
.as_ref()
.map(|dependencies| {
dependencies
.iter()
.filter_map(|dependency| {
let plugin = compilation_unit.cairo_plugins.iter().find(|plugin| {
plugin.component_dependency_id.as_ref() == Some(&dependency.id)
});

if plugin.is_none() {
error!(
"Plugin dependency `{}` not found in Scarb metadata",
dependency.id
);
}

plugin
})
.collect_vec()
})
.unwrap_or_default();

// We collect only the built-in plugins.
// Procedural macros are handled separately in the
// `crate::lang::proc_macros::controller`.

let mut builtin_plugins = crates_by_component_id
.get(&component_id)
.map(|cr| cr.builtin_plugins.clone())
.unwrap_or_default();

builtin_plugins.extend(if package.is_some_and(|p| p.name == "core") {
// Corelib is a special case because it is described by `cairo_project.toml`.
plugins_for_corelib()
} else {
plugins_from_dependencies(metadata, &plugin_dependencies)
});

let cr = Crate {
name: crate_name.into(),
discriminator: component.discriminator.as_ref().map(ToSmolStr::to_smolstr),
root: root.into(),
custom_main_file_stems,
settings,
builtin_plugins,
};

if compilation_unit.package == component.package {
Expand Down Expand Up @@ -240,6 +282,8 @@ pub fn extract_crates(metadata: &Metadata) -> Vec<Crate> {
let name = first_crate.name.clone();
let discriminator = first_crate.discriminator.clone();

let builtin_plugins = crs.iter().flat_map(|cr| cr.builtin_plugins.clone()).collect();

let custom_main_file_stems =
crs.into_iter().flat_map(|cr| cr.custom_main_file_stems.unwrap()).collect();

Expand All @@ -249,6 +293,7 @@ pub fn extract_crates(metadata: &Metadata) -> Vec<Crate> {
root,
custom_main_file_stems: Some(custom_main_file_stems),
settings,
builtin_plugins,
});
}

Expand Down Expand Up @@ -348,3 +393,21 @@ fn scarb_package_experimental_features(
coupons: contains("coupons"),
}
}

/// Returns all plugins required by the `core` crate.
fn plugins_for_corelib() -> Vec<BuiltinPlugin> {
vec![BuiltinPlugin::CairoTest, BuiltinPlugin::Starknet]
}

/// Returns all built-in plugins described by `dependencies`.
fn plugins_from_dependencies(
metadata: &Metadata,
dependencies: &[&CompilationUnitCairoPluginMetadata],
) -> Vec<BuiltinPlugin> {
dependencies
.iter()
.filter_map(|plugin_metadata| {
BuiltinPlugin::from_plugin_metadata(metadata, plugin_metadata)
})
.collect()
}