def process_as(self, stack, parse_state): """ Process an upcoming 'as' rule and decide whether it can occur. """ if parse_state.in_assignment: # use of 'as' in an assignment is definitely invalid return if parse_state.nestedness != 0: # use of 'as' inside parenthesis is definitely invalid return as_keyword = KeywordCompletionSymbol( "as", sort_group=SortGroup.ContextKeyword) suffixes = ["service_op", "service_suffix"] try: last_rule = Stack.find_closest_rule(stack, suffixes) service_name = Stack.extract(stack, "value", "service_suffix")[0].value service_command = Stack.extract(stack, last_rule)[0].value except Exception: # attempt to parse service_block failed - must be a when_block or # similar yield as_keyword return action = self.service_handler.action(service_name, service_command) if action is None: return # only yield 'as' iff the service can start an event block (=it has # events) if len(action.events()) > 0: yield as_keyword
def process_args(self, stack): """ Looks for the mutation name token in the stack and filter seen arguments. """ dot_op = self._toks(stack, before="mut_arguments") toks = [t.value for t in Stack.flatten(dot_op)] mut_name = toks.pop() # remove '.' from mut_name (.<mut_name>) expr = "".join(toks[:-1]) # second or further arguments -> filter used arguments prev_args = Stack.find_all_until(stack, "mut_arguments", ["dot_expr"], start=1, offset=3) # '(' (<name> ':' <expr>)* prev_args = [*prev_args] args = self.args(expr, mut_name, prev_args) seen = {} for arg in args: arg_name = arg.name.lower() if arg_name in seen: continue seen[arg_name] = True # ignore previously used args if arg_name not in prev_args: yield arg
def _toks(self, stack, before=None): """ Returns all tokens from the stack belonging to the current mutation. """ return [ *Stack.extract(stack, "dot_op", before), *Stack.extract(stack, "dot_expr", before), ]
def process_args(self, stack, prev_args): """ Looks for the service name and command token in the Filters previously seen arguments. """ service_name = Stack.extract(stack, "value", "service_suffix")[0].value service_command = Stack.extract(stack, "service_suffix")[0].value service = self._service_actions(service_name) args = Utils.action_args(service, service_command) yield from Utils.filter_prev_args(args, prev_args)
def _service_has_events(self, stack): """ Returns `True` if the service has events. """ service_name = Stack.extract(stack, "value")[0].value service_command = Stack.extract(stack, "service_op")[0].value action = self.service.action(service_name, service_command) if action is not None: if len(action.events()) > 0: return True return False
def process_when(self, stack): """ Process a when statement without args. """ name = Stack.extract(stack, "when_expression")[0].value when_action = Stack.extract(stack, "when_action") action = when_action[0].value prev_args = [] try: event = Stack.extract(stack, "when_action_name")[0].value except Exception: # COLON (only two names provided, add the third name as argument) event = None prev_args.append(when_action[1].value) yield from self.service.when(name, action, event, prev_args)
def process_command(self, stack, value_stack_name, command_name): """ Extract previous tokens for service argument completion. """ actions = self.process_suffix( stack, value_stack_name, in_assignment=False ) service_command = Stack.extract(stack, command_name)[0].value yield from Utils.action_args(actions, service_command)
def process_name(self, stack): """ Extract previous token for mutation completion. """ dot_op = self._toks(stack) toks = [t.value for t in Stack.flatten(dot_op)] # always remove the final dot assert toks[-1] == "." expr = "".join(toks[:-1]) yield from self.dot.complete(expr)
def process_when_command(self, stack): """ Extract previous tokens for service argument completion. """ service_name = Stack.extract(stack, "when_expression")[0].value service_command = Stack.extract(stack, "when_action")[0].value _, ty = self.service_handler.check_service_var(service_name) if ty == ServiceVarType.Undefined: # variable was not declared -> must be a service with an action action = self.service_handler.action(service_name, service_command) if action is None: return for event in action.events(): yield Event(event) return yield from self.when( service_name, service_command, event=None, prev_args=[] )
def process_args(self, stack, prev_args): """ Looks for the function name token in the stack and filter seen arguments. """ fn_name = Stack.extract(stack, "value", "fn_suffix")[0].value args = self.args(fn_name) for arg in args: arg_name = arg.name.lower() # ignore previously used args if arg_name not in prev_args: yield arg
def process_when_args(self, stack): """ Process a when statement with args. """ name = Stack.extract(stack, "when_expression")[0].value actions = Stack.extract(stack, "when_action") suffix = Stack.extract(stack, "when_action_suffix") prev_args = [ *Stack.find_all_until( stack, "when_arglist", ["when_expression"], start=0, offset=3) ] event = None assert len(actions) == 2 action = actions[0].value # it might have been the event name or an argument if len(suffix) > 0 and suffix[0].value == ":": prev_args.append(actions[1].value) else: event = actions[1].value yield from self.service.when(name, action, event, prev_args)
def process_args(self, stack): """ Extract previous token for service or function argument completion with at least one previous argument. This looks for seen args and filters them out. """ suffixes = ["fn_suffix", "service_suffix"] last_rule = Stack.find_closest_rule(stack, suffixes) # second or further arguments -> filter used arguments # <name> ':' <expr> prev_args = [ *Stack.find_all_until( stack, "arglist", suffixes, start=0, offset=3) ] if last_rule == "service_suffix": yield from self.service.process_args(stack, prev_args) else: assert last_rule == "fn_suffix" yield from self.function.process_args(stack, prev_args)
def test_extract(): stack = Parser().stack("foo bar foo:1") res = Stack.extract(stack, "arglist", "value") assert len(res) == 2 assert res[0].value == "foo" assert res[1].value == ":"
def test_stack_find_all_until_no_rule(): stack = Parser().stack("foo bar foo:1") with raises(AssertionError): [*Stack.find_all_until(stack, "arglist", ["no_rule"])]
def test_stack_find_all_until_3(): stack = Parser().stack("foo bar arg1:1 + 1 arg2:2 arg3: (foo bar arg4:1)") res = Stack.find_all_until(stack, "arglist", ["service_suffix"]) assert [*res] == ["arg1", "arg2", "arg3"]
def test_stack_find_all_until(): stack = Parser().stack("foo bar arg1:1") res = Stack.find_all_until(stack, "arglist", ["service_suffix"]) assert [*res] == ["arg1"]
def test_stack_find_closest_rule(): stack = Parser().stack("foo bar foo:1") res = Stack.find_closest_rule(stack, ["arglist", "no_rule"]) assert res == "arglist"
def process_suffix(self, stack, value_stack_name, in_assignment): """ Extract a service_suffix (=service_name) and yield its actions. """ name = Stack.extract(stack, value_stack_name)[0].value yield from self._service_actions(name, in_assignment=in_assignment)
def process_name(self, stack): """ Extract previous token for function completion. """ fn_name = Stack.extract(stack, "value")[0].value yield from self.args(fn_name)
def test_extract_seen_no_rule(): stack = Parser().stack("foo bar foo:1") with raises(AssertionError): Stack.extract(stack, "arglist", "no_rule")
def test_stack_find_closest_rule_no_rule(): stack = Parser().stack("foo bar foo:1") with raises(AssertionError): Stack.find_closest_rule(stack, ["no_rule"])