Skip to content

Commit 1722998

Browse files
committed
case by case
1 parent efba9e1 commit 1722998

File tree

3 files changed

+78
-85
lines changed

3 files changed

+78
-85
lines changed

forc-pkg/src/pkg.rs

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2046,17 +2046,17 @@ impl PkgTestEntry {
20462046

20472047
// With fixture-based testing, #[test] is mandatory and can coexist with #[fuzz] and #[case]
20482048
let has_case = test_function_decl.attributes.cases().next().is_some();
2049-
match (test_attr, fuzz_attr, has_case) {
2050-
(None, Some(_), _) | (None, None, true) => {
2051-
bail!(
2052-
"Function \"{}\" has parameterization attributes (#[fuzz] or #[case]) but is missing the required #[test] attribute",
2053-
test_function_decl.name
2054-
);
2055-
}
2056-
(None, None, false) => {
2057-
unreachable!("`test_function_decl` is guaranteed to be a test or fuzz function and it must have a `#[test]` attribute or parameterization attributes");
2058-
}
2059-
_ => {} // Valid: #[test] is present or only #[test] is present
2049+
let has_parameterization = fuzz_attr.is_some() || has_case;
2050+
2051+
if test_attr.is_none() && has_parameterization {
2052+
bail!(
2053+
"Function \"{}\" has parameterization attributes (#[fuzz] or #[case]) but is missing the required #[test] attribute",
2054+
test_function_decl.name
2055+
);
2056+
}
2057+
2058+
if test_attr.is_none() && !has_parameterization {
2059+
unreachable!("`test_function_decl` is guaranteed to be a test or fuzz function and it must have a `#[test]` attribute or parameterization attributes");
20602060
}
20612061

20622062
let pass_condition = if let Some(test_attr) = test_attr {

sway-core/src/lib.rs

Lines changed: 44 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -218,42 +218,42 @@ pub(crate) fn attr_decls_to_attributes(
218218
let first_doc_line = attributes
219219
.next()
220220
.expect("`chunk_by` guarantees existence of at least one element in the chunk");
221-
if !can_annotate(first_doc_line) {
222-
let last_doc_line = match attributes.last() {
223-
Some(last_attr) => last_attr,
224-
// There is only one doc line in the complete doc comment.
225-
None => first_doc_line,
226-
};
221+
if can_annotate(first_doc_line) {
222+
continue;
223+
}
224+
225+
let last_doc_line = attributes.last().unwrap_or(first_doc_line);
226+
handler.emit_err(
227+
ConvertParseTreeError::InvalidAttributeTarget {
228+
span: Span::join(
229+
first_doc_line.span.clone(),
230+
&last_doc_line.span.start_span(),
231+
),
232+
attribute: first_doc_line.name.clone(),
233+
target_friendly_name,
234+
can_only_annotate_help: first_doc_line
235+
.can_only_annotate_help(target_friendly_name),
236+
}
237+
.into(),
238+
);
239+
} else {
240+
// For other attributes, the error is shown for every individual attribute.
241+
for attribute in attributes {
242+
if can_annotate(attribute) {
243+
continue;
244+
}
245+
227246
handler.emit_err(
228247
ConvertParseTreeError::InvalidAttributeTarget {
229-
span: Span::join(
230-
first_doc_line.span.clone(),
231-
&last_doc_line.span.start_span(),
232-
),
233-
attribute: first_doc_line.name.clone(),
248+
span: attribute.name.span(),
249+
attribute: attribute.name.clone(),
234250
target_friendly_name,
235-
can_only_annotate_help: first_doc_line
251+
can_only_annotate_help: attribute
236252
.can_only_annotate_help(target_friendly_name),
237253
}
238254
.into(),
239255
);
240256
}
241-
} else {
242-
// For other attributes, the error is shown for every individual attribute.
243-
for attribute in attributes {
244-
if !can_annotate(attribute) {
245-
handler.emit_err(
246-
ConvertParseTreeError::InvalidAttributeTarget {
247-
span: attribute.name.span(),
248-
attribute: attribute.name.clone(),
249-
target_friendly_name,
250-
can_only_annotate_help: attribute
251-
.can_only_annotate_help(target_friendly_name),
252-
}
253-
.into(),
254-
);
255-
}
256-
}
257257
}
258258
}
259259

@@ -376,25 +376,24 @@ pub(crate) fn attr_decls_to_attributes(
376376

377377
// Check fixture-based testing requirements: #[case] or #[fuzz] require #[test]
378378
let has_test = attributes.of_kind(AttributeKind::Test).any(|_| true);
379-
let has_case = attributes.of_kind(AttributeKind::Case).any(|_| true);
380-
let has_fuzz = attributes.of_kind(AttributeKind::Fuzz).any(|_| true);
379+
let has_parameterization = attributes.of_kind(AttributeKind::Case).any(|_| true)
380+
|| attributes.of_kind(AttributeKind::Fuzz).any(|_| true);
381+
382+
if !has_parameterization || has_test {
383+
return (handler, attributes);
384+
}
381385

382-
if (has_case || has_fuzz) && !has_test {
383-
let parameterization_attr = if has_case {
384-
attributes.of_kind(AttributeKind::Case).next()
385-
} else {
386-
attributes.of_kind(AttributeKind::Fuzz).next()
387-
};
386+
let first_param_attr = attributes.of_kind(AttributeKind::Case).next()
387+
.or_else(|| attributes.of_kind(AttributeKind::Fuzz).next());
388388

389-
if let Some(attr) = parameterization_attr {
390-
handler.emit_err(
391-
ConvertParseTreeError::ParameterizedTestRequiresTestAttribute {
392-
span: attr.span.clone(),
393-
attribute: attr.name.clone(),
394-
}
395-
.into(),
396-
);
397-
}
389+
if let Some(attr) = first_param_attr {
390+
handler.emit_err(
391+
ConvertParseTreeError::ParameterizedTestRequiresTestAttribute {
392+
span: attr.span.clone(),
393+
attribute: attr.name.clone(),
394+
}
395+
.into(),
396+
);
398397
}
399398

400399
(handler, attributes)

sway-core/src/transform/attribute.rs

Lines changed: 23 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -618,23 +618,7 @@ impl Attribute {
618618
Allow => !matches!(item_kind, ItemKind::Submodule(_)),
619619
Cfg => !matches!(item_kind, ItemKind::Submodule(_)),
620620
// TODO: Adapt once https://github.com/FuelLabs/sway/issues/6942 is implemented.
621-
Deprecated => match item_kind {
622-
ItemKind::Submodule(_) => false,
623-
ItemKind::Use(_) => false,
624-
ItemKind::Struct(_) => true,
625-
ItemKind::Enum(_) => true,
626-
ItemKind::Fn(_) => true,
627-
ItemKind::Trait(_) => false,
628-
ItemKind::Impl(_) => false,
629-
ItemKind::Abi(_) => false,
630-
ItemKind::Const(_) => true,
631-
ItemKind::Storage(_) => false,
632-
// TODO: Currently, only single configurables can be deprecated.
633-
// Change to true once https://github.com/FuelLabs/sway/issues/6942 is implemented.
634-
ItemKind::Configurable(_) => false,
635-
ItemKind::TypeAlias(_) => false,
636-
ItemKind::Error(_, _) => true,
637-
},
621+
Deprecated => Self::can_deprecate_item_kind(item_kind),
638622
Fallback => matches!(item_kind, ItemKind::Fn(_)),
639623
ErrorType => matches!(item_kind, ItemKind::Enum(_)),
640624
Error => false,
@@ -644,6 +628,27 @@ impl Attribute {
644628
}
645629
}
646630

631+
fn can_deprecate_item_kind(item_kind: &ItemKind) -> bool {
632+
matches!(item_kind,
633+
ItemKind::Struct(_) |
634+
ItemKind::Enum(_) |
635+
ItemKind::Fn(_) |
636+
ItemKind::Const(_) |
637+
ItemKind::Error(_, _)
638+
)
639+
}
640+
641+
fn storage_help_text(target_friendly_name: &str) -> Vec<&'static str> {
642+
if target_friendly_name == "function signature" {
643+
vec![
644+
"\"storage\" attribute can only annotate functions that have an implementation.",
645+
"Function signatures in ABI and trait declarations do not have implementations.",
646+
]
647+
} else {
648+
vec!["\"storage\" attribute can only annotate functions."]
649+
}
650+
}
651+
647652
// TODO: Add `can_annotated_nested_item_kind`, once we properly support nested items.
648653
// E.g., the `#[test]` attribute can annotate module functions (`ItemKind::Fn`),
649654
// but will not be allowed on nested functions.
@@ -820,18 +825,7 @@ impl Attribute {
820825
vec![]
821826
},
822827
},
823-
Storage => {
824-
if target_friendly_name == "function signature" {
825-
vec![
826-
"\"storage\" attribute can only annotate functions that have an implementation.",
827-
"Function signatures in ABI and trait declarations do not have implementations.",
828-
]
829-
} else {
830-
vec![
831-
"\"storage\" attribute can only annotate functions.",
832-
]
833-
}
834-
},
828+
Storage => Self::storage_help_text(target_friendly_name),
835829
Inline => vec!["\"inline\" attribute can only annotate functions."],
836830
Test => vec!["\"test\" attribute can only annotate module functions."],
837831
Payable => vec![

0 commit comments

Comments
 (0)