FazBrowse GitHub Viewer
|
Trending
|
URL:
|
Home
Tools:
[Download Repo ZIP]
[View Raw Code]
[Original HTTPS Page]
pythonVSCode/pythonFiles/preview/jedi/refactoring.py at master · modulexcite/pythonVSCode · GitHub
modulexcite
/
pythonVSCode
Public
forked from
DonJayamanne/pythonVSCode
Notifications
You must be signed in to change notification settings
Fork
0
Star
0
Code
Pull requests
0
Actions
Projects
Wiki
Security and quality
0
Insights
Additional navigation options
Code
Pull requests
Actions
Projects
Wiki
Security and quality
Insights
Expand file tree
Breadcrumbs
pythonVSCode
/
pythonFiles
/
preview
/
jedi
/
refactoring.py
Copy path
More file actions
More file actions
Latest commit
History
History
History
202 lines (167 loc) · 6.87 KB
Breadcrumbs
pythonVSCode
/
pythonFiles
/
preview
/
jedi
/
refactoring.py
Copy path
File metadata and controls
202 lines (167 loc) · 6.87 KB
Raw
Copy raw file
Download raw file
Open symbols panel
Edit and raw actions
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
"""
Introduce some basic refactoring functions to |jedi|. This module is still in a
very early development stage and needs much testing and improvement.
.. warning:: I won't do too much here, but if anyone wants to step in, please
do. Refactoring is none of my priorities
It uses the |jedi| `API <plugin-api.html>`_ and supports currently the
following functions (sometimes bug-prone):
- rename
- extract variable
- inline variable
"""
import
difflib
from
jedi
import
common
from
jedi
.
evaluate
import
helpers
from
jedi
.
parser
import
tree
as
pt
class
Refactoring
(
object
):
def
__init__
(
self
,
change_dct
):
"""
:param change_dct: dict(old_path=(new_path, old_lines, new_lines))
"""
self
.
change_dct
=
change_dct
def
old_files
(
self
):
dct
=
{}
for
old_path
, (
new_path
,
old_l
,
new_l
)
in
self
.
change_dct
.
items
():
dct
[
new_path
]
=
'
\n
'
.
join
(
new_l
)
return
dct
def
new_files
(
self
):
dct
=
{}
for
old_path
, (
new_path
,
old_l
,
new_l
)
in
self
.
change_dct
.
items
():
dct
[
new_path
]
=
'
\n
'
.
join
(
new_l
)
return
dct
def
diff
(
self
):
texts
=
[]
for
old_path
, (
new_path
,
old_l
,
new_l
)
in
self
.
change_dct
.
items
():
if
old_path
:
udiff
=
difflib
.
unified_diff
(
old_l
,
new_l
)
else
:
udiff
=
difflib
.
unified_diff
(
old_l
,
new_l
,
old_path
,
new_path
)
texts
.
append
(
'
\n
'
.
join
(
udiff
))
return
'
\n
'
.
join
(
texts
)
def
rename
(
script
,
new_name
):
""" The `args` / `kwargs` params are the same as in `api.Script`.
:param operation: The refactoring operation to execute.
:type operation: str
:type source: str
:return: list of changed lines/changed files
"""
return
Refactoring
(
_rename
(
script
.
usages
(),
new_name
))
def
_rename
(
names
,
replace_str
):
""" For both rename and inline. """
order
=
sorted
(
names
,
key
=
lambda
x
: (
x
.
module_path
,
x
.
line
,
x
.
column
),
reverse
=
True
)
def
process
(
path
,
old_lines
,
new_lines
):
if
new_lines
is
not
None
:
# goto next file, save last
dct
[
path
]
=
path
,
old_lines
,
new_lines
dct
=
{}
current_path
=
object
()
new_lines
=
old_lines
=
None
for
name
in
order
:
if
name
.
in_builtin_module
():
continue
if
current_path
!=
name
.
module_path
:
current_path
=
name
.
module_path
process
(
current_path
,
old_lines
,
new_lines
)
if
current_path
is
not
None
:
# None means take the source that is a normal param.
with
open
(
current_path
)
as
f
:
source
=
f
.
read
()
new_lines
=
common
.
splitlines
(
common
.
source_to_unicode
(
source
))
old_lines
=
new_lines
[:]
nr
,
indent
=
name
.
line
,
name
.
column
line
=
new_lines
[
nr
-
1
]
new_lines
[
nr
-
1
]
=
line
[:
indent
]
+
replace_str
+
\
line
[
indent
+
len
(
name
.
name
):]
process
(
current_path
,
old_lines
,
new_lines
)
return
dct
def
extract
(
script
,
new_name
):
""" The `args` / `kwargs` params are the same as in `api.Script`.
:param operation: The refactoring operation to execute.
:type operation: str
:type source: str
:return: list of changed lines/changed files
"""
new_lines
=
common
.
splitlines
(
common
.
source_to_unicode
(
script
.
source
))
old_lines
=
new_lines
[:]
user_stmt
=
script
.
_parser
.
user_stmt
()
# TODO care for multiline extracts
dct
=
{}
if
user_stmt
:
pos
=
script
.
_pos
line_index
=
pos
[
0
]
-
1
arr
,
index
=
helpers
.
array_for_pos
(
user_stmt
,
pos
)
if
arr
is
not
None
:
start_pos
=
arr
[
index
].
start_pos
end_pos
=
arr
[
index
].
end_pos
# take full line if the start line is different from end line
e
=
end_pos
[
1
]
if
end_pos
[
0
]
==
start_pos
[
0
]
else
None
start_line
=
new_lines
[
start_pos
[
0
]
-
1
]
text
=
start_line
[
start_pos
[
1
]:
e
]
for
l
in
range
(
start_pos
[
0
],
end_pos
[
0
]
-
1
):
text
+=
'
\n
'
+
l
if
e
is
None
:
end_line
=
new_lines
[
end_pos
[
0
]
-
1
]
text
+=
'
\n
'
+
end_line
[:
end_pos
[
1
]]
# remove code from new lines
t
=
text
.
lstrip
()
del_start
=
start_pos
[
1
]
+
len
(
text
)
-
len
(
t
)
text
=
t
.
rstrip
()
del_end
=
len
(
t
)
-
len
(
text
)
if
e
is
None
:
new_lines
[
end_pos
[
0
]
-
1
]
=
end_line
[
end_pos
[
1
]
-
del_end
:]
e
=
len
(
start_line
)
else
:
e
=
e
-
del_end
start_line
=
start_line
[:
del_start
]
+
new_name
+
start_line
[
e
:]
new_lines
[
start_pos
[
0
]
-
1
]
=
start_line
new_lines
[
start_pos
[
0
]:
end_pos
[
0
]
-
1
]
=
[]
# add parentheses in multiline case
open_brackets
=
[
'('
,
'['
,
'{'
]
close_brackets
=
[
')'
,
']'
,
'}'
]
if
'
\n
'
in
text
and
not
(
text
[
0
]
in
open_brackets
and
text
[
-
1
]
==
close_brackets
[
open_brackets
.
index
(
text
[
0
])]):
text
=
'(%s)'
%
text
# add new line before statement
indent
=
user_stmt
.
start_pos
[
1
]
new
=
"%s%s = %s"
%
(
' '
*
indent
,
new_name
,
text
)
new_lines
.
insert
(
line_index
,
new
)
dct
[
script
.
path
]
=
script
.
path
,
old_lines
,
new_lines
return
Refactoring
(
dct
)
def
inline
(
script
):
"""
:type script: api.Script
"""
new_lines
=
common
.
splitlines
(
common
.
source_to_unicode
(
script
.
source
))
dct
=
{}
definitions
=
script
.
goto_assignments
()
with
common
.
ignored
(
AssertionError
):
assert
len
(
definitions
)
==
1
stmt
=
definitions
[
0
].
_definition
usages
=
script
.
usages
()
inlines
=
[
r
for
r
in
usages
if
not
stmt
.
start_pos
<=
(
r
.
line
,
r
.
column
)
<=
stmt
.
end_pos
]
inlines
=
sorted
(
inlines
,
key
=
lambda
x
: (
x
.
module_path
,
x
.
line
,
x
.
column
),
reverse
=
True
)
expression_list
=
stmt
.
expression_list
()
# don't allow multiline refactorings for now.
assert
stmt
.
start_pos
[
0
]
==
stmt
.
end_pos
[
0
]
index
=
stmt
.
start_pos
[
0
]
-
1
line
=
new_lines
[
index
]
replace_str
=
line
[
expression_list
[
0
].
start_pos
[
1
]:
stmt
.
end_pos
[
1
]
+
1
]
replace_str
=
replace_str
.
strip
()
# tuples need parentheses
if
expression_list
and
isinstance
(
expression_list
[
0
],
pr
.
Array
):
arr
=
expression_list
[
0
]
if
replace_str
[
0
]
not
in
[
'('
,
'['
,
'{'
]
and
len
(
arr
)
>
1
:
replace_str
=
'(%s)'
%
replace_str
# if it's the only assignment, remove the statement
if
len
(
stmt
.
get_defined_names
())
==
1
:
line
=
line
[:
stmt
.
start_pos
[
1
]]
+
line
[
stmt
.
end_pos
[
1
]:]
dct
=
_rename
(
inlines
,
replace_str
)
# remove the empty line
new_lines
=
dct
[
script
.
path
][
2
]
if
line
.
strip
():
new_lines
[
index
]
=
line
else
:
new_lines
.
pop
(
index
)
return
Refactoring
(
dct
)
Back
|
FazBrowse Home
|
New Git URL