diff --git a/crates/ty/docs/configuration.md b/crates/ty/docs/configuration.md index b3ad865ee0..a2986eeb27 100644 --- a/crates/ty/docs/configuration.md +++ b/crates/ty/docs/configuration.md @@ -1,25 +1,6 @@ # Configuration -#### `respect-ignore-files` - -Whether to automatically exclude files that are ignored by `.ignore`, -`.gitignore`, `.git/info/exclude`, and global `gitignore` files. -Enabled by default. - -**Default value**: `true` - -**Type**: `bool` - -**Example usage** (`pyproject.toml`): - -```toml -[tool.ty] -respect-ignore-files = false -``` - ---- - #### `rules` Configures the enabled rules and their severity. @@ -162,6 +143,25 @@ typeshed = "/path/to/custom/typeshed" ## `src` +#### `respect-ignore-files` + +Whether to automatically exclude files that are ignored by `.ignore`, +`.gitignore`, `.git/info/exclude`, and global `gitignore` files. +Enabled by default. + +**Default value**: `true` + +**Type**: `bool` + +**Example usage** (`pyproject.toml`): + +```toml +[tool.ty.src] +respect-ignore-files = false +``` + +--- + #### `root` The root of the project, used for finding first-party modules. diff --git a/crates/ty/src/args.rs b/crates/ty/src/args.rs index d4d49e4565..9a48b310ec 100644 --- a/crates/ty/src/args.rs +++ b/crates/ty/src/args.rs @@ -4,7 +4,7 @@ use clap::error::ErrorKind; use clap::{ArgAction, ArgMatches, Error, Parser}; use ruff_db::system::SystemPathBuf; use ty_project::combine::Combine; -use ty_project::metadata::options::{EnvironmentOptions, Options, TerminalOptions}; +use ty_project::metadata::options::{EnvironmentOptions, Options, SrcOptions, TerminalOptions}; use ty_project::metadata::value::{RangedValue, RelativePathBuf, ValueSource}; use ty_python_semantic::lint; @@ -184,9 +184,11 @@ impl CheckCommand { .map(|output_format| RangedValue::cli(output_format.into())), error_on_warning: self.error_on_warning, }), + src: Some(SrcOptions { + respect_ignore_files, + ..SrcOptions::default() + }), rules, - respect_ignore_files, - ..Default::default() }; // Merge with options passed in via --config options.combine(self.config.into_options().unwrap_or_default()) diff --git a/crates/ty/tests/cli.rs b/crates/ty/tests/cli.rs index 6daa3d27d8..5a70030528 100644 --- a/crates/ty/tests/cli.rs +++ b/crates/ty/tests/cli.rs @@ -85,7 +85,7 @@ fn test_respect_ignore_files() -> anyhow::Result<()> { "); // Test that we can set to false via config file - case.write_file("ty.toml", "respect-ignore-files = false")?; + case.write_file("ty.toml", "src.respect-ignore-files = false")?; assert_cmd_snapshot!(case.command(), @r" success: false exit_code: 1 @@ -104,7 +104,7 @@ fn test_respect_ignore_files() -> anyhow::Result<()> { "); // Ensure CLI takes precedence - case.write_file("ty.toml", "respect-ignore-files = true")?; + case.write_file("ty.toml", "src.respect-ignore-files = true")?; assert_cmd_snapshot!(case.command().arg("--no-respect-ignore-files"), @r" success: false exit_code: 1 @@ -1534,7 +1534,7 @@ fn cli_config_args_later_overrides_earlier() -> anyhow::Result<()> { #[test] fn cli_config_args_invalid_option() -> anyhow::Result<()> { let case = TestCase::with_file("test.py", r"print(1)")?; - assert_cmd_snapshot!(case.command().arg("--config").arg("bad-option=true"), @r" + assert_cmd_snapshot!(case.command().arg("--config").arg("bad-option=true"), @r###" success: false exit_code: 2 ----- stdout ----- @@ -1544,13 +1544,13 @@ fn cli_config_args_invalid_option() -> anyhow::Result<()> { | 1 | bad-option=true | ^^^^^^^^^^ - unknown field `bad-option`, expected one of `environment`, `src`, `rules`, `terminal`, `respect-ignore-files` + unknown field `bad-option`, expected one of `environment`, `src`, `rules`, `terminal` Usage: ty For more information, try '--help'. - "); + "###); Ok(()) } diff --git a/crates/ty_project/src/metadata/options.rs b/crates/ty_project/src/metadata/options.rs index 46fd5eadd8..0581684faf 100644 --- a/crates/ty_project/src/metadata/options.rs +++ b/crates/ty_project/src/metadata/options.rs @@ -57,19 +57,6 @@ pub struct Options { #[serde(skip_serializing_if = "Option::is_none")] #[option_group] pub terminal: Option, - - /// Whether to automatically exclude files that are ignored by `.ignore`, - /// `.gitignore`, `.git/info/exclude`, and global `gitignore` files. - /// Enabled by default. - #[option( - default = r#"true"#, - value_type = r#"bool"#, - example = r#" - respect-ignore-files = false - "# - )] - #[serde(skip_serializing_if = "Option::is_none")] - pub respect_ignore_files: Option, } impl Options { @@ -216,7 +203,7 @@ impl Options { pub(crate) fn to_settings(&self, db: &dyn Db) -> (Settings, Vec) { let (rules, diagnostics) = self.to_rule_selection(db); - let mut settings = Settings::new(rules, self.respect_ignore_files); + let mut settings = Settings::new(rules, self.src.as_ref()); if let Some(terminal) = self.terminal.as_ref() { settings.set_terminal(TerminalSettings { @@ -421,6 +408,19 @@ pub struct SrcOptions { "# )] pub root: Option, + + /// Whether to automatically exclude files that are ignored by `.ignore`, + /// `.gitignore`, `.git/info/exclude`, and global `gitignore` files. + /// Enabled by default. + #[option( + default = r#"true"#, + value_type = r#"bool"#, + example = r#" + respect-ignore-files = false + "# + )] + #[serde(skip_serializing_if = "Option::is_none")] + pub respect_ignore_files: Option, } #[derive(Debug, Default, Clone, Eq, PartialEq, Combine, Serialize, Deserialize)] diff --git a/crates/ty_project/src/metadata/settings.rs b/crates/ty_project/src/metadata/settings.rs index b635c5470d..0a48fc559c 100644 --- a/crates/ty_project/src/metadata/settings.rs +++ b/crates/ty_project/src/metadata/settings.rs @@ -1,5 +1,6 @@ use std::sync::Arc; +use crate::metadata::options::SrcOptions; use ruff_db::diagnostic::DiagnosticFormat; use ty_python_semantic::lint::RuleSelection; @@ -26,11 +27,15 @@ pub struct Settings { } impl Settings { - pub fn new(rules: RuleSelection, respect_ignore_files: Option) -> Self { + pub fn new(rules: RuleSelection, src_options: Option<&SrcOptions>) -> Self { + let respect_ignore_files = src_options + .and_then(|src| src.respect_ignore_files) + .unwrap_or(true); + Self { rules: Arc::new(rules), terminal: TerminalSettings::default(), - respect_ignore_files: respect_ignore_files.unwrap_or(true), + respect_ignore_files, } } diff --git a/ty.schema.json b/ty.schema.json index 0aed4e9558..f4ae8d241b 100644 --- a/ty.schema.json +++ b/ty.schema.json @@ -14,13 +14,6 @@ } ] }, - "respect-ignore-files": { - "description": "Whether to automatically exclude files that are ignored by `.ignore`, `.gitignore`, `.git/info/exclude`, and global `gitignore` files. Enabled by default.", - "type": [ - "boolean", - "null" - ] - }, "rules": { "description": "Configures the enabled rules and their severity.\n\nSee [the rules documentation](https://ty.dev/rules) for a list of all available rules.\n\nValid severities are:\n\n* `ignore`: Disable the rule. * `warn`: Enable the rule and create a warning diagnostic. * `error`: Enable the rule and create an error diagnostic. ty will exit with a non-zero code if any error diagnostics are emitted.", "anyOf": [ @@ -858,6 +851,13 @@ "SrcOptions": { "type": "object", "properties": { + "respect-ignore-files": { + "description": "Whether to automatically exclude files that are ignored by `.ignore`, `.gitignore`, `.git/info/exclude`, and global `gitignore` files. Enabled by default.", + "type": [ + "boolean", + "null" + ] + }, "root": { "description": "The root of the project, used for finding first-party modules.\n\nIf left unspecified, ty will try to detect common project layouts and initialize `src.root` accordingly:\n\n* if a `./src` directory exists, include `.` and `./src` in the first party search path (src layout or flat) * if a `.//` directory exists, include `.` and `./` in the first party search path * otherwise, default to `.` (flat layout)\n\nBesides, if a `./tests` directory exists and is not a package (i.e. it does not contain an `__init__.py` file), it will also be included in the first party search path.", "type": [