From ec8e0b437ad97998ce91b18c21582b537da5315a Mon Sep 17 00:00:00 2001 From: z80 Date: Tue, 5 Dec 2023 23:27:54 -0500 Subject: [PATCH] fix some review items mainly moving code to utils --- vyper_lsp/analyzer/AstAnalyzer.py | 46 +++++++------------------------ vyper_lsp/navigation.py | 31 +++++++++------------ vyper_lsp/utils.py | 35 +++++++++++++++++++++++ 3 files changed, 58 insertions(+), 54 deletions(-) diff --git a/vyper_lsp/analyzer/AstAnalyzer.py b/vyper_lsp/analyzer/AstAnalyzer.py index 4be40c8..b902137 100644 --- a/vyper_lsp/analyzer/AstAnalyzer.py +++ b/vyper_lsp/analyzer/AstAnalyzer.py @@ -5,6 +5,7 @@ from packaging.version import Version from lsprotocol.types import ( Diagnostic, + DiagnosticSeverity, ParameterInformation, Position, Range, @@ -22,6 +23,9 @@ get_word_at_cursor, get_installed_vyper_version, get_internal_fn_name_at_cursor, + diagnostic_from_exception, + is_internal_fn, + is_state_var, ) from lsprotocol.types import ( CompletionItem, @@ -60,21 +64,6 @@ def __init__(self, ast: AST) -> None: else: self.diagnostics_enabled = True - # REVIEW: could be standalone (does not need `self`) - def _range_from_exception(self, node: VyperException) -> Range: - return Range( - start=Position(line=node.lineno - 1, character=node.col_offset), - end=Position(line=node.end_lineno - 1, character=node.end_col_offset), - ) - - # REVIEW: could be standalone (does not need `self`) - def _diagnostic_from_exception(self, node: VyperException) -> Diagnostic: - return Diagnostic( - range=self._range_from_exception(node), - message=str(node), - severity=1, - ) - def signature_help( self, doc: Document, params: SignatureHelpParams ) -> SignatureHelp: @@ -94,10 +83,6 @@ def signature_help( return None fn_name = node.name - # REVIEW: fix arg.annotation.id -- should probably use _format_arg - arg_str = ", ".join( - [f"{arg.arg}: {arg.annotation.id}" for arg in node.args.args] - ) parameters = [] line = doc.lines[node.lineno - 1] fn_label = line.removeprefix("def ").removesuffix(":\n") @@ -106,9 +91,7 @@ def signature_help( start_index = fn_label.find(arg.arg) end_index = start_index + len(arg.arg) parameters.append( - ParameterInformation( - label=(start_index, end_index), documentation=None - ) + ParameterInformation(label=(start_index, end_index), documentation=None) ) active_parameter = current_line.split("(")[-1].count(",") return SignatureHelp( @@ -175,21 +158,12 @@ def get_completions_in_doc( return CompletionList(is_incomplete=False, items=[]) - def get_completions( self, ls: LanguageServer, params: CompletionParams ) -> CompletionList: document = ls.workspace.get_text_document(params.text_document.uri) return self.get_completions_in_doc(document, params) - # this looks like duplicated code, could be in utils - def _is_internal_fn(self, expression: str) -> bool: - return expression.startswith("self.") and "(" in expression - - # this looks like duplicated code, could be in utils - def _is_state_var(self, expression: str) -> bool: - return expression.startswith("self.") and "(" not in expression - def _format_arg(self, arg: nodes.arg) -> str: if arg.annotation is None: return arg.arg @@ -238,11 +212,11 @@ def hover_info(self, document: Document, pos: Position) -> Optional[str]: word = get_word_at_cursor(og_line, pos.character) full_word = get_expression_at_cursor(og_line, pos.character) - if self._is_internal_fn(full_word): + if is_internal_fn(full_word): node = self.ast.find_function_declaration_node_for_name(word) return node and self._format_fn_signature(node) - if self._is_state_var(full_word): + if is_state_var(full_word): node = self.ast.find_state_variable_declaration_node_for_name(word) if not node: return None @@ -285,10 +259,10 @@ def get_diagnostics(self, doc: Document) -> List[Diagnostic]: compiler_data.vyper_module_folded except VyperException as e: if e.lineno is not None and e.col_offset is not None: - diagnostics.append(self._diagnostic_from_exception(e)) + diagnostics.append(diagnostic_from_exception(e)) else: for a in e.annotations: - diagnostics.append(self._diagnostic_from_exception(a)) + diagnostics.append(diagnostic_from_exception(a)) for warning in w: m = deprecation_pattern.match(str(warning.message)) if not m: @@ -315,7 +289,7 @@ def get_diagnostics(self, doc: Document) -> List[Diagnostic]: ), ), message=f"{deprecated} is deprecated. Please use {replacement} instead.", - severity=2, + severity=DiagnosticSeverity.Warning, ) ) diff --git a/vyper_lsp/navigation.py b/vyper_lsp/navigation.py index 03b0a2f..8bfcc36 100644 --- a/vyper_lsp/navigation.py +++ b/vyper_lsp/navigation.py @@ -6,7 +6,11 @@ from pygls.workspace import Document from vyper.ast import EnumDef, FunctionDef, VyperNode from vyper_lsp.ast import AST -from vyper_lsp.utils import get_expression_at_cursor, get_word_at_cursor +from vyper_lsp.utils import ( + get_expression_at_cursor, + get_word_at_cursor, + range_from_node, +) ENUM_VARIANT_PATTERN = re.compile(r"([a-zA-Z_][a-zA-Z0-9_]*)\.([a-zA-Z_][a-zA-Z0-9_]*)") @@ -21,19 +25,10 @@ class ASTNavigator: def __init__(self, ast: AST): self.ast = ast - # REVIEW: rename to `_range_from_node` - # maybe belongs in utils - # pure function (does not need `self`) - def _create_range_from_node(self, node: VyperNode) -> Range: - return Range( - start=Position(line=node.lineno - 1, character=node.col_offset), - end=Position(line=node.end_lineno - 1, character=node.end_col_offset), - ) - def _find_state_variable_declaration(self, word: str) -> Optional[Range]: node = self.ast.find_state_variable_declaration_node_for_name(word) if node: - return self._create_range_from_node(node) + return range_from_node(node) return None @@ -42,21 +37,21 @@ def _find_variable_declaration_under_node( ) -> Optional[Range]: decl_node = AST.from_node(node).find_node_declaring_symbol(symbol) if decl_node: - return self._create_range_from_node(decl_node) + return range_from_node(decl_node) return None def _find_function_declaration(self, word: str) -> Optional[Range]: node = self.ast.find_function_declaration_node_for_name(word) if node: - return self._create_range_from_node(node) + return range_from_node(node) return None def find_type_declaration(self, word: str) -> Optional[Range]: node = self.ast.find_type_declaration_node_for_name(word) if node: - return self._create_range_from_node(node) + return range_from_node(node) return None @@ -91,13 +86,13 @@ def find_references(self, doc: Document, pos: Position) -> List[Range]: refs = [] # REVIEW: this can help with early returns - # ex. + # ex. # if word in self.ast.get_enums(): # return finalize(self.ast.find_nodes_referencing_enum(word)) # # if word in self.ast.get_structs() or word in self.ast.get_events(): # return finalize(self.ast.find_nodes_referencing_struct(word)) - #def finalize(refs): + # def finalize(refs): # return [_range_from_node(ref) for ref in refs] if word in self.ast.get_enums(): @@ -120,7 +115,7 @@ def find_references(self, doc: Document, pos: Position) -> List[Range]: refs = AST.from_node(top_level_node).find_nodes_referencing_symbol(word) for ref in refs: - range_ = self._create_range_from_node(ref) + range_ = range_from_node(ref) references.append(range_) return references @@ -131,7 +126,7 @@ def _match_enum_variant(self, full_word: str) -> Optional[re.Match]: if ( match_ and match_.group(1) in self.ast.get_enums() - and match_.group(2) in self.ast.get_enum_variants(m.group(1)) + and match_.group(2) in self.ast.get_enum_variants(match_.group(1)) ): return match_ diff --git a/vyper_lsp/utils.py b/vyper_lsp/utils.py index 4abb0f9..0162583 100644 --- a/vyper_lsp/utils.py +++ b/vyper_lsp/utils.py @@ -2,7 +2,10 @@ import re from pathlib import Path from importlib.metadata import version +from lsprotocol.types import Diagnostic, DiagnosticSeverity, Position, Range from packaging.version import Version +from vyper.ast import VyperNode +from vyper.exceptions import VyperException from vyper.compiler import CompilerData @@ -158,3 +161,35 @@ def extract_enum_name(line: str): if m: return m.group(1) return None + + +def range_from_node(node: VyperNode) -> Range: + return Range( + start=Position(line=node.lineno - 1, character=node.col_offset), + end=Position(line=node.end_lineno - 1, character=node.end_col_offset), + ) + + +def range_from_exception(node: VyperException) -> Range: + return Range( + start=Position(line=node.lineno - 1, character=node.col_offset), + end=Position(line=node.end_lineno - 1, character=node.end_col_offset), + ) + + +def diagnostic_from_exception(node: VyperException) -> Diagnostic: + return Diagnostic( + range=range_from_exception(node), + message=str(node), + severity=DiagnosticSeverity.Error, + ) + + +# this looks like duplicated code, could be in utils +def is_internal_fn(expression: str) -> bool: + return expression.startswith("self.") and "(" in expression + + +# this looks like duplicated code, could be in utils +def is_state_var(expression: str) -> bool: + return expression.startswith("self.") and "(" not in expression