diff --git a/.github/mypy-primer-ty.toml b/.github/mypy-primer-ty.toml new file mode 100644 index 0000000000..981f7d77c8 --- /dev/null +++ b/.github/mypy-primer-ty.toml @@ -0,0 +1,6 @@ +#:schema ../ty.schema.json +# Configuration overrides for the mypy primer run + +# Enable off-by-default rules. +[rules] +possibly-unresolved-reference = "warn" diff --git a/.github/workflows/mypy_primer.yaml b/.github/workflows/mypy_primer.yaml index a88e925734..4bb37f0fb8 100644 --- a/.github/workflows/mypy_primer.yaml +++ b/.github/workflows/mypy_primer.yaml @@ -50,6 +50,10 @@ jobs: run: | cd ruff + echo "Enabling mypy primer specific configuration overloads (see .github/mypy-primer-ty.toml)" + mkdir -p ~/.config/ty + cp .github/mypy-primer-ty.toml ~/.config/ty/ty.toml + PRIMER_SELECTOR="$(paste -s -d'|' crates/ty_python_semantic/resources/primer/good.txt)" echo "new commit" diff --git a/crates/ty/docs/rules.md b/crates/ty/docs/rules.md index 7dba79499c..7fb0c70c67 100644 --- a/crates/ty/docs/rules.md +++ b/crates/ty/docs/rules.md @@ -1394,33 +1394,6 @@ or `ImportError` at runtime. * [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L822) -## `possibly-unresolved-reference` - -**Default level**: warn - -
-detects references to possibly undefined names - -### What it does -Checks for references to names that are possibly not defined. - -### Why is this bad? -Using an undefined variable will raise a `NameError` at runtime. - -### Example - -```python -for i in range(0): - x = i - -print(x) # NameError: name 'x' is not defined -``` - -### Links -* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20possibly-unresolved-reference) -* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L836) -
- ## `redundant-cast` **Default level**: warn @@ -1552,3 +1525,30 @@ a = 20 / 2 * [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Fsuppression.rs#L15) +## `possibly-unresolved-reference` + +**Default level**: ignore + +
+detects references to possibly undefined names + +### What it does +Checks for references to names that are possibly not defined. + +### Why is this bad? +Using an undefined variable will raise a `NameError` at runtime. + +### Example + +```python +for i in range(0): + x = i + +print(x) # NameError: name 'x' is not defined +``` + +### Links +* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20possibly-unresolved-reference) +* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L836) +
+ diff --git a/crates/ty/tests/cli.rs b/crates/ty/tests/cli.rs index 7a2276de0d..be19281a1e 100644 --- a/crates/ty/tests/cli.rs +++ b/crates/ty/tests/cli.rs @@ -369,12 +369,12 @@ fn configuration_rule_severity() -> anyhow::Result<()> { for a in range(0, int(y)): x = a - print(x) # possibly-unresolved-reference + prin(x) # unresolved-reference "#, )?; - // Assert that there's a possibly unresolved reference diagnostic - // and that division-by-zero has a severity of error by default. + // Assert that there's an `unresolved-reference` diagnostic (error) + // and a `division-by-zero` diagnostic (error). assert_cmd_snapshot!(case.command(), @r" success: false exit_code: 1 @@ -389,15 +389,15 @@ fn configuration_rule_severity() -> anyhow::Result<()> { | info: `lint:division-by-zero` is enabled by default - warning: lint:possibly-unresolved-reference: Name `x` used when possibly not defined - --> test.py:7:7 + warning: lint:unresolved-reference: Name `prin` used when not defined + --> test.py:7:1 | 5 | x = a 6 | - 7 | print(x) # possibly-unresolved-reference - | ^ + 7 | prin(x) # unresolved-reference + | ^^^^ | - info: `lint:possibly-unresolved-reference` is enabled by default + info: `lint:unresolved-reference` is enabled by default Found 2 diagnostics @@ -409,7 +409,7 @@ fn configuration_rule_severity() -> anyhow::Result<()> { r#" [tool.ty.rules] division-by-zero = "warn" # demote to warn - possibly-unresolved-reference = "ignore" + unresolved-reference = "ignore" "#, )?; @@ -448,12 +448,12 @@ fn cli_rule_severity() -> anyhow::Result<()> { for a in range(0, int(y)): x = a - print(x) # possibly-unresolved-reference + prin(x) # unresolved-reference "#, )?; - // Assert that there's a possibly unresolved reference diagnostic - // and that division-by-zero has a severity of error by default. + // Assert that there's an `unresolved-reference` diagnostic (error), + // a `division-by-zero` (error) and a unresolved-import (error) diagnostic by default. assert_cmd_snapshot!(case.command(), @r" success: false exit_code: 1 @@ -480,15 +480,15 @@ fn cli_rule_severity() -> anyhow::Result<()> { | info: `lint:division-by-zero` is enabled by default - warning: lint:possibly-unresolved-reference: Name `x` used when possibly not defined - --> test.py:9:7 + warning: lint:unresolved-reference: Name `prin` used when not defined + --> test.py:9:1 | 7 | x = a 8 | - 9 | print(x) # possibly-unresolved-reference - | ^ + 9 | prin(x) # unresolved-reference + | ^^^^ | - info: `lint:possibly-unresolved-reference` is enabled by default + info: `lint:unresolved-reference` is enabled by default Found 3 diagnostics @@ -499,7 +499,7 @@ fn cli_rule_severity() -> anyhow::Result<()> { case .command() .arg("--ignore") - .arg("possibly-unresolved-reference") + .arg("unresolved-reference") .arg("--warn") .arg("division-by-zero") .arg("--warn") @@ -551,12 +551,12 @@ fn cli_rule_severity_precedence() -> anyhow::Result<()> { for a in range(0, int(y)): x = a - print(x) # possibly-unresolved-reference + prin(x) # unresolved-reference "#, )?; - // Assert that there's a possibly unresolved reference diagnostic - // and that division-by-zero has a severity of error by default. + // Assert that there's a `unresolved-reference` diagnostic (error) + // and a `division-by-zero` (error) by default. assert_cmd_snapshot!(case.command(), @r" success: false exit_code: 1 @@ -571,15 +571,15 @@ fn cli_rule_severity_precedence() -> anyhow::Result<()> { | info: `lint:division-by-zero` is enabled by default - warning: lint:possibly-unresolved-reference: Name `x` used when possibly not defined - --> test.py:7:7 + warning: lint:unresolved-reference: Name `prin` used when not defined + --> test.py:7:1 | 5 | x = a 6 | - 7 | print(x) # possibly-unresolved-reference - | ^ + 7 | prin(x) # unresolved-reference + | ^^^^ | - info: `lint:possibly-unresolved-reference` is enabled by default + info: `lint:unresolved-reference` is enabled by default Found 2 diagnostics @@ -590,12 +590,12 @@ fn cli_rule_severity_precedence() -> anyhow::Result<()> { case .command() .arg("--error") - .arg("possibly-unresolved-reference") + .arg("unresolved-reference") .arg("--warn") .arg("division-by-zero") // Override the error severity with warning .arg("--ignore") - .arg("possibly-unresolved-reference"), + .arg("unresolved-reference"), @r" success: true exit_code: 0 @@ -951,7 +951,7 @@ fn user_configuration() -> anyhow::Result<()> { for a in range(0, int(y)): x = a - print(x) + prin(x) "#, ), ])?; @@ -979,15 +979,15 @@ fn user_configuration() -> anyhow::Result<()> { | info: `lint:division-by-zero` was selected in the configuration file - warning: lint:possibly-unresolved-reference: Name `x` used when possibly not defined - --> main.py:7:7 + warning: lint:unresolved-reference: Name `prin` used when not defined + --> main.py:7:1 | 5 | x = a 6 | - 7 | print(x) - | ^ + 7 | prin(x) + | ^^^^ | - info: `lint:possibly-unresolved-reference` is enabled by default + info: `lint:unresolved-reference` is enabled by default Found 2 diagnostics @@ -995,7 +995,7 @@ fn user_configuration() -> anyhow::Result<()> { " ); - // The user-level configuration promotes `possibly-unresolved-reference` to an error. + // The user-level configuration sets the severity for `unresolved-reference` to error. // Changing the level for `division-by-zero` has no effect, because the project-level configuration // has higher precedence. case.write_file( @@ -1003,7 +1003,7 @@ fn user_configuration() -> anyhow::Result<()> { r#" [rules] division-by-zero = "error" - possibly-unresolved-reference = "error" + unresolved-reference = "error" "#, )?; @@ -1023,15 +1023,15 @@ fn user_configuration() -> anyhow::Result<()> { | info: `lint:division-by-zero` was selected in the configuration file - error: lint:possibly-unresolved-reference: Name `x` used when possibly not defined - --> main.py:7:7 + error: lint:unresolved-reference: Name `prin` used when not defined + --> main.py:7:1 | 5 | x = a 6 | - 7 | print(x) - | ^ + 7 | prin(x) + | ^^^^ | - info: `lint:possibly-unresolved-reference` was selected in the configuration file + info: `lint:unresolved-reference` was selected in the configuration file Found 2 diagnostics diff --git a/crates/ty_python_semantic/resources/mdtest/snapshots/for.md_-_For_loops_-_With_non-callable_iterator.snap b/crates/ty_python_semantic/resources/mdtest/snapshots/for.md_-_For_loops_-_With_non-callable_iterator.snap index dad3e73977..871733f5a4 100644 --- a/crates/ty_python_semantic/resources/mdtest/snapshots/for.md_-_For_loops_-_With_non-callable_iterator.snap +++ b/crates/ty_python_semantic/resources/mdtest/snapshots/for.md_-_For_loops_-_With_non-callable_iterator.snap @@ -59,7 +59,7 @@ info: revealed-type: Revealed type ``` ``` -warning: lint:possibly-unresolved-reference: Name `x` used when possibly not defined +info: lint:possibly-unresolved-reference: Name `x` used when possibly not defined --> src/mdtest_snippet.py:16:17 | 14 | # revealed: Unknown diff --git a/crates/ty_python_semantic/src/lint.rs b/crates/ty_python_semantic/src/lint.rs index 6658129f47..2acaa24b0f 100644 --- a/crates/ty_python_semantic/src/lint.rs +++ b/crates/ty_python_semantic/src/lint.rs @@ -475,12 +475,26 @@ impl RuleSelection { /// Creates a new rule selection from all known lints in the registry that are enabled /// according to their default severity. pub fn from_registry(registry: &LintRegistry) -> Self { + Self::from_registry_with_default(registry, None) + } + + /// Creates a new rule selection from all known lints in the registry, including lints that are default by default. + /// Lints that are disabled by default use the `default_severity`. + pub fn all(registry: &LintRegistry, default_severity: Severity) -> Self { + Self::from_registry_with_default(registry, Some(default_severity)) + } + + fn from_registry_with_default( + registry: &LintRegistry, + default_severity: Option, + ) -> Self { let lints = registry .lints() .iter() .filter_map(|lint| { Severity::try_from(lint.default_level()) .ok() + .or(default_severity) .map(|severity| (*lint, (severity, LintSource::Default))) }) .collect(); diff --git a/crates/ty_python_semantic/src/types/diagnostic.rs b/crates/ty_python_semantic/src/types/diagnostic.rs index 17a1cadd51..6adcc7d902 100644 --- a/crates/ty_python_semantic/src/types/diagnostic.rs +++ b/crates/ty_python_semantic/src/types/diagnostic.rs @@ -851,7 +851,7 @@ declare_lint! { pub(crate) static POSSIBLY_UNRESOLVED_REFERENCE = { summary: "detects references to possibly undefined names", status: LintStatus::preview("1.0.0"), - default_level: Level::Warn, + default_level: Level::Ignore, } } diff --git a/crates/ty_test/src/db.rs b/crates/ty_test/src/db.rs index 4758d12b39..384e16a8a2 100644 --- a/crates/ty_test/src/db.rs +++ b/crates/ty_test/src/db.rs @@ -1,4 +1,5 @@ use camino::{Utf8Component, Utf8PathBuf}; +use ruff_db::diagnostic::Severity; use ruff_db::files::{File, Files}; use ruff_db::system::{ CaseSensitivity, DbWithWritableSystem, InMemorySystem, OsSystem, System, SystemPath, @@ -25,7 +26,7 @@ pub(crate) struct Db { impl Db { pub(crate) fn setup() -> Self { - let rule_selection = RuleSelection::from_registry(default_lint_registry()); + let rule_selection = RuleSelection::all(default_lint_registry(), Severity::Info); Self { system: MdtestSystem::in_memory(), diff --git a/ty.schema.json b/ty.schema.json index 8750c208ed..e5b495438a 100644 --- a/ty.schema.json +++ b/ty.schema.json @@ -653,7 +653,7 @@ "possibly-unresolved-reference": { "title": "detects references to possibly undefined names", "description": "## What it does\nChecks for references to names that are possibly not defined.\n\n## Why is this bad?\nUsing an undefined variable will raise a `NameError` at runtime.\n\n## Example\n\n```python\nfor i in range(0):\n x = i\n\nprint(x) # NameError: name 'x' is not defined\n```", - "default": "warn", + "default": "ignore", "oneOf": [ { "$ref": "#/definitions/Level"