Skip to content

Commit

Permalink
Diagnose Unrecognized Annotations (FuelLabs#2547)
Browse files Browse the repository at this point in the history
* Warn if unrecognized annotation is used

* Use a list for valid names

* Update constants.rs
  • Loading branch information
AlicanC authored Aug 17, 2022
1 parent 3598086 commit 1ef4036
Show file tree
Hide file tree
Showing 7 changed files with 94 additions and 8 deletions.
6 changes: 6 additions & 0 deletions sway-core/src/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,9 @@ pub const MATCH_RETURN_VAR_NAME_PREFIX: &str = "__match_return_var_name_";
pub const STORAGE_PURITY_ATTRIBUTE_NAME: &str = "storage";
pub const STORAGE_PURITY_READ_NAME: &str = "read";
pub const STORAGE_PURITY_WRITE_NAME: &str = "write";

/// The valid attribute strings related to documentation.
pub const DOC_ATTRIBUTE_NAME: &str = "doc";

/// The list of valid attributes.
pub const VALID_ATTRIBUTE_NAMES: [&str; 2] = [STORAGE_PURITY_ATTRIBUTE_NAME, DOC_ATTRIBUTE_NAME];
28 changes: 20 additions & 8 deletions sway-core/src/convert_parse_tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ use {
crate::{
constants::{
STORAGE_PURITY_ATTRIBUTE_NAME, STORAGE_PURITY_READ_NAME, STORAGE_PURITY_WRITE_NAME,
VALID_ATTRIBUTE_NAMES,
},
error::{err, ok, CompileError, CompileResult, CompileWarning},
error::{err, ok, CompileError, CompileResult, CompileWarning, Warning},
type_system::{insert_type, AbiName, IntegerBits},
AbiCastExpression, AbiDeclaration, ArrayIndexExpression, AsmExpression, AsmOp, AsmRegister,
AsmRegisterDeclaration, AstNode, AstNodeContent, CallPath, CodeBlock, ConstantDeclaration,
Expand Down Expand Up @@ -293,7 +294,7 @@ pub fn module_to_sway_parse_tree(
}

fn item_to_ast_nodes(ec: &mut ErrorContext, item: Item) -> Result<Vec<AstNode>, ErrorEmitted> {
let attributes = item_attrs_to_map(&item.attribute_list)?;
let attributes = item_attrs_to_map(ec, &item.attribute_list)?;

let span = item.span();
let contents = match item.value {
Expand Down Expand Up @@ -394,11 +395,22 @@ fn item_to_ast_nodes(ec: &mut ErrorContext, item: Item) -> Result<Vec<AstNode>,

type AttributesMap<'a> = HashMap<&'a str, Vec<&'a Ident>>;

fn item_attrs_to_map(attribute_list: &[AttributeDecl]) -> Result<AttributesMap, ErrorEmitted> {
fn item_attrs_to_map<'a>(
ec: &mut ErrorContext,
attribute_list: &'a [AttributeDecl],
) -> Result<AttributesMap<'a>, ErrorEmitted> {
let mut attrs_map = AttributesMap::new();
for attr_decl in attribute_list {
let attr = attr_decl.attribute.get();
let name = attr.name.as_str();
if !VALID_ATTRIBUTE_NAMES.contains(&name) {
ec.warning(CompileWarning {
span: attr_decl.span().clone(),
warning_content: Warning::UnrecognizedAttribute {
attrib_name: attr.name.clone(),
},
})
}
let mut args = attr
.args
.as_ref()
Expand Down Expand Up @@ -665,7 +677,7 @@ fn item_trait_to_trait_declaration(
.into_inner()
.into_iter()
.map(|(fn_signature, _semicolon_token)| {
let attributes = item_attrs_to_map(&fn_signature.attribute_list)?;
let attributes = item_attrs_to_map(ec, &fn_signature.attribute_list)?;
fn_signature_to_trait_fn(ec, fn_signature.value, &attributes)
})
.collect::<Result<_, _>>()?
Expand All @@ -676,7 +688,7 @@ fn item_trait_to_trait_declaration(
.into_inner()
.into_iter()
.map(|item_fn| {
let attributes = item_attrs_to_map(&item_fn.attribute_list)?;
let attributes = item_attrs_to_map(ec, &item_fn.attribute_list)?;
item_fn_to_function_declaration(ec, item_fn.value, &attributes)
})
.collect::<Result<_, _>>()?,
Expand Down Expand Up @@ -708,7 +720,7 @@ fn item_impl_to_declaration(
.into_inner()
.into_iter()
.map(|item| {
let attributes = item_attrs_to_map(&item.attribute_list)?;
let attributes = item_attrs_to_map(ec, &item.attribute_list)?;
item_fn_to_function_declaration(ec, item.value, &attributes)
})
.collect::<Result<_, _>>()?
Expand Down Expand Up @@ -758,7 +770,7 @@ fn item_abi_to_abi_declaration(
.into_inner()
.into_iter()
.map(|(fn_signature, _semicolon_token)| {
let attributes = item_attrs_to_map(&fn_signature.attribute_list)?;
let attributes = item_attrs_to_map(ec, &fn_signature.attribute_list)?;
fn_signature_to_trait_fn(ec, fn_signature.value, &attributes)
})
.collect::<Result<_, _>>()?
Expand All @@ -769,7 +781,7 @@ fn item_abi_to_abi_declaration(
.into_inner()
.into_iter()
.map(|item_fn| {
let attributes = item_attrs_to_map(&item_fn.attribute_list)?;
let attributes = item_attrs_to_map(ec, &item_fn.attribute_list)?;
item_fn_to_function_declaration(ec, item_fn.value, &attributes)
})
.collect::<Result<_, _>>()?,
Expand Down
4 changes: 4 additions & 0 deletions sway-core/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,9 @@ pub enum Warning {
unneeded_attrib: String,
},
MatchExpressionUnreachableArm,
UnrecognizedAttribute {
attrib_name: Ident,
},
}

impl fmt::Display for Warning {
Expand Down Expand Up @@ -441,6 +444,7 @@ impl fmt::Display for Warning {
and can be removed."
),
MatchExpressionUnreachableArm => write!(f, "This match arm is unreachable."),
UnrecognizedAttribute {attrib_name} => write!(f, "Unknown attribute: \"{attrib_name}\"."),
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[[package]]
name = 'core'
source = 'path+from-root-1C8151ABD9941A97'
dependencies = []

[[package]]
name = 'diagnose_unknown_annotations'
source = 'root'
dependencies = ['std']

[[package]]
name = 'std'
source = 'path+from-root-1C8151ABD9941A97'
dependencies = ['core']
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[project]
authors = ["Fuel Labs <[email protected]>"]
entry = "main.sw"
license = "Apache-2.0"
name = "diagnose_unknown_annotations"

[dependencies]
std = { path = "../../../../../../../sway-lib-std" }
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
contract;

#[storage(read, write)]
#[doc(test)]
abi GoodAbi {
#[storage(read, write)]
#[doc(test)]
fn good_func() -> bool;

#[bad_attr(blah)]
fn bad_func() -> bool;
}

impl GoodAbi for Contract {
#[storage(read, write)]
#[doc(Test)]
fn good_func() -> bool {
true
}

#[bad_attr(blah)]
fn bad_func() -> bool {
true
}
}

#[bad_attr(blah)]
struct BadStruct {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
category = "compile"
validate_abi = false

# check: $()#[bad_attr(blah)]
# nextln: $()Unknown attribute: "bad_attr".
# nextln: $()fn bad_func() -> bool;

# check: $()#[bad_attr(blah)]
# nextln: $()Unknown attribute: "bad_attr".
# nextln: $()fn bad_func() -> bool {

# check: $()#[bad_attr(blah)]
# nextln: $()Unknown attribute: "bad_attr".
# nextln: $()struct BadStruct {}

0 comments on commit 1ef4036

Please sign in to comment.