Skip to content

Commit 4e0cf71

Browse files
committed
Improve error messages
1 parent 674bf6f commit 4e0cf71

File tree

3 files changed

+85
-48
lines changed

3 files changed

+85
-48
lines changed

crates/ruff/tests/lint.rs

+26-24
Original file line numberDiff line numberDiff line change
@@ -1987,18 +1987,19 @@ fn flake8_import_convention_invalid_aliases_config_alias_name() -> Result<()> {
19871987
.arg("--config")
19881988
.arg(&ruff_toml)
19891989
, @r#"
1990-
success: false
1991-
exit_code: 2
1992-
----- stdout -----
1993-
1994-
----- stderr -----
1995-
ruff failed
1996-
Cause: Failed to parse [TMP]/ruff.toml
1997-
Cause: TOML parse error at line 2, column 2
1998-
|
1999-
2 | [lint.flake8-import-conventions.aliases]
2000-
| ^^^^
2001-
alias must be a valid identifier"#);});
1990+
success: false
1991+
exit_code: 2
1992+
----- stdout -----
1993+
1994+
----- stderr -----
1995+
ruff failed
1996+
Cause: Failed to parse [TMP]/ruff.toml
1997+
Cause: TOML parse error at line 2, column 2
1998+
|
1999+
2 | [lint.flake8-import-conventions.aliases]
2000+
| ^^^^
2001+
invalid value: string "invalid.alias", expected alias must be a valid identifier
2002+
"#);});
20022003
Ok(())
20032004
}
20042005

@@ -2022,17 +2023,18 @@ fn flake8_import_convention_invalid_aliases_config_module_name() -> Result<()> {
20222023
.arg("--config")
20232024
.arg(&ruff_toml)
20242025
, @r#"
2025-
success: false
2026-
exit_code: 2
2027-
----- stdout -----
2028-
2029-
----- stderr -----
2030-
ruff failed
2031-
Cause: Failed to parse [TMP]/ruff.toml
2032-
Cause: TOML parse error at line 2, column 2
2033-
|
2034-
2 | [lint.flake8-import-conventions.aliases]
2035-
| ^^^^
2036-
module must be a valid identifier separated by single periods"#);});
2026+
success: false
2027+
exit_code: 2
2028+
----- stdout -----
2029+
2030+
----- stderr -----
2031+
ruff failed
2032+
Cause: Failed to parse [TMP]/ruff.toml
2033+
Cause: TOML parse error at line 2, column 2
2034+
|
2035+
2 | [lint.flake8-import-conventions.aliases]
2036+
| ^^^^
2037+
invalid value: string "module..invalid", expected module must be a valid identifier separated by single periods
2038+
"#);});
20372039
Ok(())
20382040
}

crates/ruff_workspace/src/options.rs

+55-23
Original file line numberDiff line numberDiff line change
@@ -1329,8 +1329,7 @@ pub struct Flake8ImportConventionsOptions {
13291329
scipy = "sp"
13301330
"#
13311331
)]
1332-
#[serde(deserialize_with = "deserialize_and_validate_aliases")]
1333-
pub aliases: Option<FxHashMap<String, String>>,
1332+
pub aliases: Option<FxHashMap<ModuleName, Alias>>,
13341333

13351334
/// A mapping from module to conventional import alias. These aliases will
13361335
/// be added to the [`aliases`](#lint_flake8-import-conventions_aliases) mapping.
@@ -1373,34 +1372,67 @@ pub struct Flake8ImportConventionsOptions {
13731372
pub banned_from: Option<FxHashSet<String>>,
13741373
}
13751374

1376-
fn deserialize_and_validate_aliases<'de, D>(
1377-
deserializer: D,
1378-
) -> Result<Option<FxHashMap<String, String>>, D::Error>
1379-
where
1380-
D: Deserializer<'de>,
1381-
{
1382-
let Some(aliases) = Option::<FxHashMap<String, String>>::deserialize(deserializer)? else {
1383-
return Ok(None);
1384-
};
1385-
1386-
for (module, alias) in &aliases {
1387-
if module.is_empty() || module.split('.').any(|part| !is_identifier(part)) {
1388-
return Err(de::Error::custom(
1389-
"module must be a valid identifier separated by single periods",
1390-
));
1391-
}
1392-
if !is_identifier(alias) {
1393-
return Err(de::Error::custom("alias must be a valid identifier"));
1375+
#[derive(Clone, Debug, PartialEq, Eq, Hash, Default, Serialize)]
1376+
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1377+
pub struct ModuleName(String);
1378+
1379+
impl ModuleName {
1380+
pub fn into_string(self) -> String {
1381+
self.0
1382+
}
1383+
}
1384+
1385+
impl<'de> Deserialize<'de> for ModuleName {
1386+
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1387+
where
1388+
D: Deserializer<'de>,
1389+
{
1390+
let name = String::deserialize(deserializer)?;
1391+
if name.is_empty() || name.split('.').any(|part| !is_identifier(part)) {
1392+
Err(de::Error::invalid_value(
1393+
de::Unexpected::Str(&name),
1394+
&"module must be a valid identifier separated by single periods",
1395+
))
1396+
} else {
1397+
Ok(Self(name))
13941398
}
13951399
}
1400+
}
1401+
1402+
#[derive(Clone, Debug, PartialEq, Eq, Hash, Default, Serialize)]
1403+
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1404+
pub struct Alias(String);
1405+
1406+
impl Alias {
1407+
pub fn into_string(self) -> String {
1408+
self.0
1409+
}
1410+
}
13961411

1397-
Ok(Some(aliases)) // Return the validated map.
1412+
impl<'de> Deserialize<'de> for Alias {
1413+
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1414+
where
1415+
D: Deserializer<'de>,
1416+
{
1417+
let name = String::deserialize(deserializer)?;
1418+
if is_identifier(&name) {
1419+
Ok(Self(name))
1420+
} else {
1421+
Err(de::Error::invalid_value(
1422+
de::Unexpected::Str(&name),
1423+
&"alias must be a valid identifier",
1424+
))
1425+
}
1426+
}
13981427
}
13991428

14001429
impl Flake8ImportConventionsOptions {
14011430
pub fn into_settings(self) -> flake8_import_conventions::settings::Settings {
1402-
let mut aliases = match self.aliases {
1403-
Some(options_aliases) => options_aliases,
1431+
let mut aliases: FxHashMap<String, String> = match self.aliases {
1432+
Some(options_aliases) => options_aliases
1433+
.into_iter()
1434+
.map(|(module, alias)| (module.into_string(), alias.into_string()))
1435+
.collect(),
14041436
None => flake8_import_conventions::settings::default_aliases(),
14051437
};
14061438
if let Some(extend_aliases) = self.extend_aliases {

ruff.schema.json

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

0 commit comments

Comments
 (0)