mirror of
https://github.com/astral-sh/ruff.git
synced 2025-10-03 15:15:33 +00:00
Remove E999
as a rule, disallow any disablement methods for syntax error (#11901)
## Summary This PR updates the way syntax errors are handled throughout the linter. The main change is that it's now not considered as a rule which involves the following changes: * Update `Message` to be an enum with two variants - one for diagnostic message and the other for syntax error message * Provide methods on the new message enum to query information required by downstream usages This means that the syntax errors cannot be hidden / disabled via any disablement methods. These are: 1. Configuration via `select`, `ignore`, `per-file-ignores`, and their `extend-*` variants ```console $ cargo run -- check ~/playground/ruff/src/lsp.py --extend-select=E999 --no-preview --no-cache Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.10s Running `target/debug/ruff check /Users/dhruv/playground/ruff/src/lsp.py --extend-select=E999 --no-preview --no-cache` warning: Rule `E999` is deprecated and will be removed in a future release. Syntax errors will always be shown regardless of whether this rule is selected or not. /Users/dhruv/playground/ruff/src/lsp.py:1:8: F401 [*] `abc` imported but unused | 1 | import abc | ^^^ F401 2 | from pathlib import Path 3 | import os | = help: Remove unused import: `abc` ``` 3. Command-line flags via `--select`, `--ignore`, `--per-file-ignores`, and their `--extend-*` variants ```console $ cargo run -- check ~/playground/ruff/src/lsp.py --no-cache --config=~/playground/ruff/pyproject.toml Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.11s Running `target/debug/ruff check /Users/dhruv/playground/ruff/src/lsp.py --no-cache --config=/Users/dhruv/playground/ruff/pyproject.toml` warning: Rule `E999` is deprecated and will be removed in a future release. Syntax errors will always be shown regardless of whether this rule is selected or not. /Users/dhruv/playground/ruff/src/lsp.py:1:8: F401 [*] `abc` imported but unused | 1 | import abc | ^^^ F401 2 | from pathlib import Path 3 | import os | = help: Remove unused import: `abc` ``` This also means that the **output format** needs to be updated: 1. The `code`, `noqa_row`, `url` fields in the JSON output is optional (`null` for syntax errors) 2. Other formats are changed accordingly For each format, a new test case specific to syntax errors have been added. Please refer to the snapshot output for the exact format for syntax error message. The output of the `--statistics` flag will have a blank entry for syntax errors: ``` 315 F821 [ ] undefined-name 119 [ ] syntax-error 103 F811 [ ] redefined-while-unused ``` The **language server** is updated to consider the syntax errors by convert them into LSP diagnostic format separately. ### Preview There are no quick fixes provided to disable syntax errors. This will automatically work for `ruff-lsp` because the `noqa_row` field will be `null` in that case. <img width="772" alt="Screenshot 2024-06-26 at 14 57 08" src="aaac827e
-4777-4ac8-8c68-eaf9f2c36774"> Even with `noqa` comment, the syntax error is displayed: <img width="763" alt="Screenshot 2024-06-26 at 14 59 51" src="ba1afb68
-7eaf-4b44-91af-6d93246475e2"> Rule documentation page: <img width="1371" alt="Screenshot 2024-06-26 at 16 48 07" src="524f01df
-d91f-4ac0-86cc-40e76b318b24"> ## Test Plan - [x] Disablement methods via config shows a warning - [x] `select`, `extend-select` - [ ] ~`ignore`~ _doesn't show any message_ - [ ] ~`per-file-ignores`, `extend-per-file-ignores`~ _doesn't show any message_ - [x] Disablement methods via command-line flag shows a warning - [x] `--select`, `--extend-select` - [ ] ~`--ignore`~ _doesn't show any message_ - [ ] ~`--per-file-ignores`, `--extend-per-file-ignores`~ _doesn't show any message_ - [x] File with syntax errors should exit with code 1 - [x] Language server - [x] Should show diagnostics for syntax errors - [x] Should not recommend a quick fix edit for adding `noqa` comment - [x] Same for `ruff-lsp` resolves: #8447
This commit is contained in:
parent
c98d8a040f
commit
e7b49694a7
52 changed files with 1235 additions and 380 deletions
|
@ -15,7 +15,6 @@ use crate::fs::relativize_path;
|
|||
use crate::line_width::{IndentWidth, LineWidthBuilder};
|
||||
use crate::message::diff::Diff;
|
||||
use crate::message::{Emitter, EmitterContext, Message};
|
||||
use crate::registry::AsRule;
|
||||
use crate::settings::types::UnsafeFixes;
|
||||
use crate::text_helpers::ShowNonprinting;
|
||||
|
||||
|
@ -146,28 +145,33 @@ pub(super) struct RuleCodeAndBody<'a> {
|
|||
|
||||
impl Display for RuleCodeAndBody<'_> {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
let kind = &self.message.kind;
|
||||
if self.show_fix_status {
|
||||
if let Some(fix) = self.message.fix.as_ref() {
|
||||
if let Some(fix) = self.message.fix() {
|
||||
// Do not display an indicator for unapplicable fixes
|
||||
if fix.applies(self.unsafe_fixes.required_applicability()) {
|
||||
if let Some(rule) = self.message.rule() {
|
||||
write!(f, "{} ", rule.noqa_code().to_string().red().bold())?;
|
||||
}
|
||||
return write!(
|
||||
f,
|
||||
"{code} {fix}{body}",
|
||||
code = kind.rule().noqa_code().to_string().red().bold(),
|
||||
"{fix}{body}",
|
||||
fix = format_args!("[{}] ", "*".cyan()),
|
||||
body = kind.body,
|
||||
body = self.message.body(),
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
write!(
|
||||
f,
|
||||
"{code} {body}",
|
||||
code = kind.rule().noqa_code().to_string().red().bold(),
|
||||
body = kind.body,
|
||||
)
|
||||
if let Some(rule) = self.message.rule() {
|
||||
write!(
|
||||
f,
|
||||
"{code} {body}",
|
||||
code = rule.noqa_code().to_string().red().bold(),
|
||||
body = self.message.body(),
|
||||
)
|
||||
} else {
|
||||
f.write_str(self.message.body())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -178,11 +182,7 @@ pub(super) struct MessageCodeFrame<'a> {
|
|||
|
||||
impl Display for MessageCodeFrame<'_> {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
let Message {
|
||||
kind, file, range, ..
|
||||
} = self.message;
|
||||
|
||||
let suggestion = kind.suggestion.as_deref();
|
||||
let suggestion = self.message.suggestion();
|
||||
let footer = if suggestion.is_some() {
|
||||
vec![Annotation {
|
||||
id: None,
|
||||
|
@ -193,9 +193,9 @@ impl Display for MessageCodeFrame<'_> {
|
|||
Vec::new()
|
||||
};
|
||||
|
||||
let source_code = file.to_source_code();
|
||||
let source_code = self.message.source_file().to_source_code();
|
||||
|
||||
let content_start_index = source_code.line_index(range.start());
|
||||
let content_start_index = source_code.line_index(self.message.start());
|
||||
let mut start_index = content_start_index.saturating_sub(2);
|
||||
|
||||
// If we're working with a Jupyter Notebook, skip the lines which are
|
||||
|
@ -218,7 +218,7 @@ impl Display for MessageCodeFrame<'_> {
|
|||
start_index = start_index.saturating_add(1);
|
||||
}
|
||||
|
||||
let content_end_index = source_code.line_index(range.end());
|
||||
let content_end_index = source_code.line_index(self.message.end());
|
||||
let mut end_index = content_end_index
|
||||
.saturating_add(2)
|
||||
.min(OneIndexed::from_zero_indexed(source_code.line_count()));
|
||||
|
@ -249,7 +249,7 @@ impl Display for MessageCodeFrame<'_> {
|
|||
|
||||
let source = replace_whitespace(
|
||||
source_code.slice(TextRange::new(start_offset, end_offset)),
|
||||
range - start_offset,
|
||||
self.message.range() - start_offset,
|
||||
);
|
||||
|
||||
let source_text = source.text.show_nonprinting();
|
||||
|
@ -260,7 +260,10 @@ impl Display for MessageCodeFrame<'_> {
|
|||
|
||||
let char_length = source.text[source.annotation_range].chars().count();
|
||||
|
||||
let label = kind.rule().noqa_code().to_string();
|
||||
let label = self
|
||||
.message
|
||||
.rule()
|
||||
.map_or_else(String::new, |rule| rule.noqa_code().to_string());
|
||||
|
||||
let snippet = Snippet {
|
||||
title: None,
|
||||
|
@ -356,7 +359,7 @@ mod tests {
|
|||
|
||||
use crate::message::tests::{
|
||||
capture_emitter_notebook_output, capture_emitter_output, create_messages,
|
||||
create_notebook_messages,
|
||||
create_notebook_messages, create_syntax_error_messages,
|
||||
};
|
||||
use crate::message::TextEmitter;
|
||||
use crate::settings::types::UnsafeFixes;
|
||||
|
@ -401,4 +404,12 @@ mod tests {
|
|||
|
||||
assert_snapshot!(content);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn syntax_errors() {
|
||||
let mut emitter = TextEmitter::default().with_show_source(true);
|
||||
let content = capture_emitter_output(&mut emitter, &create_syntax_error_messages());
|
||||
|
||||
assert_snapshot!(content);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue