1
1
use ruff_python_ast:: Alias ;
2
2
3
- use ruff_diagnostics:: { AlwaysFixableViolation , Diagnostic , Edit , Fix } ;
3
+ use ruff_diagnostics:: { Diagnostic , Edit , Fix , FixAvailability , Violation } ;
4
4
use ruff_macros:: { derive_message_formats, violation} ;
5
5
use ruff_text_size:: Ranged ;
6
6
@@ -28,16 +28,29 @@ use crate::checkers::ast::Checker;
28
28
/// import numpy
29
29
/// ```
30
30
#[ violation]
31
- pub struct UselessImportAlias ;
31
+ pub struct UselessImportAlias {
32
+ required_import_conflict : bool ,
33
+ }
34
+
35
+ impl Violation for UselessImportAlias {
36
+ const FIX_AVAILABILITY : FixAvailability = FixAvailability :: Sometimes ;
32
37
33
- impl AlwaysFixableViolation for UselessImportAlias {
34
38
#[ derive_message_formats]
35
39
fn message ( & self ) -> String {
36
- "Import alias does not rename original package" . to_string ( )
40
+ #[ allow( clippy:: if_not_else) ]
41
+ if !self . required_import_conflict {
42
+ "Import alias does not rename original package" . to_string ( )
43
+ } else {
44
+ "Required import does not rename original package." . to_string ( )
45
+ }
37
46
}
38
47
39
- fn fix_title ( & self ) -> String {
40
- "Remove import alias" . to_string ( )
48
+ fn fix_title ( & self ) -> Option < String > {
49
+ if self . required_import_conflict {
50
+ Some ( "Change required import or disable rule." . to_string ( ) )
51
+ } else {
52
+ Some ( "Remove import alias" . to_string ( ) )
53
+ }
41
54
}
42
55
}
43
56
@@ -52,11 +65,65 @@ pub(crate) fn useless_import_alias(checker: &mut Checker, alias: &Alias) {
52
65
if alias. name . as_str ( ) != asname. as_str ( ) {
53
66
return ;
54
67
}
68
+ // A required import with a useless alias causes an infinite loop.
69
+ // See https://github.com/astral-sh/ruff/issues/14283
70
+ let required_import_conflict = checker
71
+ . settings
72
+ . isort
73
+ . requires_module_import ( alias. name . to_string ( ) , Some ( asname. to_string ( ) ) ) ;
74
+ let mut diagnostic = Diagnostic :: new (
75
+ UselessImportAlias {
76
+ required_import_conflict,
77
+ } ,
78
+ alias. range ( ) ,
79
+ ) ;
80
+ if !required_import_conflict {
81
+ diagnostic. set_fix ( Fix :: unsafe_edit ( Edit :: range_replacement (
82
+ asname. to_string ( ) ,
83
+ alias. range ( ) ,
84
+ ) ) ) ;
85
+ }
86
+
87
+ checker. diagnostics . push ( diagnostic) ;
88
+ }
55
89
56
- let mut diagnostic = Diagnostic :: new ( UselessImportAlias , alias. range ( ) ) ;
57
- diagnostic. set_fix ( Fix :: unsafe_edit ( Edit :: range_replacement (
58
- asname. to_string ( ) ,
90
+ /// PLC0414
91
+ pub ( crate ) fn useless_import_from_alias (
92
+ checker : & mut Checker ,
93
+ alias : & Alias ,
94
+ module : Option < & str > ,
95
+ level : u32 ,
96
+ ) {
97
+ let Some ( asname) = & alias. asname else {
98
+ return ;
99
+ } ;
100
+ if alias. name . contains ( '.' ) {
101
+ return ;
102
+ }
103
+ if alias. name . as_str ( ) != asname. as_str ( ) {
104
+ return ;
105
+ }
106
+ // A required import with a useless alias causes an infinite loop.
107
+ // See https://github.com/astral-sh/ruff/issues/14283
108
+ let required_import_conflict = checker. settings . isort . requires_member_import (
109
+ module. map ( str:: to_string) ,
110
+ alias. name . to_string ( ) ,
111
+ Some ( asname. to_string ( ) ) ,
112
+ level,
113
+ ) ;
114
+ let mut diagnostic = Diagnostic :: new (
115
+ UselessImportAlias {
116
+ required_import_conflict,
117
+ } ,
59
118
alias. range ( ) ,
60
- ) ) ) ;
119
+ ) ;
120
+
121
+ if !required_import_conflict {
122
+ diagnostic. set_fix ( Fix :: unsafe_edit ( Edit :: range_replacement (
123
+ asname. to_string ( ) ,
124
+ alias. range ( ) ,
125
+ ) ) ) ;
126
+ }
127
+
61
128
checker. diagnostics . push ( diagnostic) ;
62
129
}
0 commit comments