5
5
use syntax:: ast;
6
6
use syntax:: util:: parser:: AssocOp ;
7
7
use utils:: { higher, snippet} ;
8
+ use syntax:: print:: pprust:: binop_to_string;
8
9
9
10
/// A helper type to build suggestion correctly handling parenthesis.
10
11
pub enum Sugg < ' a > {
@@ -16,6 +17,9 @@ pub enum Sugg<'a> {
16
17
BinOp ( AssocOp , Cow < ' a , str > ) ,
17
18
}
18
19
20
+ /// Literal constant `1`, for convenience.
21
+ pub const ONE : Sugg < ' static > = Sugg :: NonParen ( Cow :: Borrowed ( "1" ) ) ;
22
+
19
23
impl < ' a > std:: fmt:: Display for Sugg < ' a > {
20
24
fn fmt ( & self , f : & mut std:: fmt:: Formatter ) -> Result < ( ) , std:: fmt:: Error > {
21
25
match * self {
@@ -110,28 +114,43 @@ impl<'a> Sugg<'a> {
110
114
}
111
115
}
112
116
113
- /// Convenience method to create the `lhs && rhs` suggestion.
114
- pub fn and ( & self , rhs : & Self ) -> Sugg < ' static > {
115
- make_binop ( ast:: BinOpKind :: And , self , rhs)
117
+ /// Convenience method to create the `< lhs> && < rhs> ` suggestion.
118
+ pub fn and ( self , rhs : Self ) -> Sugg < ' static > {
119
+ make_binop ( ast:: BinOpKind :: And , & self , & rhs)
116
120
}
117
121
118
122
/// Convenience method to create the `&<expr>` suggestion.
119
- pub fn addr ( & self ) -> Sugg < ' static > {
120
- make_unop ( "&" , self )
123
+ pub fn addr ( self ) -> Sugg < ' static > {
124
+ make_unop ( "&" , & self )
125
+ }
126
+
127
+ /// Convenience method to create the `<lhs>..<rhs>` or `<lhs>...<rhs>` suggestion.
128
+ pub fn range ( self , end : Self , limit : ast:: RangeLimits ) -> Sugg < ' static > {
129
+ match limit {
130
+ ast:: RangeLimits :: HalfOpen => make_assoc ( AssocOp :: DotDot , & self , & end) ,
131
+ ast:: RangeLimits :: Closed => make_assoc ( AssocOp :: DotDotDot , & self , & end) ,
132
+ }
133
+ }
134
+ }
135
+
136
+ impl < ' a , ' b > std:: ops:: Add < Sugg < ' b > > for Sugg < ' a > {
137
+ type Output = Sugg < ' static > ;
138
+ fn add ( self , rhs : Sugg < ' b > ) -> Sugg < ' static > {
139
+ make_binop ( ast:: BinOpKind :: Add , & self , & rhs)
121
140
}
122
141
}
123
142
124
- impl < ' a , ' b > std:: ops:: Sub < & ' b Sugg < ' b > > for & ' a Sugg < ' a > {
143
+ impl < ' a , ' b > std:: ops:: Sub < Sugg < ' b > > for Sugg < ' a > {
125
144
type Output = Sugg < ' static > ;
126
- fn sub ( self , rhs : & ' b Sugg < ' b > ) -> Sugg < ' static > {
127
- make_binop ( ast:: BinOpKind :: Sub , self , rhs)
145
+ fn sub ( self , rhs : Sugg < ' b > ) -> Sugg < ' static > {
146
+ make_binop ( ast:: BinOpKind :: Sub , & self , & rhs)
128
147
}
129
148
}
130
149
131
- impl < ' a > std:: ops:: Not for & ' a Sugg < ' a > {
150
+ impl < ' a > std:: ops:: Not for Sugg < ' a > {
132
151
type Output = Sugg < ' static > ;
133
152
fn not ( self ) -> Sugg < ' static > {
134
- make_unop ( "!" , self )
153
+ make_unop ( "!" , & self )
135
154
}
136
155
}
137
156
@@ -172,7 +191,7 @@ pub fn make_unop(op: &str, expr: &Sugg) -> Sugg<'static> {
172
191
///
173
192
/// Precedence of shift operator relative to other arithmetic operation is often confusing so
174
193
/// parenthesis will always be added for a mix of these.
175
- pub fn make_binop ( op : ast :: BinOpKind , lhs : & Sugg , rhs : & Sugg ) -> Sugg < ' static > {
194
+ pub fn make_assoc ( op : AssocOp , lhs : & Sugg , rhs : & Sugg ) -> Sugg < ' static > {
176
195
fn is_shift ( op : & AssocOp ) -> bool {
177
196
matches ! ( * op, AssocOp :: ShiftLeft | AssocOp :: ShiftRight )
178
197
}
@@ -190,25 +209,54 @@ pub fn make_binop(op: ast::BinOpKind, lhs: &Sugg, rhs: &Sugg) -> Sugg<'static> {
190
209
is_shift ( other) && is_arith ( op)
191
210
}
192
211
193
- let aop = AssocOp :: from_ast_binop ( op) ;
194
-
195
212
let lhs_paren = if let Sugg :: BinOp ( ref lop, _) = * lhs {
196
- needs_paren ( & aop , lop, Associativity :: Left )
213
+ needs_paren ( & op , lop, Associativity :: Left )
197
214
} else {
198
215
false
199
216
} ;
200
217
201
218
let rhs_paren = if let Sugg :: BinOp ( ref rop, _) = * rhs {
202
- needs_paren ( & aop , rop, Associativity :: Right )
219
+ needs_paren ( & op , rop, Associativity :: Right )
203
220
} else {
204
221
false
205
222
} ;
206
223
207
- Sugg :: BinOp ( aop,
208
- format ! ( "{} {} {}" ,
209
- ParenHelper :: new( lhs_paren, lhs) ,
210
- op. to_string( ) ,
211
- ParenHelper :: new( rhs_paren, rhs) ) . into ( ) )
224
+ let lhs = ParenHelper :: new ( lhs_paren, lhs) ;
225
+ let rhs = ParenHelper :: new ( rhs_paren, rhs) ;
226
+ let sugg = match op {
227
+ AssocOp :: Add |
228
+ AssocOp :: BitAnd |
229
+ AssocOp :: BitOr |
230
+ AssocOp :: BitXor |
231
+ AssocOp :: Divide |
232
+ AssocOp :: Equal |
233
+ AssocOp :: Greater |
234
+ AssocOp :: GreaterEqual |
235
+ AssocOp :: LAnd |
236
+ AssocOp :: LOr |
237
+ AssocOp :: Less |
238
+ AssocOp :: LessEqual |
239
+ AssocOp :: Modulus |
240
+ AssocOp :: Multiply |
241
+ AssocOp :: NotEqual |
242
+ AssocOp :: ShiftLeft |
243
+ AssocOp :: ShiftRight |
244
+ AssocOp :: Subtract => format ! ( "{} {} {}" , lhs, op. to_ast_binop( ) . expect( "Those are AST ops" ) . to_string( ) , rhs) ,
245
+ AssocOp :: Inplace => format ! ( "in ({}) {}" , lhs, rhs) ,
246
+ AssocOp :: Assign => format ! ( "{} = {}" , lhs, rhs) ,
247
+ AssocOp :: AssignOp ( op) => format ! ( "{} {}= {}" , lhs, binop_to_string( op) , rhs) ,
248
+ AssocOp :: As => format ! ( "{} as {}" , lhs, rhs) ,
249
+ AssocOp :: DotDot => format ! ( "{}..{}" , lhs, rhs) ,
250
+ AssocOp :: DotDotDot => format ! ( "{}...{}" , lhs, rhs) ,
251
+ AssocOp :: Colon => format ! ( "{}: {}" , lhs, rhs) ,
252
+ } ;
253
+
254
+ Sugg :: BinOp ( op, sugg. into ( ) )
255
+ }
256
+
257
+ /// Convinience wrapper arround `make_assoc` and `AssocOp::from_ast_binop`.
258
+ pub fn make_binop ( op : ast:: BinOpKind , lhs : & Sugg , rhs : & Sugg ) -> Sugg < ' static > {
259
+ make_assoc ( AssocOp :: from_ast_binop ( op) , lhs, rhs)
212
260
}
213
261
214
262
#[ derive( PartialEq , Eq ) ]
0 commit comments