Skip to content
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
5 changes: 3 additions & 2 deletions crates/ruff_linter/src/checkers/ast/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ use crate::docstrings::extraction::ExtractionTarget;
use crate::importer::{ImportRequest, Importer, ResolutionError};
use crate::noqa::NoqaMapping;
use crate::package::PackageRoot;
use crate::preview::{is_semantic_errors_enabled, is_undefined_export_in_dunder_init_enabled};
use crate::registry::Rule;
use crate::rules::pyflakes::rules::{
LateFutureImport, ReturnOutsideFunction, YieldOutsideFunction,
Expand Down Expand Up @@ -618,7 +619,7 @@ impl SemanticSyntaxContext for Checker<'_> {
| SemanticSyntaxErrorKind::AsyncComprehensionInSyncComprehension(_)
| SemanticSyntaxErrorKind::DuplicateParameter(_)
| SemanticSyntaxErrorKind::NonlocalDeclarationAtModuleLevel => {
if self.settings.preview.is_enabled() {
if is_semantic_errors_enabled(self.settings) {
self.semantic_errors.borrow_mut().push(error);
}
}
Expand Down Expand Up @@ -2827,7 +2828,7 @@ impl<'a> Checker<'a> {
}
} else {
if self.enabled(Rule::UndefinedExport) {
if self.settings.preview.is_enabled()
if is_undefined_export_in_dunder_init_enabled(self.settings)
|| !self.path.ends_with("__init__.py")
{
self.diagnostics.get_mut().push(
Expand Down
4 changes: 3 additions & 1 deletion crates/ruff_linter/src/checkers/filesystem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use ruff_python_ast::PythonVersion;
use ruff_python_trivia::CommentRanges;

use crate::package::PackageRoot;
use crate::preview::is_allow_nested_roots_enabled;
use crate::registry::Rule;
use crate::rules::flake8_builtins::rules::stdlib_module_shadowing;
use crate::rules::flake8_no_pep420::rules::implicit_namespace_package;
Expand All @@ -24,14 +25,15 @@ pub(crate) fn check_file_path(

// flake8-no-pep420
if settings.rules.enabled(Rule::ImplicitNamespacePackage) {
let allow_nested_roots = is_allow_nested_roots_enabled(settings);
if let Some(diagnostic) = implicit_namespace_package(
path,
package,
locator,
comment_ranges,
&settings.project_root,
&settings.src,
settings.preview,
allow_nested_roots,
) {
diagnostics.push(diagnostic);
}
Expand Down
3 changes: 2 additions & 1 deletion crates/ruff_linter/src/checkers/noqa.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use crate::fix::edits::delete_comment;
use crate::noqa::{
Code, Directive, FileExemption, FileNoqaDirectives, NoqaDirectives, NoqaMapping,
};
use crate::preview::is_check_file_level_directives_enabled;
use crate::registry::{AsRule, Rule, RuleSet};
use crate::rule_redirects::get_redirect_target;
use crate::rules::pygrep_hooks;
Expand Down Expand Up @@ -110,7 +111,7 @@ pub(crate) fn check_noqa(
&& !exemption.includes(Rule::UnusedNOQA)
&& !per_file_ignores.contains(Rule::UnusedNOQA)
{
let directives: Vec<_> = if settings.preview.is_enabled() {
let directives: Vec<_> = if is_check_file_level_directives_enabled(settings) {
noqa_directives
.lines()
.iter()
Expand Down
1 change: 1 addition & 0 deletions crates/ruff_linter/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ pub mod message;
mod noqa;
pub mod package;
pub mod packaging;
pub mod preview;
pub mod pyproject_toml;
pub mod registry;
mod renamer;
Expand Down
3 changes: 2 additions & 1 deletion crates/ruff_linter/src/linter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ use crate::fix::{fix_file, FixResult};
use crate::message::Message;
use crate::noqa::add_noqa;
use crate::package::PackageRoot;
use crate::preview::is_unsupported_syntax_enabled;
use crate::registry::{AsRule, Rule, RuleSet};
#[cfg(any(feature = "test-rules", test))]
use crate::rules::ruff::rules::test_rules::{self, TestRule, TEST_RULES};
Expand Down Expand Up @@ -360,7 +361,7 @@ pub fn check_path(
}
}

let syntax_errors = if settings.preview.is_enabled() {
let syntax_errors = if is_unsupported_syntax_enabled(settings) {
parsed.unsupported_syntax_errors()
} else {
&[]
Expand Down
118 changes: 118 additions & 0 deletions crates/ruff_linter/src/preview.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
//! Helpers to test if a specific preview style is enabled or not.
//!
//! The motivation for these functions isn't to avoid code duplication but to ease promoting preview behavior
//! to stable. The challenge with directly checking the `preview` attribute of [`LinterSettings`] is that it is unclear
//! which specific feature this preview check is for. Having named functions simplifies the promotion:
//! Simply delete the function and let Rust tell you which checks you have to remove.

use crate::settings::LinterSettings;

// https://github.com/astral-sh/ruff/issues/17412
// https://github.com/astral-sh/ruff/issues/11934
pub(crate) const fn is_semantic_errors_enabled(settings: &LinterSettings) -> bool {
settings.preview.is_enabled()
}

// https://github.com/astral-sh/ruff/pull/16429
pub(crate) const fn is_unsupported_syntax_enabled(settings: &LinterSettings) -> bool {
settings.preview.is_enabled()
}

// Rule-specific behavior

// https://github.com/astral-sh/ruff/pull/17136
pub(crate) const fn is_shell_injection_only_trusted_input_enabled(
settings: &LinterSettings,
) -> bool {
settings.preview.is_enabled()
}

// https://github.com/astral-sh/ruff/pull/15541
pub(crate) const fn is_suspicious_function_reference_enabled(settings: &LinterSettings) -> bool {
settings.preview.is_enabled()
}

// https://github.com/astral-sh/ruff/pull/7501
pub(crate) const fn is_bool_subtype_of_annotation_enabled(settings: &LinterSettings) -> bool {
settings.preview.is_enabled()
}

// https://github.com/astral-sh/ruff/pull/10759
pub(crate) const fn is_comprehension_with_min_max_sum_enabled(settings: &LinterSettings) -> bool {
settings.preview.is_enabled()
}

// https://github.com/astral-sh/ruff/pull/12657
pub(crate) const fn is_check_comprehensions_in_tuple_call_enabled(
settings: &LinterSettings,
) -> bool {
settings.preview.is_enabled()
}

// https://github.com/astral-sh/ruff/issues/15347
pub(crate) const fn is_bad_version_info_in_non_stub_enabled(settings: &LinterSettings) -> bool {
settings.preview.is_enabled()
}

// https://github.com/astral-sh/ruff/pull/12676
pub(crate) const fn is_fix_future_annotations_in_stub_enabled(settings: &LinterSettings) -> bool {
settings.preview.is_enabled()
}

// https://github.com/astral-sh/ruff/pull/11074
pub(crate) const fn is_only_add_return_none_at_end_enabled(settings: &LinterSettings) -> bool {
settings.preview.is_enabled()
}

// https://github.com/astral-sh/ruff/pull/12796
pub(crate) const fn is_simplify_ternary_to_binary_enabled(settings: &LinterSettings) -> bool {
settings.preview.is_enabled()
}

// https://github.com/astral-sh/ruff/pull/16719
pub(crate) const fn is_fix_manual_dict_comprehension_enabled(settings: &LinterSettings) -> bool {
settings.preview.is_enabled()
}

// https://github.com/astral-sh/ruff/pull/13919
pub(crate) const fn is_fix_manual_list_comprehension_enabled(settings: &LinterSettings) -> bool {
settings.preview.is_enabled()
}

// https://github.com/astral-sh/ruff/pull/11436
// https://github.com/astral-sh/ruff/pull/11168
pub(crate) const fn is_dunder_init_fix_unused_import_enabled(settings: &LinterSettings) -> bool {
settings.preview.is_enabled()
}

// https://github.com/astral-sh/ruff/pull/15313
pub(crate) const fn is_defer_optional_to_up045_enabled(settings: &LinterSettings) -> bool {
settings.preview.is_enabled()
}

// https://github.com/astral-sh/ruff/pull/8473
pub(crate) const fn is_unicode_to_unicode_confusables_enabled(settings: &LinterSettings) -> bool {
settings.preview.is_enabled()
}

// https://github.com/astral-sh/ruff/pull/17078
pub(crate) const fn is_support_slices_in_literal_concatenation_enabled(
settings: &LinterSettings,
) -> bool {
settings.preview.is_enabled()
}

// https://github.com/astral-sh/ruff/pull/11370
pub(crate) const fn is_undefined_export_in_dunder_init_enabled(settings: &LinterSettings) -> bool {
settings.preview.is_enabled()
}

// https://github.com/astral-sh/ruff/pull/14236
pub(crate) const fn is_allow_nested_roots_enabled(settings: &LinterSettings) -> bool {
settings.preview.is_enabled()
}

// https://github.com/astral-sh/ruff/pull/17061
pub(crate) const fn is_check_file_level_directives_enabled(settings: &LinterSettings) -> bool {
settings.preview.is_enabled()
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//! Checks relating to shell injection.

use crate::preview::is_shell_injection_only_trusted_input_enabled;
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, ViolationMetadata};
use ruff_python_ast::helpers::Truthiness;
Expand Down Expand Up @@ -324,7 +325,9 @@ pub(crate) fn shell_injection(checker: &Checker, call: &ast::ExprCall) {
}
// S603
_ => {
if !is_trusted_input(arg) || checker.settings.preview.is_disabled() {
if !is_trusted_input(arg)
|| !is_shell_injection_only_trusted_input_enabled(checker.settings)
{
if checker.enabled(Rule::SubprocessWithoutShellEqualsTrue) {
checker.report_diagnostic(Diagnostic::new(
SubprocessWithoutShellEqualsTrue,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use ruff_python_ast::{self as ast, Arguments, Decorator, Expr, ExprCall, Operato
use ruff_text_size::{Ranged, TextRange};

use crate::checkers::ast::Checker;
use crate::preview::is_suspicious_function_reference_enabled;
use crate::registry::AsRule;

/// ## What it does
Expand Down Expand Up @@ -936,7 +937,7 @@ pub(crate) fn suspicious_function_call(checker: &Checker, call: &ExprCall) {
}

pub(crate) fn suspicious_function_reference(checker: &Checker, func: &Expr) {
if checker.settings.preview.is_disabled() {
if !is_suspicious_function_reference_enabled(checker.settings) {
return;
}

Expand Down Expand Up @@ -1210,7 +1211,7 @@ fn suspicious_function(
/// S308
pub(crate) fn suspicious_function_decorator(checker: &Checker, decorator: &Decorator) {
// In preview mode, references are handled collectively by `suspicious_function_reference`
if checker.settings.preview.is_disabled() {
if !is_suspicious_function_reference_enabled(checker.settings) {
suspicious_function(checker, &decorator.expression, None, decorator.range);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use ruff_python_semantic::analyze::visibility;
use ruff_python_semantic::SemanticModel;

use crate::checkers::ast::Checker;
use crate::preview::is_bool_subtype_of_annotation_enabled;
use crate::rules::flake8_boolean_trap::helpers::is_allowed_func_def;

/// ## What it does
Expand Down Expand Up @@ -128,7 +129,7 @@ pub(crate) fn boolean_type_hint_positional_argument(
let Some(annotation) = parameter.annotation() else {
continue;
};
if checker.settings.preview.is_enabled() {
if is_bool_subtype_of_annotation_enabled(checker.settings) {
if !match_annotation_to_complex_bool(annotation, checker.semantic()) {
continue;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use ruff_python_ast::{self as ast, Expr, Keyword};
use ruff_text_size::{Ranged, TextSize};

use crate::checkers::ast::Checker;
use crate::preview::is_comprehension_with_min_max_sum_enabled;
use crate::rules::flake8_comprehensions::fixes;

/// ## What it does
Expand Down Expand Up @@ -125,7 +126,7 @@ pub(crate) fn unnecessary_comprehension_in_call(
if !(matches!(
builtin_function,
SupportedBuiltins::Any | SupportedBuiltins::All
) || (checker.settings.preview.is_enabled()
) || (is_comprehension_with_min_max_sum_enabled(checker.settings)
&& matches!(
builtin_function,
SupportedBuiltins::Sum | SupportedBuiltins::Min | SupportedBuiltins::Max
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use ruff_python_trivia::{SimpleTokenKind, SimpleTokenizer};
use ruff_text_size::{Ranged, TextRange, TextSize};

use crate::checkers::ast::Checker;
use crate::preview::is_check_comprehensions_in_tuple_call_enabled;
use crate::rules::flake8_comprehensions::fixes;

use super::helpers;
Expand Down Expand Up @@ -100,7 +101,9 @@ pub(crate) fn unnecessary_literal_within_tuple_call(
let argument_kind = match argument {
Expr::Tuple(_) => TupleLiteralKind::Tuple,
Expr::List(_) => TupleLiteralKind::List,
Expr::ListComp(_) if checker.settings.preview.is_enabled() => TupleLiteralKind::ListComp,
Expr::ListComp(_) if is_check_comprehensions_in_tuple_call_enabled(checker.settings) => {
TupleLiteralKind::ListComp
}
_ => return,
};
if !checker.semantic().has_builtin_binding("tuple") {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ use ruff_text_size::{TextRange, TextSize};
use crate::comments::shebang::ShebangDirective;
use crate::fs;
use crate::package::PackageRoot;
use crate::settings::types::PreviewMode;
use crate::Locator;

/// ## What it does
Expand Down Expand Up @@ -60,7 +59,7 @@ pub(crate) fn implicit_namespace_package(
comment_ranges: &CommentRanges,
project_root: &Path,
src: &[PathBuf],
preview: PreviewMode,
allow_nested_roots: bool,
) -> Option<Diagnostic> {
if package.is_none()
// Ignore non-`.py` files, which don't require an `__init__.py`.
Expand Down Expand Up @@ -93,7 +92,7 @@ pub(crate) fn implicit_namespace_package(
));
}

if preview.is_enabled() {
if allow_nested_roots {
if let Some(PackageRoot::Nested { path: root }) = package.as_ref() {
if path.ends_with("__init__.py") {
// Identify the intermediary package that's missing the `__init__.py` file.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use ruff_macros::{derive_message_formats, ViolationMetadata};
use ruff_text_size::Ranged;

use crate::checkers::ast::Checker;
use crate::preview::is_bad_version_info_in_non_stub_enabled;
use crate::registry::Rule;

/// ## What it does
Expand Down Expand Up @@ -140,7 +141,7 @@ pub(crate) fn bad_version_info_comparison(checker: &Checker, test: &Expr, has_el
if matches!(op, CmpOp::Lt) {
if checker.enabled(Rule::BadVersionInfoOrder)
// See https://github.com/astral-sh/ruff/issues/15347
&& (checker.source_type.is_stub() || checker.settings.preview.is_enabled())
&& (checker.source_type.is_stub() || is_bad_version_info_in_non_stub_enabled(checker.settings))
{
if has_else_clause {
checker.report_diagnostic(Diagnostic::new(BadVersionInfoOrder, test.range()));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use ruff_python_ast::StmtImportFrom;
use ruff_diagnostics::{Diagnostic, Fix, FixAvailability, Violation};
use ruff_macros::{derive_message_formats, ViolationMetadata};

use crate::{checkers::ast::Checker, fix};
use crate::{checkers::ast::Checker, fix, preview::is_fix_future_annotations_in_stub_enabled};

/// ## What it does
/// Checks for the presence of the `from __future__ import annotations` import
Expand Down Expand Up @@ -55,7 +55,7 @@ pub(crate) fn from_future_import(checker: &Checker, target: &StmtImportFrom) {

let mut diagnostic = Diagnostic::new(FutureAnnotationsInStub, *range);

if checker.settings.preview.is_enabled() {
if is_fix_future_annotations_in_stub_enabled(checker.settings) {
let stmt = checker.semantic().current_statement();

diagnostic.try_set_fix(|| {
Expand Down
3 changes: 2 additions & 1 deletion crates/ruff_linter/src/rules/flake8_return/rules/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ use ruff_text_size::{Ranged, TextRange, TextSize};
use crate::checkers::ast::Checker;
use crate::fix::edits;
use crate::fix::edits::adjust_indentation;
use crate::preview::is_only_add_return_none_at_end_enabled;
use crate::registry::{AsRule, Rule};
use crate::rules::flake8_return::helpers::end_of_last_statement;
use crate::Locator;
Expand Down Expand Up @@ -552,7 +553,7 @@ fn implicit_return(checker: &Checker, function_def: &ast::StmtFunctionDef, stmt:
return;
}

if checker.settings.preview.is_enabled() {
if is_only_add_return_none_at_end_enabled(checker.settings) {
add_return_none(checker, stmt, function_def.range());
} else {
for implicit_stmt in implicit_stmts {
Expand Down
Loading
Loading