Skip to content

Commit d4cc064

Browse files
sjoerdjobvmuriart
authored andcommitted
Replace _group_matching with an inward-out grouping algorithm
All the matching between open/close was done all the time, first finding the matching closing token, and then grouping the tokens in between, and recurse over the newly created list. Instead, it is more efficient to look for the previous open-token on finding a closing-token, group these two together, and then continue on. squashed: Handle token indices in group_tokens_between and find_matching.
1 parent 896774c commit d4cc064

File tree

3 files changed

+30
-13
lines changed

3 files changed

+30
-13
lines changed

sqlparse/engine/grouping.py

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
from sqlparse import sql
44
from sqlparse import tokens as T
5-
from sqlparse.utils import recurse, imt, find_matching
5+
from sqlparse.utils import recurse, imt
66

77
M_ROLE = (T.Keyword, ('null', 'role'))
88
M_SEMICOLON = (T.Punctuation, ';')
@@ -39,13 +39,25 @@ def _group_matching(tlist, cls):
3939
"""Groups Tokens that have beginning and end. ie. parenthesis, brackets.."""
4040
idx = 1 if imt(tlist, i=cls) else 0
4141

42-
token = tlist.token_next_by(m=cls.M_OPEN, idx=idx)
43-
while token:
44-
end = find_matching(tlist, token, cls.M_OPEN, cls.M_CLOSE)
45-
if end is not None:
46-
token = tlist.group_tokens_between(cls, token, end)
47-
_group_matching(token, cls)
48-
token = tlist.token_next_by(m=cls.M_OPEN, idx=tlist.token_index(token) + 1)
42+
opens = []
43+
44+
while True:
45+
try:
46+
token = tlist.tokens[idx]
47+
except IndexError:
48+
break
49+
50+
if token.match(*cls.M_OPEN):
51+
opens.append(idx)
52+
elif token.match(*cls.M_CLOSE):
53+
try:
54+
open_idx = opens.pop()
55+
except IndexError:
56+
break
57+
tlist.group_tokens_between(cls, open_idx, idx)
58+
idx = open_idx
59+
60+
idx += 1
4961

5062

5163
def group_if(tlist):

sqlparse/sql.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -331,9 +331,14 @@ def tokens_between(self, start, end, include_end=True):
331331

332332
def group_tokens_between(self, grp_cls, start, end, include_end=True, extend=False):
333333
"""Replace tokens by an instance of *grp_cls*."""
334-
start_idx = self.token_index(start)
335-
end_idx = self.token_index(end) + include_end
336-
tokens = self.tokens[start_idx:end_idx]
334+
if isinstance(start, int):
335+
start_idx = start
336+
start = self.tokens[start_idx]
337+
else:
338+
start_idx = self.token_index(start)
339+
340+
end_idx = self.token_index(end) if not isinstance(end, int) else end
341+
end_idx += include_end
337342

338343
if extend and isinstance(start, grp_cls):
339344
subtokens = self.tokens[start_idx+1:end_idx]
@@ -344,7 +349,7 @@ def group_tokens_between(self, grp_cls, start, end, include_end=True, extend=Fal
344349
grp.value = start.__str__()
345350
else:
346351
subtokens = self.tokens[start_idx:end_idx]
347-
grp = grp_cls(tokens)
352+
grp = grp_cls(subtokens)
348353
self.tokens[start_idx:end_idx] = [grp]
349354
grp.parent = self
350355

sqlparse/utils.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ def imt(token, i=None, m=None, t=None):
164164

165165

166166
def find_matching(tlist, token, M1, M2):
167-
idx = tlist.token_index(token)
167+
idx = tlist.token_index(token) if not isinstance(token, int) else token
168168
depth = 0
169169
for token in tlist.tokens[idx:]:
170170
if token.match(*M1):

0 commit comments

Comments
 (0)