Skip to content

Commit 1b9fed8

Browse files
authored
Error on zero tab width (#6429)
## Summary Error if `tab-size` is set to zero (it is used as a divisor). Closes #6423. Also fixes a typo. ## Test Plan Running ruff with a config ```toml [tool.ruff] tab-size = 0 ``` returns an error message to the user saying that `tab-size` must be greater than zero.
1 parent 55d6fd5 commit 1b9fed8

File tree

6 files changed

+27
-19
lines changed

6 files changed

+27
-19
lines changed

crates/ruff/src/line_width.rs

+12-11
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use serde::{Deserialize, Serialize};
2+
use std::num::NonZeroU8;
23
use unicode_width::UnicodeWidthChar;
34

45
use ruff_macros::CacheKey;
@@ -83,7 +84,7 @@ impl LineWidth {
8384
}
8485

8586
fn update(mut self, chars: impl Iterator<Item = char>) -> Self {
86-
let tab_size: usize = self.tab_size.into();
87+
let tab_size: usize = self.tab_size.as_usize();
8788
for c in chars {
8889
match c {
8990
'\t' => {
@@ -144,22 +145,22 @@ impl PartialOrd<LineLength> for LineWidth {
144145
/// The size of a tab.
145146
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize, CacheKey)]
146147
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
147-
pub struct TabSize(pub u8);
148+
pub struct TabSize(pub NonZeroU8);
148149

149-
impl Default for TabSize {
150-
fn default() -> Self {
151-
Self(4)
150+
impl TabSize {
151+
fn as_usize(self) -> usize {
152+
self.0.get() as usize
152153
}
153154
}
154155

155-
impl From<u8> for TabSize {
156-
fn from(tab_size: u8) -> Self {
157-
Self(tab_size)
156+
impl Default for TabSize {
157+
fn default() -> Self {
158+
Self(NonZeroU8::new(4).unwrap())
158159
}
159160
}
160161

161-
impl From<TabSize> for usize {
162-
fn from(tab_size: TabSize) -> Self {
163-
tab_size.0 as usize
162+
impl From<NonZeroU8> for TabSize {
163+
fn from(tab_size: NonZeroU8) -> Self {
164+
Self(tab_size)
164165
}
165166
}

crates/ruff/src/message/text.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -293,12 +293,10 @@ impl Display for MessageCodeFrame<'_> {
293293
}
294294

295295
fn replace_whitespace(source: &str, annotation_range: TextRange) -> SourceCode {
296-
static TAB_SIZE: TabSize = TabSize(4); // TODO(jonathan): use `tab-size`
297-
298296
let mut result = String::new();
299297
let mut last_end = 0;
300298
let mut range = annotation_range;
301-
let mut line_width = LineWidth::new(TAB_SIZE);
299+
let mut line_width = LineWidth::new(TabSize::default());
302300

303301
for (index, c) in source.char_indices() {
304302
let old_width = line_width.get();

crates/ruff/src/rules/pycodestyle/mod.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ pub(crate) mod helpers;
66

77
#[cfg(test)]
88
mod tests {
9+
use std::num::NonZeroU8;
910
use std::path::Path;
1011

1112
use anyhow::Result;
@@ -204,7 +205,7 @@ mod tests {
204205
let diagnostics = test_path(
205206
Path::new("pycodestyle/E501_2.py"),
206207
&settings::Settings {
207-
tab_size: tab_size.into(),
208+
tab_size: NonZeroU8::new(tab_size).unwrap().into(),
208209
..settings::Settings::for_rule(Rule::LineTooLong)
209210
},
210211
)?;

crates/ruff/src/settings/options.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -312,13 +312,13 @@ pub struct Options {
312312
"#
313313
)]
314314
/// The line length to use when enforcing long-lines violations (like
315-
/// `E501`).
315+
/// `E501`). Must be greater than `0`.
316316
pub line_length: Option<LineLength>,
317317
#[option(
318318
default = "4",
319319
value_type = "int",
320320
example = r#"
321-
tab_size = 8
321+
tab-size = 8
322322
"#
323323
)]
324324
/// The tabulation size to calculate line length.

crates/ruff_cache/src/cache_key.rs

+8
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use std::borrow::Cow;
22
use std::collections::hash_map::DefaultHasher;
33
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
44
use std::hash::{Hash, Hasher};
5+
use std::num::NonZeroU8;
56
use std::ops::{Deref, DerefMut};
67
use std::path::{Path, PathBuf};
78

@@ -205,6 +206,13 @@ impl CacheKey for i8 {
205206
}
206207
}
207208

209+
impl CacheKey for NonZeroU8 {
210+
#[inline]
211+
fn cache_key(&self, state: &mut CacheKeyHasher) {
212+
state.write_u8(self.get());
213+
}
214+
}
215+
208216
macro_rules! impl_cache_key_tuple {
209217
() => (
210218
impl CacheKey for () {

ruff.schema.json

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)