diff --git a/jedi/api/__init__.py b/jedi/api/__init__.py index bb017a0f..0a1b79cd 100644 --- a/jedi/api/__init__.py +++ b/jedi/api/__init__.py @@ -550,7 +550,9 @@ class Script(object): with common.scale_speed_settings(settings.scale_call_signatures): _callable = lambda: self._evaluator.eval_call(call) - origins = cache.cache_call_signatures(_callable, user_stmt) + origins = cache.cache_call_signatures(_callable, self.source, + self._pos, user_stmt) + origins = self._evaluator.eval_call(call) debug.speed('func_call followed') return [classes.CallSignature(self._evaluator, o, call, index) diff --git a/jedi/cache.py b/jedi/cache.py index 6e5020de..d815f43a 100644 --- a/jedi/cache.py +++ b/jedi/cache.py @@ -21,6 +21,7 @@ import hashlib import gc import inspect import shutil +import re try: import cPickle as pickle except ImportError: @@ -96,9 +97,17 @@ def time_cache(time_add_setting): @time_cache("call_signatures_validity") -def cache_call_signatures(stmt): +def cache_call_signatures(source, user_pos, stmt): + """This function calculates the cache key.""" + index = user_pos[0] - 1 + lines = source.splitlines() or [''] + before_cursor = lines[index][:user_pos[1]] + other_lines = lines[stmt.start_pos[0]:index] + whole = '\n'.join(other_lines + [before_cursor]) + before_bracket = re.match(r'.*\(', whole, re.DOTALL) + module_path = stmt.get_parent_until().path - return None if module_path is None else (module_path, stmt.start_pos) + return None if module_path is None else (module_path, before_bracket, stmt.start_pos) def underscore_memoization(func): diff --git a/test/test_cache.py b/test/test_cache.py index 6ffe9e46..bbceb985 100644 --- a/test/test_cache.py +++ b/test/test_cache.py @@ -65,7 +65,7 @@ def test_modulepickling_delete_incompatible_cache(): def test_star_import_cache_duration(): new = 0.01 old, jedi.settings.star_import_cache_validity = \ - jedi.settings.star_import_cache_validity, new + jedi.settings.star_import_cache_validity, new cache._star_import_cache = {} # first empty... # path needs to be not-None (otherwise caching effects are not visible) @@ -78,3 +78,24 @@ def test_star_import_cache_duration(): length = len(cache._star_import_cache) cache._star_import_cache = {} assert length == 1 + + +def test_cache_call_signatures(): + """ + See github issue #390. + """ + def check(column, call_name, path=None): + assert jedi.Script(s, 1, column, path).call_signatures()[0].name == call_name + + s = 'str(int())' + + for i in range(3): + check(8, 'int') + check(4, 'str') + # Can keep doing these calls and always get the right result. + + # Now lets specify a source_path of boo and alternate these calls, it + # should still work. + for i in range(3): + check(8, 'int', 'boo') + check(4, 'str', 'boo')