diff --git a/jedi/api/__init__.py b/jedi/api/__init__.py index a22cb2ce..b543fee8 100644 --- a/jedi/api/__init__.py +++ b/jedi/api/__init__.py @@ -15,8 +15,7 @@ import sys from jedi.parser.python import load_grammar from jedi.parser.python import tree -from jedi.parser.python.diff import FastParser -from jedi.parser.utils import save_parser +from jedi.parser.python import parse from jedi import debug from jedi import settings from jedi import common @@ -133,10 +132,13 @@ class Script(object): @cache.memoize_method def _get_module_node(self): - parser = FastParser(self._grammar, self._source, self.path) - save_parser(self._grammar, self.path, parser, pickling=False) - - return parser.get_root_node() + return parse( + code=self._source, + path=self.path, + grammar=self._grammar, + cache=True, + diff_cache=True, + ) @cache.memoize_method def _get_module(self): diff --git a/jedi/parser/python/__init__.py b/jedi/parser/python/__init__.py index dfd8e734..c3085a40 100644 --- a/jedi/parser/python/__init__.py +++ b/jedi/parser/python/__init__.py @@ -7,8 +7,10 @@ from jedi._compatibility import FileNotFoundError from jedi.parser.pgen2.pgen import generate_grammar from jedi.parser.python.parser import Parser, ParserWithRecovery, \ _remove_last_newline +from jedi.parser.python.diff import DiffParser from jedi.parser.tokenize import source_tokens from jedi.parser import utils +from jedi.common import splitlines _loaded_grammars = {} @@ -93,14 +95,28 @@ def parse(code=None, path=None, grammar=None, error_recovery=True, kwargs = {} if error_recovery: parser = ParserWithRecovery + kwargs = dict(module_path=path) else: kwargs = dict(start_symbol=start_symbol) parser = Parser + # TODO add recovery + if diff_cache: + try: + parser_cache_item = utils.parser_cache[path] + except KeyError: + pass + else: + p = parser_cache_item.parser + lines = splitlines(code, keepends=True) + new_node = DiffParser(p).update(lines) + p._parsed = new_node + utils.save_parser(grammar, path, p, pickling=False) + return new_node p = parser(grammar, code, start_parsing=False, **kwargs) module = p.parse(tokens=tokens) if added_newline: _remove_last_newline(module) - if use_cache: - utils.save_parser(grammar, path, parser) + if use_cache or diff_cache: + utils.save_parser(grammar, path, p) return module diff --git a/jedi/parser/python/diff.py b/jedi/parser/python/diff.py index 27dc8462..ceb7e77d 100644 --- a/jedi/parser/python/diff.py +++ b/jedi/parser/python/diff.py @@ -12,7 +12,6 @@ from collections import namedtuple from jedi._compatibility import use_metaclass from jedi import settings from jedi.common import splitlines -from jedi.parser.python import load_grammar from jedi.parser.python.parser import ParserWithRecovery, _remove_last_newline from jedi.parser.python.tree import EndMarker from jedi.parser.utils import parser_cache @@ -138,6 +137,7 @@ def load_diff_parser(path, python_version=None): class NewDiffParser(object): def __init__(self, path, python_version=None): self._path = path + from jedi.parser.python import load_grammar grammar = load_grammar(version=python_version) self._parser = ParserWithRecovery(grammar) self._module = None diff --git a/jedi/parser/utils.py b/jedi/parser/utils.py index 2bdb767a..153450de 100644 --- a/jedi/parser/utils.py +++ b/jedi/parser/utils.py @@ -65,6 +65,7 @@ def load_parser(grammar, path): """ p_time = os.path.getmtime(path) if path else None try: + # TODO Add grammar sha256 parser_cache_item = parser_cache[path] if not path or p_time <= parser_cache_item.change_time: return parser_cache_item.parser @@ -82,7 +83,7 @@ def save_parser(grammar, path, parser, pickling=True): item = ParserCacheItem(parser, p_time) parser_cache[path] = item - if settings.use_filesystem_cache and pickling: + if settings.use_filesystem_cache and pickling and path is not None: ParserPickling.save_parser(grammar, path, item)