Skip to content

Commit

Permalink
Move signature code to dedicated handler
Browse files Browse the repository at this point in the history
  • Loading branch information
z80dev committed Dec 15, 2024
1 parent 57dbcfe commit 8bc0af8
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 79 deletions.
3 changes: 2 additions & 1 deletion tests/test_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from pygls.workspace import Document
from vyper_lsp.ast import AST
from vyper_lsp.analyzer.AstAnalyzer import AstAnalyzer
from vyper_lsp.handlers.signatures import SignatureHandler


def test_signature_help(ast: AST):
Expand All @@ -23,7 +24,7 @@ def foobar():
self.foo(self.baz(1), 2)
"""
ast.build_ast(src)
analyzer = AstAnalyzer(ast)
analyzer = SignatureHandler(ast)

doc = Document(uri="<inline source code>", source=src)

Expand Down
77 changes: 0 additions & 77 deletions vyper_lsp/analyzer/AstAnalyzer.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,83 +57,6 @@ def __init__(self, ast: AST) -> None:
else:
self.diagnostics_enabled = True

def _handle_internal_fn_signature(
self, current_line: str, fn_name: str
) -> Optional[SignatureHelp]:
node = self.ast.find_function_declaration_node_for_name(fn_name)
if not node:
return None

fn_name = node.name
parameters = []

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

for arg in node.args.args:
start_index = fn_label.find(arg.arg)
end_index = start_index + len(arg.arg)
parameters.append(
ParameterInformation(label=(start_index, end_index), documentation=None)
)
active_parameter = current_line.split("(")[-1].count(",")
return SignatureHelp(
signatures=[
SignatureInformation(
label=fn_label,
parameters=parameters,
documentation=None,
active_parameter=active_parameter or 0,
)
],
active_signature=0,
)

def _handle_imported_fn_signature(
self, current_line: str, module: str, fn_name: str
) -> Optional[SignatureHelp]:
if module in self.ast.imports:
if fn := self.ast.imports[module].functions[fn_name]:
logger.info(f"getting signature for {fn_name}")
logger.info(fn.decl_node)
node: FunctionDef = fn.decl_node
label = node.node_source_code.split("def ")[1].split(":\n")[0]
parameters = []
for arg in node.args.args:
parameters.append(
ParameterInformation(label=arg.arg, documentation=None)
)
active_parameter = current_line.split("(")[-1].count(",")
return SignatureHelp(
signatures=[
SignatureInformation(
label=label,
parameters=parameters,
documentation=None,
active_parameter=active_parameter or 0,
)
],
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

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

def _dot_completions_for_module(
self, element: str, top_level_node=None, line: str = ""
) -> List[CompletionItem]:
Expand Down
93 changes: 93 additions & 0 deletions vyper_lsp/handlers/signatures.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import logging

from pygls.workspace import Document
from vyper.ast import FunctionDef
from typing import Optional

from lsprotocol.types import ParameterInformation, SignatureHelp, SignatureHelpParams, SignatureInformation
from vyper_lsp import utils
from vyper_lsp.ast import AST
from vyper_lsp.utils import get_expression_at_cursor

logger = logging.getLogger("vyper-lsp")

class SignatureHandler:
def __init__(self, ast: AST):
self.ast = ast

def _handle_internal_fn_signature(
self, current_line: str, fn_name: str
) -> Optional[SignatureHelp]:
node = self.ast.find_function_declaration_node_for_name(fn_name)
if not node:
return None

fn_name = node.name
parameters = []

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

for arg in node.args.args:
start_index = fn_label.find(arg.arg)
end_index = start_index + len(arg.arg)
parameters.append(
ParameterInformation(label=(start_index, end_index), documentation=None)
)
active_parameter = current_line.split("(")[-1].count(",")
return SignatureHelp(
signatures=[
SignatureInformation(
label=fn_label,
parameters=parameters,
documentation=None,
active_parameter=active_parameter or 0,
)
],
active_signature=0,
)

def _handle_imported_fn_signature(
self, current_line: str, module: str, fn_name: str
) -> Optional[SignatureHelp]:
if module in self.ast.imports:
if fn := self.ast.imports[module].functions[fn_name]:
logger.info(f"getting signature for {fn_name}")
logger.info(fn.decl_node)
node: FunctionDef = fn.decl_node
label = node.node_source_code.split("def ")[1].split(":\n")[0]
parameters = []
for arg in node.args.args:
parameters.append(
ParameterInformation(label=arg.arg, documentation=None)
)
active_parameter = current_line.split("(")[-1].count(",")
return SignatureHelp(
signatures=[
SignatureInformation(
label=label,
parameters=parameters,
documentation=None,
active_parameter=active_parameter or 0,
)
],
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

# this returns for all external functions
if module == "self":
return self._handle_internal_fn_signature(current_line, fn_name)
else:
return self._handle_imported_fn_signature(current_line, module, fn_name)
4 changes: 3 additions & 1 deletion vyper_lsp/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
from packaging.version import Version
from pygls.server import LanguageServer
from vyper_lsp.analyzer.AstAnalyzer import AstAnalyzer
from vyper_lsp.handlers.signatures import SignatureHandler
from vyper_lsp.analyzer.SourceAnalyzer import SourceAnalyzer
from vyper_lsp.debounce import Debouncer

Expand All @@ -53,6 +54,7 @@
completer = ast_analyzer
source_analyzer = SourceAnalyzer()

signature_handler = SignatureHandler(ast)

debouncer = Debouncer(wait=0.5)

Expand Down Expand Up @@ -152,7 +154,7 @@ def hover(ls: LanguageServer, params: HoverParams):
)
def signature_help(ls: LanguageServer, params: SignatureHelpParams):
document = ls.workspace.get_text_document(params.text_document.uri)
signature_info = ast_analyzer.signature_help(document, params)
signature_info = signature_handler.signature_help(document, params)
if signature_info:
return signature_info

Expand Down

0 comments on commit 8bc0af8

Please sign in to comment.