reproto 0.0.8__py3-none-any.whl → 0.0.9__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 (54) hide show
  1. .git/COMMIT_EDITMSG +14 -1
  2. .git/FETCH_HEAD +2 -0
  3. .git/index +0 -0
  4. .git/logs/HEAD +4 -0
  5. .git/logs/refs/heads/iyue +4 -0
  6. .git/logs/refs/remotes/gitlab/iyue +4 -0
  7. .git/logs/refs/remotes/origin/iyue +4 -0
  8. .git/objects/29/4708b82b343e04e7a6685f5cd1287f3d17f7a9 +0 -0
  9. .git/objects/2c/fcddd7eebeb4eee0562dc384a79366bc7b04bb +0 -0
  10. .git/objects/34/192f0df5f5b694c881d086019eda349608d222 +0 -0
  11. .git/objects/3e/d953d5ed2c66722045f5e39d068696a0853b4f +0 -0
  12. .git/objects/44/4af3a0d68ba81976f67c7b638c9b0db4640709 +0 -0
  13. .git/objects/4b/43f5f577e1cdc35f8e06d178d8f5c892034061 +0 -0
  14. .git/objects/4c/16984be6ef7b24d01604821e9728cb579acd69 +0 -0
  15. .git/objects/56/79064a3138031d3a92d60aa629b82009fd0d1d +0 -0
  16. .git/objects/58/0d8f872aa869e42ba608f64888b1349f8b3ff4 +0 -0
  17. .git/objects/5a/11f9d70791e06a0570e01d3dcbbae39cde55db +0 -0
  18. .git/objects/5c/715dcb05e32db7a7a3b030f07524bdd8a56849 +0 -0
  19. .git/objects/5d/e2e9d536c2c0b78e8f9b3b61daa531a55332dc +0 -0
  20. .git/objects/66/7291e131d4769e7d028346a0cc7a0c05d500e5 +0 -0
  21. .git/objects/67/f54a4a3ede6749acc7c718ad97a86634215b5e +0 -0
  22. .git/objects/70/ded03ee69f30850c938a8129be308cb30772d9 +0 -0
  23. .git/objects/78/3e7e252c20e73e33615c703174766036546ff6 +3 -0
  24. .git/objects/94/ce01b61b90d1fb21d2d339fbeb22e821b6f413 +0 -0
  25. .git/objects/97/71dd4958faa94d3db229c129f6af35b508905a +0 -0
  26. .git/objects/9e/9978522bc8ca79133d7c11ef8ca3fe3c7eed0a +0 -0
  27. .git/objects/9f/b57064e0c53ed80af8507acaab718a1e80184e +0 -0
  28. .git/objects/b3/28dc445ee33220db9359370fc0089a77174101 +0 -0
  29. .git/objects/b3/d2b3037bede44e7e4d18dc99419f8c712c9c62 +0 -0
  30. .git/objects/c3/93db4841dbbb8acf54e9af12b6705c9f5ecde9 +0 -0
  31. .git/objects/c3/c8594874dd9ff9c21662fd06cac9b5baadbba0 +0 -0
  32. .git/objects/c9/a6ca8f8efee4a5632e9a655ced29f1b708f35e +0 -0
  33. .git/objects/c9/cdef9ab627b874ffe6455a47583a75bf16496d +0 -0
  34. .git/objects/df/f8f64cee2b97df7d86f73207c5e690f98f0208 +0 -0
  35. .git/objects/eb/528f06c622d54e411e9e05b3a200b4ac624a90 +0 -0
  36. .git/objects/fd/267d9de63212db235135fa6834f62572224fc6 +0 -0
  37. .git/refs/heads/iyue +1 -1
  38. .git/refs/remotes/gitlab/iyue +1 -1
  39. .git/refs/remotes/origin/iyue +1 -1
  40. .gitignore +4 -1
  41. ARCHITECTURE.md +146 -48
  42. README.md +145 -24
  43. core/bytecode_parser.py +2 -5
  44. core/info_decoder.py +9 -83
  45. core/reconstructor.py +91 -211
  46. generation/proto_generator.py +6 -61
  47. parsing/java_parser.py +219 -46
  48. pyproject.toml +1 -1
  49. reproto-0.0.9.dist-info/METADATA +295 -0
  50. {reproto-0.0.8.dist-info → reproto-0.0.9.dist-info}/RECORD +53 -22
  51. utils/type_utils.py +414 -0
  52. reproto-0.0.8.dist-info/METADATA +0 -174
  53. {reproto-0.0.8.dist-info → reproto-0.0.9.dist-info}/WHEEL +0 -0
  54. {reproto-0.0.8.dist-info → reproto-0.0.9.dist-info}/entry_points.txt +0 -0
core/reconstructor.py CHANGED
@@ -12,7 +12,7 @@ Author: AI Assistant
12
12
  import re
13
13
  from pathlib import Path
14
14
  from collections import deque
15
- from typing import Set, Dict, List, Optional
15
+ from typing import Set, Dict, List, Optional, Tuple
16
16
 
17
17
  from parsing.java_parser import JavaParser
18
18
  from parsing.enum_parser import EnumParser
@@ -20,6 +20,8 @@ from core.info_decoder import InfoDecoder
20
20
  from generation.proto_generator import ProtoGenerator
21
21
  from models.message_definition import MessageDefinition, EnumDefinition, EnumValueDefinition
22
22
  from utils.logger import get_logger
23
+ from utils.file_cache import get_file_cache
24
+ from utils.type_utils import type_mapper, naming_converter
23
25
 
24
26
 
25
27
  class JavaSourceAnalyzer:
@@ -32,7 +34,6 @@ class JavaSourceAnalyzer:
32
34
  # 初始化JavaParser用于字段类型解析
33
35
  self.java_parser = JavaParser()
34
36
  # 使用文件缓存系统优化I/O性能
35
- from utils.file_cache import get_file_cache
36
37
  self.file_cache = get_file_cache()
37
38
 
38
39
  def set_current_class(self, class_name: str):
@@ -186,41 +187,9 @@ class JavaSourceAnalyzer:
186
187
  java_type: Java类型名
187
188
 
188
189
  Returns:
189
- protobuf类型名
190
+ 对应的protobuf类型名
190
191
  """
191
- if not java_type:
192
- return 'string'
193
-
194
- # 基础类型映射
195
- basic_types = {
196
- 'int': 'int32',
197
- 'long': 'int64',
198
- 'float': 'float',
199
- 'double': 'double',
200
- 'boolean': 'bool',
201
- 'String': 'string',
202
- 'java.lang.String': 'string',
203
- 'java.lang.Integer': 'int32',
204
- 'java.lang.Long': 'int64',
205
- 'java.lang.Float': 'float',
206
- 'java.lang.Double': 'double',
207
- 'java.lang.Boolean': 'bool',
208
- 'byte[]': 'bytes',
209
- 'ByteString': 'bytes',
210
- 'com.google.protobuf.ByteString': 'bytes',
211
- }
212
-
213
- # 检查是否为基础类型
214
- if java_type in basic_types:
215
- return basic_types[java_type]
216
-
217
- # 如果是完整的类名,提取简单类名
218
- if '.' in java_type:
219
- simple_name = java_type.split('.')[-1]
220
- return simple_name
221
-
222
- # 默认返回原类型名
223
- return java_type
192
+ return type_mapper.java_to_proto_type(java_type)
224
193
 
225
194
  def _get_type_from_setter(self, field_name: str) -> Optional[str]:
226
195
  """
@@ -351,9 +320,9 @@ class ProtoReconstructor:
351
320
  self.java_source_analyzer = JavaSourceAnalyzer(sources_dir)
352
321
  self.info_decoder.java_source_analyzer = self.java_source_analyzer
353
322
 
354
- # 初始化类型索引(延迟加载)
355
- from utils.type_index import get_type_index
356
- self.type_index = get_type_index(sources_dir)
323
+ # 🚀 性能优化:移除未使用的索引系统,简化代码
324
+ # 索引系统在实际使用中被基础类型检测绕过,且构建耗时
325
+ # 改为使用直接的文件路径构造和智能包名推断
357
326
 
358
327
  # 任务调度状态
359
328
  self.processed_classes: Set[str] = set() # 已处理的类
@@ -397,8 +366,7 @@ class ProtoReconstructor:
397
366
  file_cache = get_file_cache()
398
367
  file_cache.print_stats()
399
368
 
400
- # 输出类型索引统计
401
- self.type_index.print_stats()
369
+ # 🚀 性能优化:索引系统已移除,无需统计
402
370
 
403
371
  # 6. 返回统计信息
404
372
  # 报告未知类型统计
@@ -633,7 +601,7 @@ class ProtoReconstructor:
633
601
 
634
602
  def _should_skip_class(self, class_name: str) -> bool:
635
603
  """
636
- 判断是否应该跳过某个类
604
+ 判断是否应该跳过某个类的处理
637
605
 
638
606
  Args:
639
607
  class_name: 类名
@@ -641,27 +609,15 @@ class ProtoReconstructor:
641
609
  Returns:
642
610
  是否应该跳过
643
611
  """
644
- # 跳过已经处理过的类
612
+ # 已处理过的类
645
613
  if class_name in self.processed_classes:
646
614
  return True
647
-
648
- # 跳过基础类型(包括Java基础类型和常见的系统类型)
649
- basic_types = {
650
- # Java基础类型
651
- 'int', 'long', 'float', 'double', 'boolean', 'byte', 'short', 'char',
652
- 'String', 'Object', 'Integer', 'Long', 'Float', 'Double', 'Boolean',
653
- 'Byte', 'Short', 'Character',
654
- # Java系统类型
655
- 'java.lang.String', 'java.lang.Integer', 'java.lang.Long',
656
- 'java.lang.Boolean', 'java.lang.Float', 'java.lang.Double',
657
- 'java.lang.Object', 'java.util.List', 'java.util.Map',
658
- 'com.google.protobuf.ByteString', 'com.google.protobuf.MessageLite'
659
- }
660
615
 
661
- if class_name in basic_types:
616
+ # 使用TypeMapper判断基础类型和系统包
617
+ if type_mapper.is_java_basic_type(class_name) or type_mapper.is_system_package(class_name):
662
618
  return True
663
619
 
664
- # 跳过明显的系统类型和内部类型
620
+ # 跳过明显不是protobuf类的包
665
621
  if self._is_system_or_internal_type(class_name):
666
622
  return True
667
623
 
@@ -764,12 +720,7 @@ class ProtoReconstructor:
764
720
  return None
765
721
 
766
722
  # 检查是否为基础类型
767
- basic_proto_types = {
768
- 'string', 'int32', 'int64', 'uint32', 'uint64', 'sint32', 'sint64',
769
- 'fixed32', 'fixed64', 'sfixed32', 'sfixed64', 'bool', 'float', 'double', 'bytes'
770
- }
771
-
772
- if type_name in basic_proto_types:
723
+ if type_mapper.is_basic_proto_type(type_name):
773
724
  return None
774
725
 
775
726
  # 如果已经是完整类名,直接返回
@@ -794,7 +745,7 @@ class ProtoReconstructor:
794
745
 
795
746
  def _find_java_file(self, class_name: str) -> Optional[Path]:
796
747
  """
797
- 根据类名查找对应的Java文件
748
+ 根据类名查找对应的Java文件(优化版本)
798
749
 
799
750
  Args:
800
751
  class_name: 完整的Java类名
@@ -802,6 +753,7 @@ class ProtoReconstructor:
802
753
  Returns:
803
754
  Java文件路径,如果找不到则返回None
804
755
  """
756
+ # 🚀 优化1:直接根据包名和类名构造文件路径(你的建议)
805
757
  # 标准路径:com.example.Model -> com/example/Model.java
806
758
  file_path = class_name.replace('.', '/') + '.java'
807
759
  full_path = self.sources_dir / file_path
@@ -809,31 +761,43 @@ class ProtoReconstructor:
809
761
  if full_path.exists():
810
762
  return full_path
811
763
 
812
- # 处理内部类:支持多层嵌套
813
- # com.example.Models$Inner$Deep -> com/example/Models$Inner$Deep.java
764
+ # 🚀 优化2:处理内部类,但避免全目录扫描
814
765
  if '$' in class_name:
815
- # 找到最后一个.的位置,分离包名和类名部分
766
+ # 内部类处理:com.example.Models$Inner -> com/example/Models.java
816
767
  last_dot_index = class_name.rfind('.')
817
768
  if last_dot_index != -1:
818
- package_path = class_name[:last_dot_index].replace('.', '/') # 包路径
819
- class_part = class_name[last_dot_index + 1:] # 类名部分(可能包含多个$)
820
- inner_class_file_path = f"{package_path}/{class_part}.java"
821
- inner_class_full_path = self.sources_dir / inner_class_file_path
769
+ package_path = class_name[:last_dot_index].replace('.', '/')
770
+ class_part = class_name[last_dot_index + 1:]
822
771
 
823
- if inner_class_full_path.exists():
824
- return inner_class_full_path
825
-
826
- # 备选方案:按简单类名搜索
827
- simple_name = class_name.split('.')[-1]
828
- # 对于内部类,简单名称可能包含多个$符号
829
- if '$' in simple_name:
830
- # 对于内部类,直接使用包含$的完整文件名搜索
831
- for java_file in self.sources_dir.rglob(f"{simple_name}.java"):
832
- return java_file
833
- else:
834
- # 对于普通类,使用原来的逻辑
835
- for java_file in self.sources_dir.rglob(f"{simple_name}.java"):
836
- return java_file
772
+ # 提取外部类名($之前的部分)
773
+ outer_class = class_part.split('$')[0]
774
+ outer_class_file_path = f"{package_path}/{outer_class}.java"
775
+ outer_class_full_path = self.sources_dir / outer_class_file_path
776
+
777
+ if outer_class_full_path.exists():
778
+ return outer_class_full_path
779
+
780
+ # 🚀 优化3:简化文件查找逻辑,移除索引依赖
781
+
782
+ # 🚀 优化4:最后的备选方案 - 限制搜索范围
783
+ # 只在当前包及其父包中搜索,避免全目录扫描
784
+ package_parts = class_name.split('.')[:-1] # 获取包名部分
785
+ simple_name = class_name.split('.')[-1].split('$')[0] # 提取简单类名
786
+
787
+ # 构造搜索路径列表,限制搜索范围
788
+ search_paths = []
789
+ for i in range(len(package_parts), 0, -1):
790
+ package_path = '/'.join(package_parts[:i])
791
+ search_paths.append(self.sources_dir / package_path)
792
+
793
+ # 在限定范围内搜索
794
+ for search_path in search_paths:
795
+ if search_path.exists():
796
+ for java_file in search_path.rglob(f"{simple_name}.java"):
797
+ # 验证找到的文件是否匹配
798
+ relative_path = java_file.relative_to(self.sources_dir)
799
+ if relative_path.stem == simple_name:
800
+ return java_file
837
801
 
838
802
  return None
839
803
 
@@ -857,7 +821,7 @@ class ProtoReconstructor:
857
821
  return candidate
858
822
 
859
823
  return None
860
-
824
+
861
825
  def _generate_candidate_packages(self, current_package: str) -> List[str]:
862
826
  """
863
827
  动态生成候选包名列表
@@ -930,7 +894,7 @@ class ProtoReconstructor:
930
894
 
931
895
  def _find_best_matching_class(self, type_name: str, current_package: str, current_class: str = None) -> Optional[str]:
932
896
  """
933
- 查找最佳匹配的类(使用索引优化)
897
+ 查找最佳匹配的类(高性能版本)
934
898
 
935
899
  Args:
936
900
  type_name: 类型名(如 IdData)
@@ -940,27 +904,20 @@ class ProtoReconstructor:
940
904
  Returns:
941
905
  最佳匹配的完整类名
942
906
  """
943
- # 首先尝试从当前类的Java源码中获取实际类型
944
- if current_class:
945
- actual_type = self._extract_actual_field_type(current_class, type_name)
946
- if actual_type:
947
- self.logger.info(f" 🔍 源码分析: {type_name} -> {actual_type}")
948
- return actual_type
949
-
950
- # 预检查:如果是基础字段名,可能不需要创建单独的类
907
+ # 🚀 性能优化:优先进行基础类型检测,避免不必要的文件IO
951
908
  if self._is_basic_field_type(type_name, current_class):
952
- self.logger.info(f" 🔍 基础字段类型检测: {type_name} -> 跳过类匹配")
909
+ self.logger.debug(f" 🔍 基础字段类型检测: {type_name} -> 跳过类匹配")
953
910
  return None
954
911
 
955
- # 使用类型索引进行快速匹配
956
- best_match = self.type_index.find_best_match(type_name, current_package)
957
-
958
- if best_match:
959
- self.logger.info(f" 🔍 索引匹配: {type_name} -> {best_match}")
960
- return best_match
912
+ # 🚀 性能优化:直接使用智能包名推断,避免索引开销
913
+ # 1. 首先尝试推断完整类名
914
+ inferred_name = self._infer_full_class_name(type_name, current_package)
915
+ if inferred_name:
916
+ self.logger.info(f" 🔍 包名推断: {type_name} -> {inferred_name}")
917
+ return inferred_name
961
918
 
962
- # 索引未找到匹配,回退到传统方法(保留兼容性)
963
- self.logger.debug(f" ⚠️ 索引未找到匹配,回退到目录扫描: {type_name}")
919
+ # 2. 如果推断失败,使用限制范围的目录搜索
920
+ self.logger.debug(f" 🔍 启用目录搜索: {type_name}")
964
921
  return self._fallback_directory_search(type_name, current_package)
965
922
 
966
923
  def _fallback_directory_search(self, type_name: str, current_package: str) -> Optional[str]:
@@ -1004,7 +961,7 @@ class ProtoReconstructor:
1004
961
 
1005
962
  def _is_basic_field_type(self, type_name: str, current_class: str = None) -> bool:
1006
963
  """
1007
- 检查是否为基础字段类型,避免为简单字段创建不必要的类
964
+ 快速检查是否为基础字段类型(高性能版本)
1008
965
 
1009
966
  Args:
1010
967
  type_name: 类型名
@@ -1013,61 +970,11 @@ class ProtoReconstructor:
1013
970
  Returns:
1014
971
  是否为基础字段类型
1015
972
  """
1016
- # 首先检查是否为Java基础类型
1017
- basic_java_types = {
1018
- 'int', 'long', 'float', 'double', 'boolean', 'byte', 'short', 'char',
1019
- 'String', 'Object', 'Integer', 'Long', 'Float', 'Double', 'Boolean',
1020
- 'Byte', 'Short', 'Character'
1021
- }
1022
-
1023
- if type_name in basic_java_types:
1024
- return True
1025
-
1026
- # 常见的基础字段名模式
1027
- basic_patterns = [
1028
- 'tags', # tags_ 字段通常是 repeated string
1029
- 'ids', # ids_ 字段通常是 repeated string 或 repeated int64
1030
- 'values', # values_ 字段通常是基础类型数组
1031
- 'names', # names_ 字段通常是 repeated string
1032
- 'urls', # urls_ 字段通常是 repeated string
1033
- 'emails', # emails_ 字段通常是 repeated string
1034
- ]
1035
-
1036
- type_lower = type_name.lower()
1037
-
1038
- # 检查是否匹配基础模式
1039
- if type_lower in basic_patterns:
1040
- return True
1041
-
1042
- # 如果有当前类,尝试从Java源码中验证
1043
- if current_class:
1044
- try:
1045
- java_file = self._find_java_file(current_class)
1046
- if java_file:
1047
- content = java_file.read_text(encoding='utf-8')
1048
-
1049
- # 查找对应的字段声明,检查是否为基础类型
1050
- field_name_pattern = type_lower.rstrip('s') + 's?_' # tags -> tags?_
1051
- import re
1052
-
1053
- # 查找字段声明:private List<String> tags_; 或 private Internal.ProtobufList<String> tags_;
1054
- patterns = [
1055
- rf'private\s+(?:Internal\.)?ProtobufList<String>\s+{field_name_pattern}',
1056
- rf'private\s+List<String>\s+{field_name_pattern}',
1057
- rf'private\s+(?:Internal\.)?ProtobufList<Integer>\s+{field_name_pattern}',
1058
- rf'private\s+List<Integer>\s+{field_name_pattern}',
1059
- rf'private\s+(?:Internal\.)?ProtobufList<Long>\s+{field_name_pattern}',
1060
- rf'private\s+List<Long>\s+{field_name_pattern}',
1061
- ]
1062
-
1063
- for pattern in patterns:
1064
- if re.search(pattern, content, re.IGNORECASE):
1065
- return True
1066
-
1067
- except Exception as e:
1068
- self.logger.debug(f" 检查基础字段类型时出错: {e}")
973
+ # 🚀 性能优化:使用缓存的类型检查器,避免重复计算
974
+ from utils.type_utils import TypeMapper
1069
975
 
1070
- return False
976
+ # 直接使用统一的基础类型检查,无需额外逻辑
977
+ return TypeMapper.is_java_basic_type(type_name)
1071
978
 
1072
979
  def _is_valid_package_for_matching(self, candidate_package: str, current_package: str) -> bool:
1073
980
  """
@@ -1138,7 +1045,7 @@ class ProtoReconstructor:
1138
1045
 
1139
1046
  def _extract_actual_field_type(self, class_name: str, inferred_type: str) -> Optional[str]:
1140
1047
  """
1141
- 从Java源码中提取字段的实际类型
1048
+ 从Java源码中提取字段的实际类型(优化版本)
1142
1049
 
1143
1050
  Args:
1144
1051
  class_name: 当前类的完整名称
@@ -1147,61 +1054,36 @@ class ProtoReconstructor:
1147
1054
  Returns:
1148
1055
  实际的完整类型名
1149
1056
  """
1150
- # 首先检查是否为基础类型,如果是则直接跳过
1151
- basic_types = {
1152
- 'int', 'long', 'float', 'double', 'boolean', 'byte', 'short', 'char',
1153
- 'String', 'Object', 'Integer', 'Long', 'Float', 'Double', 'Boolean',
1154
- 'Byte', 'Short', 'Character'
1155
- }
1057
+ # 🚀 优化:使用统一的类型检查器
1058
+ from utils.type_utils import TypeMapper
1156
1059
 
1157
- if inferred_type in basic_types:
1060
+ if TypeMapper.is_java_basic_type(inferred_type):
1158
1061
  self.logger.debug(f" 跳过基础类型: {inferred_type}")
1159
1062
  return None
1160
1063
 
1064
+ # 🚀 性能优化:简化源码分析,避免复杂的正则表达式匹配
1065
+ # 对于大多数情况,索引系统已经能够提供足够准确的匹配
1066
+ # 这里只做最基本的检查,避免耗时的文件IO和正则匹配
1067
+
1161
1068
  try:
1162
- java_file = self._find_java_file(class_name)
1163
- if not java_file:
1164
- return None
1165
-
1166
- # 使用缓存读取Java源码
1167
- from utils.file_cache import get_file_cache
1168
- file_cache = get_file_cache()
1169
- content = file_cache.get_content(java_file)
1170
- if not content:
1171
- return None
1172
-
1173
- # 查找字段声明模式:private SomeType fieldName_;
1174
- # 我们要找的是以inferred_type结尾的类型声明
1175
- import re
1069
+ # 使用索引系统进行快速查找,避免文件IO
1070
+ from utils.type_index import get_type_index
1071
+ type_index = get_type_index(self.sources_dir)
1176
1072
 
1177
- # 匹配模式:private (.*IdData) .*_;
1178
- pattern = rf'private\s+(\w*{re.escape(inferred_type)})\s+\w+_;'
1179
- matches = re.findall(pattern, content)
1073
+ # 构造可能的完整类名
1074
+ package_name = '.'.join(class_name.split('.')[:-1])
1075
+ possible_full_name = f"{package_name}.{inferred_type}"
1180
1076
 
1181
- if matches:
1182
- # 取第一个匹配的类型
1183
- actual_type_simple = matches[0]
1184
-
1185
- # 再次检查匹配的类型是否为基础类型
1186
- if actual_type_simple in basic_types:
1187
- self.logger.debug(f" 匹配到基础类型,跳过: {actual_type_simple}")
1188
- return None
1189
-
1190
- # 检查是否有import语句
1191
- import_pattern = rf'import\s+([^;]*\.{re.escape(actual_type_simple)});'
1192
- import_matches = re.findall(import_pattern, content)
1193
-
1194
- if import_matches:
1195
- return import_matches[0] # 返回完整的包名.类名
1196
- else:
1197
- # 如果没有import,假设在同一个包中
1198
- package_name = '.'.join(class_name.split('.')[:-1])
1199
- return f"{package_name}.{actual_type_simple}"
1077
+ # 使用索引快速检查
1078
+ result = type_index.find_best_match(inferred_type, package_name)
1079
+ if result:
1080
+ self.logger.debug(f" 索引快速匹配: {inferred_type} -> {result}")
1081
+ return result
1200
1082
 
1201
1083
  return None
1202
1084
 
1203
1085
  except Exception as e:
1204
- self.logger.error(f" ⚠️ 源码分析失败: {e}")
1086
+ self.logger.debug(f" ⚠️ 快速类型匹配失败: {e}")
1205
1087
  return None
1206
1088
 
1207
1089
  def _create_enum_definition(self, class_name: str, enum_values: List[tuple]) -> EnumDefinition:
@@ -1334,7 +1216,7 @@ class ProtoReconstructor:
1334
1216
  @staticmethod
1335
1217
  def _to_snake_case(camel_str: str) -> str:
1336
1218
  """
1337
- 将CamelCase转换为snake_case
1219
+ 将CamelCase转换为snake_case(使用统一的命名转换器)
1338
1220
 
1339
1221
  Args:
1340
1222
  camel_str: 驼峰命名字符串
@@ -1342,8 +1224,6 @@ class ProtoReconstructor:
1342
1224
  Returns:
1343
1225
  蛇形命名字符串
1344
1226
  """
1345
- # 处理连续大写字母:XMLParser -> XML_Parser
1346
- s1 = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', camel_str)
1347
- # 处理小写字母后跟大写字母:userId -> user_Id
1348
- s2 = re.sub('([a-z0-9])([A-Z])', r'\1_\2', s1)
1349
- return s2.lower()
1227
+ # 🚀 优化:使用统一的命名转换器,避免重复实现
1228
+ from utils.type_utils import NamingConverter
1229
+ return NamingConverter.to_snake_case(camel_str)
@@ -11,6 +11,7 @@ Author: AI Assistant
11
11
  import re
12
12
  from typing import Dict, Set, List, Union
13
13
  from models.message_definition import MessageDefinition, FieldDefinition, EnumDefinition, EnumValueDefinition
14
+ from utils.type_utils import type_mapper, naming_converter, field_name_processor
14
15
 
15
16
 
16
17
  class ProtoGenerator:
@@ -410,16 +411,7 @@ class ProtoGenerator:
410
411
  Returns:
411
412
  基础proto类型,如果不是基础类型则返回None
412
413
  """
413
- basic_type_mapping = {
414
- 'string': 'string',
415
- 'int32': 'int32',
416
- 'int64': 'int64',
417
- 'bool': 'bool',
418
- 'float': 'float',
419
- 'double': 'double',
420
- 'bytes': 'bytes',
421
- }
422
- return basic_type_mapping.get(type_name)
414
+ return type_mapper.java_to_proto_type(type_name) if type_mapper.is_java_basic_type(type_name) else None
423
415
 
424
416
  def _generate_enum_type_name(self, field_name: str) -> str:
425
417
  """
@@ -431,33 +423,7 @@ class ProtoGenerator:
431
423
  Returns:
432
424
  枚举类型名(PascalCase)
433
425
  """
434
- name = field_name.rstrip('_')
435
-
436
- # 特殊字段名修正
437
- field_name_corrections = {
438
- 'access': 'Access', # 修正拼写
439
- }
440
-
441
- if name in field_name_corrections:
442
- return field_name_corrections[name]
443
-
444
- # 处理常见的枚举后缀
445
- suffix_mappings = {
446
- '_type': 'Type',
447
- '_status': 'Status',
448
- '_code': 'Code'
449
- }
450
-
451
- for suffix, replacement in suffix_mappings.items():
452
- if name.endswith(suffix):
453
- name = name[:-len(suffix)] + replacement
454
- break
455
-
456
- # 处理复数形式:badges -> badge
457
- if name.endswith('s') and len(name) > 1:
458
- name = name[:-1]
459
-
460
- return self._to_pascal_case(name)
426
+ return field_name_processor.generate_type_name_from_field(field_name, 'enum')
461
427
 
462
428
  def _generate_message_type_name(self, field_name: str) -> str:
463
429
  """
@@ -469,23 +435,7 @@ class ProtoGenerator:
469
435
  Returns:
470
436
  消息类型名(PascalCase)
471
437
  """
472
- name = field_name.rstrip('_')
473
-
474
- # 处理常见的消息后缀
475
- suffix_mappings = {
476
- '_info': 'Info',
477
- '_data': 'Data',
478
- '_stats': 'Stats',
479
- '_profile': 'Profile',
480
- '_config': 'Config'
481
- }
482
-
483
- for suffix, replacement in suffix_mappings.items():
484
- if name.endswith(suffix):
485
- name = name[:-len(suffix)] + replacement
486
- break
487
-
488
- return self._to_pascal_case(name)
438
+ return field_name_processor.generate_type_name_from_field(field_name, 'message')
489
439
 
490
440
  @staticmethod
491
441
  def _to_pascal_case(snake_str: str) -> str:
@@ -498,8 +448,7 @@ class ProtoGenerator:
498
448
  Returns:
499
449
  帕斯卡命名字符串
500
450
  """
501
- components = snake_str.split('_')
502
- return ''.join(word.capitalize() for word in components)
451
+ return naming_converter.to_pascal_case(snake_str)
503
452
 
504
453
  @staticmethod
505
454
  def _to_snake_case(camel_str: str) -> str:
@@ -512,8 +461,4 @@ class ProtoGenerator:
512
461
  Returns:
513
462
  蛇形命名字符串
514
463
  """
515
- # 处理连续大写字母:XMLParser -> XML_Parser
516
- s1 = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', camel_str)
517
- # 处理小写字母后跟大写字母:userId -> user_Id
518
- s2 = re.sub('([a-z0-9])([A-Z])', r'\1_\2', s1)
519
- return s2.lower()
464
+ return naming_converter.to_snake_case(camel_str)