diff --git a/jedi/api/completion.py b/jedi/api/completion.py index 74faf5fd..aa5be0af 100644 --- a/jedi/api/completion.py +++ b/jedi/api/completion.py @@ -95,6 +95,7 @@ class Completion: self._like_name = helpers.get_on_completion_name(self._module_node, code_lines, position) # The actual cursor position is not what we need to calculate # everything. We want the start of the name we're on. + self._original_position = position self._position = position[0], position[1] - len(self._like_name) self._call_signatures_callback = call_signatures_callback @@ -104,7 +105,8 @@ class Completion: if string is not None: completions = list(file_name_completions( self._evaluator, self._module_context, start_leaf, string, - self._like_name, self._call_signatures_callback + self._like_name, self._call_signatures_callback, + self._code_lines, self._original_position )) if completions: return completions diff --git a/jedi/api/file_name.py b/jedi/api/file_name.py index 01e24d1c..d6ecb708 100644 --- a/jedi/api/file_name.py +++ b/jedi/api/file_name.py @@ -1,7 +1,5 @@ import os -from parso.tree import search_ancestor - from jedi._compatibility import FileNotFoundError, force_unicode from jedi.evaluate.names import AbstractArbitraryName from jedi.api import classes @@ -10,7 +8,7 @@ from jedi.parser_utils import get_string_quote def file_name_completions(evaluator, module_context, start_leaf, string, - like_name, call_signatures_callback): + like_name, call_signatures_callback, code_lines, position): # First we want to find out what can actually be changed as a name. like_name_length = len(os.path.basename(string) + like_name) @@ -40,13 +38,19 @@ def file_name_completions(evaluator, module_context, start_leaf, string, for name in listed: if name.startswith(must_start_with): path_for_name = os.path.join(base_path, name) - if is_in_os_path_join: + if is_in_os_path_join or not os.path.isdir(path_for_name): if start_leaf.type == 'string': - name += get_string_quote(start_leaf) + quote = get_string_quote(start_leaf) else: assert start_leaf.type == 'error_leaf' - name += start_leaf.value - elif os.path.isdir(path_for_name): + quote = start_leaf.value + potential_other_quote = \ + code_lines[position[0] - 1][position[1]:position[1] + len(quote)] + # Add a quote if it's not already there. + print(repr(quote), repr(potential_other_quote), position) + if quote != potential_other_quote: + name += quote + else: name += os.path.sep yield classes.Completion( diff --git a/test/test_api/test_completion.py b/test/test_api/test_completion.py index 2e52240b..07959b7b 100644 --- a/test/test_api/test_completion.py +++ b/test/test_api/test_completion.py @@ -182,7 +182,7 @@ os_path = 'from os.path import *\n' ('example.py', 'rb"' + join('..', 'jedi', 'tes'), None, ['t' + s]), # Absolute paths - (None, '"' + join(root_dir, 'test', 'test_ca'), None, ['che.py']), + (None, '"' + join(root_dir, 'test', 'test_ca'), None, ['che.py"']), (None, '"%s"' % join(root_dir, 'test', 'test_ca'), len(root_dir) + 14, ['che.py']), # Longer quotes @@ -190,10 +190,11 @@ os_path = 'from os.path import *\n' ('example.py', 'r"""\ntest', None, []), ('example.py', 'u"""tes\n', (1, 7), ['t' + s]), ('example.py', '"""test%stest_cache.p"""' % s, 20, ['y']), + ('example.py', '"""test%stest_cache.p"""' % s, 19, ['py"""']), # Adding - ('example.py', '"test" + "%stest_cac' % s, None, ['he.py']), - ('example.py', '"test" + "%s" + "test_cac' % s, None, ['he.py']), + ('example.py', '"test" + "%stest_cac' % s, None, ['he.py"']), + ('example.py', '"test" + "%s" + "test_cac' % s, None, ['he.py"']), ('example.py', 'x = 1 + "test', None, []), ('example.py', 'x = f("te" + "st)', 16, [s]), ('example.py', 'x = f("te" + "st', 16, [s]), @@ -207,16 +208,16 @@ os_path = 'from os.path import *\n' # __file__ (f1, os_path + 'dirname(__file__) + "%stest' % s, None, [s]), - (f2, os_path + 'dirname(__file__) + "%stest_ca' % s, None, ['che.py']), - (f2, os_path + 'dirname(abspath(__file__)) + sep + "test_ca', None, ['che.py']), - (f2, os_path + 'join(dirname(__file__), "completion") + sep + "basi', None, ['c.py']), - (f2, os_path + 'join("test", "completion") + sep + "basi', None, ['c.py']), + (f2, os_path + 'dirname(__file__) + "%stest_ca' % s, None, ['che.py"']), + (f2, os_path + 'dirname(abspath(__file__)) + sep + "test_ca', None, ['che.py"']), + (f2, os_path + 'join(dirname(__file__), "completion") + sep + "basi', None, ['c.py"']), + (f2, os_path + 'join("test", "completion") + sep + "basi', None, ['c.py"']), # inside join (f2, os_path + 'join(dirname(__file__), "completion", "basi', None, ['c.py"']), (f2, os_path + 'join(dirname(__file__), "completion", "basi)', 43, ['c.py"']), - (f2, os_path + 'join(dirname(__file__), "completion", "basi")', 43, ['c.py"']), - (f2, os_path + 'join(dirname(__file__), "completion", "basi)', 35, ['"']), + (f2, os_path + 'join(dirname(__file__), "completion", "basi")', 43, ['c.py']), + (f2, os_path + 'join(dirname(__file__), "completion", "basi)', 35, ['']), (f2, os_path + 'join(dirname(__file__), "completion", "basi)', 33, ['on"']), (f2, os_path + 'join(dirname(__file__), "completion", "basi")', 33, ['on"']), @@ -225,8 +226,8 @@ os_path = 'from os.path import *\n' # really matter. (f2, os_path + 'join("tes', 9, ['t"']), (f2, os_path + 'join(\'tes)', 9, ["t'"]), - (f2, os_path + 'join(r"tes"', 10, ['t"']), - (f2, os_path + 'join("""tes""")', 11, ['t"""']), + (f2, os_path + 'join(r"tes"', 10, ['t']), + (f2, os_path + 'join("""tes""")', 11, ['t']), # Almost like join but not really (f2, os_path + 'join["tes', 9, ['t' + s]), @@ -238,8 +239,8 @@ os_path = 'from os.path import *\n' # With full paths (f2, 'import os\nos.path.join(os.path.dirname(__file__), "completi', 49, ['on"']), - (f2, 'import os\nos.path.join(os.path.dirname(__file__), "completi"', 49, ['on"']), - (f2, 'import os\nos.path.join(os.path.dirname(__file__), "completi")', 49, ['on"']), + (f2, 'import os\nos.path.join(os.path.dirname(__file__), "completi"', 49, ['on']), + (f2, 'import os\nos.path.join(os.path.dirname(__file__), "completi")', 49, ['on']), # With alias (f2, 'import os.path as p as p\np.join(p.dirname(__file__), "completi', None, ['on"']), @@ -250,7 +251,7 @@ os_path = 'from os.path import *\n' (f2, os_path + 'join(["tes', 10, ['t' + s]), (f2, os_path + 'join(["tes"]', 10, ['t' + s]), (f2, os_path + 'join(["tes"])', 10, ['t' + s]), - (f2, os_path + 'join("test", "test_cac" + x,', 22, ['he.py"']), + (f2, os_path + 'join("test", "test_cac" + x,', 22, ['he.py']), ] ) def test_file_path_completions(Script, file, code, column, expected):