forked from VimPlug/jedi
Implement binary search for get_leaf_for_position. This makes it a lot faster.
This commit is contained in:
@@ -223,20 +223,11 @@ class Parser(object):
|
|||||||
newline = endmarker.get_previous_leaf()
|
newline = endmarker.get_previous_leaf()
|
||||||
except IndexError:
|
except IndexError:
|
||||||
return # This means that the parser is empty.
|
return # This means that the parser is empty.
|
||||||
while True:
|
|
||||||
if newline.value == '':
|
assert newline.value.endswith('\n')
|
||||||
# Must be a DEDENT, just continue.
|
newline.value = newline.value[:-1]
|
||||||
try:
|
endmarker.start_pos = \
|
||||||
newline = newline.get_previous_leaf()
|
newline.start_pos[0], newline.start_pos[1] + len(newline.value)
|
||||||
except IndexError:
|
|
||||||
# If there's a statement that fails to be parsed, there
|
|
||||||
# will be no previous leaf. So just ignore it.
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
assert newline.value.endswith('\n')
|
|
||||||
newline.value = newline.value[:-1]
|
|
||||||
endmarker.start_pos = newline.start_pos
|
|
||||||
break
|
|
||||||
|
|
||||||
|
|
||||||
class ParserWithRecovery(Parser):
|
class ParserWithRecovery(Parser):
|
||||||
|
|||||||
@@ -258,6 +258,8 @@ def generate_tokens(readline, use_exact_op_types=False):
|
|||||||
# If a literal starts but doesn't end the whole rest of the
|
# If a literal starts but doesn't end the whole rest of the
|
||||||
# line is an error token.
|
# line is an error token.
|
||||||
txt = line[pos:]
|
txt = line[pos:]
|
||||||
|
if txt.endswith('\n'):
|
||||||
|
new_line = True
|
||||||
yield TokenInfo(ERRORTOKEN, txt, (lnum, pos), prefix)
|
yield TokenInfo(ERRORTOKEN, txt, (lnum, pos), prefix)
|
||||||
break
|
break
|
||||||
|
|
||||||
|
|||||||
@@ -543,19 +543,29 @@ class BaseNode(Base):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
def get_leaf_for_position(self, position, include_prefixes=False):
|
def get_leaf_for_position(self, position, include_prefixes=False):
|
||||||
for c in self.children:
|
def binary_search(lower, upper):
|
||||||
if include_prefixes:
|
if lower == upper:
|
||||||
start_pos = c.get_start_pos_of_prefix()
|
element = self.children[lower]
|
||||||
else:
|
if not include_prefixes and position < element.start_pos:
|
||||||
start_pos = c.start_pos
|
# We're on a prefix.
|
||||||
|
return None
|
||||||
if start_pos <= position <= c.end_pos:
|
# In case we have prefixes, a leaf always matches
|
||||||
try:
|
try:
|
||||||
return c.get_leaf_for_position(position, include_prefixes)
|
return element.get_leaf_for_position(position, include_prefixes)
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
return c
|
return element
|
||||||
|
|
||||||
return None
|
|
||||||
|
index = int((lower + upper) / 2)
|
||||||
|
element = self.children[index]
|
||||||
|
if position <= element.end_pos:
|
||||||
|
return binary_search(lower, index)
|
||||||
|
else:
|
||||||
|
return binary_search(index + 1, upper)
|
||||||
|
|
||||||
|
if not ((1, 0) <= position <= self.children[-1].end_pos):
|
||||||
|
raise ValueError('Please provide a position that exists within this node.')
|
||||||
|
return binary_search(0, len(self.children) - 1)
|
||||||
|
|
||||||
@Python3Method
|
@Python3Method
|
||||||
def get_statement_for_position(self, pos):
|
def get_statement_for_position(self, pos):
|
||||||
|
|||||||
Reference in New Issue
Block a user