cppgolf 0.1.0__tar.gz → 0.1.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {cppgolf-0.1.0 → cppgolf-0.1.1}/PKG-INFO +1 -1
- {cppgolf-0.1.0 → cppgolf-0.1.1}/cppgolf/__main__.py +3 -3
- {cppgolf-0.1.0 → cppgolf-0.1.1}/cppgolf/golf_rename.py +287 -198
- {cppgolf-0.1.0 → cppgolf-0.1.1}/cppgolf/transforms.py +27 -16
- {cppgolf-0.1.0 → cppgolf-0.1.1}/cppgolf.egg-info/PKG-INFO +1 -1
- {cppgolf-0.1.0 → cppgolf-0.1.1}/pyproject.toml +1 -1
- {cppgolf-0.1.0 → cppgolf-0.1.1}/README.md +0 -0
- {cppgolf-0.1.0 → cppgolf-0.1.1}/cppgolf/__init__.py +0 -0
- {cppgolf-0.1.0 → cppgolf-0.1.1}/cppgolf/merge.py +0 -0
- {cppgolf-0.1.0 → cppgolf-0.1.1}/cppgolf/strip_comments.py +0 -0
- {cppgolf-0.1.0 → cppgolf-0.1.1}/cppgolf/whitespace.py +0 -0
- {cppgolf-0.1.0 → cppgolf-0.1.1}/cppgolf.egg-info/SOURCES.txt +0 -0
- {cppgolf-0.1.0 → cppgolf-0.1.1}/cppgolf.egg-info/dependency_links.txt +0 -0
- {cppgolf-0.1.0 → cppgolf-0.1.1}/cppgolf.egg-info/entry_points.txt +0 -0
- {cppgolf-0.1.0 → cppgolf-0.1.1}/cppgolf.egg-info/requires.txt +0 -0
- {cppgolf-0.1.0 → cppgolf-0.1.1}/cppgolf.egg-info/top_level.txt +0 -0
- {cppgolf-0.1.0 → cppgolf-0.1.1}/setup.cfg +0 -0
|
@@ -96,8 +96,8 @@ def build_parser() -> argparse.ArgumentParser:
|
|
|
96
96
|
help='单语句 if/for/while 去花括号')
|
|
97
97
|
g2.add_argument('--shortcuts', dest='define_shortcuts', action='store_true',
|
|
98
98
|
help='高频 cout/cin 用 #define 缩写')
|
|
99
|
-
g2.add_argument('
|
|
100
|
-
help='
|
|
99
|
+
g2.add_argument('-no-rename', dest='no_rename_symbols', action='store_true',
|
|
100
|
+
help='不将用户变量/成员名压缩为短名(需要 tree-sitter-cpp)')
|
|
101
101
|
|
|
102
102
|
p.add_argument('--stats', action='store_true', help='显示压缩率统计')
|
|
103
103
|
return p
|
|
@@ -124,7 +124,7 @@ def main():
|
|
|
124
124
|
keep_inline=args.keep_inline,
|
|
125
125
|
aggressive=args.aggressive,
|
|
126
126
|
define_shortcuts=args.define_shortcuts,
|
|
127
|
-
rename_symbols=args.
|
|
127
|
+
rename_symbols=not(args.no_rename_symbols),
|
|
128
128
|
)
|
|
129
129
|
|
|
130
130
|
def print_stats(final_size: int):
|
|
@@ -2,9 +2,11 @@
|
|
|
2
2
|
golf_rename.py — Pass 5: 符号名压缩(tree-sitter AST 驱动)
|
|
3
3
|
"""
|
|
4
4
|
import re
|
|
5
|
-
import sys
|
|
6
5
|
import itertools
|
|
7
6
|
|
|
7
|
+
from tree_sitter import Language, Parser
|
|
8
|
+
import tree_sitter_cpp as tscpp
|
|
9
|
+
|
|
8
10
|
_DECLARATOR_CONTAINERS = frozenset({
|
|
9
11
|
'init_declarator', 'pointer_declarator', 'reference_declarator',
|
|
10
12
|
'array_declarator', 'abstract_pointer_declarator',
|
|
@@ -12,6 +14,28 @@ _DECLARATOR_CONTAINERS = frozenset({
|
|
|
12
14
|
})
|
|
13
15
|
_MIN_RENAME_LEN = 2
|
|
14
16
|
|
|
17
|
+
# C/C++ 保留关键字,生成短名时不得使用
|
|
18
|
+
_CXX_KEYWORDS = frozenset({
|
|
19
|
+
# C keywords
|
|
20
|
+
'auto', 'break', 'case', 'char', 'const', 'continue', 'default',
|
|
21
|
+
'do', 'double', 'else', 'enum', 'extern', 'float', 'for', 'goto',
|
|
22
|
+
'if', 'inline', 'int', 'long', 'register', 'restrict', 'return',
|
|
23
|
+
'short', 'signed', 'sizeof', 'static', 'struct', 'switch', 'typedef',
|
|
24
|
+
'union', 'unsigned', 'void', 'volatile', 'while',
|
|
25
|
+
# C++ keywords
|
|
26
|
+
'alignas', 'alignof', 'and', 'and_eq', 'asm', 'bitand', 'bitor',
|
|
27
|
+
'bool', 'catch', 'class', 'compl', 'concept', 'consteval', 'constexpr',
|
|
28
|
+
'constinit', 'co_await', 'co_return', 'co_yield', 'decltype', 'delete',
|
|
29
|
+
'explicit', 'export', 'false', 'friend', 'mutable', 'namespace',
|
|
30
|
+
'new', 'noexcept', 'not', 'not_eq', 'nullptr', 'operator', 'or',
|
|
31
|
+
'or_eq', 'private', 'protected', 'public', 'requires', 'static_assert',
|
|
32
|
+
'static_cast', 'dynamic_cast', 'reinterpret_cast', 'const_cast',
|
|
33
|
+
'template', 'this', 'thread_local', 'throw', 'true', 'try', 'typeid',
|
|
34
|
+
'typename', 'using', 'virtual', 'wchar_t', 'xor', 'xor_eq',
|
|
35
|
+
# common macros / built-ins that must not be shadowed
|
|
36
|
+
'NULL', 'TRUE', 'FALSE', 'EOF', 'stdin', 'stdout', 'stderr',
|
|
37
|
+
})
|
|
38
|
+
|
|
15
39
|
|
|
16
40
|
def _gen_short_names():
|
|
17
41
|
for length in itertools.count(1):
|
|
@@ -54,14 +78,20 @@ class _RenameCtx:
|
|
|
54
78
|
return self.src[node.start_byte:node.end_byte].decode('utf-8')
|
|
55
79
|
|
|
56
80
|
def _get_primary_type_name(self, node) -> str | None:
|
|
81
|
+
result = None
|
|
57
82
|
for ch in node.children:
|
|
58
83
|
if ch.type in ('type_identifier', 'primitive_type'):
|
|
59
|
-
|
|
60
|
-
|
|
84
|
+
result = self.name_of(ch)
|
|
85
|
+
elif ch.type == 'qualified_identifier':
|
|
61
86
|
for sub in reversed(ch.children):
|
|
62
87
|
if sub.type in ('identifier', 'type_identifier'):
|
|
63
|
-
|
|
64
|
-
|
|
88
|
+
result = self.name_of(sub); break
|
|
89
|
+
elif ch.type == 'ERROR':
|
|
90
|
+
# tree-sitter 遇到宏(如 F_BEGIN)时会把真正的类型包进 ERROR 节点
|
|
91
|
+
for sub in ch.children:
|
|
92
|
+
if sub.type in ('type_identifier', 'identifier'):
|
|
93
|
+
result = self.name_of(sub); break
|
|
94
|
+
return result
|
|
65
95
|
|
|
66
96
|
def _is_qid_name(self, node) -> bool:
|
|
67
97
|
par = node.parent
|
|
@@ -219,16 +249,82 @@ class _RenameCtx:
|
|
|
219
249
|
if vtype:
|
|
220
250
|
return vtype
|
|
221
251
|
return self._extract_init_cast_type(child, var_name)
|
|
252
|
+
# function_definition:参数列表不在祖先链上,需主动下探
|
|
253
|
+
if node.type == 'function_definition':
|
|
254
|
+
for child in node.children:
|
|
255
|
+
if child.type in ('function_declarator', 'pointer_declarator',
|
|
256
|
+
'reference_declarator'):
|
|
257
|
+
for sub in child.children:
|
|
258
|
+
if sub.type == 'parameter_list':
|
|
259
|
+
for param in sub.children:
|
|
260
|
+
if param.type != 'parameter_declaration':
|
|
261
|
+
continue
|
|
262
|
+
vtype = self._get_primary_type_name(param)
|
|
263
|
+
if not vtype:
|
|
264
|
+
continue
|
|
265
|
+
for ch in param.children:
|
|
266
|
+
if ch.type == 'identifier' and self.name_of(ch) == var_name:
|
|
267
|
+
return vtype
|
|
268
|
+
elif ch.type in _DECLARATOR_CONTAINERS:
|
|
269
|
+
id_nd = _extract_declarator_id(ch, False)
|
|
270
|
+
if id_nd and self.name_of(id_nd) == var_name:
|
|
271
|
+
return vtype
|
|
272
|
+
# for-range loop 变量:for (Type var : range)
|
|
273
|
+
if node.type == 'for_range_loop':
|
|
274
|
+
loop_type = self._get_primary_type_name(node) # 直接子节点里找 type_identifier
|
|
275
|
+
found_first = False
|
|
276
|
+
for ch in node.children:
|
|
277
|
+
if ch.type in (':', 'compound_statement'):
|
|
278
|
+
break
|
|
279
|
+
if ch.is_named and not found_first:
|
|
280
|
+
found_first = True # 跳过类型说明符节点本身
|
|
281
|
+
continue
|
|
282
|
+
if ch.type == 'identifier' and self.name_of(ch) == var_name:
|
|
283
|
+
return loop_type
|
|
284
|
+
elif ch.type in _DECLARATOR_CONTAINERS:
|
|
285
|
+
id_nd = _extract_declarator_id(ch, False)
|
|
286
|
+
if id_nd and self.name_of(id_nd) == var_name:
|
|
287
|
+
return loop_type
|
|
288
|
+
# 类/结构体成员字段(方法内访问 this->field 或其他成员变量)
|
|
289
|
+
if node.type in ('struct_specifier', 'class_specifier', 'union_specifier'):
|
|
290
|
+
for ch in node.children:
|
|
291
|
+
if ch.type == 'field_declaration_list':
|
|
292
|
+
for fd in ch.children:
|
|
293
|
+
if fd.type != 'field_declaration':
|
|
294
|
+
continue
|
|
295
|
+
vtype = self._get_primary_type_name(fd)
|
|
296
|
+
for fc in fd.children:
|
|
297
|
+
if fc.type == 'field_identifier' and self.name_of(fc) == var_name:
|
|
298
|
+
return vtype
|
|
299
|
+
elif fc.type in _DECLARATOR_CONTAINERS or fc.type == 'init_declarator':
|
|
300
|
+
id_nd = _extract_declarator_id(fc, True)
|
|
301
|
+
if id_nd and self.name_of(id_nd) == var_name:
|
|
302
|
+
return vtype
|
|
303
|
+
break
|
|
222
304
|
node = node.parent
|
|
223
305
|
return self.var_type_map.get(var_name)
|
|
224
306
|
|
|
225
307
|
# ── 字段访问对象类型推断 ─────────────────────────────────────────────
|
|
308
|
+
def _enclosing_class(self, node) -> str | None:
|
|
309
|
+
"""向上找最近的 class/struct/union 定义,返回其名字。"""
|
|
310
|
+
n = node.parent
|
|
311
|
+
while n is not None:
|
|
312
|
+
if n.type in ('struct_specifier', 'class_specifier', 'union_specifier'):
|
|
313
|
+
for ch in n.children:
|
|
314
|
+
if ch.type == 'type_identifier':
|
|
315
|
+
return self.name_of(ch)
|
|
316
|
+
n = n.parent
|
|
317
|
+
return None
|
|
318
|
+
|
|
226
319
|
def _resolve_field_object_type(self, field_expr_node) -> str | None:
|
|
227
320
|
if not field_expr_node.children:
|
|
228
321
|
return None
|
|
229
322
|
value_node = field_expr_node.children[0]
|
|
230
323
|
vt = value_node.type
|
|
231
324
|
td = self.typedef_map
|
|
325
|
+
if vt == 'this':
|
|
326
|
+
cls = self._enclosing_class(field_expr_node)
|
|
327
|
+
return td.get(cls, cls) if cls else None
|
|
232
328
|
if vt == 'identifier':
|
|
233
329
|
t = self._lookup_var_type_in_scope(value_node)
|
|
234
330
|
return td.get(t, t)
|
|
@@ -255,198 +351,191 @@ class _RenameCtx:
|
|
|
255
351
|
elif arr.type == 'field_expression':
|
|
256
352
|
return self._resolve_field_object_type(arr)
|
|
257
353
|
return None
|
|
258
|
-
|
|
259
|
-
# ── 步骤 1:收集声明位节点 ────────────────────────────────────────────
|
|
260
|
-
def collect_decl_nodes(self):
|
|
261
|
-
local_decl: list = []
|
|
262
|
-
member_decl: list = []
|
|
263
|
-
|
|
264
|
-
def walk(node):
|
|
265
|
-
nt = node.type
|
|
266
|
-
if nt == 'declaration':
|
|
267
|
-
for ch in node.children:
|
|
268
|
-
if ch.type == 'identifier':
|
|
269
|
-
local_decl.append(ch)
|
|
270
|
-
elif ch.type in _DECLARATOR_CONTAINERS or ch.type == 'init_declarator':
|
|
271
|
-
id_node = _extract_declarator_id(ch, False)
|
|
272
|
-
if id_node: local_decl.append(id_node)
|
|
273
|
-
elif ch.type == 'function_declarator':
|
|
274
|
-
decl_type = self._get_primary_type_name(node)
|
|
275
|
-
if decl_type and decl_type in self.user_struct_names:
|
|
276
|
-
for sub in ch.children:
|
|
277
|
-
if sub.type == 'identifier':
|
|
278
|
-
local_decl.append(sub); break
|
|
279
|
-
elif nt == 'parameter_declaration':
|
|
280
|
-
for ch in node.children:
|
|
281
|
-
if ch.type == 'identifier':
|
|
282
|
-
local_decl.append(ch)
|
|
283
|
-
elif ch.type in _DECLARATOR_CONTAINERS:
|
|
284
|
-
id_node = _extract_declarator_id(ch, False)
|
|
285
|
-
if id_node: local_decl.append(id_node)
|
|
286
|
-
elif nt == 'for_range_loop':
|
|
287
|
-
found_type = False
|
|
288
|
-
for ch in node.children:
|
|
289
|
-
if ch.type in (':', 'compound_statement'): break
|
|
290
|
-
if ch.is_named and not found_type:
|
|
291
|
-
found_type = True; continue
|
|
292
|
-
if ch.type == 'identifier':
|
|
293
|
-
local_decl.append(ch); break
|
|
294
|
-
elif ch.type in _DECLARATOR_CONTAINERS:
|
|
295
|
-
id_node = _extract_declarator_id(ch, False)
|
|
296
|
-
if id_node: local_decl.append(id_node)
|
|
297
|
-
break
|
|
298
|
-
elif nt == 'field_declaration':
|
|
299
|
-
for ch in node.children:
|
|
300
|
-
if ch.type == 'field_identifier':
|
|
301
|
-
member_decl.append(ch)
|
|
302
|
-
elif ch.type in _DECLARATOR_CONTAINERS or ch.type == 'init_declarator':
|
|
303
|
-
id_node = _extract_declarator_id(ch, True)
|
|
304
|
-
if id_node: member_decl.append(id_node)
|
|
305
|
-
if nt == 'function_declarator':
|
|
306
|
-
for ch in node.children:
|
|
307
|
-
if ch.type != 'identifier': walk(ch)
|
|
308
|
-
else:
|
|
309
|
-
for ch in node.children: walk(ch)
|
|
310
|
-
|
|
311
|
-
walk(self.tree.root_node)
|
|
312
|
-
return local_decl, member_decl
|
|
313
|
-
|
|
314
|
-
# ── 步骤 3:统计频率 ──────────────────────────────────────────────────
|
|
315
|
-
def count_freq(self, local_names, member_names) -> dict:
|
|
316
|
-
freq: dict = {}
|
|
317
|
-
def walk(node):
|
|
318
|
-
if node.type == 'identifier':
|
|
319
|
-
n = self.name_of(node)
|
|
320
|
-
if n in local_names:
|
|
321
|
-
freq[n] = freq.get(n, 0) + 1
|
|
322
|
-
elif n in member_names and self._is_qid_name(node):
|
|
323
|
-
scope_cls = self._get_qid_scope_class(node.parent)
|
|
324
|
-
real_cls = self.typedef_map.get(scope_cls, scope_cls) if scope_cls else None
|
|
325
|
-
if real_cls and real_cls in self.user_struct_names:
|
|
326
|
-
freq[n] = freq.get(n, 0) + 1
|
|
327
|
-
elif node.type == 'field_identifier':
|
|
328
|
-
n = self.name_of(node)
|
|
329
|
-
if n in member_names: freq[n] = freq.get(n, 0) + 1
|
|
330
|
-
elif node.type == 'type_identifier':
|
|
331
|
-
n = self.name_of(node)
|
|
332
|
-
if n in local_names:
|
|
333
|
-
par = node.parent
|
|
334
|
-
if (par and par.type == 'parameter_declaration'
|
|
335
|
-
and par.parent and par.parent.type == 'parameter_list'
|
|
336
|
-
and par.parent.parent and par.parent.parent.type == 'function_declarator'
|
|
337
|
-
and par.parent.parent.parent
|
|
338
|
-
and par.parent.parent.parent.type == 'declaration'):
|
|
339
|
-
freq[n] = freq.get(n, 0) + 1
|
|
340
|
-
for ch in node.children: walk(ch)
|
|
341
|
-
walk(self.tree.root_node)
|
|
354
|
+
|
|
355
|
+
# ── 步骤 1:收集声明位节点 ────────────────────────────────────────────
|
|
356
|
+
def collect_decl_nodes(self):
|
|
357
|
+
local_decl: list = []
|
|
358
|
+
member_decl: list = []
|
|
359
|
+
|
|
360
|
+
def walk(node):
|
|
361
|
+
nt = node.type
|
|
362
|
+
if nt == 'declaration':
|
|
363
|
+
for ch in node.children:
|
|
364
|
+
if ch.type == 'identifier':
|
|
365
|
+
local_decl.append(ch)
|
|
366
|
+
elif ch.type in _DECLARATOR_CONTAINERS or ch.type == 'init_declarator':
|
|
367
|
+
id_node = _extract_declarator_id(ch, False)
|
|
368
|
+
if id_node: local_decl.append(id_node)
|
|
369
|
+
elif ch.type == 'function_declarator':
|
|
370
|
+
decl_type = self._get_primary_type_name(node)
|
|
371
|
+
if decl_type and decl_type in self.user_struct_names:
|
|
372
|
+
for sub in ch.children:
|
|
373
|
+
if sub.type == 'identifier':
|
|
374
|
+
local_decl.append(sub); break
|
|
375
|
+
elif nt == 'parameter_declaration':
|
|
376
|
+
for ch in node.children:
|
|
377
|
+
if ch.type == 'identifier':
|
|
378
|
+
local_decl.append(ch)
|
|
379
|
+
elif ch.type in _DECLARATOR_CONTAINERS:
|
|
380
|
+
id_node = _extract_declarator_id(ch, False)
|
|
381
|
+
if id_node: local_decl.append(id_node)
|
|
382
|
+
elif nt == 'for_range_loop':
|
|
383
|
+
found_type = False
|
|
384
|
+
for ch in node.children:
|
|
385
|
+
if ch.type in (':', 'compound_statement'): break
|
|
386
|
+
if ch.is_named and not found_type:
|
|
387
|
+
found_type = True; continue
|
|
388
|
+
if ch.type == 'identifier':
|
|
389
|
+
local_decl.append(ch); break
|
|
390
|
+
elif ch.type in _DECLARATOR_CONTAINERS:
|
|
391
|
+
id_node = _extract_declarator_id(ch, False)
|
|
392
|
+
if id_node: local_decl.append(id_node)
|
|
393
|
+
break
|
|
394
|
+
elif nt == 'field_declaration':
|
|
395
|
+
for ch in node.children:
|
|
396
|
+
if ch.type == 'field_identifier':
|
|
397
|
+
member_decl.append(ch)
|
|
398
|
+
elif ch.type in _DECLARATOR_CONTAINERS or ch.type == 'init_declarator':
|
|
399
|
+
id_node = _extract_declarator_id(ch, True)
|
|
400
|
+
if id_node: member_decl.append(id_node)
|
|
401
|
+
if nt == 'function_declarator':
|
|
402
|
+
for ch in node.children:
|
|
403
|
+
if ch.type != 'identifier': walk(ch)
|
|
404
|
+
else:
|
|
405
|
+
for ch in node.children: walk(ch)
|
|
406
|
+
|
|
407
|
+
walk(self.tree.root_node)
|
|
408
|
+
return local_decl, member_decl
|
|
409
|
+
|
|
410
|
+
# ── 步骤 3:统计频率 ──────────────────────────────────────────────────
|
|
411
|
+
def count_freq(self, local_names, member_names) -> dict:
|
|
412
|
+
freq: dict = {}
|
|
413
|
+
def walk(node):
|
|
414
|
+
if node.type == 'identifier':
|
|
415
|
+
n = self.name_of(node)
|
|
416
|
+
if n in local_names:
|
|
417
|
+
freq[n] = freq.get(n, 0) + 1
|
|
418
|
+
elif n in member_names and self._is_qid_name(node):
|
|
419
|
+
scope_cls = self._get_qid_scope_class(node.parent)
|
|
420
|
+
real_cls = self.typedef_map.get(scope_cls, scope_cls) if scope_cls else None
|
|
421
|
+
if real_cls and real_cls in self.user_struct_names:
|
|
422
|
+
freq[n] = freq.get(n, 0) + 1
|
|
423
|
+
elif node.type == 'field_identifier':
|
|
424
|
+
n = self.name_of(node)
|
|
425
|
+
if n in member_names: freq[n] = freq.get(n, 0) + 1
|
|
426
|
+
elif node.type == 'type_identifier':
|
|
427
|
+
n = self.name_of(node)
|
|
428
|
+
if n in local_names:
|
|
429
|
+
par = node.parent
|
|
430
|
+
if (par and par.type == 'parameter_declaration'
|
|
431
|
+
and par.parent and par.parent.type == 'parameter_list'
|
|
432
|
+
and par.parent.parent and par.parent.parent.type == 'function_declarator'
|
|
433
|
+
and par.parent.parent.parent
|
|
434
|
+
and par.parent.parent.parent.type == 'declaration'):
|
|
435
|
+
freq[n] = freq.get(n, 0) + 1
|
|
436
|
+
for ch in node.children: walk(ch)
|
|
437
|
+
walk(self.tree.root_node)
|
|
342
438
|
return freq
|
|
343
|
-
|
|
344
|
-
# ── 步骤 5:收集替换位置 ──────────────────────────────────────────────
|
|
345
|
-
def build_replacements(self, rename_map, local_names, member_names):
|
|
346
|
-
replacements: list = []
|
|
347
|
-
class_stack: list = []
|
|
348
|
-
|
|
349
|
-
def walk(node):
|
|
350
|
-
entered = False
|
|
351
|
-
nt = node.type
|
|
352
|
-
if nt in ('struct_specifier', 'class_specifier', 'union_specifier'):
|
|
353
|
-
for ch in node.children:
|
|
354
|
-
if ch.type == 'type_identifier':
|
|
355
|
-
class_stack.append(self.name_of(ch)); entered = True; break
|
|
356
|
-
|
|
357
|
-
if nt == 'identifier':
|
|
358
|
-
n = self.name_of(node)
|
|
359
|
-
if n in rename_map and n in local_names:
|
|
360
|
-
replacements.append((node.start_byte, node.end_byte, rename_map[n].encode()))
|
|
361
|
-
elif n in rename_map and n in member_names and class_stack:
|
|
362
|
-
replacements.append((node.start_byte, node.end_byte, rename_map[n].encode()))
|
|
363
|
-
elif n in rename_map and n in member_names and self._is_qid_name(node):
|
|
364
|
-
scope_cls = self._get_qid_scope_class(node.parent)
|
|
365
|
-
real_cls = self.typedef_map.get(scope_cls, scope_cls) if scope_cls else None
|
|
366
|
-
if real_cls and real_cls in self.user_struct_names:
|
|
367
|
-
replacements.append((node.start_byte, node.end_byte, rename_map[n].encode()))
|
|
368
|
-
elif nt == 'type_identifier':
|
|
369
|
-
n = self.name_of(node)
|
|
370
|
-
if n in rename_map and n in local_names:
|
|
371
|
-
par = node.parent
|
|
372
|
-
if (par and par.type == 'parameter_declaration'
|
|
373
|
-
and par.parent and par.parent.type == 'parameter_list'
|
|
374
|
-
and par.parent.parent and par.parent.parent.type == 'function_declarator'
|
|
375
|
-
and par.parent.parent.parent
|
|
376
|
-
and par.parent.parent.parent.type == 'declaration'):
|
|
377
|
-
decl_type = self._get_primary_type_name(par.parent.parent.parent)
|
|
378
|
-
if decl_type and decl_type in self.user_struct_names:
|
|
379
|
-
replacements.append((node.start_byte, node.end_byte, rename_map[n].encode()))
|
|
380
|
-
elif nt == 'field_identifier':
|
|
381
|
-
n = self.name_of(node)
|
|
382
|
-
if n in rename_map and n in member_names:
|
|
383
|
-
parent = node.parent
|
|
384
|
-
if parent and parent.type == 'field_expression':
|
|
385
|
-
obj_type = self._resolve_field_object_type(parent)
|
|
386
|
-
if obj_type and obj_type in self.user_struct_names:
|
|
387
|
-
replacements.append((node.start_byte, node.end_byte, rename_map[n].encode()))
|
|
388
|
-
else:
|
|
389
|
-
replacements.append((node.start_byte, node.end_byte, rename_map[n].encode()))
|
|
390
|
-
|
|
391
|
-
for ch in node.children: walk(ch)
|
|
392
|
-
if entered: class_stack.pop()
|
|
393
|
-
|
|
394
|
-
walk(self.tree.root_node)
|
|
395
|
-
return replacements
|
|
396
|
-
|
|
397
|
-
# ── 步骤 6:应用替换 ──────────────────────────────────────────────────
|
|
398
|
-
def apply(self, replacements) -> str:
|
|
399
|
-
replacements.sort(key=lambda x: x[0], reverse=True)
|
|
400
|
-
buf = bytearray(self.src)
|
|
401
|
-
for start, end, new in replacements:
|
|
402
|
-
buf[start:end] = new
|
|
403
|
-
return buf.decode('utf-8')
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
# ─────────────────────────────────────────────────────────────────────────────
|
|
407
|
-
# 公开入口
|
|
408
|
-
# ─────────────────────────────────────────────────────────────────────────────
|
|
409
|
-
def golf_rename_symbols(code: str) -> str:
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
short = next(gen)
|
|
446
|
-
rename_map[original] = short
|
|
447
|
-
occupied.add(short)
|
|
448
|
-
|
|
449
|
-
replacements = ctx.build_replacements(rename_map, local_names, member_names)
|
|
450
|
-
if not replacements:
|
|
451
|
-
return code
|
|
439
|
+
|
|
440
|
+
# ── 步骤 5:收集替换位置 ──────────────────────────────────────────────
|
|
441
|
+
def build_replacements(self, rename_map, local_names, member_names):
|
|
442
|
+
replacements: list = []
|
|
443
|
+
class_stack: list = []
|
|
444
|
+
|
|
445
|
+
def walk(node):
|
|
446
|
+
entered = False
|
|
447
|
+
nt = node.type
|
|
448
|
+
if nt in ('struct_specifier', 'class_specifier', 'union_specifier'):
|
|
449
|
+
for ch in node.children:
|
|
450
|
+
if ch.type == 'type_identifier':
|
|
451
|
+
class_stack.append(self.name_of(ch)); entered = True; break
|
|
452
|
+
|
|
453
|
+
if nt == 'identifier':
|
|
454
|
+
n = self.name_of(node)
|
|
455
|
+
if n in rename_map and n in local_names:
|
|
456
|
+
replacements.append((node.start_byte, node.end_byte, rename_map[n].encode()))
|
|
457
|
+
elif n in rename_map and n in member_names and class_stack:
|
|
458
|
+
replacements.append((node.start_byte, node.end_byte, rename_map[n].encode()))
|
|
459
|
+
elif n in rename_map and n in member_names and self._is_qid_name(node):
|
|
460
|
+
scope_cls = self._get_qid_scope_class(node.parent)
|
|
461
|
+
real_cls = self.typedef_map.get(scope_cls, scope_cls) if scope_cls else None
|
|
462
|
+
if real_cls and real_cls in self.user_struct_names:
|
|
463
|
+
replacements.append((node.start_byte, node.end_byte, rename_map[n].encode()))
|
|
464
|
+
elif nt == 'type_identifier':
|
|
465
|
+
n = self.name_of(node)
|
|
466
|
+
if n in rename_map and n in local_names:
|
|
467
|
+
par = node.parent
|
|
468
|
+
if (par and par.type == 'parameter_declaration'
|
|
469
|
+
and par.parent and par.parent.type == 'parameter_list'
|
|
470
|
+
and par.parent.parent and par.parent.parent.type == 'function_declarator'
|
|
471
|
+
and par.parent.parent.parent
|
|
472
|
+
and par.parent.parent.parent.type == 'declaration'):
|
|
473
|
+
decl_type = self._get_primary_type_name(par.parent.parent.parent)
|
|
474
|
+
if decl_type and decl_type in self.user_struct_names:
|
|
475
|
+
replacements.append((node.start_byte, node.end_byte, rename_map[n].encode()))
|
|
476
|
+
elif nt == 'field_identifier':
|
|
477
|
+
n = self.name_of(node)
|
|
478
|
+
if n in rename_map and n in member_names:
|
|
479
|
+
parent = node.parent
|
|
480
|
+
if parent and parent.type == 'field_expression':
|
|
481
|
+
obj_type = self._resolve_field_object_type(parent)
|
|
482
|
+
if obj_type and obj_type in self.user_struct_names:
|
|
483
|
+
replacements.append((node.start_byte, node.end_byte, rename_map[n].encode()))
|
|
484
|
+
else:
|
|
485
|
+
replacements.append((node.start_byte, node.end_byte, rename_map[n].encode()))
|
|
486
|
+
|
|
487
|
+
for ch in node.children: walk(ch)
|
|
488
|
+
if entered: class_stack.pop()
|
|
489
|
+
|
|
490
|
+
walk(self.tree.root_node)
|
|
491
|
+
return replacements
|
|
492
|
+
|
|
493
|
+
# ── 步骤 6:应用替换 ──────────────────────────────────────────────────
|
|
494
|
+
def apply(self, replacements) -> str:
|
|
495
|
+
replacements.sort(key=lambda x: x[0], reverse=True)
|
|
496
|
+
buf = bytearray(self.src)
|
|
497
|
+
for start, end, new in replacements:
|
|
498
|
+
buf[start:end] = new
|
|
499
|
+
return buf.decode('utf-8')
|
|
500
|
+
|
|
501
|
+
|
|
502
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
503
|
+
# 公开入口
|
|
504
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
505
|
+
def golf_rename_symbols(code: str) -> str:
|
|
506
|
+
_lang = Language(tscpp.language())
|
|
507
|
+
|
|
508
|
+
src_bytes = code.encode('utf-8')
|
|
509
|
+
parser = Parser(_lang)
|
|
510
|
+
tree = parser.parse(src_bytes)
|
|
511
|
+
|
|
512
|
+
ctx = _RenameCtx(src_bytes, tree)
|
|
513
|
+
ctx.build_type_context()
|
|
514
|
+
|
|
515
|
+
local_decl, member_decl = ctx.collect_decl_nodes()
|
|
516
|
+
name_of = ctx.name_of
|
|
517
|
+
|
|
518
|
+
local_names = {name_of(n) for n in local_decl if len(name_of(n)) >= _MIN_RENAME_LEN}
|
|
519
|
+
member_names = {name_of(n) for n in member_decl if len(name_of(n)) >= _MIN_RENAME_LEN}
|
|
520
|
+
if not local_names and not member_names:
|
|
521
|
+
return code
|
|
522
|
+
|
|
523
|
+
all_targets = local_names | member_names
|
|
524
|
+
freq = ctx.count_freq(local_names, member_names)
|
|
525
|
+
|
|
526
|
+
# 步骤 4:生成重命名映射
|
|
527
|
+
all_existing = set(re.findall(r'\b[A-Za-z_]\w*\b', code))
|
|
528
|
+
occupied = all_existing | _CXX_KEYWORDS
|
|
529
|
+
rename_map: dict = {}
|
|
530
|
+
gen = _gen_short_names()
|
|
531
|
+
for original in sorted(all_targets, key=lambda x: -freq.get(x, 0)):
|
|
532
|
+
short = next(gen)
|
|
533
|
+
while short in occupied or short == original:
|
|
534
|
+
short = next(gen)
|
|
535
|
+
rename_map[original] = short
|
|
536
|
+
occupied.add(short)
|
|
537
|
+
|
|
538
|
+
replacements = ctx.build_replacements(rename_map, local_names, member_names)
|
|
539
|
+
if not replacements:
|
|
540
|
+
return code
|
|
452
541
|
return ctx.apply(replacements)
|
|
@@ -20,29 +20,40 @@ def golf_std_namespace(code: str) -> str:
|
|
|
20
20
|
|
|
21
21
|
|
|
22
22
|
def golf_typedefs(code: str) -> str:
|
|
23
|
-
"""对高频长类型名添加
|
|
23
|
+
"""对高频长类型名添加 typedef 缩写(出现 ≥2 次时触发)。"""
|
|
24
24
|
replacements = [
|
|
25
|
-
(r'\blong long\b', 'll', '
|
|
26
|
-
(r'\bunsigned long long\b', 'ull', '
|
|
27
|
-
(r'\blong double\b', 'ld', '
|
|
28
|
-
(r'\bvector<int>\b', 'vi', '
|
|
29
|
-
(r'\bvector<ll>\b', 'vll', '
|
|
30
|
-
(r'\bpair<int,int>\b', 'pii', '
|
|
31
|
-
(r'\bpair<ll,ll>\b', 'pll', '
|
|
25
|
+
(r'\blong long\b', 'll', 'typedef long long ll;'),
|
|
26
|
+
(r'\bunsigned long long\b', 'ull', 'typedef unsigned long long ull;'),
|
|
27
|
+
(r'\blong double\b', 'ld', 'typedef long double ld;'),
|
|
28
|
+
(r'\bvector<int>\b', 'vi', 'typedef vector<int> vi;'),
|
|
29
|
+
(r'\bvector<ll>\b', 'vll', 'typedef vector<ll> vll;'),
|
|
30
|
+
(r'\bpair<int,int>\b', 'pii', 'typedef pair<int,int> pii;'),
|
|
31
|
+
(r'\bpair<ll,ll>\b', 'pll', 'typedef pair<ll,ll> pll;'),
|
|
32
32
|
]
|
|
33
33
|
defines_to_add = []
|
|
34
34
|
for pattern, short, defline in replacements:
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
35
|
+
# 提取缩写名(typedef ... short;)
|
|
36
|
+
macro = defline.rstrip(';').split()[-1]
|
|
37
|
+
# 匹配已有的 typedef 或 #define 形式
|
|
38
|
+
existing_re = re.compile(
|
|
39
|
+
r'^[ \t]*(?:'
|
|
40
|
+
r'typedef\b[^\n]+\b' + re.escape(macro) + r'\s*;'
|
|
41
|
+
r'|#[ \t]*define[ \t]+' + re.escape(macro) + r'\b[^\n]*'
|
|
42
|
+
r')[ \t]*\n?',
|
|
43
|
+
re.MULTILINE,
|
|
44
|
+
)
|
|
45
|
+
existing = existing_re.search(code)
|
|
46
|
+
if existing:
|
|
47
|
+
# 已有定义:从原位删掉,稍后统一插到顶部
|
|
48
|
+
code = code[:existing.start()] + code[existing.end():]
|
|
49
|
+
defines_to_add.append(defline)
|
|
50
|
+
elif len(re.findall(pattern, code)) >= 2:
|
|
39
51
|
defines_to_add.append(defline)
|
|
40
52
|
code = re.sub(pattern, short, code)
|
|
41
53
|
if defines_to_add:
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
)
|
|
54
|
+
# 插入点:文件顶部 include 块末尾
|
|
55
|
+
include_ends = [m.end() for m in re.finditer(r'^[ \t]*#[ \t]*include\b.*$', code, re.MULTILINE)]
|
|
56
|
+
last = include_ends[-1] if include_ends else 0
|
|
46
57
|
code = code[:last] + '\n' + '\n'.join(defines_to_add) + '\n' + code[last:]
|
|
47
58
|
return code
|
|
48
59
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|