Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 2 additions & 5 deletions crates/ruff/src/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -225,8 +225,7 @@ pub(crate) fn lint_path(
return Ok(Diagnostics::from_source_error(&err, Some(path), settings));
}
};
let source_file = SourceFileBuilder::new(path.to_string_lossy(), contents).finish();
lint_pyproject_toml(&source_file, settings)
lint_pyproject_toml(path, &contents, settings)
} else {
vec![]
};
Expand Down Expand Up @@ -370,16 +369,14 @@ pub(crate) fn lint_stdin(
}

let path = path.unwrap();
let source_file =
SourceFileBuilder::new(path.to_string_lossy(), contents.clone()).finish();

match fix_mode {
flags::FixMode::Diff | flags::FixMode::Generate => {}
flags::FixMode::Apply => write!(&mut io::stdout().lock(), "{contents}")?,
}

return Ok(Diagnostics {
inner: lint_pyproject_toml(&source_file, &settings.linter),
inner: lint_pyproject_toml(path, &contents, &settings.linter),
fixed: FixMap::from_iter([(fs::relativize_path(path), FixTable::default())]),
notebook_indexes: FxHashMap::default(),
});
Expand Down
17 changes: 17 additions & 0 deletions crates/ruff_linter/resources/mdtest/ruff/invalid-pyproject-toml.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
select = ["RUF200"]
```

## Reports an invalid `pyproject.toml`

`pyproject.toml`:

```toml
Expand All @@ -20,3 +22,18 @@ error[RUF200]: Failed to parse pyproject.toml: invalid type: integer `1`, expect
| ^
|
```

## Respects per-file ignores

```toml
[lint]
select = ["RUF200"]
per-file-ignores = { "pyproject.toml" = ["RUF200"] }
```

`pyproject.toml`:

```toml
[project]
name = 1
```
5 changes: 5 additions & 0 deletions crates/ruff_linter/src/checkers/ast/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3548,6 +3548,11 @@ impl<'a> LintContext<'a> {
(self.diagnostics.into_inner(), self.source_file)
}

#[inline]
pub(crate) fn into_diagnostics(self) -> Vec<Diagnostic> {
self.diagnostics.into_inner()
}

#[inline]
pub(crate) fn as_mut_vec(&mut self) -> &mut Vec<Diagnostic> {
self.diagnostics.get_mut()
Expand Down
66 changes: 15 additions & 51 deletions crates/ruff_linter/src/pyproject_toml.rs
Original file line number Diff line number Diff line change
@@ -1,61 +1,25 @@
use colored::Colorize;
use log::warn;
use pyproject_toml::PyProjectToml;
use ruff_text_size::{TextRange, TextSize};
use std::path::Path;

use pyproject_toml::PyProjectToml;
use ruff_db::diagnostic::Diagnostic;
use ruff_source_file::SourceFile;

use crate::registry::Rule;
use crate::rules::ruff::rules::InvalidPyprojectToml;
use crate::checkers::ast::LintContext;
use crate::codes::Rule;
use crate::rules::ruff::rules::invalid_pyproject_toml;
use crate::settings::LinterSettings;
use crate::{IOError, Violation};

/// RUF200
pub fn lint_pyproject_toml(source_file: &SourceFile, settings: &LinterSettings) -> Vec<Diagnostic> {
let Some(err) = toml::from_str::<PyProjectToml>(source_file.source_text()).err() else {
return Vec::default();
};
pub fn lint_pyproject_toml(
path: &Path,
contents: &str,
settings: &LinterSettings,
) -> Vec<Diagnostic> {
let context = LintContext::new(path, contents, settings);

let mut messages = Vec::new();
let range = match err.span() {
// This is bad but sometimes toml and/or serde just don't give us spans
// TODO(konstin,micha): https://github.com/astral-sh/ruff/issues/4571
None => TextRange::default(),
Some(range) => {
let Ok(end) = TextSize::try_from(range.end) else {
let message = format!(
"{} is larger than 4GB, but ruff assumes all files to be smaller",
source_file.name(),
);
if settings.rules.enabled(Rule::IOError) {
let diagnostic =
IOError { message }.into_diagnostic(TextRange::default(), source_file);
messages.push(diagnostic);
} else {
warn!(
"{}{}{} {message}",
"Failed to lint ".bold(),
source_file.name().bold(),
":".bold()
);
}
return messages;
};
TextRange::new(
// start <= end, so if end < 4GB follows start < 4GB
TextSize::try_from(range.start).unwrap(),
end,
)
if let Err(err) = toml::from_str::<PyProjectToml>(contents) {
if context.is_rule_enabled(Rule::InvalidPyprojectToml) {
invalid_pyproject_toml(&context, &err);
}
};

if settings.rules.enabled(Rule::InvalidPyprojectToml) {
let toml_err = err.message().to_string();
let diagnostic =
InvalidPyprojectToml { message: toml_err }.into_diagnostic(range, source_file);
messages.push(diagnostic);
}

messages
context.into_diagnostics()
}
5 changes: 2 additions & 3 deletions crates/ruff_linter/src/rules/ruff/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ mod tests {
use anyhow::Result;
use regex::Regex;
use ruff_python_ast::PythonVersion;
use ruff_source_file::SourceFileBuilder;
use rustc_hash::FxHashSet;
use test_case::test_case;

Expand Down Expand Up @@ -795,9 +794,9 @@ mod tests {
.join(path)
.join("pyproject.toml");
let contents = fs::read_to_string(path)?;
let source_file = SourceFileBuilder::new("pyproject.toml", contents).finish();
let messages = lint_pyproject_toml(
&source_file,
Path::new("pyproject.toml"),
&contents,
&settings::LinterSettings::for_rule(Rule::InvalidPyprojectToml),
);
assert_diagnostics!(snapshot, messages);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_text_size::{TextRange, TextSize};

use crate::{FixAvailability, Violation};
use crate::{FixAvailability, Violation, checkers::ast::LintContext};

/// ## What it does
/// Checks for any pyproject.toml that does not conform to the schema from the relevant PEPs.
Expand Down Expand Up @@ -45,3 +46,19 @@ impl Violation for InvalidPyprojectToml {
format!("Failed to parse pyproject.toml: {message}")
}
}

/// RUF200
pub(crate) fn invalid_pyproject_toml(context: &LintContext, err: &toml::de::Error) {
let range = match err.span() {
// This is bad but sometimes toml and/or serde just don't give us spans
// TODO(konstin,micha): https://github.com/astral-sh/ruff/issues/4571
None => TextRange::default(),
Some(range) => TextRange::new(
TextSize::try_from(range.start).unwrap(),
TextSize::try_from(range.end).unwrap(),
),
};

let toml_err = err.message().to_string();
context.report_diagnostic(InvalidPyprojectToml { message: toml_err }, range);
}
1 change: 0 additions & 1 deletion crates/ruff_mdtest/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ ruff_db = { workspace = true, features = ["os", "testing"] }
ruff_linter = { workspace = true, features = ["testing"] }
ruff_python_ast = { workspace = true }
ruff_ranged_value = { workspace = true }
ruff_source_file = { workspace = true }
ruff_workspace = { workspace = true }

anyhow = { workspace = true }
Expand Down
6 changes: 1 addition & 5 deletions crates/ruff_mdtest/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ use ruff_linter::source_kind::SourceKind;
use ruff_linter::test::test_contents;
use ruff_python_ast::SourceType;
use ruff_ranged_value::{ValueSource, ValueSourceGuard};
use ruff_source_file::SourceFileBuilder;
use ruff_workspace::configuration::Configuration;
use ruff_workspace::options::Options;

Expand Down Expand Up @@ -128,10 +127,7 @@ fn run_test(
test_contents(&source_kind, path, &settings.linter).0
}
SourceType::Toml(source_type) if source_type.is_pyproject() => {
let source_file =
SourceFileBuilder::new(path.to_string_lossy(), source.as_str())
.finish();
lint_pyproject_toml(&source_file, &settings.linter)
lint_pyproject_toml(path, source.as_str(), &settings.linter)
}
SourceType::Toml(_) | SourceType::Markdown => Vec::new(),
}
Expand Down
Loading