From 1d165bdbc21972a337958a9247ca9a94560e021e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Sm=C3=B3=C5=82ka?= Date: Fri, 17 Jan 2025 19:04:42 +0100 Subject: [PATCH] Store plugins in the Crate structure commit-id:988401af --- src/project/crate_data.rs | 15 ++++++++- src/project/scarb.rs | 67 +++++++++++++++++++++++++++++++++++++-- 2 files changed, 79 insertions(+), 3 deletions(-) diff --git a/src/project/crate_data.rs b/src/project/crate_data.rs index 73cccf72..c147e81b 100644 --- a/src/project/crate_data.rs +++ b/src/project/crate_data.rs @@ -1,3 +1,4 @@ +use std::collections::HashSet; use std::path::PathBuf; use cairo_lang_defs::db::DefsGroup; @@ -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. @@ -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, } impl Crate { @@ -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`]. @@ -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. diff --git a/src/project/scarb.rs b/src/project/scarb.rs index 68bbd45a..d4b58ce7 100644 --- a/src/project/scarb.rs +++ b/src/project/scarb.rs @@ -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; @@ -183,12 +184,53 @@ pub fn extract_crates(metadata: &Metadata) -> Vec { 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 { @@ -240,6 +282,8 @@ pub fn extract_crates(metadata: &Metadata) -> Vec { 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(); @@ -249,6 +293,7 @@ pub fn extract_crates(metadata: &Metadata) -> Vec { root, custom_main_file_stems: Some(custom_main_file_stems), settings, + builtin_plugins, }); } @@ -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 { + vec![BuiltinPlugin::CairoTest, BuiltinPlugin::Starknet] +} + +/// Returns all built-in plugins described by `dependencies`. +fn plugins_from_dependencies( + metadata: &Metadata, + dependencies: &[&CompilationUnitCairoPluginMetadata], +) -> Vec { + dependencies + .iter() + .filter_map(|plugin_metadata| { + BuiltinPlugin::from_plugin_metadata(metadata, plugin_metadata) + }) + .collect() +}