11# Copyright 2022- Python Language Server Contributors.
22
33import logging
4- from typing import Any , Dict , Generator , List , Set
4+ from typing import Any , Dict , Generator , List , Optional , Set
55
66import parso
77from jedi import Script
1515from pylsp .config .config import Config
1616from pylsp .workspace import Document , Workspace
1717
18+ from ._rope_task_handle import PylspTaskHandle
19+
1820log = logging .getLogger (__name__ )
1921
2022_score_pow = 5
@@ -46,8 +48,10 @@ def _should_insert(expr: tree.BaseNode, word_node: tree.Leaf) -> bool: # pylint
4648 if first_child == word_node :
4749 return True # If the word is the first word then its fine
4850 if len (expr .children ) > 1 :
49- if any (node .type == "operator" and "." in node .value or
50- node .type == "trailer" for node in expr .children ):
51+ if any (
52+ node .type == "operator" and "." in node .value or node .type == "trailer"
53+ for node in expr .children
54+ ):
5155 return False # Check if we're on a method of a function
5256 if isinstance (first_child , (tree .PythonErrorNode , tree .PythonNode )):
5357 # The tree will often include error nodes like this to indicate errors
@@ -56,8 +60,7 @@ def _should_insert(expr: tree.BaseNode, word_node: tree.Leaf) -> bool: # pylint
5660 return _handle_first_child (first_child , expr , word_node )
5761
5862
59- def _handle_first_child (first_child : NodeOrLeaf , expr : tree .BaseNode ,
60- word_node : tree .Leaf ) -> bool :
63+ def _handle_first_child (first_child : NodeOrLeaf , expr : tree .BaseNode , word_node : tree .Leaf ) -> bool :
6164 """Check if we suggest imports given the following first child."""
6265 if isinstance (first_child , tree .Import ):
6366 return False
@@ -121,22 +124,16 @@ def _process_statements(
121124 insert_line = autoimport .find_insertion_line (document .source ) - 1
122125 start = {"line" : insert_line , "character" : 0 }
123126 edit_range = {"start" : start , "end" : start }
124- edit = {
125- "range" : edit_range ,
126- "newText" : suggestion .import_statement + "\n "
127- }
128- score = _get_score (suggestion .source , suggestion .import_statement ,
129- suggestion .name , word )
127+ edit = {"range" : edit_range , "newText" : suggestion .import_statement + "\n " }
128+ score = _get_score (suggestion .source , suggestion .import_statement , suggestion .name , word )
130129 if score > _score_max :
131130 continue
132131 # TODO make this markdown
133132 yield {
134133 "label" : suggestion .name ,
135134 "kind" : suggestion .itemkind ,
136135 "sortText" : _sort_import (score ),
137- "data" : {
138- "doc_uri" : doc_uri
139- },
136+ "data" : {"doc_uri" : doc_uri },
140137 "detail" : _document (suggestion .import_statement ),
141138 "additionalTextEdits" : [edit ],
142139 }
@@ -150,8 +147,7 @@ def get_names(script: Script) -> Set[str]:
150147
151148
152149@hookimpl
153- def pylsp_completions (config : Config , workspace : Workspace , document : Document ,
154- position ):
150+ def pylsp_completions (config : Config , workspace : Workspace , document : Document , position ):
155151 """Get autoimport suggestions."""
156152 line = document .lines [position ["line" ]]
157153 expr = parso .parse (line )
@@ -161,17 +157,15 @@ def pylsp_completions(config: Config, workspace: Workspace, document: Document,
161157 word = word_node .value
162158 log .debug (f"autoimport: searching for word: { word } " )
163159 rope_config = config .settings (document_path = document .path ).get ("rope" , {})
164- ignored_names : Set [str ] = get_names (
165- document .jedi_script (use_document_path = True ))
160+ ignored_names : Set [str ] = get_names (document .jedi_script (use_document_path = True ))
166161 autoimport = workspace ._rope_autoimport (rope_config )
167- suggestions = list (
168- autoimport .search_full (word , ignored_names = ignored_names ))
162+ suggestions = list (autoimport .search_full (word , ignored_names = ignored_names ))
169163 results = list (
170164 sorted (
171- _process_statements (suggestions , document .uri , word , autoimport ,
172- document ),
165+ _process_statements (suggestions , document .uri , word , autoimport , document ),
173166 key = lambda statement : statement ["sortText" ],
174- ))
167+ )
168+ )
175169 if len (results ) > MAX_RESULTS :
176170 results = results [:MAX_RESULTS ]
177171 return results
@@ -181,11 +175,10 @@ def _document(import_statement: str) -> str:
181175 return """# Auto-Import\n """ + import_statement
182176
183177
184- def _get_score (source : int , full_statement : str , suggested_name : str ,
185- desired_name ) -> int :
178+ def _get_score (source : int , full_statement : str , suggested_name : str , desired_name ) -> int :
186179 import_length = len ("import" )
187180 full_statement_score = len (full_statement ) - import_length
188- suggested_name_score = ((len (suggested_name ) - len (desired_name )))** 2
181+ suggested_name_score = ((len (suggested_name ) - len (desired_name ))) ** 2
189182 source_score = 20 * source
190183 return suggested_name_score + full_statement_score + source_score
191184
@@ -198,24 +191,37 @@ def _sort_import(score: int) -> str:
198191 return "[z" + str (score ).rjust (_score_pow , "0" )
199192
200193
201- @hookimpl
202- def pylsp_initialize (config : Config , workspace : Workspace ):
203- """Initialize AutoImport. Generates the cache for local and global items."""
204- memory : bool = config .plugin_settings ("rope_autoimport" ).get (
205- "memory" , False )
194+ def _reload_cache (config : Config , workspace : Workspace , files : Optional [List [Document ]] = None ):
195+ memory : bool = config .plugin_settings ("rope_autoimport" ).get ("memory" , False )
206196 rope_config = config .settings ().get ("rope" , {})
207197 autoimport = workspace ._rope_autoimport (rope_config , memory )
208- autoimport .generate_modules_cache ()
209- autoimport .generate_cache ()
198+ task_handle = PylspTaskHandle (workspace )
199+ resources : Optional [List [Resource ]] = (
200+ None if files is None else [document ._rope_resource (rope_config ) for document in files ]
201+ )
202+ autoimport .generate_cache (task_handle = task_handle , resources = resources )
203+ autoimport .generate_modules_cache (task_handle = task_handle )
210204
211205
212206@hookimpl
213- def pylsp_document_did_save (config : Config , workspace : Workspace ,
214- document : Document ):
207+ def pylsp_initialize (config : Config , workspace : Workspace ):
208+ """Initialize AutoImport.
209+
210+ Generates the cache for local and global items.
211+ """
212+ _reload_cache (config , workspace )
213+
214+
215+ @hookimpl
216+ def pylsp_document_did_open (config : Config , workspace : Workspace ):
217+ """Initialize AutoImport.
218+
219+ Generates the cache for local and global items.
220+ """
221+ _reload_cache (config , workspace )
222+
223+
224+ @hookimpl
225+ def pylsp_document_did_save (config : Config , workspace : Workspace , document : Document ):
215226 """Update the names associated with this document."""
216- rope_config = config .settings ().get ("rope" , {})
217- rope_doucment : Resource = document ._rope_resource (rope_config )
218- autoimport = workspace ._rope_autoimport (rope_config )
219- autoimport .generate_cache (resources = [rope_doucment ])
220- # Might as well using saving the document as an indicator to regenerate the module cache
221- autoimport .generate_modules_cache ()
227+ _reload_cache (config , workspace , [document ])
0 commit comments