def test_story_parse(patch, story): patch.init(Parser) patch.object(Parser, 'parse') story.parse() Parser.__init__.assert_called_with(ebnf_file=None) Parser.parse.assert_called_with(story.story, debug=False) assert story.tree == Parser.parse()
def test_ast(magic, patch): registry = magic() context = magic() patch.object(Parser, 'parse') patch.object(ASTAnalyzer, 'try_ast') context.line = 'foo' ast = ASTAnalyzer(service_registry=registry) result = ast.complete(context) Parser.parse.assert_called_with(context.line) ASTAnalyzer.try_ast.assert_called_with(Parser.parse(), context.word, False) assert result == ASTAnalyzer.try_ast()
def test_story_parse_lower(patch, story, parser): patch.object(Lowering, 'process') story.parse(parser=parser, lower=True) parser.parse.assert_called_with(story.story) Lowering.process.assert_called_with(Parser.parse()) assert story.tree == Lowering.process(Lowering.process())
def test_story_parse(patch, story, parser): story.parse(parser=parser) parser.parse.assert_called_with(story.story) assert story.tree == Parser.parse()
def test_story_parse(patch, story, parser): story.parse(parser=parser) parser.parse.assert_called_with(story.story, allow_single_quotes=False) assert story.tree == Parser.parse()
class ASTAnalyzer: # TODO: add basic keywords # TODO: add existing variables # TODO: add existing functions def __init__(self, service_registry): self.parser = Parser() self.service_registry = service_registry def complete(self, context): is_space = len(context.line) > 0 and context.line[-1] == ' ' log.debug(f"line: '{context.line}'") line = context.line if len(line.strip()) == 0: # start of a new line return self.complete_name() if ':' in line: return [] try: if '=' in line: # try to convert assignments to expressions for now assignment = line.split('=')[-1] if len(assignment.strip()) > 0: line = assignment ast = self.parser.parse(line, allow_single_quotes=False) log.debug(ast.pretty()) return self.try_ast(ast, context.word, is_space) except UnexpectedCharacters as e: log.error(e) pass except UnexpectedToken as e: if 'NAME' in e.expected: return self.complete_name() log.error(e) return [] def complete_name(self): # variables or services return self.get_services('') def try_ast(self, ast, word, is_space): if ast.block is not None: ast = ast.block if ast.rules is not None: ast = ast.rules if ast.service_block is not None: ast = ast.service_block.service if ast.service_fragment and \ ast.service_fragment.command is not None: service = ast.path.child(0).value if is_space: # argument command = ast.service_fragment.command.children[0].value return self.get_arguments(service, command) # it's the command return self.get_commands(service) if is_space: # fresh command starts here service = ast.path.child(0).value return self.get_commands(service) else: return self.get_services(word) return [] def get_arguments(self, service_name, command_name): service = self.service_registry.get_service(service_name) command = service.command(command_name) action = service.action(command_name) result = [] if command is not None: result.extend(command.args()) if action is not None: result.extend(action.args()) return result def get_commands(self, service_name): service = self.service_registry.get_service(service_name) log.info(service.description()) log.info(service.commands()) return [ *service.commands(), *service.actions(), ] def get_services(self, word): return self.service_registry.find_services(word)
def test_story_parse(patch, story, parser): story.parse() Parser.__init__.assert_called_with(ebnf=None) Parser.parse.assert_called_with(story.story) assert story.tree == Parser.parse()