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

Introduced queries for crate plugins in DefsGroup and SemanticGroup #6840

Merged
merged 1 commit into from
Feb 3, 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
95 changes: 93 additions & 2 deletions crates/cairo-lang-defs/src/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,10 +96,48 @@ pub trait DefsGroup:
// Plugins.
// ========
#[salsa::input]
fn macro_plugins(&self) -> Vec<Arc<dyn MacroPlugin>>;
#[salsa::input]
fn macro_plugins(&self) -> Vec<Arc<dyn MacroPlugin>>; // TODO: Delete in favour or [`default_macro_plugins`]
#[salsa::input] // TODO: Delete in favour or [`default_inline_macro_plugins`]
fn inline_macro_plugins(&self) -> Arc<OrderedHashMap<String, Arc<dyn InlineMacroExprPlugin>>>;

#[salsa::input]
fn default_macro_plugins(&self) -> Arc<[MacroPluginId]>;

#[salsa::input]
fn macro_plugin_overrides(&self) -> Arc<OrderedHashMap<CrateId, Arc<[MacroPluginId]>>>;

#[salsa::interned]
fn intern_macro_plugin(&self, plugin: MacroPluginLongId) -> MacroPluginId;

/// Returns [`MacroPluginId`]s of the plugins set for the crate with [`CrateId`].
/// Provides an override if it has been set with
/// [`DefsGroupEx::set_override_crate_macro_plugins`] or the default
/// ([`DefsGroup::default_macro_plugins`]) otherwise.
fn crate_macro_plugins(&self, crate_id: CrateId) -> Arc<[MacroPluginId]>;

#[salsa::input]
fn default_inline_macro_plugins(&self) -> Arc<OrderedHashMap<String, InlineMacroExprPluginId>>;

#[salsa::input]
fn inline_macro_plugin_overrides(
&self,
) -> Arc<OrderedHashMap<CrateId, Arc<OrderedHashMap<String, InlineMacroExprPluginId>>>>;

#[salsa::interned]
fn intern_inline_macro_plugin(
&self,
plugin: InlineMacroExprPluginLongId,
) -> InlineMacroExprPluginId;

/// Returns [`InlineMacroExprPluginId`]s of the plugins set for the crate with [`CrateId`].
/// Provides an override if it has been set with
/// [`DefsGroupEx::set_override_crate_inline_macro_plugins`] or the default
/// ([`DefsGroup::default_inline_macro_plugins`]) otherwise.
fn crate_inline_macro_plugins(
&self,
crate_id: CrateId,
) -> Arc<OrderedHashMap<String, InlineMacroExprPluginId>>;

/// Returns the set of attributes allowed anywhere.
/// An attribute on any item that is not in this set will be handled as an unknown attribute.
fn allowed_attributes(&self) -> Arc<OrderedHashSet<String>>;
Expand Down Expand Up @@ -261,6 +299,29 @@ pub trait DefsGroup:
) -> Maybe<Arc<PluginFileDiagnosticNotes>>;
}

/// Initializes the [`DefsGroup`] database to a proper state.
pub fn init_defs_group(db: &mut dyn DefsGroup) {
db.set_macro_plugin_overrides(Arc::new(OrderedHashMap::default()));
db.set_inline_macro_plugin_overrides(Arc::new(OrderedHashMap::default()));
}

fn crate_macro_plugins(db: &dyn DefsGroup, crate_id: CrateId) -> Arc<[MacroPluginId]> {
db.macro_plugin_overrides()
.get(&crate_id)
.cloned()
.unwrap_or_else(|| db.default_macro_plugins())
}

fn crate_inline_macro_plugins(
db: &dyn DefsGroup,
crate_id: CrateId,
) -> Arc<OrderedHashMap<String, InlineMacroExprPluginId>> {
db.inline_macro_plugin_overrides()
.get(&crate_id)
.cloned()
.unwrap_or_else(|| db.default_inline_macro_plugins())
}

fn allowed_attributes(db: &dyn DefsGroup) -> Arc<OrderedHashSet<String>> {
let base_attrs = [
INLINE_ATTR,
Expand Down Expand Up @@ -1145,3 +1206,33 @@ fn module_item_name_stable_ptr(
}
})
}

pub trait DefsGroupEx: DefsGroup {
/// Overrides the default macro plugins available for [`CrateId`] with `plugins`.
///
/// *Note*: Sets the following Salsa input: `DefsGroup::macro_plugin_overrides`.
fn set_override_crate_macro_plugins(
&mut self,
crate_id: CrateId,
plugins: Arc<[MacroPluginId]>,
) {
let mut overrides = self.macro_plugin_overrides().as_ref().clone();
overrides.insert(crate_id, plugins);
self.set_macro_plugin_overrides(Arc::new(overrides));
}

/// Overrides the default inline macro plugins available for [`CrateId`] with `plugins`.
///
/// *Note*: Sets the following Salsa input: `DefsGroup::inline_macro_plugin_overrides`.
fn set_override_crate_inline_macro_plugins(
&mut self,
crate_id: CrateId,
plugins: Arc<OrderedHashMap<String, InlineMacroExprPluginId>>,
) {
let mut overrides = self.inline_macro_plugin_overrides().as_ref().clone();
overrides.insert(crate_id, plugins);
self.set_inline_macro_plugin_overrides(Arc::new(overrides));
}
}

impl<T: DefsGroup + ?Sized> DefsGroupEx for T {}
102 changes: 102 additions & 0 deletions crates/cairo-lang-defs/src/ids.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
//
// Call sites, variable usages, assignments, etc. are NOT definitions.

use std::hash::{Hash, Hasher};
use std::sync::Arc;

use cairo_lang_debug::debug::DebugWithDb;
use cairo_lang_diagnostics::Maybe;
pub use cairo_lang_filesystem::ids::UnstableSalsaId;
Expand All @@ -37,6 +40,7 @@ use smol_str::SmolStr;

use crate::db::DefsGroup;
use crate::diagnostic_utils::StableLocation;
use crate::plugin::{InlineMacroExprPlugin, MacroPlugin};

// A trait for an id for a language element.
pub trait LanguageElementId {
Expand Down Expand Up @@ -321,6 +325,104 @@ define_short_id!(
intern_plugin_generated_file
);

/// An ID allowing for interning the [`MacroPlugin`] into Salsa database.
#[derive(Clone, Debug)]
pub struct MacroPluginLongId(pub Arc<dyn MacroPlugin>);

impl MacroPlugin for MacroPluginLongId {
fn generate_code(
&self,
db: &dyn SyntaxGroup,
item_ast: ast::ModuleItem,
metadata: &crate::plugin::MacroPluginMetadata<'_>,
) -> crate::plugin::PluginResult {
self.0.generate_code(db, item_ast, metadata)
}

fn declared_attributes(&self) -> Vec<String> {
self.0.declared_attributes()
}

fn declared_derives(&self) -> Vec<String> {
self.0.declared_derives()
}

fn executable_attributes(&self) -> Vec<String> {
self.0.executable_attributes()
}

fn phantom_type_attributes(&self) -> Vec<String> {
self.0.phantom_type_attributes()
}
}

// `PartialEq` and `Hash` cannot be derived on `Arc<dyn ...>`,
// but pointer-based equality and hash semantics are enough in this case.
impl PartialEq for MacroPluginLongId {
fn eq(&self, other: &Self) -> bool {
Arc::ptr_eq(&self.0, &other.0)
}
}

impl Eq for MacroPluginLongId {}

impl Hash for MacroPluginLongId {
fn hash<H: Hasher>(&self, state: &mut H) {
Arc::as_ptr(&self.0).hash(state)
}
}

define_short_id!(
MacroPluginId,
MacroPluginLongId,
DefsGroup,
lookup_intern_macro_plugin,
intern_macro_plugin
);

/// An ID allowing for interning the [`InlineMacroExprPlugin`] into Salsa database.
#[derive(Clone, Debug)]
pub struct InlineMacroExprPluginLongId(pub Arc<dyn InlineMacroExprPlugin>);

impl InlineMacroExprPlugin for InlineMacroExprPluginLongId {
fn generate_code(
&self,
db: &dyn SyntaxGroup,
item_ast: &ast::ExprInlineMacro,
metadata: &crate::plugin::MacroPluginMetadata<'_>,
) -> crate::plugin::InlinePluginResult {
self.0.generate_code(db, item_ast, metadata)
}

fn documentation(&self) -> Option<String> {
self.0.documentation()
}
}

// `PartialEq` and `Hash` cannot be derived on `Arc<dyn ...>`,
// but pointer-based equality and hash semantics are enough in this case.
impl PartialEq for InlineMacroExprPluginLongId {
fn eq(&self, other: &Self) -> bool {
Arc::ptr_eq(&self.0, &other.0)
}
}

impl Eq for InlineMacroExprPluginLongId {}

impl Hash for InlineMacroExprPluginLongId {
fn hash<H: Hasher>(&self, state: &mut H) {
Arc::as_ptr(&self.0).hash(state)
}
}

define_short_id!(
InlineMacroExprPluginId,
InlineMacroExprPluginLongId,
DefsGroup,
lookup_intern_inline_macro_plugin,
intern_inline_macro_plugin
);

define_language_element_id_as_enum! {
#[toplevel]
/// Id for direct children of a module.
Expand Down
45 changes: 45 additions & 0 deletions crates/cairo-lang-semantic/src/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ use smol_str::SmolStr;

use crate::diagnostic::SemanticDiagnosticKind;
use crate::expr::inference::{self, ImplVar, ImplVarId};
use crate::ids::{AnalyzerPluginId, AnalyzerPluginLongId};
use crate::items::constant::{ConstCalcInfo, ConstValueId, Constant, ImplConstantId};
use crate::items::function_with_body::FunctionBody;
use crate::items::functions::{GenericFunctionId, ImplicitPrecedence, InlineConfiguration};
Expand Down Expand Up @@ -1587,6 +1588,21 @@ pub trait SemanticGroup:
#[salsa::input]
fn analyzer_plugins(&self) -> Vec<Arc<dyn AnalyzerPlugin>>;

#[salsa::input]
fn default_analyzer_plugins(&self) -> Arc<[AnalyzerPluginId]>;

#[salsa::input]
fn analyzer_plugin_overrides(&self) -> Arc<OrderedHashMap<CrateId, Arc<[AnalyzerPluginId]>>>;

#[salsa::interned]
fn intern_analyzer_plugin(&self, plugin: AnalyzerPluginLongId) -> AnalyzerPluginId;

/// Returns [`AnalyzerPluginId`]s of the plugins set for the crate with [`CrateId`].
/// Returns
/// [`SemanticGroupEx::set_override_crate_analyzer_plugins`] if it has been set,
/// or the ([`SemanticGroup::default_analyzer_plugins`]) otherwise.
fn crate_analyzer_plugins(&self, crate_id: CrateId) -> Arc<[AnalyzerPluginId]>;

/// Returns the set of `allow` that were declared as by a plugin.
/// An allow that is not in this set will be handled as an unknown allow.
fn declared_allows(&self) -> Arc<OrderedHashSet<String>>;
Expand Down Expand Up @@ -1633,6 +1649,11 @@ pub trait SemanticGroup:
) -> Arc<[(TraitId, String)]>;
}

/// Initializes the [`SemanticGroup`] database to a proper state.
pub fn init_semantic_group(db: &mut dyn SemanticGroup) {
db.set_analyzer_plugin_overrides(Arc::new(OrderedHashMap::default()));
}

impl<T: Upcast<dyn SemanticGroup + 'static>> Elongate for T {
fn elongate(&self) -> &(dyn SemanticGroup + 'static) {
self.upcast()
Expand Down Expand Up @@ -1736,6 +1757,13 @@ fn module_semantic_diagnostics(
Ok(diagnostics.build())
}

fn crate_analyzer_plugins(db: &dyn SemanticGroup, crate_id: CrateId) -> Arc<[AnalyzerPluginId]> {
db.analyzer_plugin_overrides()
.get(&crate_id)
.cloned()
.unwrap_or_else(|| db.default_analyzer_plugins())
}

fn declared_allows(db: &dyn SemanticGroup) -> Arc<OrderedHashSet<String>> {
Arc::new(OrderedHashSet::from_iter(
db.analyzer_plugins().into_iter().flat_map(|plugin| plugin.declared_allows()),
Expand Down Expand Up @@ -1880,3 +1908,20 @@ pub fn get_resolver_data_options(
.flatten()
.collect()
}

pub trait SemanticGroupEx: SemanticGroup {
/// Overrides the default analyzer plugins available for [`CrateId`] with `plugins`.
///
/// *Note*: Sets the following Salsa input: `SemanticGroup::analyzer_plugin_overrides`.
fn set_override_crate_analyzer_plugins(
&mut self,
crate_id: CrateId,
plugins: Arc<[AnalyzerPluginId]>,
) {
let mut overrides = self.analyzer_plugin_overrides().as_ref().clone();
overrides.insert(crate_id, plugins);
self.set_analyzer_plugin_overrides(Arc::new(overrides));
}
}

impl<T: SemanticGroup + ?Sized> SemanticGroupEx for T {}
49 changes: 49 additions & 0 deletions crates/cairo-lang-semantic/src/ids.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
use std::hash::{Hash, Hasher};
use std::sync::Arc;

use cairo_lang_utils::define_short_id;

use crate::db::SemanticGroup;
use crate::plugin::AnalyzerPlugin;

/// An Id allowing interning [`AnalyzerPlugin`] into Salsa database.
#[derive(Clone, Debug)]
pub struct AnalyzerPluginLongId(pub Arc<dyn AnalyzerPlugin>);

impl AnalyzerPlugin for AnalyzerPluginLongId {
fn diagnostics(
&self,
db: &dyn crate::db::SemanticGroup,
module_id: cairo_lang_defs::ids::ModuleId,
) -> Vec<cairo_lang_defs::plugin::PluginDiagnostic> {
self.0.diagnostics(db, module_id)
}

fn declared_allows(&self) -> Vec<String> {
self.0.declared_allows()
}
}

// `PartialEq` and `Hash` cannot be derived on `Arc<dyn ...>`,
// but pointer-based equality and hash semantics are enough in this case.
impl PartialEq for AnalyzerPluginLongId {
fn eq(&self, other: &Self) -> bool {
Arc::ptr_eq(&self.0, &other.0)
}
}

impl Eq for AnalyzerPluginLongId {}

impl Hash for AnalyzerPluginLongId {
fn hash<H: Hasher>(&self, state: &mut H) {
Arc::as_ptr(&self.0).hash(state)
}
}

define_short_id!(
AnalyzerPluginId,
AnalyzerPluginLongId,
SemanticGroup,
lookup_intern_analyzer_plugin,
intern_analyzer_plugin
);
1 change: 1 addition & 0 deletions crates/cairo-lang-semantic/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ pub mod db;
pub mod diagnostic;
pub mod expr;
pub mod helper;
pub mod ids;
pub mod inline_macros;
pub mod items;
pub mod literals;
Expand Down