Skip to content

Commit bf06715

Browse files
tomcodgenfrainfreezetkfoss
authored
[CG-8705] feat: Implement Namespace as TS graph node type (#40)
Co-authored-by: tomcodegen <[email protected]> Co-authored-by: tomcodgen <[email protected]>
1 parent d83e574 commit bf06715

File tree

9 files changed

+660
-70
lines changed

9 files changed

+660
-70
lines changed

src/codegen/sdk/core/expressions/chained_attribute.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -134,19 +134,16 @@ def object(self) -> Object:
134134
@noapidoc
135135
@override
136136
def _resolved_types(self) -> Generator[ResolutionStack[Self], None, None]:
137-
from codegen.sdk.typescript.namespace import TSNamespace
138-
139137
if not self.ctx.config.method_usages:
140138
return
141139
if res := self.file.valid_import_names.get(self.full_name, None):
142140
# Module imports
143141
yield from self.with_resolution_frame(res)
144142
return
145-
# HACK: This is a hack to skip the resolved types for namespaces
146-
if isinstance(self.object, TSNamespace):
147-
return
143+
148144
for resolved_type in self.object.resolved_type_frames:
149145
top = resolved_type.top
146+
150147
if not isinstance(top.node, HasAttribute):
151148
generics: dict = resolved_type.generics.copy()
152149
if top.node.source.lower() == "dict" and self.attribute.source in ("values", "get", "pop"):

src/codegen/sdk/python/import_resolution.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,12 @@
1515
from tree_sitter import Node as TSNode
1616

1717
from codegen.sdk.codebase.codebase_context import CodebaseContext
18+
from codegen.sdk.core.file import SourceFile
1819
from codegen.sdk.core.interfaces.editable import Editable
1920
from codegen.sdk.core.interfaces.exportable import Exportable
2021
from codegen.sdk.core.node_id_factory import NodeId
2122
from codegen.sdk.core.statements.import_statement import ImportStatement
2223
from codegen.sdk.python.file import PyFile
23-
from src.codegen.sdk.core.file import SourceFile
2424

2525

2626
logger = get_logger(__name__)

src/codegen/sdk/typescript/import_resolution.py

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from codegen.sdk.core.expressions import Name
99
from codegen.sdk.core.import_resolution import Import, ImportResolution, WildcardImport
1010
from codegen.sdk.core.interfaces.exportable import Exportable
11-
from codegen.sdk.enums import ImportType, NodeType
11+
from codegen.sdk.enums import ImportType, NodeType, SymbolType
1212
from codegen.sdk.utils import find_all_descendants, find_first_ancestor, find_first_descendant
1313
from codegen.shared.decorators.docs import noapidoc, ts_apidoc
1414

@@ -24,6 +24,7 @@
2424
from codegen.sdk.core.statements.import_statement import ImportStatement
2525
from codegen.sdk.core.symbol import Symbol
2626
from codegen.sdk.typescript.file import TSFile
27+
from codegen.sdk.typescript.namespace import TSNamespace
2728
from codegen.sdk.typescript.statements.import_statement import TSImportStatement
2829

2930

@@ -578,6 +579,48 @@ def names(self) -> Generator[tuple[str, Self | WildcardImport[Self]], None, None
578579
return
579580
yield from super().names
580581

582+
@property
583+
def namespace_imports(self) -> list[TSNamespace]:
584+
"""Returns any namespace objects imported by this import statement.
585+
586+
For example:
587+
import * as MyNS from './mymodule';
588+
589+
Returns:
590+
List of namespace objects imported
591+
"""
592+
if not self.is_namespace_import():
593+
return []
594+
595+
from codegen.sdk.typescript.namespace import TSNamespace
596+
597+
resolved = self.resolved_symbol
598+
if resolved is None or not isinstance(resolved, TSNamespace):
599+
return []
600+
601+
return [resolved]
602+
603+
@property
604+
def is_namespace_import(self) -> bool:
605+
"""Returns True if this import is importing a namespace.
606+
607+
Examples:
608+
import { MathUtils } from './file1'; # True if MathUtils is a namespace
609+
import * as AllUtils from './utils'; # True
610+
"""
611+
# For wildcard imports with namespace alias
612+
if self.import_type == ImportType.WILDCARD and self.namespace:
613+
return True
614+
615+
# For named imports, check if any imported symbol is a namespace
616+
if self.import_type == ImportType.NAMED_EXPORT:
617+
for name, _ in self.names:
618+
symbol = self.resolved_symbol
619+
if symbol and symbol.symbol_type == SymbolType.Namespace:
620+
return True
621+
622+
return False
623+
581624
@override
582625
def set_import_module(self, new_module: str) -> None:
583626
"""Sets the module of an import.

0 commit comments

Comments
 (0)