Skip to content

Commit

Permalink
handle multi-line fn defs in signatuer lookup
Browse files Browse the repository at this point in the history
  • Loading branch information
z80dev committed Dec 14, 2024
1 parent 3cc3fbd commit b4b970e
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 32 deletions.
57 changes: 26 additions & 31 deletions vyper_lsp/analyzer/AstAnalyzer.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,45 +57,17 @@ def __init__(self, ast: AST) -> None:
else:
self.diagnostics_enabled = True

def signature_help(
self, doc: Document, params: SignatureHelpParams
def _handle_internal_fn_signature(
self, doc: Document, current_line: str, fn_name: str
) -> Optional[SignatureHelp]:
# TODO: Implement checking external functions, module functions, and interfaces
current_line = doc.lines[params.position.line]
expression = get_expression_at_cursor(
current_line, params.position.character - 1
)
parsed = utils.parse_fncall_expression(expression)
if parsed is None:
return None
module, fn_name = parsed

logger.info(f"looking up function {fn_name} in module {module}")
if module in self.ast.imports:
logger.info("found module")
if fn := self.ast.imports[module].functions[fn_name]:
logger.info(f"args: {fn.arguments}")

# this returns for all external functions
if module != "self":
return None

node = self.ast.find_function_declaration_node_for_name(fn_name)
if not node:
return None

fn_name = node.name
parameters = []
line = doc.lines[node.lineno - 1]

decl_str = f"def {fn_name}("
search_start_line_no = 0

while not line.startswith(decl_str):
line = doc.lines[search_start_line_no]
search_start_line_no += 1

fn_label = line.removeprefix("def ").removesuffix(":\n")
fn_label = node.node_source_code.split(":\n")[0].removeprefix("def ")

for arg in node.args.args:
start_index = fn_label.find(arg.arg)
Expand All @@ -116,6 +88,29 @@ def signature_help(
active_signature=0,
)

def signature_help(
self, doc: Document, params: SignatureHelpParams
) -> Optional[SignatureHelp]:
# TODO: Implement checking external functions, module functions, and interfaces
current_line = doc.lines[params.position.line]
expression = get_expression_at_cursor(
current_line, params.position.character - 1
)
parsed = utils.parse_fncall_expression(expression)
if parsed is None:
return None
module, fn_name = parsed

logger.info(f"looking up function {fn_name} in module {module}")
if module in self.ast.imports:
logger.info("found module")
if fn := self.ast.imports[module].functions[fn_name]:
logger.info(f"args: {fn.arguments}")

# this returns for all external functions
if module == "self":
return self._handle_internal_fn_signature(doc, current_line, fn_name)

def _dot_completions_for_element(
self, element: str, top_level_node=None, line: str = ""
) -> List[CompletionItem]:
Expand Down
4 changes: 3 additions & 1 deletion vyper_lsp/ast.py
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,9 @@ def get_attributes_for_symbol(self, symbol: str):

return []

def find_function_declaration_node_for_name(self, function: str):
def find_function_declaration_node_for_name(
self, function: str
) -> Optional[nodes.FunctionDef]:
for node in self.get_descendants(nodes.FunctionDef):
name_match = node.name == function
not_interface_declaration = not isinstance(
Expand Down

0 comments on commit b4b970e

Please sign in to comment.