Added first version of console autocompletion

This commit is contained in:
2020-06-09 22:26:47 +02:00
parent d7573f095f
commit af3a3ffe92
23 changed files with 1314 additions and 88 deletions
+4
View File
@@ -13,6 +13,10 @@ class ConceptEvaluator(OneReturnValueEvaluator):
NAME = "Concept"
def __init__(self, return_body=False):
"""
:param return_body: if True force the body of the concept
"""
super().__init__(self.NAME, [BuiltinConcepts.EVALUATION], 50)
self.return_body = return_body
@@ -0,0 +1,110 @@
from collections import namedtuple
import parso
from core.builtin_concepts import BuiltinConcepts
from core.sheerka.ExecutionContext import ExecutionContext
from core.sheerka.services.SheerkaFunctionsParametersHistory import SheerkaFunctionsParametersHistory
from evaluators.BaseEvaluator import OneReturnValueEvaluator
from evaluators.PythonEvaluator import PythonEvaluator
from parso.python.tree import Name, PythonNode, Operator
func_found = namedtuple("func_found", "name params")
class UpdateFunctionsParametersEvaluator(OneReturnValueEvaluator):
"""
This evaluator scans all successful PythonEvaluator results
It then records the parameters of every functions found.
For example, if the PythonEvaluator successfully evaluated
foo(1, 'string') + bar(3.14)
the parameters 1 and 'string' will be recorded for the function 'foo'
and the parameter 3.14 will be recorded for the function 'bar'
These records will later be used as input for auto-completion
"""
NAME = "UpdateFunctionsParameters"
def __init__(self):
super().__init__(self.NAME, [BuiltinConcepts.AFTER_EVALUATION], 79)
def matches(self, context, return_value):
"""
True if the return value is the successful result of PythonEvaluator
:param context:
:param return_value:
:return:
"""
return return_value.status and return_value.who == context.sheerka.get_evaluator_name(PythonEvaluator.NAME)
def eval(self, context: ExecutionContext, return_value):
sheerka = context.sheerka
params_record_service = sheerka.services[SheerkaFunctionsParametersHistory.NAME]
if not return_value.parents:
return self.add_not_found_error(sheerka, return_value)
for parent in return_value.parents:
if parent.who == sheerka.get_parser_name("Python") and \
parent.status and \
sheerka.isinstance(parent.body, BuiltinConcepts.PARSER_RESULT):
break
else:
return self.add_not_found_error(sheerka, return_value)
source = parent.body.source
parsed = parso.parse(source)
self.process_functions(context, params_record_service, parsed)
return return_value
def process_functions(self, context, service, node):
if not hasattr(node, "children"):
return
if (func := self.get_function(node)) is not None:
for i, p in enumerate(func.params):
service.record_function_parameter(context, func.name, i, p)
function_params = node.children[1].children[1]
if hasattr(function_params, "children"):
for child in function_params.children: # function parameters
self.process_functions(context, service, child)
else:
for child in node.children:
self.process_functions(context, service, child)
def add_not_found_error(self, sheerka, return_value):
error = sheerka.ret(self.name,
False,
sheerka.new(BuiltinConcepts.NOT_FOUND, body="source code"),
parents=[return_value])
if return_value.parents is None:
return_value.parents = [error]
else:
return_value.parents.append(error)
return return_value
@staticmethod
def get_function(node):
if len(node.children) == 2 and \
isinstance(node.children[0], Name) and \
isinstance(node.children[1], PythonNode) and \
node.children[1].type == "trailer" and \
len(node.children[1].children) >= 2 and \
isinstance(node.children[1].children[0], Operator) and \
node.children[1].children[0].value == "(" and \
isinstance(node.children[1].children[-1], Operator) and \
node.children[1].children[-1].value == ")":
name = node.children[0].value
if len(node.children[1].children) == 2:
params = []
else:
params_nodes = node.children[1].children[1]
if hasattr(params_nodes, "children"):
params = [p.get_code().strip() for p in params_nodes.children if not isinstance(p, Operator)]
else:
params = [params_nodes.get_code().strip()]
return func_found(name=name, params=params)
else:
return None