Skip to content

Commit

Permalink
feat(semantic): add declared allows in analyzer plugins (#6429)
Browse files Browse the repository at this point in the history
  • Loading branch information
0xLucqs authored Oct 1, 2024
1 parent 98fb56b commit cd5f6bc
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 14 deletions.
10 changes: 10 additions & 0 deletions crates/cairo-lang-semantic/src/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1532,6 +1532,10 @@ pub trait SemanticGroup:
#[salsa::input]
fn analyzer_plugins(&self) -> Vec<Arc<dyn AnalyzerPlugin>>;

/// 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>>;

// Helpers for language server.
// ============================
/// Returns all methods in a module that match the given type filter.
Expand Down Expand Up @@ -1674,6 +1678,12 @@ fn module_semantic_diagnostics(
Ok(diagnostics.build())
}

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()),
))
}

/// Adds diagnostics for unused items in a module.
///
/// Returns `None` if skipped attempt to add diagnostics.
Expand Down
5 changes: 5 additions & 0 deletions crates/cairo-lang-semantic/src/diagnostic_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,10 @@ impl AnalyzerPlugin for NoU128RenameAnalyzerPlugin {
}
diagnostics
}

fn declared_allows(&self) -> Vec<String> {
vec!["u128_rename".to_string()]
}
}

#[test]
Expand All @@ -256,6 +260,7 @@ fn test_analyzer_diagnostics() {
use core::integer::u128 as long_u128_rename;
use u128 as short_u128_rename;
use inner::long_u128_rename as additional_u128_rename;
#[allow(u128_rename)]
use core::integer::u64 as long_u64_rename;
use u64 as short_u64_rename;
use inner::long_u64_rename as additional_u64_rename;
Expand Down
2 changes: 1 addition & 1 deletion crates/cairo-lang-semantic/src/expr/compute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3332,7 +3332,7 @@ pub fn compute_statement_semantic(
.resolver
.data
.feature_config
.override_with(extract_item_feature_config(syntax_db, &syntax, ctx.diagnostics));
.override_with(extract_item_feature_config(db, &syntax, ctx.diagnostics));
let statement = match &syntax {
ast::Statement::Let(let_syntax) => {
let rhs_syntax = &let_syntax.rhs(syntax_db);
Expand Down
27 changes: 14 additions & 13 deletions crates/cairo-lang-semantic/src/items/feature_kind.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use cairo_lang_defs::db::DefsGroup;
use cairo_lang_defs::diagnostic_utils::StableLocation;
use cairo_lang_defs::ids::{LanguageElementId, ModuleId};
use cairo_lang_diagnostics::DiagnosticsBuilder;
Expand All @@ -15,6 +14,7 @@ use cairo_lang_utils::ordered_hash_set::OrderedHashSet;
use cairo_lang_utils::try_extract_matches;
use smol_str::SmolStr;

use crate::db::SemanticGroup;
use crate::diagnostic::{SemanticDiagnosticKind, SemanticDiagnostics, SemanticDiagnosticsBuilder};
use crate::SemanticDiagnostic;

Expand Down Expand Up @@ -176,33 +176,34 @@ pub struct FeatureConfigRestore {

/// Returns the allowed features of an object which supports attributes.
pub fn extract_item_feature_config(
db: &dyn SyntaxGroup,
db: &dyn SemanticGroup,
syntax: &impl QueryAttrs,
diagnostics: &mut SemanticDiagnostics,
) -> FeatureConfig {
let syntax_db = db.upcast();
let mut config = FeatureConfig::default();
process_feature_attr_kind(
db,
syntax_db,
syntax,
FEATURE_ATTR,
|| SemanticDiagnosticKind::UnsupportedFeatureAttrArguments,
diagnostics,
|value| {
if let ast::Expr::String(value) = value {
config.allowed_features.insert(value.text(db));
config.allowed_features.insert(value.text(syntax_db));
true
} else {
false
}
},
);
process_feature_attr_kind(
db,
syntax_db,
syntax,
ALLOW_ATTR,
|| SemanticDiagnosticKind::UnsupportedAllowAttrArguments,
diagnostics,
|value| match value.as_syntax_node().get_text_without_trivia(db).as_str() {
|value| match value.as_syntax_node().get_text_without_trivia(syntax_db).as_str() {
"deprecated" => {
config.allow_deprecated = true;
true
Expand All @@ -211,7 +212,7 @@ pub fn extract_item_feature_config(
config.allow_unused_imports = true;
true
}
_ => false,
other => db.declared_allows().contains(other),
},
);
config
Expand Down Expand Up @@ -245,14 +246,14 @@ fn process_feature_attr_kind(
/// Extracts the allowed features of an element, considering its parent modules as well as its
/// attributes.
pub fn extract_feature_config(
db: &dyn DefsGroup,
db: &dyn SemanticGroup,
element_id: &impl LanguageElementId,
syntax: &impl QueryAttrs,
diagnostics: &mut SemanticDiagnostics,
) -> FeatureConfig {
let syntax_db = db.upcast();
let mut current_module_id = element_id.parent_module(db);
let mut config_stack = vec![extract_item_feature_config(syntax_db, syntax, diagnostics)];
let defs_db = db.upcast();
let mut current_module_id = element_id.parent_module(defs_db);
let mut config_stack = vec![extract_item_feature_config(db, syntax, diagnostics)];
let mut config = loop {
match current_module_id {
ModuleId::CrateRoot(crate_id) => {
Expand All @@ -265,11 +266,11 @@ pub fn extract_feature_config(
};
}
ModuleId::Submodule(id) => {
current_module_id = id.parent_module(db);
current_module_id = id.parent_module(defs_db);
let module = &db.module_submodules(current_module_id).unwrap()[&id];
// TODO(orizi): Add parent module diagnostics.
let ignored = &mut SemanticDiagnostics::default();
config_stack.push(extract_item_feature_config(syntax_db, module, ignored));
config_stack.push(extract_item_feature_config(db, module, ignored));
}
}
};
Expand Down
8 changes: 8 additions & 0 deletions crates/cairo-lang-semantic/src/plugin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,14 @@ use crate::db::SemanticGroup;
pub trait AnalyzerPlugin: std::fmt::Debug + Sync + Send {
/// Runs the plugin on a module.
fn diagnostics(&self, db: &dyn SemanticGroup, module_id: ModuleId) -> Vec<PluginDiagnostic>;
/// Allows this plugin supplies.
/// Any allow the plugin supplies without declaring here are likely to cause a
/// compilation error for unknown allow.
/// If the plugin checks for patterns that you want to allow in some places, for example
/// `#[allow(some_pattern)]` you will need to declare it here.
fn declared_allows(&self) -> Vec<String> {
Vec::new()
}
}

/// A suite of plugins.
Expand Down

0 comments on commit cd5f6bc

Please sign in to comment.