1- from typing import Optional , cast , List
1+ from typing import Optional , cast , List , TypeVar
22
33import rewrite .java as j
4- from rewrite import Tree
4+ from rewrite import Tree , list_map
55from rewrite .java import J , Assignment , JLeftPadded , AssignmentOperation , MemberReference , MethodInvocation , \
6- MethodDeclaration , Empty , ArrayAccess , Space , If , Block , ClassDeclaration
6+ MethodDeclaration , Empty , ArrayAccess , Space , If , Block , ClassDeclaration , VariableDeclarations , JRightPadded
77from rewrite .python import PythonVisitor , SpacesStyle , Binary , ChainedAssignment
88from rewrite .visitor import P
99
@@ -20,7 +20,7 @@ def visit_class_declaration(self, class_declaration: ClassDeclaration, p: P) ->
2020 # Handle space before parentheses for class declaration e.g. class A () <-> class A()
2121 if c .padding .implements is not None :
2222 c = c .padding .with_implements (
23- self . space_before_container (c .padding .implements , self ._style .before_parentheses .method_call )
23+ space_before_container (c .padding .implements , self ._style .before_parentheses .method_call )
2424 )
2525
2626 param_size = len (c .padding .implements .elements )
@@ -29,14 +29,14 @@ def visit_class_declaration(self, class_declaration: ClassDeclaration, p: P) ->
2929 # TODO: Refactor to remove duplicate code.
3030 def _process_argument (index , arg , args_size ):
3131 if index == 0 :
32- arg = arg .with_element (self . space_before (arg .element , use_space ))
32+ arg = arg .with_element (space_before (arg .element , use_space ))
3333 else :
34- arg = arg .with_element (self . space_before (arg .element , self ._style .other .after_comma ))
34+ arg = arg .with_element (space_before (arg .element , self ._style .other .after_comma ))
3535
3636 if index == args_size - 1 :
37- arg = self . space_after (arg , use_space )
37+ arg = space_after (arg , use_space )
3838 else :
39- arg = self . space_after (arg , self ._style .other .before_comma )
39+ arg = space_after (arg , self ._style .other .before_comma )
4040
4141 return arg
4242
@@ -53,7 +53,7 @@ def visit_method_declaration(self, method_declaration: MethodDeclaration, p: P)
5353 m : MethodDeclaration = cast (MethodDeclaration , super ().visit_method_declaration (method_declaration , p ))
5454
5555 m = m .padding .with_parameters (
56- self . space_before_container (m .padding .parameters , self ._style .before_parentheses .method_declaration )
56+ space_before_container (m .padding .parameters , self ._style .before_parentheses .method_declaration )
5757 )
5858
5959 param_size = len (m .parameters )
@@ -62,18 +62,24 @@ def visit_method_declaration(self, method_declaration: MethodDeclaration, p: P)
6262 def _process_argument (index , arg , args_size ):
6363 # TODO: Fix Type hint handling
6464 # Handle space before type hint colon e.g. foo(a: int) <-> foo(a:int)
65- arg = arg .with_element (arg .element .with_type_expression (
66- self .space_before (arg .element .type_expression , False )))
65+ if isinstance (arg .element , VariableDeclarations ) and arg .element .type_expression :
66+ vd = cast (VariableDeclarations , arg .element )
67+ arg = arg .with_element (vd .with_type_expression (
68+ space_before (vd .type_expression , self ._style .other .after_colon ))
69+ .padding .with_variables (
70+ list_map (lambda v : space_after_right_padded (v , self ._style .other .before_colon ),
71+ vd .padding .variables ))
72+ )
6773
6874 if index == 0 :
69- arg = arg .with_element (self . space_before (arg .element , use_space ))
75+ arg = arg .with_element (space_before (arg .element , use_space ))
7076 else :
71- arg = arg .with_element (self . space_before (arg .element , self ._style .other .after_comma ))
77+ arg = arg .with_element (space_before (arg .element , self ._style .other .after_comma ))
7278
7379 if index == args_size - 1 :
74- arg = self . space_after (arg , use_space )
80+ arg = space_after (arg , use_space )
7581 else :
76- arg = self . space_after (arg , self ._style .other .before_comma )
82+ arg = space_after (arg , self ._style .other .before_comma )
7783 return arg
7884
7985 m = m .padding .with_parameters (
@@ -95,7 +101,7 @@ def _process_argument(index, arg, args_size):
95101
96102 def visit_block (self , block : Block , p : P ) -> J :
97103 b = cast (Block , super ().visit_block (block , p ))
98- b = self . space_before (b , self ._style .other .before_colon )
104+ b = space_before (b , self ._style .other .before_colon )
99105 return b
100106
101107 def visit_method_invocation (self , method_invocation : MethodInvocation , p : P ) -> J :
@@ -110,7 +116,7 @@ def visit_method_invocation(self, method_invocation: MethodInvocation, p: P) ->
110116 use_space = self ._style .within .empty_method_call_parentheses
111117 m = m .padding .with_arguments (
112118 m .padding .arguments .padding .with_elements (
113- [arg .with_element (self . space_before (arg .element , use_space )) for arg in
119+ [arg .with_element (space_before (arg .element , use_space )) for arg in
114120 m .padding .arguments .padding .elements ]
115121 )
116122 )
@@ -124,14 +130,14 @@ def visit_method_invocation(self, method_invocation: MethodInvocation, p: P) ->
124130
125131 def _process_argument (index , arg , args_size , use_space ):
126132 if index == 0 :
127- arg = arg .with_element (self . space_before (arg .element , use_space ))
133+ arg = arg .with_element (space_before (arg .element , use_space ))
128134 else :
129- arg = arg .with_element (self . space_before (arg .element , self ._style .other .after_comma ))
135+ arg = arg .with_element (space_before (arg .element , self ._style .other .after_comma ))
130136
131137 if index == args_size - 1 :
132- arg = self . space_after (arg , use_space )
138+ arg = space_after (arg , use_space )
133139 else :
134- arg = self . space_after (arg , self ._style .other .before_comma )
140+ arg = space_after (arg , self ._style .other .before_comma )
135141
136142 return arg
137143
@@ -166,10 +172,10 @@ def visit_assignment(self, assignment: Assignment, p: P) -> J:
166172 """
167173 a : Assignment = cast (Assignment , super ().visit_assignment (assignment , p ))
168174 a = a .padding .with_assignment (
169- self . space_before_jleftpadded (a .padding .assignment , self ._style .around_operators .assignment ))
175+ space_before_left_padded (a .padding .assignment , self ._style .around_operators .assignment ))
170176 a = a .padding .with_assignment (
171177 a .padding .assignment .with_element (
172- self . space_before (a .padding .assignment .element , self ._style .around_operators .assignment )))
178+ space_before (a .padding .assignment .element , self ._style .around_operators .assignment )))
173179 return a
174180
175181 def visit_assignment_operation (self , assignment_operation : AssignmentOperation , p : P ) -> J :
@@ -180,7 +186,7 @@ def visit_assignment_operation(self, assignment_operation: AssignmentOperation,
180186 operator : JLeftPadded = a .padding .operator
181187 a = a .padding .with_operator (
182188 operator .with_before (update_space (operator .before , self ._style .around_operators .assignment )))
183- return a .with_assignment (self . space_before (a .assignment , self ._style .around_operators .assignment ))
189+ return a .with_assignment (space_before (a .assignment , self ._style .around_operators .assignment ))
184190
185191 def visit_chained_assignment (self , chained_assignment : ChainedAssignment , p : P ) -> J :
186192 """
@@ -192,10 +198,10 @@ def visit_chained_assignment(self, chained_assignment: ChainedAssignment, p: P)
192198
193199 a = a .padding .with_variables (
194200 [v .with_element (
195- self . space_before (v .element , self ._style .around_operators .assignment if idx >= 1 else False )) for idx , v
201+ space_before (v .element , self ._style .around_operators .assignment if idx >= 1 else False )) for idx , v
196202 in enumerate (a .padding .variables )])
197203
198- return a .with_assignment (self . space_before (a .assignment , self ._style .around_operators .assignment ))
204+ return a .with_assignment (space_before (a .assignment , self ._style .around_operators .assignment ))
199205
200206 def visit_member_reference (self , member_reference : MemberReference , p : P ) -> J :
201207 m : MemberReference = cast (MemberReference , super ().visit_member_reference (member_reference , p ))
@@ -247,96 +253,112 @@ def _apply_binary_space_around(self, binary, use_space_around: bool):
247253 binary = binary .padding .with_operator (
248254 operator .with_before (update_space (operator .before , use_space_around ))
249255 )
250- binary = binary .with_right (self . space_before (binary .right , use_space_around ))
256+ binary = binary .with_right (space_before (binary .right , use_space_around ))
251257 return binary
252258
253259 def visit_if (self , if_stm : If , p : P ) -> J :
254260 if_ : j .If = cast (If , super ().visit_if (if_stm , p ))
255261
256262 # Handle space before if condition e.g. if True: <-> if True:
257- if_ = if_ .with_if_condition (self . space_before (if_ ._if_condition , True ))
263+ if_ = if_ .with_if_condition (space_before (if_ ._if_condition , True ))
258264
259265 # Handle space before if colon e.g. if True: pass <-> if True: pass
260266 if_ = if_ .with_if_condition (
261267 if_ .if_condition .padding .with_tree (
262- SpacesVisitor . space_after (if_ .if_condition .padding .tree , self ._style .other .before_colon ))
268+ space_after (if_ .if_condition .padding .tree , self ._style .other .before_colon ))
263269 )
264270 return if_
265271
266272 def visit_else (self , else_ : If .Else , p : P ) -> J :
267273 e : j .If .Else = cast (j .If .Else , super ().visit_else (else_ , p ))
268- e = e .padding .with_body (self . space_before_right_padded_element (e .padding .body , self ._style .other .before_colon ))
274+ e = e .padding .with_body (space_before_right_padded_element (e .padding .body , self ._style .other .before_colon ))
269275
270276 return e
271277
272- @staticmethod
273- def space_before (j : J , space_before : bool ) -> J :
274- space : Space = cast (Space , j .prefix )
275- if space .comments or '\\ ' in space .whitespace :
276- # don't touch whitespaces with comments or continuation characters
277- return j
278-
279- return j .with_prefix (Space .SINGLE_SPACE if space_before else Space .EMPTY )
280-
281- @staticmethod
282- def space_before_container (container : j .JContainer , space_before : bool ) -> j .JContainer :
283- if container .before .comments :
284- # Perform the space rule for the suffix of the last comment only. Same as IntelliJ.
285- comments : List [j .Comment ] = SpacesVisitor .space_last_comment_suffix (container .before .comments , space_before )
286- return container .with_before (container .before .with_comments (comments ))
287-
288- if space_before and not_single_space (container .before .whitespace ):
289- return container .with_before (container .before .with_whitespace (" " ))
290- elif not space_before and only_spaces_and_not_empty (container .before .whitespace ):
291- return container .with_before (container .before .with_whitespace ("" ))
292- else :
293- return container
294-
295- @staticmethod
296- def space_before_right_padded_element (container : j .JRightPadded , space_before : bool ) -> j .JRightPadded :
297- return container .with_element (SpacesVisitor .space_before (container .element , space_before ))
298-
299- @staticmethod
300- def space_last_comment_suffix (comments : List [j .Comment ], space_suffix : bool ) -> List [j .Comment ]:
301- return [SpacesVisitor .space_suffix (comment , space_suffix ) if i == len (comments ) - 1 else comment for i , comment
302- in
303- enumerate (comments )]
304-
305- @staticmethod
306- def space_suffix (comment : j .Comment , space_suffix : bool ) -> j .Comment :
307- if space_suffix and not_single_space (comment .suffix ):
308- return comment .with_suffix (" " )
309- elif not space_suffix and only_spaces_and_not_empty (comment .suffix ):
310- return comment .with_suffix ("" )
311- else :
312- return comment
313-
314- @staticmethod
315- def space_before_jleftpadded (j : JLeftPadded [J ], space_before ) -> JLeftPadded [J ]:
316- space : Space = cast (Space , j .before )
317- if space .comments or '\\ ' in space .whitespace :
318- # don't touch whitespaces with comments or continuation characters
319- return j
320-
321- if space_before and not_single_space (space .whitespace ):
322- return j .with_before (space .with_whitespace (" " ))
323- elif not space_before and only_spaces_and_not_empty (space .whitespace ):
324- return j .with_before (space .with_whitespace ("" ))
278+
279+ J2 = TypeVar ('J2' , bound = j .J )
280+
281+
282+ def space_before (j : J2 , add_space : bool ) -> J2 :
283+ space : Space = cast (Space , j .prefix )
284+ if space .comments or '\\ ' in space .whitespace :
285+ # don't touch whitespaces with comments or continuation characters
286+ return j
287+
288+ return j .with_prefix (Space .SINGLE_SPACE if add_space else Space .EMPTY )
289+
290+
291+ def space_before_container (container : j .JContainer , add_space : bool ) -> j .JContainer :
292+ if container .before .comments :
293+ # Perform the space rule for the suffix of the last comment only. Same as IntelliJ.
294+ comments : List [j .Comment ] = space_last_comment_suffix (container .before .comments , add_space )
295+ return container .with_before (container .before .with_comments (comments ))
296+
297+ if add_space and not_single_space (container .before .whitespace ):
298+ return container .with_before (container .before .with_whitespace (" " ))
299+ elif not add_space and only_spaces_and_not_empty (container .before .whitespace ):
300+ return container .with_before (container .before .with_whitespace ("" ))
301+ else :
302+ return container
303+
304+
305+ def space_before_right_padded_element (container : j .JRightPadded , add_space : bool ) -> j .JRightPadded :
306+ return container .with_element (space_before (container .element , add_space ))
307+
308+
309+ def space_last_comment_suffix (comments : List [j .Comment ], add_space : bool ) -> List [j .Comment ]:
310+ return [space_suffix (comment , add_space ) if i == len (comments ) - 1 else comment for i , comment
311+ in
312+ enumerate (comments )]
313+
314+
315+ def space_suffix (comment : j .Comment , add_space : bool ) -> j .Comment :
316+ if add_space and not_single_space (comment .suffix ):
317+ return comment .with_suffix (" " )
318+ elif not add_space and only_spaces_and_not_empty (comment .suffix ):
319+ return comment .with_suffix ("" )
320+ else :
321+ return comment
322+
323+
324+ def space_before_left_padded (j : JLeftPadded [J2 ], add_space ) -> JLeftPadded [J2 ]:
325+ space : Space = cast (Space , j .before )
326+ if space .comments or '\\ ' in space .whitespace :
327+ # don't touch whitespaces with comments or continuation characters
325328 return j
326329
327- @ staticmethod
328- def space_after ( j : J , space_after : bool ) -> J :
329- space : Space = cast ( Space , j . after )
330- if space . comments or ' \\ ' in space .whitespace :
331- # don't touch whitespaces with comments or continuation characters
332- return j
333-
334- if space_after and not_single_space ( space . whitespace ) :
335- return j . with_after ( space . with_whitespace ( " " ) )
336- elif not space_after and only_spaces_and_not_empty ( space .whitespace ) :
337- return j . with_after ( space . with_whitespace ( "" ))
330+ if add_space and not_single_space ( space . whitespace ):
331+ return j . with_before ( space . with_whitespace ( " " ))
332+ elif not add_space and only_spaces_and_not_empty ( space . whitespace ):
333+ return j . with_before ( space .with_whitespace ( "" ))
334+ return j
335+
336+
337+ def space_after ( j : J2 , add_space : bool ) -> J2 :
338+ space : Space = cast ( Space , j . after )
339+ if space . comments or ' \\ ' in space .whitespace :
340+ # don't touch whitespaces with comments or continuation characters
338341 return j
339342
343+ if add_space and not_single_space (space .whitespace ):
344+ return j .with_after (space .with_whitespace (" " ))
345+ elif not add_space and only_spaces_and_not_empty (space .whitespace ):
346+ return j .with_after (space .with_whitespace ("" ))
347+ return j
348+
349+
350+ def space_after_right_padded (right : JRightPadded [J2 ], add_space : bool ) -> JRightPadded [J2 ]:
351+ space : Space = right .after
352+ if space .comments or '\\ ' in space .whitespace :
353+ # don't touch whitespaces with comments or continuation characters
354+ return right
355+
356+ if add_space and not_single_space (space .whitespace ):
357+ return right .with_after (space .with_whitespace (" " ))
358+ elif not add_space and only_spaces_and_not_empty (space .whitespace ):
359+ return right .with_after (space .with_whitespace ("" ))
360+ return right
361+
340362
341363def update_space (s : Space , have_space : bool ) -> Space :
342364 if s .comments :
0 commit comments