mirror of
				https://github.com/astral-sh/ruff.git
				synced 2025-10-31 20:08:19 +00:00 
			
		
		
		
	 85bd961fd3
			
		
	
	
		85bd961fd3
		
			
		
	
	
	
		
			
	
		
	
	
		
			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(())
 | |
| }
 |