import pytest from prompt_toolkit.completion import CompleteEvent from prompt_toolkit.document import Document from core.concept import Concept from core.tokenizer import TokenKind from repl.SheerkaPromptCompleter import SheerkaPromptCompleter, FuncFound, ConceptCompleterHelper from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka class TestSheerkaPromptCompleter(TestUsingMemoryBasedSheerka): def test_i_can_complete_with_builtins(self): sheerka = self.get_sheerka() completions = SheerkaPromptCompleter(sheerka).get_completions(Document("get"), CompleteEvent()) as_dict = {c.display_text: c for c in completions} assert "get_partition" in as_dict assert as_dict["get_partition"].text == "get_partition(" assert as_dict["get_partition"].display_text == "get_partition" assert as_dict["get_partition"].display_meta_text == "builtin" completions = SheerkaPromptCompleter(sheerka).get_completions(Document("cache"), CompleteEvent()) as_dict = {c.display_text: c for c in completions} assert "caches_names" in as_dict assert as_dict["caches_names"].text == "caches_names()" assert as_dict["caches_names"].display_text == "caches_names" assert as_dict["caches_names"].display_meta_text == "builtin" def test_i_can_complete_with_commands(self): sheerka = self.get_sheerka() completions = SheerkaPromptCompleter(sheerka).get_completions(Document("q"), CompleteEvent()) as_dict = {c.display_text: c for c in completions} assert "quit" in as_dict assert as_dict["quit"].text == "quit" assert as_dict["quit"].display_text == "quit" assert as_dict["quit"].display_meta_text == "command" @pytest.mark.parametrize("concept_name", [ "foo", "a long name", ]) def test_i_can_complete_concept(self, concept_name): sheerka, context, foo = self.init_concepts(Concept(concept_name), create_new=True) completer = SheerkaPromptCompleter(sheerka) completer.complete_commands = False completer.complete_builtins = False for i in range(1, len(concept_name)): before_cursor = concept_name[:i] completions = list(completer.get_completions(Document(before_cursor), CompleteEvent())) as_dict = {c.display_text: c for c in completions} assert concept_name in as_dict, f"{i=}, {before_cursor=}" def test_i_can_complete_sya_concept_with_variable(self): sheerka, context, foo, something, bar = self.init_concepts( Concept("if true x then do y else do z end").def_var("x").def_var("y").def_var("z"), Concept("something"), Concept("bar"), create_new=True) completer = SheerkaPromptCompleter(sheerka) completer.complete_commands = False completer.complete_builtins = False text = "if true some cond then do some thing else do something else end" # i 0123456789012345678901234567890123456789012345678901234567890123 # 0 1 2 3 4 5 6 for i in range(1, len(text) + 1): before_cursor = text[:i] d, c = Document(before_cursor), CompleteEvent() completions = list(completer.get_completions(d, c)) display_as_dict = {(c.display_text, c.start_position): c for c in completions} if i == 0: assert len(completer.concepts_candidates) == 3 assert (foo.name, 0) in display_as_dict assert display_as_dict[(foo.name, 0)].text == "if true " assert (something.name, 0) in display_as_dict assert (bar.name, 0) in display_as_dict if i in range(1, 8): # 'if true' assert len(completer.concepts_candidates) == 1 assert (foo.name, -i) in display_as_dict assert completer.concepts_candidates[(foo.id, 1)].last_part_index == 0 assert display_as_dict[(foo.name, -i)].text == "if true " assert len(display_as_dict) == 1 if i == 8: # 'if true ' assert len(completer.concepts_candidates) == 1 assert (foo.name, -i) in display_as_dict assert completer.concepts_candidates[(foo.id, 1)].last_part_index == 1 assert display_as_dict[(foo.name, -i)].text == "if true " assert len(display_as_dict) == 1 elif i in range(9, 13): # 'some' assert len(completer.concepts_candidates) == 2 assert (foo.name, -i) in display_as_dict assert completer.concepts_candidates[(foo.id, 1)].last_part_index == 1 assert display_as_dict[(foo.name, -i)].text == before_cursor.rstrip() + " then do " assert (something.name, 8 - i) in display_as_dict assert display_as_dict[(something.name, 8 - i)].text == "something" elif i in range(13, 18): # ' cond' assert len(completer.concepts_candidates) == 2, f"{i=}, {before_cursor=}" assert (foo.name, -i) in display_as_dict assert completer.concepts_candidates[(foo.id, 1)].last_part_index == 1 assert display_as_dict[(foo.name, -i)].text == before_cursor.rstrip() + " then do " elif i == 18: # 'cond ' assert len(completer.concepts_candidates) == 2, f"{i=}, {before_cursor=}" assert (foo.name, -i) in display_as_dict assert completer.concepts_candidates[(foo.id, 1)].last_part_index == 1 assert display_as_dict[(foo.name, -i)].text == before_cursor.rstrip() + " then do " elif i in range(19, 26): # 'then do' assert len(completer.concepts_candidates) == 2, f"{i=}, {before_cursor=}" assert (foo.name, -i) in display_as_dict assert completer.concepts_candidates[(foo.id, 1)].last_part_index == 2 assert display_as_dict[(foo.name, -i)].text == "if true some cond then do " elif i == 26: # 'then do ' assert len(completer.concepts_candidates) == 2, f"{i=}, {before_cursor=}" assert (foo.name, -i) in display_as_dict assert completer.concepts_candidates[(foo.id, 1)].last_part_index == 3 assert display_as_dict[(foo.name, -i)].text == "if true some cond then do " elif i in range(27, 31): # 'some' assert len(completer.concepts_candidates) == 3, f"{i=}, {before_cursor=}" assert (foo.name, -i) in display_as_dict assert completer.concepts_candidates[(foo.id, 1)].last_part_index == 3 assert display_as_dict[(foo.name, -i)].text == before_cursor.rstrip() + " else do " assert (something.name, 26 - i) in display_as_dict assert display_as_dict[(something.name, 26 - i)].text == "something" elif i in range(31, 38): # ' thing ' assert len(completer.concepts_candidates) == 3, f"{i=}, {before_cursor=}" assert (foo.name, -i) in display_as_dict assert completer.concepts_candidates[(foo.id, 1)].last_part_index == 3 assert display_as_dict[(foo.name, -i)].text == before_cursor.rstrip() + " else do " elif i in range(38, 45): # 'else do' assert len(completer.concepts_candidates) == 3, f"{i=}, {before_cursor=}" assert (foo.name, -i) in display_as_dict assert completer.concepts_candidates[(foo.id, 1)].last_part_index == 4 assert display_as_dict[(foo.name, -i)].text == "if true some cond then do some thing else do " elif i == 45: # 'else do ' assert len(completer.concepts_candidates) == 3, f"{i=}, {before_cursor=}" assert (foo.name, -i) in display_as_dict assert completer.concepts_candidates[(foo.id, 1)].last_part_index == 5 assert display_as_dict[(foo.name, -i)].text == "if true some cond then do some thing else do " elif i in range(46, 54): # 'something' assert len(completer.concepts_candidates) == 4, f"{i=}, {before_cursor=}" assert (foo.name, -i) in display_as_dict assert completer.concepts_candidates[(foo.id, 1)].last_part_index == 5 assert display_as_dict[(foo.name, -i)].text == before_cursor.rstrip() + " end" assert (something.name, 45 - i) in display_as_dict assert display_as_dict[(something.name, 45 - i)].text == "something" elif i == 54: # 'g' from 'something' assert len(completer.concepts_candidates) == 4, f"{i=}, {before_cursor=}" assert (foo.name, -i) in display_as_dict assert completer.concepts_candidates[(foo.id, 1)].last_part_index == 5 assert display_as_dict[(foo.name, -i)].text == before_cursor.rstrip() + " end" elif i == 55: # ' ' before 'else ' assert len(completer.concepts_candidates) == 7, f"{i=}, {before_cursor=}" assert (foo.name, -i) in display_as_dict assert completer.concepts_candidates[(foo.id, 1)].last_part_index == 5 assert display_as_dict[(foo.name, -i)].text == before_cursor.rstrip() + " end" elif i == 56: # 'e' from 'else ' assert len(completer.concepts_candidates) == 7, f"{i=}, {before_cursor=}" assert (foo.name, -i) in display_as_dict assert completer.concepts_candidates[(foo.id, 1)].last_part_index == 6 assert display_as_dict[(foo.name, -i)].text == "if true some cond then do some thing else do something end" elif i in range(57, 60): # 'lse ' assert len(completer.concepts_candidates) == 7, f"{i=}, {before_cursor=}" assert (foo.name, -i) in display_as_dict assert completer.concepts_candidates[(foo.id, 1)].last_part_index == 5 assert display_as_dict[(foo.name, -i)].text == before_cursor.rstrip() + " end" # @pytest.mark.parametrize("text, expected", [ # ("func(", ["10", "20", "30"]), # ("func(1", ["10"]), # ("func( 1", ["10"]), # ("func( 10, ", ["'hello'"]), # ("func( 10, v", []), # ("func( 10, 'hel", ["'hello'"]), # ('func( 10, "hel', []), # ("func('hell,,', func2(2,4), 'w", ["'world'"]), # ]) # def test_i_can_complete_function_parameters(self, text, expected): # sheerka = self.get_sheerka() # context = self.get_context(sheerka) # params_history_service = sheerka.services[SheerkaFunctionsParametersHistory.NAME] # params_history_service.record_function_parameter(context, "func", 0, "10") # params_history_service.record_function_parameter(context, "func", 0, "20") # params_history_service.record_function_parameter(context, "func", 0, "30") # params_history_service.record_function_parameter(context, "func", 1, "'hello'") # params_history_service.record_function_parameter(context, "func", 2, "'world'") # # document = Document(text) # completions = SheerkaPromptCompleter(sheerka).get_completions(document, CompleteEvent()) # as_list = [c.display_text for c in completions] # assert as_list == expected @pytest.mark.parametrize("text, pos, expected", [ ("", 0, None), ("foo", 3, None), ("foo(", 4, FuncFound("foo", 0, 3)), ("foo(a, ", 7, FuncFound("foo", 0, 3)), ("foo( a , ", 9, FuncFound("foo", 0, 3)), ("foo(bar)", 8, None), ("foo(bar)", 7, FuncFound("foo", 0, 3)), ("foo()", 5, None), ("foo()", 4, FuncFound("foo", 0, 3)), ("xxx foo(", 8, FuncFound("foo", 4, 7)), ("foo (", 5, FuncFound("foo", 0, 4)), ("foo (", 6, FuncFound("foo", 0, 5)), ]) def test_inside_function(self, text, pos, expected): assert SheerkaPromptCompleter.inside_function(text, pos) == expected @pytest.mark.parametrize("text, expected_param_number, expected_comma_index", [ ("", 0, -1), ("foo", 0, -1), ("foo, ", 1, 3), ("foo, ", 1, 3), ("foo, 'he,llo', ", 2, 13), ("foo, (he,llo), ", 2, 13), ("foo, (he,llo ", 1, 3), ("foo, 'he,llo ", 1, 3), ]) def test_get_param_number(self, text, expected_param_number, expected_comma_index): assert SheerkaPromptCompleter.get_param_number(text) == (expected_param_number, expected_comma_index) @pytest.mark.parametrize("concept, expected_parts", [ (Concept("if true x then do y else do z end").def_var("x").def_var("y").def_var("z"), [ "if true ", TokenKind.VAR_DEF, "then do ", TokenKind.VAR_DEF, "else do ", TokenKind.VAR_DEF, "end" ]), (Concept("x something y").def_var("x").def_var("y"), ["something ", TokenKind.VAR_DEF]), (Concept("foo x y").def_var("x").def_var("y"), ["foo ", TokenKind.VAR_DEF]), (Concept("foo x y bar").def_var("x").def_var("y"), ["foo ", TokenKind.VAR_DEF, "bar"]), (Concept("x y foo").def_var("x").def_var("y"), ["foo"]), ]) def test_i_can_initialize_concept_parts(self, concept, expected_parts): concept.init_key() parts = ConceptCompleterHelper.initialize_parts(concept) assert parts == expected_parts # def test_jedi_infer(self): # sheerka = self.get_sheerka() # # document = Document("get_partition(") # SheerkaPromptCompleter(sheerka).test_jedi(document) # pass # # def test_parso_parser(self): # import parso # module = parso.parse("get_results() | filter('id==4', param2) | format_d()") # pass