Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 57dbcfe

Browse files
committedDec 15, 2024··
refactor dot completion
1 parent 4e0c13a commit 57dbcfe

File tree

1 file changed

+48
-63
lines changed

1 file changed

+48
-63
lines changed
 

‎vyper_lsp/analyzer/AstAnalyzer.py

+48-63
Original file line numberDiff line numberDiff line change
@@ -134,55 +134,63 @@ def signature_help(
134134
else:
135135
return self._handle_imported_fn_signature(current_line, module, fn_name)
136136

137+
def _dot_completions_for_module(
138+
self, element: str, top_level_node=None, line: str = ""
139+
) -> List[CompletionItem]:
140+
completions = []
141+
for name, fn in self.ast.imports[element].functions.items():
142+
doc_string = ""
143+
if getattr(fn.ast_def, "doc_string", False):
144+
doc_string = fn.ast_def.doc_string.value
145+
146+
out = format_fn(fn)
147+
148+
# NOTE: this just gets ignored by most editors
149+
# so we put the signature in the documentation string also
150+
completion_item_label_details = CompletionItemLabelDetails(detail=out)
151+
152+
doc_string = f"{out}\n{doc_string}"
153+
154+
show_external: bool = isinstance(
155+
top_level_node, nodes.ExportsDecl
156+
) or line.startswith("exports:")
157+
show_internal_and_deploy: bool = isinstance(
158+
top_level_node, nodes.FunctionDef
159+
)
160+
161+
if show_internal_and_deploy and (fn.is_internal or fn.is_deploy):
162+
completions.append(
163+
CompletionItem(
164+
label=name,
165+
documentation=doc_string,
166+
label_details=completion_item_label_details,
167+
)
168+
)
169+
elif show_external and fn.is_external:
170+
completions.append(
171+
CompletionItem(
172+
label=name,
173+
documentation=doc_string,
174+
label_details=completion_item_label_details,
175+
)
176+
)
177+
178+
return completions
179+
137180
def _dot_completions_for_element(
138181
self, element: str, top_level_node=None, line: str = ""
139182
) -> List[CompletionItem]:
140183
completions = []
141-
logger.info(f"getting dot completions for element: {element}")
142184
if element == "self":
143185
for fn in self.ast.get_internal_functions():
144186
completions.append(CompletionItem(label=fn))
145187
# TODO: This should exclude constants and immutables
146188
for var in self.ast.get_state_variables():
147189
completions.append(CompletionItem(label=var))
148190
elif self.ast.imports and element in self.ast.imports.keys():
149-
for name, fn in self.ast.imports[element].functions.items():
150-
doc_string = ""
151-
if getattr(fn.ast_def, "doc_string", False):
152-
doc_string = fn.ast_def.doc_string.value
153-
154-
# out = self._format_fn_signature(fn.decl_node)
155-
out = format_fn(fn)
156-
157-
# NOTE: this just gets ignored by most editors
158-
# so we put the signature in the documentation string also
159-
completion_item_label_details = CompletionItemLabelDetails(detail=out)
160-
161-
doc_string = f"{out}\n{doc_string}"
162-
163-
show_external: bool = isinstance(
164-
top_level_node, nodes.ExportsDecl
165-
) or line.startswith("exports:")
166-
show_internal_and_deploy: bool = isinstance(
167-
top_level_node, nodes.FunctionDef
168-
)
169-
170-
if show_internal_and_deploy and (fn.is_internal or fn.is_deploy):
171-
completions.append(
172-
CompletionItem(
173-
label=name,
174-
documentation=doc_string,
175-
label_details=completion_item_label_details,
176-
)
177-
)
178-
elif show_external and fn.is_external:
179-
completions.append(
180-
CompletionItem(
181-
label=name,
182-
documentation=doc_string,
183-
label_details=completion_item_label_details,
184-
)
185-
)
191+
completions = self._dot_completions_for_module(
192+
element, top_level_node=top_level_node, line=line
193+
)
186194
elif element in self.ast.flags:
187195
members = self.ast.flags[element]._flag_members
188196
for member in members.keys():
@@ -229,7 +237,6 @@ def _get_completions_in_doc(
229237
if len(dot_completions) > 0:
230238
return CompletionList(is_incomplete=False, items=dot_completions)
231239
else:
232-
logger.info(f"no dot completions for {element}")
233240
for attr in self.ast.get_attributes_for_symbol(element):
234241
items.append(CompletionItem(label=attr))
235242
completions = CompletionList(is_incomplete=False, items=items)
@@ -242,13 +249,14 @@ def _get_completions_in_doc(
242249
return completions
243250

244251
if params.context.trigger_character == ":":
245-
# return empty_completions if the line starts with "flag", "struct", or "event"
252+
# return empty_completions if colon isn't for a type annotation
246253
object_declaration_keywords = [
247254
"flag",
248255
"struct",
249256
"event",
250257
"enum",
251258
"interface",
259+
"def",
252260
]
253261
if any(
254262
current_line.startswith(keyword)
@@ -278,29 +286,6 @@ def get_completions(
278286
document = ls.workspace.get_text_document(params.text_document.uri)
279287
return self._get_completions_in_doc(document, params)
280288

281-
def _format_arg(self, arg: nodes.arg) -> str:
282-
if arg.annotation is None:
283-
return arg.arg
284-
285-
# Handle case when annotation is a subscript (e.g., List[int])
286-
if isinstance(arg.annotation, nodes.Subscript):
287-
annotation_base = arg.annotation.value.id # e.g., 'List' in 'List[int]'
288-
289-
# Check if the subscript's slice is a simple name
290-
if isinstance(arg.annotation.slice.value, nodes.Name):
291-
annotation_subscript = (
292-
arg.annotation.slice.value.id
293-
) # e.g., 'int' in 'List[int]'
294-
else:
295-
annotation_subscript = (
296-
arg.annotation.slice.value.value
297-
) # Handle other subscript types
298-
299-
return f"{arg.arg}: {annotation_base}[{annotation_subscript}]"
300-
301-
# Default case for simple annotations
302-
return f"{arg.arg}: {arg.annotation.id}"
303-
304289
def _format_fn_signature(self, node: nodes.FunctionDef) -> str:
305290
pattern = r"def\s+(\w+)\((?:[^()]|\n)*\)(?:\s*->\s*[\w\[\], \n]+)?:"
306291
match = re.search(pattern, node.node_source_code, re.MULTILINE)

0 commit comments

Comments
 (0)
Please sign in to comment.