55from os import environ
66from subprocess import Popen , PIPE
77
8- PLUGIN_VERSION = "0.14 .0"
8+ PLUGIN_VERSION = "0.15 .0"
99
1010PACKAGE_PATH = os .path .abspath (os .path .dirname (__file__ ))
1111PACKAGE_NAME = os .path .basename (PACKAGE_PATH )
@@ -994,10 +994,11 @@ def selection_in_js_scope(view, point = -1, except_for = ""):
994994 return False
995995
996996 @staticmethod
997- def replace_with_tab (view , region , pre = "" , after = "" , add_to_each_line_before = "" , add_to_each_line_after = "" ) :
998- lines = view .substr (region ).split ( " \n " )
997+ def replace_with_tab (view , region , pre = "" , after = "" , add_to_each_line_before = "" , add_to_each_line_after = "" , lstrip = False ) :
998+ lines = view .substr (region ).splitlines ( )
999999 body = list ()
10001000 empty_line = 0
1001+ first_line = False
10011002 for line in lines :
10021003 if line .strip () == "" :
10031004 empty_line = empty_line + 1
@@ -1006,15 +1007,17 @@ def replace_with_tab(view, region, pre="", after="", add_to_each_line_before="",
10061007 continue
10071008 else :
10081009 empty_line = 0
1009- line = "\t " + add_to_each_line_before + line + add_to_each_line_after
1010+ line = ("\t " if (line and line [0 ] == " " ) or not first_line else "" ) + add_to_each_line_before + (line .lstrip () if lstrip else line ) + add_to_each_line_after
1011+ if not first_line :
1012+ first_line = True
10101013 body .append (line )
10111014 if body [len (body )- 1 ].strip () == "" :
10121015 del body [len (body )- 1 ]
10131016 body = "\n " .join (body )
10141017 return pre + body + after
10151018
10161019 @staticmethod
1017- def replace_without_tab (view , region , pre = "" , after = "" , add_to_each_line_before = "" , add_to_each_line_after = "" ) :
1020+ def replace_without_tab (view , region , pre = "" , after = "" , add_to_each_line_before = "" , add_to_each_line_after = "" , lstrip = False ) :
10181021 lines = view .substr (region ).split ("\n " )
10191022 body = list ()
10201023 empty_line = 0
@@ -1026,15 +1029,16 @@ def replace_without_tab(view, region, pre="", after="", add_to_each_line_before=
10261029 continue
10271030 else :
10281031 empty_line = 0
1029- body .append (add_to_each_line_before + line + add_to_each_line_after )
1032+ body .append (add_to_each_line_before + ( line . lstrip () if lstrip else line ) + add_to_each_line_after )
10301033 if body [len (body )- 1 ].strip () == "" :
10311034 del body [len (body )- 1 ]
10321035 body = "\n " .join (body )
10331036 return pre + body + after
10341037
10351038 @staticmethod
10361039 def get_whitespace_from_line_begin (view , region ) :
1037- return " " * ( region .begin () - view .line (region ).begin () )
1040+ n_space = len (view .substr (view .line (region ))) - len (view .substr (view .line (region )).lstrip ())
1041+ return " " * n_space
10381042
10391043 @staticmethod
10401044 def add_whitespace_indentation (view , region , string , replace = "\t " , add_whitespace_end = True ) :
@@ -1262,30 +1266,30 @@ def _wrapper_func_stdout_listen_error(process, func_stdout=None, args_func_stdou
12621266 char = b""
12631267
12641268 @staticmethod
1265- def nested_lookup (key , values , document , wild = False ):
1269+ def nested_lookup (key , values , document , wild = False , return_parent = False ):
12661270 """Lookup a key in a nested document, return a list of values"""
1267- return list (Util ._nested_lookup (key , values , document , wild = wild ))
1271+ return list (Util ._nested_lookup (key , values , document , wild = wild , return_parent = return_parent ))
12681272
12691273 @staticmethod
1270- def _nested_lookup (key , values , document , wild = False ):
1274+ def _nested_lookup (key , values , document , wild = False , return_parent = False ):
12711275 """Lookup a key in a nested document, yield a value"""
12721276 if isinstance (document , list ):
12731277 for d in document :
1274- for result in Util ._nested_lookup (key , values , d , wild = wild ):
1278+ for result in Util ._nested_lookup (key , values , d , wild = wild , return_parent = ( document if return_parent else False ) ):
12751279 yield result
12761280
12771281 if isinstance (document , dict ):
12781282 for k , v in document .items ():
12791283 if values and v in values and (key == k or (wild and key .lower () in k .lower ())):
1280- yield document
1284+ yield ( document if not return_parent else return_parent )
12811285 elif not values and key == k or (wild and key .lower () in k .lower ()):
1282- yield document
1286+ yield ( document if not return_parent else return_parent )
12831287 elif isinstance (v , dict ):
1284- for result in Util ._nested_lookup (key , values , v , wild = wild ):
1288+ for result in Util ._nested_lookup (key , values , v , wild = wild , return_parent = ( document if return_parent else False ) ):
12851289 yield result
12861290 elif isinstance (v , list ):
12871291 for d in v :
1288- for result in Util ._nested_lookup (key , values , d , wild = wild ):
1292+ for result in Util ._nested_lookup (key , values , d , wild = wild , return_parent = ( document if return_parent else False ) ):
12891293 yield result
12901294
12911295import time , os , re , threading , socket , traceback , sys , struct
@@ -6522,7 +6526,7 @@ def run(self, edit, **args):
65226526 windowView = WindowView (title = "Refactor - Safe Move" , use_compare_layout = True )
65236527 windowView .addTitle (text = "Refactor - Safe Move" )
65246528 windowView .add (text = "\n \n " )
6525- windowView .add (text = "NOTE: If you want this command checks all files and not just those with @flow, you need to add \" all=true\" into the .flowconfig [options]. See " )
6529+ windowView .add (text = "NOTE: If you want this command checks all the imported/exported JavaScript dependencies and not just those with @flow, you need to add \" all=true\" into the .flowconfig [options]. See " )
65266530 windowView .addLink (text = "here" , link = "https://flow.org/en/docs/config/options/#toc-all-boolean" , scope = "flow-toc-all-boolean" )
65276531 windowView .add (text = ".\n \n " )
65286532 windowView .addInput (value = view .file_name (), label = "Move to: " , region_id = "new_path" )
@@ -6539,7 +6543,7 @@ def run(self, edit, **args):
65396543 windowView = WindowView (title = "Refactor - Safe Copy" , use_compare_layout = True )
65406544 windowView .addTitle (text = "Refactor - Safe Copy" )
65416545 windowView .add (text = "\n \n " )
6542- windowView .add (text = "NOTE: If you want this command checks all files and not just those with @flow, you need to add \" all=true\" into the .flowconfig [options]. See " )
6546+ windowView .add (text = "NOTE: If you want this command checks all the imported/exported JavaScript dependencies and not just those with @flow, you need to add \" all=true\" into the .flowconfig [options]. See " )
65436547 windowView .addLink (text = "here" , link = "https://flow.org/en/docs/config/options/#toc-all-boolean" , scope = "flow-toc-all-boolean" )
65446548 windowView .add (text = ".\n \n " )
65456549 windowView .addInput (value = view .file_name (), label = "Copy to: " , region_id = "new_path" )
@@ -6556,7 +6560,7 @@ def run(self, edit, **args):
65566560 windowView = WindowView (title = "Refactor - Safe Delete" , use_compare_layout = True )
65576561 windowView .addTitle (text = "Refactor - Safe Delete" )
65586562 windowView .add (text = "\n \n " )
6559- windowView .add (text = "NOTE: If you want this command checks all files and not just those with @flow, you need to add \" all=true\" into the .flowconfig [options]. See " )
6563+ windowView .add (text = "NOTE: If you want this command checks all the imported/exported JavaScript dependencies and not just those with @flow, you need to add \" all=true\" into the .flowconfig [options]. See " )
65606564 windowView .addLink (text = "here" , link = "https://flow.org/en/docs/config/options/#toc-all-boolean" , scope = "flow-toc-all-boolean" )
65616565 windowView .add (text = ".\n \n " )
65626566 windowView .add (text = "File to delete: " + view .file_name ())
@@ -6575,9 +6579,6 @@ def run(self, edit, **args):
65756579 select_options = ['Global scope' , 'Current scope' , 'Class method' ]
65766580 if not view .match_selector (view .sel ()[0 ].begin (), 'meta.class.js' ):
65776581 select_options .remove ('Class method' )
6578- print (scope , len (scope .split (" " )))
6579- if len (scope .split (" " )) <= 2 :
6580- select_options .remove ('Global scope' )
65816582
65826583 windowView = WindowView (title = "Refactor - Extract Method" , use_compare_layout = True )
65836584 windowView .addTitle (text = "Refactor - Extract Method" )
@@ -7362,8 +7363,8 @@ class RefactorExtractMethodCommand(sublime_plugin.TextCommand):
73627363 def run (self , edit , ** args ):
73637364 view = self .view
73647365 selection = view .sel ()[0 ]
7366+ selection = Util .trim_Region (view , selection )
73657367 inputs = args .get ("inputs" )
7366- view_id_caller = args .get ("view_id_caller" ) if "view_id_caller" in args else None
73677368 scope = view .scope_name (selection .begin ()).strip ()
73687369 function_name = inputs ["function_name" ].strip ()
73697370 parameters = inputs ["parameters" ].strip ()
@@ -7440,34 +7441,92 @@ def run(self, edit, **args):
74407441 else :
74417442 for item in body :
74427443 r = sublime .Region (int (item ["range" ][0 ]), int (item ["range" ][1 ]))
7443- if r .contains (selection ):
7444+ if r .contains (selection ) or r . intersects ( selection ) :
74447445 region = r
74457446 break
74467447
74477448 if region :
7449+ prev_line_is_empty = Util .prev_line_is_empty (view , selection )
7450+ next_line_is_empty = Util .next_line_is_empty (view , selection )
7451+ space = Util .get_whitespace_from_line_begin (view , selection )
7452+ space_before = ("\n " + space if not prev_line_is_empty else "" )
7453+ space_after = "\n " + space
7454+ new_text = Util .replace_with_tab (view , selection , space_before + "function " + function_name + " " + parameters + " {\n " + space , "\n " + space + "}" + space_after )
74487455
7449- space = Util .get_whitespace_from_line_begin (view , region )
7450- new_text = Util .replace_with_tab (view , selection , "function " + function_name + " " + parameters + " {\n " + space , "\n " + space + "}\n " + space )
7456+ view .erase (edit , selection )
74517457 if Util .region_contains_scope (view , selection , "variable.language.this.js" ):
7452- view .replace (edit , selection , function_name + ".call(this" + (", " + parameters [1 :- 1 ] if parameters [1 :- 1 ].strip () else "" )+ ")" )
7458+ view .insert (edit , selection . begin () , function_name + ".call(this" + (", " + parameters [1 :- 1 ] if parameters [1 :- 1 ].strip () else "" )+ ")" )
74537459 else :
7454- view .replace (edit , selection , function_name + parameters )
7455- view .insert (edit , region .begin (), new_text )
7460+ view .insert (edit , selection . begin () , function_name + parameters )
7461+ view .insert (edit , region .begin () + ( 1 if view . substr ( region . begin ()) == "{" else 0 ) , new_text )
74567462
74577463 elif inputs ["scope" ] == "Global scope" :
74587464
7459- region_class = Util .get_region_scope_first_match (view , scope , selection , scope .split (" " )[1 ])["region" ]
7460- space = Util .get_whitespace_from_line_begin (view , region_class )
7461- new_text = Util .replace_with_tab (view , selection , "function " + function_name + " " + parameters + " {\n " + space , "\n " + space + "}\n \n " + space )
7465+ flow_cli = "flow"
7466+ is_from_bin = True
7467+ chdir = ""
7468+ use_node = True
7469+ bin_path = ""
74627470
7463- if Util .region_contains_scope (view , selection , "variable.language.this.js" ):
7464- view .replace (edit , selection , function_name + ".call(this" + (", " + parameters [1 :- 1 ] if parameters [1 :- 1 ].strip () else "" )+ ")" )
7465- else :
7466- view .replace (edit , selection , function_name + parameters )
7467- view .insert (edit , region_class .begin (), new_text )
7471+ settings = get_project_settings ()
7472+ if settings and settings ["project_settings" ]["flow_cli_custom_path" ]:
7473+ flow_cli = os .path .basename (settings ["project_settings" ]["flow_cli_custom_path" ])
7474+ bin_path = os .path .dirname (settings ["project_settings" ]["flow_cli_custom_path" ])
7475+ is_from_bin = False
7476+ chdir = settings ["project_dir_name" ]
7477+ use_node = False
7478+
7479+ node = NodeJS (check_local = True )
7480+
7481+ result = node .execute_check_output (
7482+ flow_cli ,
7483+ [
7484+ 'ast' ,
7485+ '--from' , 'sublime_text'
7486+ ],
7487+ is_from_bin = is_from_bin ,
7488+ use_fp_temp = True ,
7489+ fp_temp_contents = view .substr (sublime .Region (0 , view .size ())),
7490+ is_output_json = True ,
7491+ chdir = chdir ,
7492+ bin_path = bin_path ,
7493+ use_node = use_node
7494+ )
74687495
7469- if view_id_caller :
7470- windowViewManager .get (view_id_caller ).close ()
7496+ if result [0 ]:
7497+ if "body" in result [1 ]:
7498+ body = result [1 ]["body" ]
7499+ items = Util .nested_lookup ("type" , ["BlockStatement" ], body , return_parent = True )[::- 1 ]
7500+ region = None
7501+
7502+ for item in items :
7503+ r = sublime .Region (int (item ["range" ][0 ]), int (item ["range" ][1 ]))
7504+ if r .contains (selection ):
7505+ region = r
7506+ break
7507+ else :
7508+ for item in body :
7509+ r = sublime .Region (int (item ["range" ][0 ]), int (item ["range" ][1 ]))
7510+ if r .contains (selection ) or r .intersects (selection ):
7511+ region = r
7512+ break
7513+
7514+ if region :
7515+
7516+ prev_line_is_empty = Util .prev_line_is_empty (view , region )
7517+ next_line_is_empty = Util .next_line_is_empty (view , region )
7518+ space_before = ("\n " if not prev_line_is_empty else "" )
7519+
7520+ new_text = Util .replace_with_tab (view , selection , space_before + "function " + function_name + " " + parameters + " {\n " , "\n }\n \n " , lstrip = True )
7521+
7522+ view .erase (edit , selection )
7523+ view .insert (edit , region .begin (), new_text )
7524+ if Util .region_contains_scope (view , selection , "variable.language.this.js" ):
7525+ view .insert (edit , selection .begin () + len (Util .convert_tabs_using_tab_size (view , new_text )), function_name + ".call(this" + (", " + parameters [1 :- 1 ] if parameters [1 :- 1 ].strip () else "" )+ ")" )
7526+ else :
7527+ view .insert (edit , selection .begin () + len (Util .convert_tabs_using_tab_size (view , new_text )), function_name + parameters )
7528+
7529+ windowViewManager .close (view .id ())
74717530
74727531 def is_enabled (self , ** args ) :
74737532 view = self .view
@@ -8438,8 +8497,8 @@ def run(self, edit, **args):
84388497 if need_to_import :
84398498 last_import_region = ( import_regions [- 1 ] if import_regions else (sublime .Region (0 , 0 ) if not view .match_selector (0 , 'comment' ) else view .extract_scope (0 )) )
84408499
8441- text = "\n import " + ( "{ " + export_name + " }" if file_already_exists or export_to_search == "VariableDeclaration" else export_name ) + " from '" + rel_new_path + "'\n "
8442-
8500+ text = "\n import " + ( "{ " + export_name + " }" if file_already_exists or export_to_search == "VariableDeclaration" else export_name ) + " from '" + rel_new_path + "'\n " + ( " \n " if not Util . next_line_is_empty ( view , last_import_region ) else "" )
8501+
84438502 if not args .get ("preview" ):
84448503 view .insert (edit , last_import_region .end (), text )
84458504 else :
0 commit comments