use std::path::Path; use ruff_linter::settings::LinterSettings; use ruff_workspace::resolver::{match_any_exclusion, match_any_inclusion}; use ruff_workspace::{FileResolverSettings, FormatterSettings}; use crate::edit::LanguageId; /// Return `true` if the document at the given [`Path`] should be excluded from linting. pub(crate) fn is_document_excluded_for_linting( path: &Path, resolver_settings: &FileResolverSettings, linter_settings: &LinterSettings, language_id: Option, ) -> bool { is_document_excluded( path, resolver_settings, Some(linter_settings), None, language_id, ) } /// Return `true` if the document at the given [`Path`] should be excluded from formatting. pub(crate) fn is_document_excluded_for_formatting( path: &Path, resolver_settings: &FileResolverSettings, formatter_settings: &FormatterSettings, language_id: Option, ) -> bool { is_document_excluded( path, resolver_settings, None, Some(formatter_settings), language_id, ) } /// Return `true` if the document at the given [`Path`] should be excluded. /// /// The tool-specific settings should be provided if the request for the document is specific to /// that tool. For example, a diagnostics request should provide the linter settings while the /// formatting request should provide the formatter settings. /// /// The logic for the resolution considers both inclusion and exclusion and is as follows: /// 1. Check for global `exclude` and `extend-exclude` options along with tool specific `exclude` /// option (`lint.exclude`, `format.exclude`). /// 2. Check for global `include` and `extend-include` options. /// 3. Check if the language ID is Python, in which case the document is included. /// 4. If none of the above conditions are met, the document is excluded. fn is_document_excluded( path: &Path, resolver_settings: &FileResolverSettings, linter_settings: Option<&LinterSettings>, formatter_settings: Option<&FormatterSettings>, language_id: Option, ) -> bool { if let Some(exclusion) = match_any_exclusion( path, resolver_settings, linter_settings.map(|s| &*s.exclude), formatter_settings.map(|s| &*s.exclude), ) { tracing::debug!("Ignored path via `{}`: {}", exclusion, path.display()); return true; } if let Some(inclusion) = match_any_inclusion(path, resolver_settings) { tracing::debug!("Included path via `{}`: {}", inclusion, path.display()); false } else if let Some(LanguageId::Python) = language_id { tracing::debug!("Included path via Python language ID: {}", path.display()); false } else { tracing::debug!( "Ignored path as it's not in the inclusion set: {}", path.display() ); true } }