# completions_utils.py # # Copyright 2021 James Westman # # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as # published by the Free Software Foundation; either version 3 of the # License, or (at your option) any later version. # # This file is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this program. If not, see . # # SPDX-License-Identifier: LGPL-3.0-or-later import typing as T from . import ast from .tokenizer import Token, TokenType from .lsp_utils import Completion new_statement_patterns = [ [(TokenType.OPEN_BLOCK, None)], [(TokenType.CLOSE_BLOCK, None)], [(TokenType.STMT_END, None)], ] def applies_to(*ast_types): """ Decorator describing which AST nodes the completer should apply in. """ def decorator(func): for c in ast_types: c.completers.append(func) return func return decorator def completer(applies_in: T.List, matches: T.List=[], applies_in_subclass=None): def decorator(func): def inner(prev_tokens: T.List[Token], ast_node): # For completers that apply in ObjectContent nodes, we can further # check that the object is the right class if applies_in_subclass is not None: type = ast_node.root.gir.get_type(applies_in_subclass[1], applies_in_subclass[0]) if ast_node.gir_class and not ast_node.gir_class.assignable_to(type): return any_match = len(matches) == 0 match_variables: T.List[str] = [] for pattern in matches: match_variables = [] if len(pattern) <= len(prev_tokens): for i in range(0, len(pattern)): type, value = pattern[i] token = prev_tokens[i - len(pattern)] if token.type != type or (value is not None and str(token) != value): break if value is None: match_variables.append(str(token)) else: any_match = True break if not any_match: return yield from func(ast_node, match_variables) for c in applies_in: c.completers.append(inner) return inner return decorator