diff --git a/crates/ruff/tests/integration_test.rs b/crates/ruff/tests/integration_test.rs index 7aed76fee2df3..0edfcc7e20d6c 100644 --- a/crates/ruff/tests/integration_test.rs +++ b/crates/ruff/tests/integration_test.rs @@ -839,14 +839,12 @@ fn nursery_direct() { assert_cmd_snapshot!(cmd .pass_stdin("I=42\n"), @r###" success: false - exit_code: 1 + exit_code: 2 ----- stdout ----- - -:1:2: E225 [*] Missing whitespace around operator - Found 1 error. - [*] 1 fixable with the `--fix` option. ----- stderr ----- - warning: Selection of nursery rule `E225` without the `--preview` flag is deprecated. + ruff failed + Cause: Selection of unstable rule `E225` without the `--preview` flag is not allowed. "###); } @@ -857,15 +855,12 @@ fn nursery_group_selector() { assert_cmd_snapshot!(cmd .pass_stdin("I=42\n"), @r###" success: false - exit_code: 1 + exit_code: 2 ----- stdout ----- - -:1:1: CPY001 Missing copyright notice at top of file - -:1:2: E225 [*] Missing whitespace around operator - Found 2 errors. - [*] 1 fixable with the `--fix` option. ----- stderr ----- - warning: The `NURSERY` selector has been deprecated. Use the `--preview` flag instead. + ruff failed + Cause: The `NURSERY` selector was removed. Use the `--preview` flag instead. "###); } @@ -883,7 +878,7 @@ fn nursery_group_selector_preview_enabled() { ----- stderr ----- ruff failed - Cause: The `NURSERY` selector is deprecated and cannot be used with preview mode enabled. + Cause: The `NURSERY` selector was removed. Unstable rules should be selected individually or by their respective groups. "###); } diff --git a/crates/ruff_workspace/src/configuration.rs b/crates/ruff_workspace/src/configuration.rs index 3025d50acd9f1..2ffe116a35b66 100644 --- a/crates/ruff_workspace/src/configuration.rs +++ b/crates/ruff_workspace/src/configuration.rs @@ -863,10 +863,12 @@ impl LintConfiguration { for (kind, selector) in selection.selectors_by_kind() { #[allow(deprecated)] if matches!(selector, RuleSelector::Nursery) { - if preview.mode.is_enabled() { - return Err(anyhow!("The `NURSERY` selector is deprecated and cannot be used with preview mode enabled.")); - } - warn_user_once!("The `NURSERY` selector has been deprecated. Use the `--preview` flag instead."); + let suggestion = if preview.mode.is_disabled() { + " Use the `--preview` flag instead." + } else { + " Unstable rules should be selected individually or by their respective groups." + }; + return Err(anyhow!("The `NURSERY` selector was removed.{suggestion}")); }; // Only warn for the following selectors if used to enable rules @@ -904,9 +906,24 @@ impl LintConfiguration { ); } - for selection in deprecated_nursery_selectors { - let (prefix, code) = selection.prefix_and_code(); - warn_user!("Selection of nursery rule `{prefix}{code}` without the `--preview` flag is deprecated.",); + let deprecated_nursery_selectors = deprecated_nursery_selectors.iter().collect::>(); + match deprecated_nursery_selectors.as_slice() { + [] => (), + [selection] => { + let (prefix, code) = selection.prefix_and_code(); + return Err(anyhow!("Selection of unstable rule `{prefix}{code}` without the `--preview` flag is not allowed.")); + } + [..] => { + let mut message = "Selection of unstable rules without the `--preview` flag is not allowed. Enable preview or remove selection of:".to_string(); + for selection in deprecated_nursery_selectors { + let (prefix, code) = selection.prefix_and_code(); + message.push_str("\n\t- "); + message.push_str(prefix); + message.push_str(code); + } + message.push('\n'); + return Err(anyhow!(message)); + } } for selection in ignored_preview_selectors { @@ -1339,51 +1356,6 @@ mod tests { use ruff_linter::RuleSelector; use std::str::FromStr; - const NURSERY_RULES: &[Rule] = &[ - Rule::MissingCopyrightNotice, - Rule::IndentationWithInvalidMultiple, - Rule::NoIndentedBlock, - Rule::UnexpectedIndentation, - Rule::IndentationWithInvalidMultipleComment, - Rule::NoIndentedBlockComment, - Rule::UnexpectedIndentationComment, - Rule::OverIndented, - Rule::WhitespaceAfterOpenBracket, - Rule::WhitespaceBeforeCloseBracket, - Rule::WhitespaceBeforePunctuation, - Rule::WhitespaceBeforeParameters, - Rule::MultipleSpacesBeforeOperator, - Rule::MultipleSpacesAfterOperator, - Rule::TabBeforeOperator, - Rule::TabAfterOperator, - Rule::MissingWhitespaceAroundOperator, - Rule::MissingWhitespaceAroundArithmeticOperator, - Rule::MissingWhitespaceAroundBitwiseOrShiftOperator, - Rule::MissingWhitespaceAroundModuloOperator, - Rule::MissingWhitespace, - Rule::MultipleSpacesAfterComma, - Rule::TabAfterComma, - Rule::UnexpectedSpacesAroundKeywordParameterEquals, - Rule::MissingWhitespaceAroundParameterEquals, - Rule::TooFewSpacesBeforeInlineComment, - Rule::NoSpaceAfterInlineComment, - Rule::NoSpaceAfterBlockComment, - Rule::MultipleLeadingHashesForBlockComment, - Rule::MultipleSpacesAfterKeyword, - Rule::MultipleSpacesBeforeKeyword, - Rule::TabAfterKeyword, - Rule::TabBeforeKeyword, - Rule::MissingWhitespaceAfterKeyword, - Rule::CompareToEmptyString, - Rule::NoSelfUse, - Rule::EqWithoutHash, - Rule::BadDunderMethodName, - Rule::RepeatedAppend, - Rule::DeleteFullSlice, - Rule::CheckAndRemoveFromSet, - Rule::QuadraticListSummation, - ]; - const PREVIEW_RULES: &[Rule] = &[ Rule::AndOrTernary, Rule::AssignmentInAssert, @@ -1785,9 +1757,8 @@ mod tests { #[test] fn nursery_select_code() -> Result<()> { - // Backwards compatible behavior allows selection of nursery rules with their exact code - // when preview is disabled - let actual = resolve_rules( + // We do not allow selection of nursery rules when preview is disabled + assert!(resolve_rules( [RuleSelection { select: Some(vec![Flake8Copyright::_001.into()]), ..RuleSelection::default() @@ -1796,9 +1767,8 @@ mod tests { mode: PreviewMode::Disabled, ..PreviewOptions::default() }), - )?; - let expected = RuleSet::from_rule(Rule::MissingCopyrightNotice); - assert_eq!(actual, expected); + ) + .is_err()); let actual = resolve_rules( [RuleSelection { @@ -1817,10 +1787,9 @@ mod tests { #[test] #[allow(deprecated)] - fn select_nursery() -> Result<()> { - // Backwards compatible behavior allows selection of nursery rules with the nursery selector - // when preview is disabled - let actual = resolve_rules( + fn select_nursery() { + // We no longer allow use of the NURSERY selector and should error in both cases + assert!(resolve_rules( [RuleSelection { select: Some(vec![RuleSelector::Nursery]), ..RuleSelection::default() @@ -1829,11 +1798,8 @@ mod tests { mode: PreviewMode::Disabled, ..PreviewOptions::default() }), - )?; - let expected = RuleSet::from_rules(NURSERY_RULES); - assert_eq!(actual, expected); - - // When preview is enabled, use of NURSERY is banned + ) + .is_err()); assert!(resolve_rules( [RuleSelection { select: Some(vec![RuleSelector::Nursery]), @@ -1845,8 +1811,6 @@ mod tests { }), ) .is_err()); - - Ok(()) } #[test] diff --git a/docs/preview.md b/docs/preview.md index 1bea9e451db6e..048fcbe9b6510 100644 --- a/docs/preview.md +++ b/docs/preview.md @@ -143,12 +143,3 @@ In our previous example, `--select` with `ALL` `HYP`, `HYP0`, or `HYP00` would n rule will need to be selected with its exact code, e.g. `--select ALL,HYP001`. If preview mode is not enabled, this setting has no effect. - -## Legacy behavior - -Before the preview mode was introduced, new rules were added in a "nursery" category that required selection of -rules with their exact codes — similar to if `explicit-preview-rules` is enabled. - -The nursery category has been deprecated and all rules in the nursery are now considered to be in preview. -For backwards compatibility, nursery rules are selectable with their exact codes without enabling preview mode. -However, this behavior will display a warning and support will be removed in a future release.