mirror of
https://github.com/astral-sh/ruff.git
synced 2025-08-04 02:38:25 +00:00

Some checks failed
CI / Determine changes (push) Has been cancelled
CI / cargo fmt (push) Has been cancelled
CI / cargo build (release) (push) Has been cancelled
CI / python package (push) Has been cancelled
CI / pre-commit (push) Has been cancelled
CI / mkdocs (push) Has been cancelled
[ty Playground] Release / publish (push) Has been cancelled
CI / cargo clippy (push) Has been cancelled
CI / cargo test (linux) (push) Has been cancelled
CI / cargo test (linux, release) (push) Has been cancelled
CI / cargo test (windows) (push) Has been cancelled
CI / cargo test (wasm) (push) Has been cancelled
CI / cargo build (msrv) (push) Has been cancelled
CI / cargo fuzz build (push) Has been cancelled
CI / fuzz parser (push) Has been cancelled
CI / test scripts (push) Has been cancelled
CI / ecosystem (push) Has been cancelled
CI / Fuzz for new ty panics (push) Has been cancelled
CI / cargo shear (push) Has been cancelled
CI / formatter instabilities and black similarity (push) Has been cancelled
CI / test ruff-lsp (push) Has been cancelled
CI / check playground (push) Has been cancelled
CI / benchmarks-instrumented (push) Has been cancelled
CI / benchmarks-walltime (push) Has been cancelled
Co-authored-by: Nathaniel Roman <nroman@openai.com> Co-authored-by: Micha Reiser <micha@reiser.io>
954 lines
27 KiB
Rust
954 lines
27 KiB
Rust
use insta_cmd::assert_cmd_snapshot;
|
|
|
|
use crate::CliTest;
|
|
|
|
/// Test exclude CLI argument functionality
|
|
#[test]
|
|
fn exclude_argument() -> anyhow::Result<()> {
|
|
let case = CliTest::with_files([
|
|
(
|
|
"src/main.py",
|
|
r#"
|
|
print(undefined_var) # error: unresolved-reference
|
|
"#,
|
|
),
|
|
(
|
|
"tests/test_main.py",
|
|
r#"
|
|
print(another_undefined_var) # error: unresolved-reference
|
|
"#,
|
|
),
|
|
(
|
|
"temp_file.py",
|
|
r#"
|
|
print(temp_undefined_var) # error: unresolved-reference
|
|
"#,
|
|
),
|
|
])?;
|
|
|
|
// Test that exclude argument is recognized and works
|
|
assert_cmd_snapshot!(case.command().arg("--exclude").arg("tests/"), @r"
|
|
success: false
|
|
exit_code: 1
|
|
----- stdout -----
|
|
error[unresolved-reference]: Name `undefined_var` used when not defined
|
|
--> src/main.py:2:7
|
|
|
|
|
2 | print(undefined_var) # error: unresolved-reference
|
|
| ^^^^^^^^^^^^^
|
|
|
|
|
info: rule `unresolved-reference` is enabled by default
|
|
|
|
error[unresolved-reference]: Name `temp_undefined_var` used when not defined
|
|
--> temp_file.py:2:7
|
|
|
|
|
2 | print(temp_undefined_var) # error: unresolved-reference
|
|
| ^^^^^^^^^^^^^^^^^^
|
|
|
|
|
info: rule `unresolved-reference` is enabled by default
|
|
|
|
Found 2 diagnostics
|
|
|
|
----- stderr -----
|
|
WARN ty is pre-release software and not ready for production use. Expect to encounter bugs, missing features, and fatal errors.
|
|
");
|
|
|
|
// Test multiple exclude patterns
|
|
assert_cmd_snapshot!(case.command().arg("--exclude").arg("tests/").arg("--exclude").arg("temp_*.py"), @r"
|
|
success: false
|
|
exit_code: 1
|
|
----- stdout -----
|
|
error[unresolved-reference]: Name `undefined_var` used when not defined
|
|
--> src/main.py:2:7
|
|
|
|
|
2 | print(undefined_var) # error: unresolved-reference
|
|
| ^^^^^^^^^^^^^
|
|
|
|
|
info: rule `unresolved-reference` is enabled by default
|
|
|
|
Found 1 diagnostic
|
|
|
|
----- stderr -----
|
|
WARN ty is pre-release software and not ready for production use. Expect to encounter bugs, missing features, and fatal errors.
|
|
");
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Test configuration file include functionality
|
|
#[test]
|
|
fn configuration_include() -> anyhow::Result<()> {
|
|
let case = CliTest::with_files([
|
|
(
|
|
"src/main.py",
|
|
r#"
|
|
print(undefined_var) # error: unresolved-reference
|
|
"#,
|
|
),
|
|
(
|
|
"tests/test_main.py",
|
|
r#"
|
|
print(another_undefined_var) # error: unresolved-reference
|
|
"#,
|
|
),
|
|
(
|
|
"other.py",
|
|
r#"
|
|
print(other_undefined_var) # error: unresolved-reference
|
|
"#,
|
|
),
|
|
])?;
|
|
|
|
// Test include via configuration - should only check included files
|
|
case.write_file(
|
|
"ty.toml",
|
|
r#"
|
|
[src]
|
|
include = ["src"]
|
|
"#,
|
|
)?;
|
|
|
|
assert_cmd_snapshot!(case.command(), @r"
|
|
success: false
|
|
exit_code: 1
|
|
----- stdout -----
|
|
error[unresolved-reference]: Name `undefined_var` used when not defined
|
|
--> src/main.py:2:7
|
|
|
|
|
2 | print(undefined_var) # error: unresolved-reference
|
|
| ^^^^^^^^^^^^^
|
|
|
|
|
info: rule `unresolved-reference` is enabled by default
|
|
|
|
Found 1 diagnostic
|
|
|
|
----- stderr -----
|
|
WARN ty is pre-release software and not ready for production use. Expect to encounter bugs, missing features, and fatal errors.
|
|
");
|
|
|
|
// Test multiple include patterns via configuration
|
|
case.write_file(
|
|
"ty.toml",
|
|
r#"
|
|
[src]
|
|
include = ["src", "other.py"]
|
|
"#,
|
|
)?;
|
|
|
|
assert_cmd_snapshot!(case.command(), @r"
|
|
success: false
|
|
exit_code: 1
|
|
----- stdout -----
|
|
error[unresolved-reference]: Name `other_undefined_var` used when not defined
|
|
--> other.py:2:7
|
|
|
|
|
2 | print(other_undefined_var) # error: unresolved-reference
|
|
| ^^^^^^^^^^^^^^^^^^^
|
|
|
|
|
info: rule `unresolved-reference` is enabled by default
|
|
|
|
error[unresolved-reference]: Name `undefined_var` used when not defined
|
|
--> src/main.py:2:7
|
|
|
|
|
2 | print(undefined_var) # error: unresolved-reference
|
|
| ^^^^^^^^^^^^^
|
|
|
|
|
info: rule `unresolved-reference` is enabled by default
|
|
|
|
Found 2 diagnostics
|
|
|
|
----- stderr -----
|
|
WARN ty is pre-release software and not ready for production use. Expect to encounter bugs, missing features, and fatal errors.
|
|
");
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Test configuration file exclude functionality
|
|
#[test]
|
|
fn configuration_exclude() -> anyhow::Result<()> {
|
|
let case = CliTest::with_files([
|
|
(
|
|
"src/main.py",
|
|
r#"
|
|
print(undefined_var) # error: unresolved-reference
|
|
"#,
|
|
),
|
|
(
|
|
"tests/test_main.py",
|
|
r#"
|
|
print(another_undefined_var) # error: unresolved-reference
|
|
"#,
|
|
),
|
|
(
|
|
"temp_file.py",
|
|
r#"
|
|
print(temp_undefined_var) # error: unresolved-reference
|
|
"#,
|
|
),
|
|
])?;
|
|
|
|
// Test exclude via configuration
|
|
case.write_file(
|
|
"ty.toml",
|
|
r#"
|
|
[src]
|
|
exclude = ["tests/"]
|
|
"#,
|
|
)?;
|
|
|
|
assert_cmd_snapshot!(case.command(), @r"
|
|
success: false
|
|
exit_code: 1
|
|
----- stdout -----
|
|
error[unresolved-reference]: Name `undefined_var` used when not defined
|
|
--> src/main.py:2:7
|
|
|
|
|
2 | print(undefined_var) # error: unresolved-reference
|
|
| ^^^^^^^^^^^^^
|
|
|
|
|
info: rule `unresolved-reference` is enabled by default
|
|
|
|
error[unresolved-reference]: Name `temp_undefined_var` used when not defined
|
|
--> temp_file.py:2:7
|
|
|
|
|
2 | print(temp_undefined_var) # error: unresolved-reference
|
|
| ^^^^^^^^^^^^^^^^^^
|
|
|
|
|
info: rule `unresolved-reference` is enabled by default
|
|
|
|
Found 2 diagnostics
|
|
|
|
----- stderr -----
|
|
WARN ty is pre-release software and not ready for production use. Expect to encounter bugs, missing features, and fatal errors.
|
|
");
|
|
|
|
// Test multiple exclude patterns via configuration
|
|
case.write_file(
|
|
"ty.toml",
|
|
r#"
|
|
[src]
|
|
exclude = ["tests/", "temp_*.py"]
|
|
"#,
|
|
)?;
|
|
|
|
assert_cmd_snapshot!(case.command(), @r"
|
|
success: false
|
|
exit_code: 1
|
|
----- stdout -----
|
|
error[unresolved-reference]: Name `undefined_var` used when not defined
|
|
--> src/main.py:2:7
|
|
|
|
|
2 | print(undefined_var) # error: unresolved-reference
|
|
| ^^^^^^^^^^^^^
|
|
|
|
|
info: rule `unresolved-reference` is enabled by default
|
|
|
|
Found 1 diagnostic
|
|
|
|
----- stderr -----
|
|
WARN ty is pre-release software and not ready for production use. Expect to encounter bugs, missing features, and fatal errors.
|
|
");
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Test that exclude takes precedence over include in configuration
|
|
#[test]
|
|
fn exclude_precedence_over_include() -> anyhow::Result<()> {
|
|
let case = CliTest::with_files([
|
|
(
|
|
"src/main.py",
|
|
r#"
|
|
print(undefined_var) # error: unresolved-reference
|
|
"#,
|
|
),
|
|
(
|
|
"src/test_helper.py",
|
|
r#"
|
|
print(helper_undefined_var) # error: unresolved-reference
|
|
"#,
|
|
),
|
|
(
|
|
"other.py",
|
|
r#"
|
|
print(other_undefined_var) # error: unresolved-reference
|
|
"#,
|
|
),
|
|
])?;
|
|
|
|
// Include all src files but exclude test files - exclude should win
|
|
case.write_file(
|
|
"ty.toml",
|
|
r#"
|
|
[src]
|
|
include = ["src"]
|
|
exclude = ["**/test_*.py"]
|
|
"#,
|
|
)?;
|
|
|
|
assert_cmd_snapshot!(case.command(), @r"
|
|
success: false
|
|
exit_code: 1
|
|
----- stdout -----
|
|
error[unresolved-reference]: Name `undefined_var` used when not defined
|
|
--> src/main.py:2:7
|
|
|
|
|
2 | print(undefined_var) # error: unresolved-reference
|
|
| ^^^^^^^^^^^^^
|
|
|
|
|
info: rule `unresolved-reference` is enabled by default
|
|
|
|
Found 1 diagnostic
|
|
|
|
----- stderr -----
|
|
WARN ty is pre-release software and not ready for production use. Expect to encounter bugs, missing features, and fatal errors.
|
|
");
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Test that CLI exclude overrides configuration include
|
|
#[test]
|
|
fn exclude_argument_precedence_include_argument() -> anyhow::Result<()> {
|
|
let case = CliTest::with_files([
|
|
(
|
|
"src/main.py",
|
|
r#"
|
|
print(undefined_var) # error: unresolved-reference
|
|
"#,
|
|
),
|
|
(
|
|
"tests/test_main.py",
|
|
r#"
|
|
print(another_undefined_var) # error: unresolved-reference
|
|
"#,
|
|
),
|
|
(
|
|
"other.py",
|
|
r#"
|
|
print(other_undefined_var) # error: unresolved-reference
|
|
"#,
|
|
),
|
|
])?;
|
|
|
|
// Configuration includes all files, but CLI excludes tests
|
|
case.write_file(
|
|
"ty.toml",
|
|
r#"
|
|
[src]
|
|
include = ["src/", "tests/"]
|
|
"#,
|
|
)?;
|
|
|
|
assert_cmd_snapshot!(case.command().arg("--exclude").arg("tests/"), @r###"
|
|
success: false
|
|
exit_code: 1
|
|
----- stdout -----
|
|
error[unresolved-reference]: Name `undefined_var` used when not defined
|
|
--> src/main.py:2:7
|
|
|
|
|
2 | print(undefined_var) # error: unresolved-reference
|
|
| ^^^^^^^^^^^^^
|
|
|
|
|
info: rule `unresolved-reference` is enabled by default
|
|
|
|
Found 1 diagnostic
|
|
|
|
----- stderr -----
|
|
WARN ty is pre-release software and not ready for production use. Expect to encounter bugs, missing features, and fatal errors.
|
|
"###);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Test that default excludes can be removed using negated patterns
|
|
#[test]
|
|
fn remove_default_exclude() -> anyhow::Result<()> {
|
|
let case = CliTest::with_files([
|
|
(
|
|
"src/main.py",
|
|
r#"
|
|
print(undefined_var) # error: unresolved-reference
|
|
"#,
|
|
),
|
|
(
|
|
"dist/generated.py",
|
|
r#"
|
|
print(another_undefined_var) # error: unresolved-reference
|
|
"#,
|
|
),
|
|
])?;
|
|
|
|
// By default, 'dist' directory should be excluded (see default excludes)
|
|
assert_cmd_snapshot!(case.command(), @r"
|
|
success: false
|
|
exit_code: 1
|
|
----- stdout -----
|
|
error[unresolved-reference]: Name `undefined_var` used when not defined
|
|
--> src/main.py:2:7
|
|
|
|
|
2 | print(undefined_var) # error: unresolved-reference
|
|
| ^^^^^^^^^^^^^
|
|
|
|
|
info: rule `unresolved-reference` is enabled by default
|
|
|
|
Found 1 diagnostic
|
|
|
|
----- stderr -----
|
|
WARN ty is pre-release software and not ready for production use. Expect to encounter bugs, missing features, and fatal errors.
|
|
");
|
|
|
|
// Now override the default exclude by using a negated pattern to re-include 'dist'
|
|
case.write_file(
|
|
"ty.toml",
|
|
r#"
|
|
[src]
|
|
exclude = ["!**/dist/"]
|
|
"#,
|
|
)?;
|
|
|
|
assert_cmd_snapshot!(case.command(), @r"
|
|
success: false
|
|
exit_code: 1
|
|
----- stdout -----
|
|
error[unresolved-reference]: Name `another_undefined_var` used when not defined
|
|
--> dist/generated.py:2:7
|
|
|
|
|
2 | print(another_undefined_var) # error: unresolved-reference
|
|
| ^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
|
info: rule `unresolved-reference` is enabled by default
|
|
|
|
error[unresolved-reference]: Name `undefined_var` used when not defined
|
|
--> src/main.py:2:7
|
|
|
|
|
2 | print(undefined_var) # error: unresolved-reference
|
|
| ^^^^^^^^^^^^^
|
|
|
|
|
info: rule `unresolved-reference` is enabled by default
|
|
|
|
Found 2 diagnostics
|
|
|
|
----- stderr -----
|
|
WARN ty is pre-release software and not ready for production use. Expect to encounter bugs, missing features, and fatal errors.
|
|
");
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Test that configuration excludes can be removed via CLI negation
|
|
#[test]
|
|
fn cli_removes_config_exclude() -> anyhow::Result<()> {
|
|
let case = CliTest::with_files([
|
|
(
|
|
"src/main.py",
|
|
r#"
|
|
print(undefined_var) # error: unresolved-reference
|
|
"#,
|
|
),
|
|
(
|
|
"build/output.py",
|
|
r#"
|
|
print(build_undefined_var) # error: unresolved-reference
|
|
"#,
|
|
),
|
|
])?;
|
|
|
|
// Configuration excludes the build directory
|
|
case.write_file(
|
|
"ty.toml",
|
|
r#"
|
|
[src]
|
|
exclude = ["build/"]
|
|
"#,
|
|
)?;
|
|
|
|
// Verify that build/ is excluded by configuration
|
|
assert_cmd_snapshot!(case.command(), @r"
|
|
success: false
|
|
exit_code: 1
|
|
----- stdout -----
|
|
error[unresolved-reference]: Name `undefined_var` used when not defined
|
|
--> src/main.py:2:7
|
|
|
|
|
2 | print(undefined_var) # error: unresolved-reference
|
|
| ^^^^^^^^^^^^^
|
|
|
|
|
info: rule `unresolved-reference` is enabled by default
|
|
|
|
Found 1 diagnostic
|
|
|
|
----- stderr -----
|
|
WARN ty is pre-release software and not ready for production use. Expect to encounter bugs, missing features, and fatal errors.
|
|
");
|
|
|
|
// Now remove the configuration exclude via CLI negation
|
|
assert_cmd_snapshot!(case.command().arg("--exclude").arg("!build/"), @r"
|
|
success: false
|
|
exit_code: 1
|
|
----- stdout -----
|
|
error[unresolved-reference]: Name `build_undefined_var` used when not defined
|
|
--> build/output.py:2:7
|
|
|
|
|
2 | print(build_undefined_var) # error: unresolved-reference
|
|
| ^^^^^^^^^^^^^^^^^^^
|
|
|
|
|
info: rule `unresolved-reference` is enabled by default
|
|
|
|
error[unresolved-reference]: Name `undefined_var` used when not defined
|
|
--> src/main.py:2:7
|
|
|
|
|
2 | print(undefined_var) # error: unresolved-reference
|
|
| ^^^^^^^^^^^^^
|
|
|
|
|
info: rule `unresolved-reference` is enabled by default
|
|
|
|
Found 2 diagnostics
|
|
|
|
----- stderr -----
|
|
WARN ty is pre-release software and not ready for production use. Expect to encounter bugs, missing features, and fatal errors.
|
|
");
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Test behavior when explicitly checking a path that matches an exclude pattern
|
|
#[test]
|
|
fn explicit_path_overrides_exclude() -> anyhow::Result<()> {
|
|
let case = CliTest::with_files([
|
|
(
|
|
"src/main.py",
|
|
r#"
|
|
print(undefined_var) # error: unresolved-reference
|
|
"#,
|
|
),
|
|
(
|
|
"tests/generated.py",
|
|
r#"
|
|
print(dist_undefined_var) # error: unresolved-reference
|
|
"#,
|
|
),
|
|
(
|
|
"dist/other.py",
|
|
r#"
|
|
print(other_undefined_var) # error: unresolved-reference
|
|
"#,
|
|
),
|
|
(
|
|
"ty.toml",
|
|
r#"
|
|
[src]
|
|
exclude = ["tests/generated.py"]
|
|
"#,
|
|
),
|
|
])?;
|
|
|
|
// dist is excluded by default and `tests/generated` is excluded in the project, so only src/main.py should be checked
|
|
assert_cmd_snapshot!(case.command(), @r"
|
|
success: false
|
|
exit_code: 1
|
|
----- stdout -----
|
|
error[unresolved-reference]: Name `undefined_var` used when not defined
|
|
--> src/main.py:2:7
|
|
|
|
|
2 | print(undefined_var) # error: unresolved-reference
|
|
| ^^^^^^^^^^^^^
|
|
|
|
|
info: rule `unresolved-reference` is enabled by default
|
|
|
|
Found 1 diagnostic
|
|
|
|
----- stderr -----
|
|
WARN ty is pre-release software and not ready for production use. Expect to encounter bugs, missing features, and fatal errors.
|
|
");
|
|
|
|
// Explicitly checking a file in an excluded directory should still check that file
|
|
assert_cmd_snapshot!(case.command().arg("tests/generated.py"), @r"
|
|
success: false
|
|
exit_code: 1
|
|
----- stdout -----
|
|
error[unresolved-reference]: Name `dist_undefined_var` used when not defined
|
|
--> tests/generated.py:2:7
|
|
|
|
|
2 | print(dist_undefined_var) # error: unresolved-reference
|
|
| ^^^^^^^^^^^^^^^^^^
|
|
|
|
|
info: rule `unresolved-reference` is enabled by default
|
|
|
|
Found 1 diagnostic
|
|
|
|
----- stderr -----
|
|
WARN ty is pre-release software and not ready for production use. Expect to encounter bugs, missing features, and fatal errors.
|
|
");
|
|
|
|
// Explicitly checking the entire excluded directory should check all files in it
|
|
assert_cmd_snapshot!(case.command().arg("dist/"), @r"
|
|
success: false
|
|
exit_code: 1
|
|
----- stdout -----
|
|
error[unresolved-reference]: Name `other_undefined_var` used when not defined
|
|
--> dist/other.py:2:7
|
|
|
|
|
2 | print(other_undefined_var) # error: unresolved-reference
|
|
| ^^^^^^^^^^^^^^^^^^^
|
|
|
|
|
info: rule `unresolved-reference` is enabled by default
|
|
|
|
Found 1 diagnostic
|
|
|
|
----- stderr -----
|
|
WARN ty is pre-release software and not ready for production use. Expect to encounter bugs, missing features, and fatal errors.
|
|
");
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
fn invalid_include_pattern() -> anyhow::Result<()> {
|
|
let case = CliTest::with_files([
|
|
(
|
|
"src/main.py",
|
|
r#"
|
|
print(undefined_var) # error: unresolved-reference
|
|
"#,
|
|
),
|
|
(
|
|
"ty.toml",
|
|
r#"
|
|
[src]
|
|
include = [
|
|
"src/**test/"
|
|
]
|
|
"#,
|
|
),
|
|
])?;
|
|
|
|
// By default, dist/ is excluded, so only src/main.py should be checked
|
|
assert_cmd_snapshot!(case.command(), @r#"
|
|
success: false
|
|
exit_code: 2
|
|
----- stdout -----
|
|
|
|
----- stderr -----
|
|
WARN ty is pre-release software and not ready for production use. Expect to encounter bugs, missing features, and fatal errors.
|
|
ty failed
|
|
Cause: error[invalid-glob]: Invalid include pattern
|
|
--> ty.toml:4:5
|
|
|
|
|
2 | [src]
|
|
3 | include = [
|
|
4 | "src/**test/"
|
|
| ^^^^^^^^^^^^^ Too many stars at position 5
|
|
5 | ]
|
|
|
|
|
"#);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
fn invalid_include_pattern_concise_output() -> anyhow::Result<()> {
|
|
let case = CliTest::with_files([
|
|
(
|
|
"src/main.py",
|
|
r#"
|
|
print(undefined_var) # error: unresolved-reference
|
|
"#,
|
|
),
|
|
(
|
|
"ty.toml",
|
|
r#"
|
|
[src]
|
|
include = [
|
|
"src/**test/"
|
|
]
|
|
"#,
|
|
),
|
|
])?;
|
|
|
|
// By default, dist/ is excluded, so only src/main.py should be checked
|
|
assert_cmd_snapshot!(case.command().arg("--output-format").arg("concise"), @r"
|
|
success: false
|
|
exit_code: 2
|
|
----- stdout -----
|
|
|
|
----- stderr -----
|
|
WARN ty is pre-release software and not ready for production use. Expect to encounter bugs, missing features, and fatal errors.
|
|
ty failed
|
|
Cause: ty.toml:4:5: error[invalid-glob] Invalid include pattern: Too many stars at position 5
|
|
");
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
fn invalid_exclude_pattern() -> anyhow::Result<()> {
|
|
let case = CliTest::with_files([
|
|
(
|
|
"src/main.py",
|
|
r#"
|
|
print(undefined_var) # error: unresolved-reference
|
|
"#,
|
|
),
|
|
(
|
|
"ty.toml",
|
|
r#"
|
|
[src]
|
|
exclude = [
|
|
"../src"
|
|
]
|
|
"#,
|
|
),
|
|
])?;
|
|
|
|
// By default, dist/ is excluded, so only src/main.py should be checked
|
|
assert_cmd_snapshot!(case.command(), @r#"
|
|
success: false
|
|
exit_code: 2
|
|
----- stdout -----
|
|
|
|
----- stderr -----
|
|
WARN ty is pre-release software and not ready for production use. Expect to encounter bugs, missing features, and fatal errors.
|
|
ty failed
|
|
Cause: error[invalid-glob]: Invalid exclude pattern
|
|
--> ty.toml:4:5
|
|
|
|
|
2 | [src]
|
|
3 | exclude = [
|
|
4 | "../src"
|
|
| ^^^^^^^^ The parent directory operator (`..`) at position 1 is not allowed
|
|
5 | ]
|
|
|
|
|
"#);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Test that ty works correctly with Bazel's symlinked file structure
|
|
#[test]
|
|
#[cfg(unix)]
|
|
fn bazel_symlinked_files() -> anyhow::Result<()> {
|
|
let case = CliTest::with_files([
|
|
// Original source files in the project
|
|
(
|
|
"main.py",
|
|
r#"
|
|
import library
|
|
|
|
result = library.process_data()
|
|
print(undefined_var) # error: unresolved-reference
|
|
"#,
|
|
),
|
|
(
|
|
"library.py",
|
|
r#"
|
|
def process_data():
|
|
return missing_value # error: unresolved-reference
|
|
"#,
|
|
),
|
|
// Another source file that won't be symlinked
|
|
(
|
|
"other.py",
|
|
r#"
|
|
print(other_undefined) # error: unresolved-reference
|
|
"#,
|
|
),
|
|
])?;
|
|
|
|
// Create Bazel-style symlinks pointing to the actual source files
|
|
// Bazel typically creates symlinks in bazel-out/k8-fastbuild/bin/ that point to actual sources
|
|
std::fs::create_dir_all(case.project_dir.join("bazel-out/k8-fastbuild/bin"))?;
|
|
|
|
// Use absolute paths to ensure the symlinks work correctly
|
|
case.write_symlink(
|
|
case.project_dir.join("main.py"),
|
|
"bazel-out/k8-fastbuild/bin/main.py",
|
|
)?;
|
|
case.write_symlink(
|
|
case.project_dir.join("library.py"),
|
|
"bazel-out/k8-fastbuild/bin/library.py",
|
|
)?;
|
|
|
|
// Change to the bazel-out directory and run ty from there
|
|
// The symlinks should be followed and errors should be found
|
|
assert_cmd_snapshot!(case.command().current_dir(case.project_dir.join("bazel-out/k8-fastbuild/bin")), @r"
|
|
success: false
|
|
exit_code: 1
|
|
----- stdout -----
|
|
error[unresolved-reference]: Name `missing_value` used when not defined
|
|
--> library.py:3:12
|
|
|
|
|
2 | def process_data():
|
|
3 | return missing_value # error: unresolved-reference
|
|
| ^^^^^^^^^^^^^
|
|
|
|
|
info: rule `unresolved-reference` is enabled by default
|
|
|
|
error[unresolved-reference]: Name `undefined_var` used when not defined
|
|
--> main.py:5:7
|
|
|
|
|
4 | result = library.process_data()
|
|
5 | print(undefined_var) # error: unresolved-reference
|
|
| ^^^^^^^^^^^^^
|
|
|
|
|
info: rule `unresolved-reference` is enabled by default
|
|
|
|
Found 2 diagnostics
|
|
|
|
----- stderr -----
|
|
WARN ty is pre-release software and not ready for production use. Expect to encounter bugs, missing features, and fatal errors.
|
|
");
|
|
|
|
// Test that when checking a specific symlinked file from the bazel-out directory, it works correctly
|
|
assert_cmd_snapshot!(case.command().current_dir(case.project_dir.join("bazel-out/k8-fastbuild/bin")).arg("main.py"), @r"
|
|
success: false
|
|
exit_code: 1
|
|
----- stdout -----
|
|
error[unresolved-reference]: Name `undefined_var` used when not defined
|
|
--> main.py:5:7
|
|
|
|
|
4 | result = library.process_data()
|
|
5 | print(undefined_var) # error: unresolved-reference
|
|
| ^^^^^^^^^^^^^
|
|
|
|
|
info: rule `unresolved-reference` is enabled by default
|
|
|
|
Found 1 diagnostic
|
|
|
|
----- stderr -----
|
|
WARN ty is pre-release software and not ready for production use. Expect to encounter bugs, missing features, and fatal errors.
|
|
");
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Test that exclude patterns match on symlink source names, not target names
|
|
#[test]
|
|
#[cfg(unix)]
|
|
fn exclude_symlink_source_not_target() -> anyhow::Result<()> {
|
|
let case = CliTest::with_files([
|
|
// Target files with generic names
|
|
(
|
|
"src/module.py",
|
|
r#"
|
|
def process():
|
|
return undefined_var # error: unresolved-reference
|
|
"#,
|
|
),
|
|
(
|
|
"src/utils.py",
|
|
r#"
|
|
def helper():
|
|
return missing_value # error: unresolved-reference
|
|
"#,
|
|
),
|
|
(
|
|
"regular.py",
|
|
r#"
|
|
print(regular_undefined) # error: unresolved-reference
|
|
"#,
|
|
),
|
|
])?;
|
|
|
|
// Create symlinks with names that differ from their targets
|
|
// This simulates build systems that rename files during symlinking
|
|
case.write_symlink("src/module.py", "generated_module.py")?;
|
|
case.write_symlink("src/utils.py", "generated_utils.py")?;
|
|
|
|
// Exclude pattern should match on the symlink name (generated_*), not the target name
|
|
assert_cmd_snapshot!(case.command().arg("--exclude").arg("generated_*.py"), @r"
|
|
success: false
|
|
exit_code: 1
|
|
----- stdout -----
|
|
error[unresolved-reference]: Name `regular_undefined` used when not defined
|
|
--> regular.py:2:7
|
|
|
|
|
2 | print(regular_undefined) # error: unresolved-reference
|
|
| ^^^^^^^^^^^^^^^^^
|
|
|
|
|
info: rule `unresolved-reference` is enabled by default
|
|
|
|
error[unresolved-reference]: Name `undefined_var` used when not defined
|
|
--> src/module.py:3:12
|
|
|
|
|
2 | def process():
|
|
3 | return undefined_var # error: unresolved-reference
|
|
| ^^^^^^^^^^^^^
|
|
|
|
|
info: rule `unresolved-reference` is enabled by default
|
|
|
|
error[unresolved-reference]: Name `missing_value` used when not defined
|
|
--> src/utils.py:3:12
|
|
|
|
|
2 | def helper():
|
|
3 | return missing_value # error: unresolved-reference
|
|
| ^^^^^^^^^^^^^
|
|
|
|
|
info: rule `unresolved-reference` is enabled by default
|
|
|
|
Found 3 diagnostics
|
|
|
|
----- stderr -----
|
|
WARN ty is pre-release software and not ready for production use. Expect to encounter bugs, missing features, and fatal errors.
|
|
");
|
|
|
|
// Exclude pattern on target path should not affect symlinks with different names
|
|
assert_cmd_snapshot!(case.command().arg("--exclude").arg("src/*.py"), @r"
|
|
success: false
|
|
exit_code: 1
|
|
----- stdout -----
|
|
error[unresolved-reference]: Name `undefined_var` used when not defined
|
|
--> generated_module.py:3:12
|
|
|
|
|
2 | def process():
|
|
3 | return undefined_var # error: unresolved-reference
|
|
| ^^^^^^^^^^^^^
|
|
|
|
|
info: rule `unresolved-reference` is enabled by default
|
|
|
|
error[unresolved-reference]: Name `missing_value` used when not defined
|
|
--> generated_utils.py:3:12
|
|
|
|
|
2 | def helper():
|
|
3 | return missing_value # error: unresolved-reference
|
|
| ^^^^^^^^^^^^^
|
|
|
|
|
info: rule `unresolved-reference` is enabled by default
|
|
|
|
error[unresolved-reference]: Name `regular_undefined` used when not defined
|
|
--> regular.py:2:7
|
|
|
|
|
2 | print(regular_undefined) # error: unresolved-reference
|
|
| ^^^^^^^^^^^^^^^^^
|
|
|
|
|
info: rule `unresolved-reference` is enabled by default
|
|
|
|
Found 3 diagnostics
|
|
|
|
----- stderr -----
|
|
WARN ty is pre-release software and not ready for production use. Expect to encounter bugs, missing features, and fatal errors.
|
|
");
|
|
|
|
// Test that explicitly passing a symlink always checks it, even if excluded
|
|
assert_cmd_snapshot!(case.command().arg("--exclude").arg("generated_*.py").arg("generated_module.py"), @r"
|
|
success: false
|
|
exit_code: 1
|
|
----- stdout -----
|
|
error[unresolved-reference]: Name `undefined_var` used when not defined
|
|
--> generated_module.py:3:12
|
|
|
|
|
2 | def process():
|
|
3 | return undefined_var # error: unresolved-reference
|
|
| ^^^^^^^^^^^^^
|
|
|
|
|
info: rule `unresolved-reference` is enabled by default
|
|
|
|
Found 1 diagnostic
|
|
|
|
----- stderr -----
|
|
WARN ty is pre-release software and not ready for production use. Expect to encounter bugs, missing features, and fatal errors.
|
|
");
|
|
|
|
Ok(())
|
|
}
|