@@ -172,151 +172,85 @@ def _process_node(cls, node: Node, code: bytes, codeFile: CodeFileModel):
172172 cls ._process_node (child , code , codeFile )
173173
174174 @classmethod
175- def _process_import_node (cls , node : Node , code : bytes , codeFile : CodeFileModel ):
176- """
177- Process different types of import statements:
178- 1. Side-effect imports: import './App.css'
179- 2. Default imports: import React from 'react'
180- 3. Named imports: import { useState } from 'react'
181- 4. Namespace imports: import * as React from 'react'
182- 5. Type-only imports: import type { User } from './types'
183- 6. Mixed imports: import React, { useState } from 'react'
184- """
175+ def _process_import_clause_node (cls , node : Node , code : bytes ) -> Tuple [List [str ], List [Optional [str ]]]:
176+ names = []
177+ aliases = []
185178
186- # Debug: Print the full import statement
187- import_text = cls ._get_content (code , node )
188- print (f"Processing import: { import_text } " )
179+ for child in node .children :
180+ if child .type == "named_imports" :
181+ for import_child in child .children :
182+ if import_child .type == "import_specifier" :
183+ current_name = None
184+ current_alias = None
185+ next_is_alias = False
186+
187+ for alias_child in import_child .children :
188+ if alias_child .type == "identifier" and not next_is_alias :
189+ current_name = cls ._get_content (code , alias_child )
190+ elif alias_child .type == "as" :
191+ next_is_alias = True
192+ elif alias_child .type == "identifier" and next_is_alias :
193+ current_alias = cls ._get_content (code , alias_child )
194+ next_is_alias = False
195+
196+ if current_name :
197+ names .append (current_name )
198+ aliases .append (current_alias )
199+
200+ elif child .type == "identifier" :
201+ name = cls ._get_content (code , child )
202+ if name :
203+ names .append (name )
204+ aliases .append (None )
189205
190- # Initialize variables
206+ return names , aliases
207+
208+ @classmethod
209+ def _process_import_node (cls , node : Node , code : bytes , codeFile : CodeFileModel ):
191210 source = None
192211 names = []
193212 aliases = []
194- is_type_only = False
195- is_namespace = False
196- namespace_alias = None
213+ next_is_from_import = False
214+ next_is_import = False
197215
198- # First pass: identify import type and extract source
199216 for child in node .children :
200- child_text = cls ._get_content (code , child )
201- print (f" Child: { child .type } = '{ child_text } '" )
202-
203- # Check for type-only import
204- if child .type == "type" or child_text == "type" :
205- is_type_only = True
206-
207- # Extract source (the string literal)
208- elif child .type == "string" :
209- source = child_text .strip ("'\" " ) # Remove quotes
210-
211- # Second pass: process import clause if it exists
212- import_clause = None
213- for child in node .children :
214- if child .type == "import_clause" :
215- import_clause = child
216- break
217-
218- if import_clause :
219- names , aliases , is_namespace , namespace_alias = cls ._process_import_clause_node (
220- import_clause , code
221- )
222-
223- # Handle different import types
217+ if child .type == "import" :
218+ next_is_import = True
219+ elif child .type == "import_clause" and next_is_import :
220+ names , aliases = cls ._process_import_clause_node (child , code )
221+ next_is_import = False
222+ elif next_is_import :
223+ source = cls ._get_content (code , child )
224+ next_is_import = False
225+ elif child .type == "from" :
226+ next_is_from_import = True
227+ elif child .type == "string" and next_is_from_import :
228+ source = cls ._get_content (code , child )
229+ if names and source is None :
230+ source = names [0 ] if len (names ) == 1 else None
231+ if source :
232+ names = []
233+ aliases = []
234+
224235 if source :
225- if is_namespace and namespace_alias :
226- # Namespace import: import * as React from 'react'
227- importStatement = ImportStatement (
228- source = source ,
229- name = "*" , # Indicates namespace import
230- alias = namespace_alias ,
231- is_type_only = is_type_only
232- )
233- codeFile .add_import (importStatement )
234- cls ._generate_unique_import_id (codeFile .imports [- 1 ])
235-
236- elif names :
237- # Named imports or default + named imports
236+ if names :
238237 for name , alias in zip (names , aliases ):
239238 importStatement = ImportStatement (
240239 source = source ,
241240 name = name ,
242- alias = alias ,
243- is_type_only = is_type_only
241+ alias = alias
244242 )
245243 codeFile .add_import (importStatement )
246244 cls ._generate_unique_import_id (codeFile .imports [- 1 ])
247245 else :
248- # Side-effect import: import './App.css'
249246 importStatement = ImportStatement (
250247 source = source ,
251248 name = None ,
252- alias = None ,
253- is_type_only = is_type_only ,
254- is_side_effect = True
249+ alias = None
255250 )
256251 codeFile .add_import (importStatement )
257252 cls ._generate_unique_import_id (codeFile .imports [- 1 ])
258253
259- @classmethod
260- def _process_import_clause_node (cls , node : Node , code : bytes ) -> Tuple [List [str ], List [str ], bool , Optional [str ]]:
261- """
262- Process import_clause node to extract names and aliases.
263- Returns: (names, aliases, is_namespace, namespace_alias)
264- """
265- names = []
266- aliases = []
267- is_namespace = False
268- namespace_alias = None
269-
270- def process_node_recursively (current_node : Node ):
271- nonlocal names , aliases , is_namespace , namespace_alias # noqa: F824
272-
273- node_text = cls ._get_content (code , current_node )
274- print (f" Processing clause node: { current_node .type } = '{ node_text } '" )
275-
276- if current_node .type == "namespace_import" :
277- # Handle: * as React
278- is_namespace = True
279- for child in current_node .children :
280- if child .type == "identifier" :
281- namespace_alias = cls ._get_content (code , child )
282-
283- elif current_node .type == "identifier" :
284- # Default import or named import identifier
285- identifier = cls ._get_content (code , current_node )
286- names .append (identifier )
287- aliases .append (None ) # No alias by default
288-
289- elif current_node .type == "import_specifier" :
290- # Named import with possible alias: { name } or { name as alias }
291- name = None
292- alias = None
293-
294- for child in current_node .children :
295- child_text = cls ._get_content (code , child )
296- if child .type == "identifier" :
297- if name is None :
298- name = child_text
299- else :
300- alias = child_text # This is the alias part
301-
302- if name :
303- names .append (name )
304- aliases .append (alias )
305-
306- elif current_node .type == "named_imports" :
307- # Process children of named_imports (the part inside {})
308- for child in current_node .children :
309- if child .type not in ["{" , "}" , "," ]: # Skip punctuation
310- process_node_recursively (child )
311-
312- else :
313- # Recursively process children for other node types
314- for child in current_node .children :
315- process_node_recursively (child )
316-
317- process_node_recursively (node )
318- return names , aliases , is_namespace , namespace_alias
319-
320254 @classmethod
321255 def _process_class_node (cls , node : Node , code : bytes , codeFile : CodeFileModel , node_type :Literal ["class" , "interface" , "type" ]= "class" ):
322256 # TODO add support for modifiers at variables, classes i.e
@@ -457,7 +391,6 @@ def _process_variable_declaration(cls, node: Node, code: bytes, codeFile: CodeFi
457391
458392 @classmethod
459393 def _process_variable_declarator (cls , node : Node , code : bytes , codeFile : CodeFileModel ):
460- # TODO debug this with GitRecap
461394 name = None
462395 type_hint = None
463396 value = None
0 commit comments