22
33from codelimit .common .Language import Language
44from codelimit .common .Token import Token
5- from codelimit .common .TokenRange import TokenRange
5+ from codelimit .common .TokenRange import TokenRange , sort_token_ranges
66from codelimit .common .gsm .Expression import Expression
77from codelimit .common .gsm .matcher import find_all , starts_with
8- from codelimit .common .scope .Header import Header
8+ from codelimit .common .scope .Header import Header , sort_headers
99from codelimit .common .scope .Scope import Scope
1010from codelimit .common .source_utils import filter_tokens , filter_nocl_comment_tokens
11- from codelimit .common .token_utils import (
12- sort_tokens ,
13- sort_token_ranges ,
14- get_balanced_symbol_token_indices ,
15- )
11+ from codelimit .common .token_utils import get_balanced_symbol_token_indices
1612from codelimit .common .utils import delete_indices
1713
1814
@@ -21,8 +17,8 @@ def build_scopes(tokens: list[Token], language: Language) -> list[Scope]:
2117 nocl_comment_tokens = filter_nocl_comment_tokens (tokens )
2218 headers = language .extract_headers (code_tokens )
2319 blocks = language .extract_blocks (code_tokens , headers )
24- scopes = _build_scopes_from_headers_and_blocks (headers , blocks )
25- filtered_scopes = _filter_nocl_scopes (scopes , nocl_comment_tokens )
20+ scopes = _build_scopes_from_headers_and_blocks (headers , blocks , code_tokens )
21+ filtered_scopes = _filter_nocl_scopes (scopes , code_tokens , nocl_comment_tokens )
2622 if language .allow_nested_functions :
2723 return fold_scopes (filtered_scopes )
2824 else :
@@ -66,26 +62,23 @@ def filter_scopes_nested_functions(scopes: list[Scope]) -> list[Scope]:
6662
6763
6864def _build_scopes_from_headers_and_blocks (
69- headers : list [Header ], blocks : list [TokenRange ]
65+ headers : list [Header ], blocks : list [TokenRange ], tokens : list [ Token ]
7066) -> list [Scope ]:
7167 result : list [Scope ] = []
72- reverse_headers = headers [:: - 1 ]
68+ reverse_headers = sort_headers ( headers , tokens , reverse = True )
7369 for header in reverse_headers :
7470 scope_blocks_indices = _find_scope_blocks_indices (header .token_range , blocks )
7571 if len (scope_blocks_indices ) > 0 :
76- scope_tokens = []
77- for i in scope_blocks_indices :
78- scope_tokens .extend (blocks [i ].tokens )
79- scope_tokens = sort_tokens (scope_tokens )
80- scope_block = TokenRange (scope_tokens )
81- result .append (Scope (header , scope_block ))
72+ start = min (blocks [bi ].start for bi in scope_blocks_indices )
73+ end = max (blocks [bi ].end for bi in scope_blocks_indices )
74+ result .append (Scope (header , TokenRange (start , end )))
8275 blocks = delete_indices (blocks , scope_blocks_indices )
8376 result .reverse ()
8477 return result
8578
8679
8780def _find_scope_blocks_indices (
88- header : TokenRange , blocks : list [TokenRange ]
81+ header : TokenRange , blocks : list [TokenRange ]
8982) -> list [int ]:
9083 body_block = _get_nearest_block (header , blocks )
9184 if body_block :
@@ -97,7 +90,7 @@ def _find_scope_blocks_indices(
9790
9891
9992def _get_nearest_block (
100- header : TokenRange , blocks : list [TokenRange ]
93+ header : TokenRange , blocks : list [TokenRange ]
10194) -> Optional [TokenRange ]:
10295 reverse_blocks = blocks [::- 1 ]
10396 result = None
@@ -112,13 +105,15 @@ def _get_nearest_block(
112105
113106
114107def _filter_nocl_scopes (
115- scopes : list [Scope ], nocl_comment_tokens : list [Token ]
108+ scopes : list [Scope ], tokens : list [ Token ], nocl_comment_tokens : list [Token ]
116109) -> list [Scope ]:
117110 nocl_comment_lines = [t .location .line for t in nocl_comment_tokens ]
118111
119112 def get_scope_header_lines (scope : Scope ) -> set [int ]:
120- result = set ([t .location .line for t in scope .header .token_range .tokens ])
121- first_line = scope .header .token_range .tokens [0 ].location .line
113+ header_token_range = scope .header .token_range
114+ header_tokens = tokens [header_token_range .start :header_token_range .end ]
115+ result = set ([t .location .line for t in header_tokens ])
116+ first_line = header_tokens [0 ].location .line
122117 if first_line > 0 :
123118 result .add (first_line - 1 )
124119 return result
@@ -139,25 +134,43 @@ def has_curly_suffix(tokens: list[Token], index):
139134
140135
141136def get_headers (
142- tokens : list [Token ], expression : Expression , followed_by : Expression = None
137+ tokens : list [Token ], expression : Expression , followed_by : Expression = None
143138) -> list [Header ]:
144139 # expression = replace_string_literal_with_predicate(expression)
145140 patterns = find_all (expression , tokens )
146141 if followed_by :
147- patterns = [p for p in patterns if starts_with (followed_by , tokens [p .end :])]
142+ patterns = [p for p in patterns if starts_with (followed_by , tokens [p .end :])]
148143 result = []
149144 for pattern in patterns :
150145 name_token = next (t for t in pattern .tokens if t .is_name ())
151146 if name_token :
152- result .append (Header (name_token .value , TokenRange (pattern .tokens )))
147+ result .append (Header (name_token .value , TokenRange (pattern .start , pattern . end )))
153148 return result
154149
155150
156151def get_blocks (
157- tokens : list [Token ], open : str , close : str , extract_nested = True
152+ tokens : list [Token ], open : str , close : str , extract_nested = True
158153) -> list [TokenRange ]:
159154 balanced_tokens = get_balanced_symbol_token_indices (
160155 tokens , open , close , extract_nested
161156 )
162- token_ranges = [TokenRange (tokens [bt [0 ] : bt [1 ] + 1 ]) for bt in balanced_tokens ]
163- return sort_token_ranges (token_ranges )
157+ token_ranges = [TokenRange (bt [0 ], bt [1 ] + 1 ) for bt in balanced_tokens ]
158+ return sort_token_ranges (token_ranges , tokens )
159+
160+
161+ def count_lines (scope : Scope , tokens : list [Token ]):
162+ return len (set ([t .location .line for t in _scope_tokens (scope , tokens )]))
163+
164+
165+ def _scope_tokens (scope : Scope , tokens : list [Token ]) -> list [Token ]:
166+ result = []
167+ children_token_ranges = []
168+ for child in scope .children :
169+ children_token_ranges .append (TokenRange (child .header .token_range .start , child .block .end ))
170+ children_token_ranges = sort_token_ranges (children_token_ranges , tokens )
171+ for index in range (scope .header .token_range .start , scope .block .end ):
172+ while len (children_token_ranges ) > 0 and index > children_token_ranges [0 ].end :
173+ children_token_ranges .pop (0 )
174+ if len (children_token_ranges ) == 0 or index < children_token_ranges [0 ].start :
175+ result .append (tokens [index ])
176+ return result
0 commit comments