@@ -67,6 +67,83 @@ def execute(
6767 has_results = bool (results ["core_data" ]) or bool (results ["swiftdata" ])
6868 return has_results , results
6969
70+ # === RAW SOURCE EXTRACTION ===
71+
72+ def get_raw_source (self , model_name : str ) -> tuple [bool , str ]:
73+ """Get raw source for a named model.
74+
75+ Searches SwiftData @Model classes first, then Core Data XML entities.
76+
77+ Args:
78+ model_name: Class or entity name to look up
79+
80+ Returns:
81+ (success, raw_source) tuple
82+ """
83+ # Search SwiftData files
84+ swift_files = sorted (self .project_path .rglob ("*.swift" ))
85+ skip_dirs = {"DerivedData" , "Pods" , "Carthage" }
86+
87+ model_pattern = re .compile (
88+ r"@Model\s*\n\s*(?:final\s+)?class\s+(\w+)" ,
89+ re .MULTILINE ,
90+ )
91+
92+ for swift_file in swift_files :
93+ if any (
94+ part in skip_dirs or part .startswith ("." )
95+ for part in swift_file .relative_to (self .project_path ).parts
96+ ):
97+ continue
98+
99+ try :
100+ content = swift_file .read_text (encoding = "utf-8" )
101+ except (OSError , UnicodeDecodeError ):
102+ continue
103+
104+ for match in model_pattern .finditer (content ):
105+ if match .group (1 ) == model_name :
106+ class_start = match .start ()
107+ body = self ._extract_class_body (content , match .end ())
108+ if body is None :
109+ continue
110+ # Find closing brace position
111+ brace_start = content .find ("{" , match .end ())
112+ depth = 0
113+ end = brace_start
114+ for i in range (brace_start , len (content )):
115+ if content [i ] == "{" :
116+ depth += 1
117+ elif content [i ] == "}" :
118+ depth -= 1
119+ if depth == 0 :
120+ end = i + 1
121+ break
122+ rel_path = swift_file .relative_to (self .project_path )
123+ raw = content [class_start :end ]
124+ return True , f"// { rel_path } \n { raw } "
125+
126+ # Search Core Data XML
127+ for package in self ._find_xcdatamodeld ():
128+ current_version = self ._detect_current_version (package )
129+ versions = [d for d in package .iterdir () if d .suffix == ".xcdatamodel" ]
130+ target = current_version or (versions [0 ].name if versions else None )
131+ if not target :
132+ continue
133+ contents_path = package / target / "contents"
134+ if not contents_path .exists ():
135+ continue
136+ try :
137+ tree = ElementTree .parse (contents_path )
138+ except ElementTree .ParseError :
139+ continue
140+ for entity_elem in tree .getroot ().findall ("entity" ):
141+ if entity_elem .get ("name" ) == model_name :
142+ raw_xml = ElementTree .tostring (entity_elem , encoding = "unicode" )
143+ return True , f"<!-- { package .name } /{ target } /contents -->\n { raw_xml } "
144+
145+ return False , f"Model '{ model_name } ' not found"
146+
70147 # === CORE DATA PARSING ===
71148
72149 def _find_xcdatamodeld (self ) -> list [Path ]:
@@ -495,6 +572,7 @@ def main():
495572 python scripts/model_inspector.py --project-path . --json
496573 python scripts/model_inspector.py --project-path . --show-versions
497574 python scripts/model_inspector.py --project-path . --core-data-only
575+ python scripts/model_inspector.py --project-path . --raw TrainingSession
498576 """ ,
499577 )
500578
@@ -519,6 +597,11 @@ def main():
519597 action = "store_true" ,
520598 help = "List all model versions with current version highlighted" ,
521599 )
600+ inspection_group .add_argument (
601+ "--raw" ,
602+ metavar = "MODEL_NAME" ,
603+ help = "Dump raw source for a specific model (Swift class or Core Data entity)" ,
604+ )
522605
523606 output_group = parser .add_argument_group ("Output Options" )
524607 output_group .add_argument ("--json" , action = "store_true" , help = "Output as JSON" )
@@ -527,6 +610,16 @@ def main():
527610 args = parser .parse_args ()
528611
529612 inspector = ModelInspector (project_path = args .project_path )
613+
614+ if args .raw :
615+ success , raw = inspector .get_raw_source (args .raw )
616+ if success :
617+ print (raw )
618+ else :
619+ print (f"Error: { raw } " , file = sys .stderr )
620+ sys .exit (1 )
621+ return
622+
530623 success , results = inspector .execute (
531624 core_data_only = args .core_data_only ,
532625 swiftdata_only = args .swiftdata_only ,
0 commit comments