reproto 0.1.1__py3-none-any.whl → 0.1.3__py3-none-any.whl

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.
Files changed (127) hide show
  1. .git/COMMIT_EDITMSG +29 -1
  2. .git/index +0 -0
  3. .git/logs/HEAD +4 -0
  4. .git/logs/refs/heads/iyue +4 -0
  5. .git/logs/refs/remotes/gitlab/iyue +4 -0
  6. .git/logs/refs/remotes/origin/iyue +4 -0
  7. .git/objects/00/81a7e1ec3251cc192ed2b73d5be897593fb872 +0 -0
  8. .git/objects/00/885cebf557ff261574deb93cb96449d06db01c +0 -0
  9. .git/objects/02/33f5b60263e5dc6d041c0b223a0724eb650faa +0 -0
  10. .git/objects/03/3fab23ccc74b707a31f6f37dc5df42c100aac0 +0 -0
  11. .git/objects/07/557fbd1d149ce51af8e98e8ca8590757a89dfa +0 -0
  12. .git/objects/07/b71df33935c14ddf99e3480c04eca4685028bc +0 -0
  13. .git/objects/0b/e20ea749c6ae1075ae98f9426e00b0a4a235af +0 -0
  14. .git/objects/12/f9cc4ad0b4f0af4f7bae379f281b2cebe7cc7f +0 -0
  15. .git/objects/13/5f50fea51c72f977f48d06a7584aba0f61e260 +0 -0
  16. .git/objects/1b/97584ebada3e93d7a2cfa4a1aae0b79c414d20 +0 -0
  17. .git/objects/1b/f0c1ad9586578e8332d061f7648dcb041ec063 +0 -0
  18. .git/objects/1e/46816d16e7c9db7575f1964403c3daa105be5c +0 -0
  19. .git/objects/24/d78e796570a8572a03bc1dd26608a7cfb506f8 +2 -0
  20. .git/objects/27/24208ca2442e8ab9b453d0eb230fa41243b270 +0 -0
  21. .git/objects/2a/fe93d8bcbeab9e136d8b6766604c32b3610314 +0 -0
  22. .git/objects/2d/2b812ca27c477f9e1b2c2706a5eb795ffcf8eb +0 -0
  23. .git/objects/2d/8a0da260a710010ae62be134ac1cea6ceecfd1 +0 -0
  24. .git/objects/2d/e8ecbb5ab5de1a032bef3f4606ce5fa7c6c4e8 +0 -0
  25. .git/objects/30/9347e5681d80bd3c7949882e27090dd9070d16 +0 -0
  26. .git/objects/33/633c9df669ff8cf38638717937a54990814268 +0 -0
  27. .git/objects/39/993e3600bf4ab82aa361b738ee97a108787450 +0 -0
  28. .git/objects/3b/ab663710fd6b43d9372313fced9043c4cb07dd +0 -0
  29. .git/objects/3e/b3f1273caf6814dfa69325ccbd9fd1340cf20a +0 -0
  30. .git/objects/3f/b8830f516342a0ae1cb7c34b65016827cb9570 +4 -0
  31. .git/objects/41/f40c22247de377be99e30784229f3f128508a2 +0 -0
  32. .git/objects/45/fbc774dedb61c7c205ea732f59a8dca8d13555 +3 -0
  33. .git/objects/48/cb11e75518a53be14146018214110986fade67 +0 -0
  34. .git/objects/4f/c6dc41f9c0a1a8e0eedd3ba49c43d78d0dbaba +0 -0
  35. .git/objects/59/4c23f158ccbd0a4288f9ea046d06160195afbf +0 -0
  36. .git/objects/5b/d4d87753b79e9157817f0c2e6964a731052854 +0 -0
  37. .git/objects/60/5cb6fd6a9f8894ad4d43a9b8e4785c1b3b0e17 +1 -0
  38. .git/objects/60/f61a0ea50091eac8d344c86597375cbdfc2785 +0 -0
  39. .git/objects/63/ddda2a403efaab3f4c6597b3a73a7b1147adb5 +0 -0
  40. .git/objects/65/0189fe083bd711e45d463b229a72be619abad2 +0 -0
  41. .git/objects/66/663db35bfec8ef5f1a5b1c840fde1bb62a0eb8 +0 -0
  42. .git/objects/66/6c5c5fc30435228116fa08c9d821bebaaa8926 +0 -0
  43. .git/objects/7c/ef0adfb28fd774bc78061c6f088e1ef9b050f6 +0 -0
  44. .git/objects/7d/dc129188a10c68ab756ef2cacb292c76920403 +0 -0
  45. .git/objects/80/17038e0f7818a44a742f77c86f4f88ed768fcd +0 -0
  46. .git/objects/87/c7db6c91c17a2df84b56d30bd24a0f6b9dbdd9 +0 -0
  47. .git/objects/8a/0ed0ed8886fbc823e8d2258fa6d18699e94e25 +0 -0
  48. .git/objects/8d/d857b3d0ab3f5cd2e9173d532ef86e30df8eda +0 -0
  49. .git/objects/92/984cf67b2c25d435468a8218daa26ba0466054 +0 -0
  50. .git/objects/93/140b54b1fb9116ee214afee8abf2c72a232487 +0 -0
  51. .git/objects/93/68f2c32f83054ab072b7c9686d8baa0bad7f12 +4 -0
  52. .git/objects/9a/5ad062be9f6e001f4237a598a08981aba731e6 +0 -0
  53. .git/objects/9e/23448ac58f907d9d123c32bdccedbb3d6741b5 +0 -0
  54. .git/objects/a0/d192999af7e2cbfa6a9ccd04d720a04e5a06d5 +0 -0
  55. .git/objects/a1/655e0cb323c300562f97dcc67d5a446908c8ec +0 -0
  56. .git/objects/a5/38cc82cef7c49500d3522220f0f60a9ebc1ae6 +0 -0
  57. .git/objects/a9/41063a7ce89c353fa24378ec7c3f12f08f9df8 +0 -0
  58. .git/objects/a9/cc7923c34a4c97c5711d6309672f41d46c612a +0 -0
  59. .git/objects/ac/5c983d949d8c928bb022badf801e45e75e785e +0 -0
  60. .git/objects/af/c9cc15629847447063e86a82b8b56abb4fc08f +0 -0
  61. .git/objects/b0/82ca2c1b5a03edff25da3c2b2b573d049877e9 +0 -0
  62. .git/objects/b1/db1c131cf32916028342c0037ce8eb57a8eb26 +0 -0
  63. .git/objects/b2/8334b94392b8af397a05ed702690fa6c9ab1ca +0 -0
  64. .git/objects/b8/7c89dcfce9e244ff5ef6a4bd394de12e8c8092 +0 -0
  65. .git/objects/bc/e98bdb71c8681acb460195fdcbbe5d36290976 +0 -0
  66. .git/objects/c1/87d5e047eca86cfd8d444be2987aaa3f62c4d6 +0 -0
  67. .git/objects/c4/c2da96b0bb8db2acb0e6615cf340c7e51af26b +0 -0
  68. .git/objects/c5/13a96e7584636b20b12280c029750d5bc3da1e +0 -0
  69. .git/objects/c7/c34283697bd3cce07db53953eda25ee7cc371e +0 -0
  70. .git/objects/c9/d60d922a04b87587cd67b0abf9fe5a7b7b76cd +0 -0
  71. .git/objects/d2/69b1676dbf32f76a7c405d0b4ea6a70ac3a626 +0 -0
  72. .git/objects/d3/5a918b1d9125ad35d60e08b181323df3246f1a +0 -0
  73. .git/objects/d8/eaf86669fbfd10497570c1784db1ed2696b588 +0 -0
  74. .git/objects/d9/3bd435c8c7ad4efb83dff04d5450fabb9e3faf +0 -0
  75. .git/objects/d9/90e6d553577d37ebce8b28b3015ecbde038b42 +0 -0
  76. .git/objects/da/13cc15bcd8ee39c81f36dee7f179a569ecab0b +0 -0
  77. .git/objects/e3/27755808d88c7ae5c06c229cf18bd0519646df +0 -0
  78. .git/objects/e4/4c1d8a90207ac082d8ab7ff0db66708e2ebc31 +0 -0
  79. .git/objects/e5/83e7c40be934d16a1fa2e973487b395d930f42 +0 -0
  80. .git/objects/ed/1ae867d5e63195845afc58d88c38ecbdea97df +0 -0
  81. .git/objects/ef/f44e5099da27f7fb1ef14bb34902ccf4250b89 +0 -0
  82. .git/objects/f5/1be495b96272fa2e47f30071aed35ac1f0dd2c +0 -0
  83. .git/objects/f8/ed595d25bd9d500e765a792c513878f7ddb1f7 +0 -0
  84. .git/objects/fd/0bc07dc3c95e6168ab6d367d9eca139ac1e539 +0 -0
  85. .git/refs/heads/iyue +1 -1
  86. .git/refs/remotes/gitlab/iyue +1 -1
  87. .git/refs/remotes/origin/iyue +1 -1
  88. .gitignore +2 -1
  89. README.md +104 -190
  90. core/__init__.py +23 -0
  91. core/info_decoder.py +520 -10
  92. core/reconstructor.py +159 -21
  93. generation/__init__.py +17 -0
  94. generation/proto_generator.py +62 -16
  95. include/google/protobuf/any.proto +162 -0
  96. include/google/protobuf/api.proto +207 -0
  97. include/google/protobuf/compiler/plugin.proto +180 -0
  98. include/google/protobuf/cpp_features.proto +67 -0
  99. include/google/protobuf/descriptor.proto +1417 -0
  100. include/google/protobuf/duration.proto +115 -0
  101. include/google/protobuf/empty.proto +51 -0
  102. include/google/protobuf/field_mask.proto +245 -0
  103. include/google/protobuf/go_features.proto +80 -0
  104. include/google/protobuf/java_features.proto +130 -0
  105. include/google/protobuf/source_context.proto +48 -0
  106. include/google/protobuf/struct.proto +95 -0
  107. include/google/protobuf/timestamp.proto +144 -0
  108. include/google/protobuf/type.proto +193 -0
  109. include/google/protobuf/wrappers.proto +157 -0
  110. main.py +53 -56
  111. models/__init__.py +31 -24
  112. parsing/__init__.py +22 -0
  113. parsing/enum_parser.py +10 -2
  114. parsing/java_parser.py +302 -13
  115. pyproject.toml +1 -1
  116. reproto-0.1.3.dist-info/METADATA +209 -0
  117. {reproto-0.1.1.dist-info → reproto-0.1.3.dist-info}/RECORD +125 -31
  118. utils/__init__.py +40 -0
  119. utils/builtin_proto.py +269 -0
  120. utils/file_cache.py +8 -1
  121. utils/report_utils.py +71 -0
  122. utils/type_index.py +8 -1
  123. utils/type_utils.py +39 -6
  124. core/bytecode_parser.py +0 -274
  125. reproto-0.1.1.dist-info/METADATA +0 -295
  126. {reproto-0.1.1.dist-info → reproto-0.1.3.dist-info}/WHEEL +0 -0
  127. {reproto-0.1.1.dist-info → reproto-0.1.3.dist-info}/entry_points.txt +0 -0
utils/builtin_proto.py ADDED
@@ -0,0 +1,269 @@
1
+ """
2
+ Google Protobuf 内置类型管理模块
3
+ 处理内置proto文件的检测、拷贝和导入语句生成
4
+ """
5
+
6
+ import os
7
+ import shutil
8
+ from pathlib import Path
9
+ from typing import Dict, Set, Optional
10
+
11
+ # 智能导入:同时支持相对导入(包环境)和绝对导入(开发环境)
12
+ try:
13
+ # 相对导入(包环境)
14
+ from .logger import logger
15
+ except ImportError:
16
+ # 绝对导入(开发环境)
17
+ from utils.logger import logger
18
+
19
+
20
+ def find_include_directory() -> Optional[Path]:
21
+ """
22
+ 查找include目录,支持开发环境和安装包环境
23
+
24
+ Returns:
25
+ include目录的路径,如果找不到则返回None
26
+ """
27
+ # 尝试多个可能的位置
28
+ possible_locations = [
29
+ # 1. 相对于当前文件的位置(开发环境)
30
+ Path(__file__).parent.parent / "include",
31
+
32
+ # 2. 相对于包安装位置(安装包环境)
33
+ Path(__file__).parent.parent.parent / "include",
34
+
35
+ # 3. 在site-packages中的位置
36
+ Path(__file__).parent / "include",
37
+
38
+ # 4. 使用pkg_resources查找(如果可用)
39
+ ]
40
+
41
+ # 尝试使用pkg_resources(推荐方式)
42
+ try:
43
+ import pkg_resources
44
+ try:
45
+ include_path = Path(pkg_resources.resource_filename('reproto', 'include'))
46
+ if include_path.exists():
47
+ possible_locations.insert(0, include_path)
48
+ except (pkg_resources.DistributionNotFound, FileNotFoundError):
49
+ pass
50
+ except ImportError:
51
+ pass
52
+
53
+ # 尝试使用importlib.resources(Python 3.9+推荐方式)
54
+ try:
55
+ import importlib.resources as resources
56
+ try:
57
+ # 对于Python 3.9+
58
+ if hasattr(resources, 'files'):
59
+ include_ref = resources.files('reproto') / 'include'
60
+ if include_ref.is_dir():
61
+ possible_locations.insert(0, Path(str(include_ref)))
62
+ except Exception:
63
+ pass
64
+ except ImportError:
65
+ pass
66
+
67
+ # 按优先级检查每个位置
68
+ for location in possible_locations:
69
+ if location.exists() and location.is_dir():
70
+ # 验证这确实是包含proto文件的include目录
71
+ wrappers_file = location / "google" / "protobuf" / "wrappers.proto"
72
+ if wrappers_file.exists():
73
+ logger.debug(f"找到include目录: {location}")
74
+ return location
75
+
76
+ logger.error("无法找到include目录")
77
+ return None
78
+
79
+
80
+ class BuiltinProtoManager:
81
+ """Google Protobuf 内置proto文件管理器"""
82
+
83
+ # 内置类型到proto文件的映射
84
+ _BUILTIN_TYPE_TO_FILE = {
85
+ # Wrapper types - 都在 wrappers.proto 中
86
+ 'google.protobuf.BoolValue': 'google/protobuf/wrappers.proto',
87
+ 'google.protobuf.Int32Value': 'google/protobuf/wrappers.proto',
88
+ 'google.protobuf.Int64Value': 'google/protobuf/wrappers.proto',
89
+ 'google.protobuf.UInt32Value': 'google/protobuf/wrappers.proto',
90
+ 'google.protobuf.UInt64Value': 'google/protobuf/wrappers.proto',
91
+ 'google.protobuf.FloatValue': 'google/protobuf/wrappers.proto',
92
+ 'google.protobuf.DoubleValue': 'google/protobuf/wrappers.proto',
93
+ 'google.protobuf.StringValue': 'google/protobuf/wrappers.proto',
94
+ 'google.protobuf.BytesValue': 'google/protobuf/wrappers.proto',
95
+
96
+ # Well-known types
97
+ 'google.protobuf.Any': 'google/protobuf/any.proto',
98
+ 'google.protobuf.Timestamp': 'google/protobuf/timestamp.proto',
99
+ 'google.protobuf.Duration': 'google/protobuf/duration.proto',
100
+ 'google.protobuf.Empty': 'google/protobuf/empty.proto',
101
+ 'google.protobuf.Struct': 'google/protobuf/struct.proto',
102
+ 'google.protobuf.Value': 'google/protobuf/struct.proto',
103
+ 'google.protobuf.ListValue': 'google/protobuf/struct.proto',
104
+ 'google.protobuf.NullValue': 'google/protobuf/struct.proto',
105
+ 'google.protobuf.FieldMask': 'google/protobuf/field_mask.proto',
106
+
107
+ # API types
108
+ 'google.protobuf.Api': 'google/protobuf/api.proto',
109
+ 'google.protobuf.Method': 'google/protobuf/api.proto',
110
+ 'google.protobuf.Mixin': 'google/protobuf/api.proto',
111
+
112
+ # Type definitions
113
+ 'google.protobuf.Type': 'google/protobuf/type.proto',
114
+ 'google.protobuf.Field': 'google/protobuf/type.proto',
115
+ 'google.protobuf.Enum': 'google/protobuf/type.proto',
116
+ 'google.protobuf.EnumValue': 'google/protobuf/type.proto',
117
+ 'google.protobuf.Option': 'google/protobuf/type.proto',
118
+ 'google.protobuf.Syntax': 'google/protobuf/type.proto',
119
+
120
+ # Source context
121
+ 'google.protobuf.SourceContext': 'google/protobuf/source_context.proto',
122
+ }
123
+
124
+ def __init__(self, include_dir: str, output_dir: str):
125
+ """
126
+ 初始化内置proto管理器
127
+
128
+ Args:
129
+ include_dir: include目录路径
130
+ output_dir: 输出目录路径
131
+ """
132
+ self.include_dir = Path(include_dir)
133
+ self.output_dir = Path(output_dir)
134
+ self._copied_files: Set[str] = set()
135
+
136
+ def is_builtin_type(self, proto_type: str) -> bool:
137
+ """
138
+ 检查是否为内置类型
139
+
140
+ Args:
141
+ proto_type: proto类型名称
142
+
143
+ Returns:
144
+ 是否为内置类型
145
+ """
146
+ return proto_type in self._BUILTIN_TYPE_TO_FILE
147
+
148
+ def get_import_path(self, proto_type: str) -> Optional[str]:
149
+ """
150
+ 获取内置类型的导入路径
151
+
152
+ Args:
153
+ proto_type: proto类型名称
154
+
155
+ Returns:
156
+ 导入路径,如果不是内置类型则返回None
157
+ """
158
+ return self._BUILTIN_TYPE_TO_FILE.get(proto_type)
159
+
160
+ def ensure_builtin_proto_file(self, proto_type: str) -> bool:
161
+ """
162
+ 确保内置proto文件存在于输出目录中
163
+
164
+ Args:
165
+ proto_type: proto类型名称
166
+
167
+ Returns:
168
+ 是否成功处理
169
+ """
170
+ if not self.is_builtin_type(proto_type):
171
+ return False
172
+
173
+ import_path = self.get_import_path(proto_type)
174
+ if not import_path:
175
+ return False
176
+
177
+ # 如果已经拷贝过,直接返回
178
+ if import_path in self._copied_files:
179
+ return True
180
+
181
+ # 源文件路径
182
+ source_file = self.include_dir / import_path
183
+ if not source_file.exists():
184
+ logger.error(f"内置proto文件不存在: {source_file}")
185
+ return False
186
+
187
+ # 目标文件路径
188
+ target_file = self.output_dir / import_path
189
+
190
+ # 创建目标目录
191
+ target_file.parent.mkdir(parents=True, exist_ok=True)
192
+
193
+ try:
194
+ # 拷贝文件
195
+ shutil.copy2(source_file, target_file)
196
+ self._copied_files.add(import_path)
197
+ logger.info(f"📄 拷贝内置proto文件: {import_path}")
198
+ return True
199
+ except Exception as e:
200
+ logger.error(f"拷贝内置proto文件失败: {source_file} -> {target_file}, 错误: {e}")
201
+ return False
202
+
203
+ def process_dependencies(self, dependencies: Set[str]) -> Dict[str, str]:
204
+ """
205
+ 处理依赖列表,返回需要的导入语句映射
206
+
207
+ Args:
208
+ dependencies: 依赖类型集合
209
+
210
+ Returns:
211
+ 类型名到导入路径的映射
212
+ """
213
+ imports = {}
214
+
215
+ for dep_type in dependencies:
216
+ if self.is_builtin_type(dep_type):
217
+ import_path = self.get_import_path(dep_type)
218
+ if import_path and self.ensure_builtin_proto_file(dep_type):
219
+ imports[dep_type] = import_path
220
+
221
+ return imports
222
+
223
+ def get_copied_files(self) -> Set[str]:
224
+ """
225
+ 获取已拷贝的文件列表
226
+
227
+ Returns:
228
+ 已拷贝文件路径的集合
229
+ """
230
+ return self._copied_files.copy()
231
+
232
+
233
+ # 全局实例(在需要时初始化)
234
+ _builtin_manager: Optional[BuiltinProtoManager] = None
235
+
236
+
237
+ def get_builtin_manager(include_dir: str = None, output_dir: str = None) -> BuiltinProtoManager:
238
+ """
239
+ 获取全局内置proto管理器实例
240
+
241
+ Args:
242
+ include_dir: include目录路径(可选,如果不提供会自动查找)
243
+ output_dir: 输出目录路径(首次调用时必需)
244
+
245
+ Returns:
246
+ BuiltinProtoManager实例
247
+ """
248
+ global _builtin_manager
249
+
250
+ if _builtin_manager is None:
251
+ if output_dir is None:
252
+ raise ValueError("首次调用get_builtin_manager时必须提供output_dir")
253
+
254
+ # 如果没有提供include_dir,自动查找
255
+ if include_dir is None:
256
+ include_path = find_include_directory()
257
+ if include_path is None:
258
+ raise ValueError("无法找到include目录,请手动指定include_dir参数")
259
+ include_dir = str(include_path)
260
+
261
+ _builtin_manager = BuiltinProtoManager(include_dir, output_dir)
262
+
263
+ return _builtin_manager
264
+
265
+
266
+ def reset_builtin_manager():
267
+ """重置全局内置proto管理器(主要用于测试)"""
268
+ global _builtin_manager
269
+ _builtin_manager = None
utils/file_cache.py CHANGED
@@ -10,7 +10,14 @@ Author: AI Assistant
10
10
  from pathlib import Path
11
11
  from typing import Optional, Dict
12
12
  import threading
13
- from utils.logger import get_logger
13
+
14
+ # 智能导入:同时支持相对导入(包环境)和绝对导入(开发环境)
15
+ try:
16
+ # 相对导入(包环境)
17
+ from .logger import get_logger
18
+ except ImportError:
19
+ # 绝对导入(开发环境)
20
+ from utils.logger import get_logger
14
21
 
15
22
 
16
23
  class FileContentCache:
utils/report_utils.py ADDED
@@ -0,0 +1,71 @@
1
+ """
2
+ 结果报告工具模块
3
+
4
+ 提供重构结果的统计、报告和展示功能
5
+ """
6
+
7
+ import sys
8
+ from typing import Dict, Any, TYPE_CHECKING
9
+
10
+ # 智能导入:同时支持相对导入(包环境)和绝对导入(开发环境)
11
+ if TYPE_CHECKING:
12
+ try:
13
+ # 相对导入(包环境)
14
+ from ..core.reconstructor import ProtoReconstructor
15
+ except ImportError:
16
+ # 绝对导入(开发环境)
17
+ from core.reconstructor import ProtoReconstructor
18
+
19
+
20
+ def print_results_summary(reconstructor: 'ProtoReconstructor', results: Dict[str, Any], logger, verbose: bool) -> None:
21
+ """
22
+ 打印重构结果的详细统计信息
23
+
24
+ Args:
25
+ reconstructor: 重构器实例
26
+ results: 重构结果字典
27
+ logger: 日志记录器
28
+ verbose: 是否显示详细信息
29
+ """
30
+ if not results:
31
+ logger.error("❌ 没有生成任何proto文件!")
32
+ logger.error("请检查:")
33
+ logger.error(" 1. 根类名是否正确")
34
+ logger.error(" 2. Java源码目录是否包含对应的文件")
35
+ logger.error(" 3. 类是否为protobuf消息类")
36
+
37
+ # 显示详细的失败信息
38
+ if hasattr(reconstructor, 'failed_classes') and reconstructor.failed_classes:
39
+ logger.error("失败的类:")
40
+ for failed_class, reason in reconstructor.failed_classes.items():
41
+ logger.error(f" • {failed_class}: {reason}")
42
+
43
+ sys.exit(1)
44
+
45
+ # 统计成功和失败的数量
46
+ success_count = len(results)
47
+ failed_count = len(reconstructor.failed_classes) if hasattr(reconstructor, 'failed_classes') else 0
48
+ total_attempted = success_count + failed_count
49
+
50
+ logger.success("✅ 重构完成!")
51
+ logger.info(f"📊 处理统计: 共尝试处理 {total_attempted} 个类型")
52
+
53
+ # 统计消息和枚举数量
54
+ message_count = sum(1 for r in results.values() if hasattr(r, 'fields'))
55
+ enum_count = sum(1 for r in results.values() if hasattr(r, 'values'))
56
+
57
+ logger.info(f" - ✅ 成功: {success_count} 个 (消息: {message_count}, 枚举: {enum_count})")
58
+
59
+ # 显示失败的类
60
+ if hasattr(reconstructor, 'failed_classes') and reconstructor.failed_classes:
61
+ logger.warning(f" - ❌ 失败: {failed_count} 个")
62
+ for failed_class, reason in reconstructor.failed_classes.items():
63
+ logger.warning(f" • {failed_class}: {reason}")
64
+
65
+ # 显示跳过的类
66
+ if hasattr(reconstructor, 'skipped_classes') and reconstructor.skipped_classes:
67
+ skipped_count = len(reconstructor.skipped_classes)
68
+ logger.info(f" - ⏭️ 跳过: {skipped_count} 个 (基础类型或已处理)")
69
+ if verbose:
70
+ for skipped_class, reason in reconstructor.skipped_classes.items():
71
+ logger.info(f" • {skipped_class}: {reason}")
utils/type_index.py CHANGED
@@ -10,7 +10,14 @@ Author: AI Assistant
10
10
  from pathlib import Path
11
11
  from typing import Dict, List, Optional, Set
12
12
  import threading
13
- from utils.logger import get_logger
13
+
14
+ # 智能导入:同时支持相对导入(包环境)和绝对导入(开发环境)
15
+ try:
16
+ # 相对导入(包环境)
17
+ from .logger import get_logger
18
+ except ImportError:
19
+ # 绝对导入(开发环境)
20
+ from utils.logger import get_logger
14
21
 
15
22
 
16
23
  class TypeMatchingIndex:
utils/type_utils.py CHANGED
@@ -169,9 +169,17 @@ class TypeMapper:
169
169
  """获取类型所需的导入语句"""
170
170
  imports = []
171
171
  if cls.is_well_known_type(proto_type):
172
- # 提取具体的well-known type名称
173
- type_name = proto_type.split('.')[-1].lower()
174
- imports.append(f"google/protobuf/{type_name}.proto")
172
+ # 使用内置proto管理器获取正确的导入路径
173
+ try:
174
+ from utils.builtin_proto import get_builtin_manager
175
+ builtin_manager = get_builtin_manager()
176
+ import_path = builtin_manager.get_import_path(proto_type)
177
+ if import_path:
178
+ imports.append(import_path)
179
+ except (ImportError, ValueError):
180
+ # 如果内置管理器不可用,使用旧逻辑作为后备
181
+ type_name = proto_type.split('.')[-1].lower()
182
+ imports.append(f"google/protobuf/{type_name}.proto")
175
183
  return imports
176
184
 
177
185
  @classmethod
@@ -227,7 +235,7 @@ class NamingConverter:
227
235
  @staticmethod
228
236
  def to_snake_case(camel_str: str) -> str:
229
237
  """
230
- 将CamelCase转换为snake_case
238
+ 将CamelCase转换为snake_case,同时处理$符号
231
239
 
232
240
  Args:
233
241
  camel_str: 驼峰命名字符串
@@ -238,11 +246,18 @@ class NamingConverter:
238
246
  if not camel_str:
239
247
  return camel_str
240
248
 
249
+ # 首先处理$符号:将$替换为_,处理内部类和匿名类
250
+ s0 = camel_str.replace('$', '_')
251
+
241
252
  # 处理连续大写字母:XMLParser -> XML_Parser
242
- s1 = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', camel_str)
253
+ s1 = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', s0)
243
254
  # 处理小写字母后跟大写字母:userId -> user_Id
244
255
  s2 = re.sub('([a-z0-9])([A-Z])', r'\1_\2', s1)
245
- return s2.lower()
256
+
257
+ # 清理多余的下划线:将连续的下划线替换为单个下划线
258
+ s3 = re.sub('_+', '_', s2)
259
+
260
+ return s3.lower()
246
261
 
247
262
  @staticmethod
248
263
  def to_pascal_case(snake_str: str) -> str:
@@ -281,6 +296,24 @@ class NamingConverter:
281
296
 
282
297
  # 第一个单词保持小写,其余单词首字母大写
283
298
  return components[0].lower() + ''.join(word.capitalize() for word in components[1:] if word)
299
+
300
+ @staticmethod
301
+ def clean_proto_name(name: str) -> str:
302
+ """
303
+ 清理proto名称中的$符号,用于消息和枚举名称
304
+
305
+ Args:
306
+ name: 原始名称(可能包含$符号)
307
+
308
+ Returns:
309
+ 清理后的名称
310
+ """
311
+ if not name:
312
+ return name
313
+
314
+ # 将$替换为空字符串,这样Models$Device变成ModelsDevice
315
+ # 这符合proto命名规范,避免语法错误
316
+ return name.replace('$', '')
284
317
 
285
318
 
286
319
  class FieldNameProcessor: