Skip to content
This repository was archived by the owner on Jan 13, 2026. It is now read-only.

Commit 0a9ea9c

Browse files
committed
More type attribution logic
1 parent 5e2d6e3 commit 0a9ea9c

File tree

2 files changed

+68
-6
lines changed

2 files changed

+68
-6
lines changed

rewrite/rewrite/java/support_types.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -435,13 +435,23 @@ class Unknown(FullyQualified):
435435
pass
436436

437437
class Class(FullyQualified):
438-
pass
438+
_flags_bit_map: int
439+
_fully_qualified_name: str
440+
_kind: FullyQualified.Kind
441+
_type_parameters: Optional[List[JavaType]]
442+
_supertype: Optional[JavaType.FullyQualified]
443+
_owning_class: Optional[JavaType.FullyQualified]
444+
_annotations: Optional[List[JavaType.FullyQualified]]
445+
_interfaces: Optional[List[JavaType.FullyQualified]]
446+
_members: Optional[List[JavaType.Variable]]
447+
_methods: Optional[List[JavaType.Method]]
439448

440449
class ShallowClass(Class):
441450
pass
442451

443452
class Parameterized(FullyQualified):
444-
pass
453+
_type: JavaType.FullyQualified
454+
_type_parameters: Optional[List[JavaType]]
445455

446456
class GenericTypeVariable:
447457
class Variance(Enum):

rewrite/rewrite/python/type_mapping.py

Lines changed: 56 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,28 +2,32 @@
22
from typing import Optional
33

44
from pytype import config
5-
from pytype.pytd.pytd import CallableType
5+
from pytype.pytd.pytd import CallableType, GenericType, ClassType, UnionType, NothingType, TypeParameter
66
from pytype.tools.annotate_ast.annotate_ast import AnnotateAstVisitor, PytypeError, infer_types
77

88
from ..java import JavaType
99

1010

1111
class PythonTypeMapping:
1212
__enabled = False
13+
__cache: dict[str, JavaType] = {}
1314

1415
def __init__(self, source: str):
15-
pytype_options = config.Options.create(python_version='3.12', check=False, precise_return=True, output_debug=False)
16+
pytype_options = config.Options.create(python_version='3.12', check=False, precise_return=True,
17+
output_debug=False)
1618
try:
1719
self._source_with_types = infer_types(source, pytype_options) if self.__enabled else None
1820
except PytypeError:
1921
self._source_with_types = None
2022

2123
def resolve_types(self, node):
2224
if self._source_with_types:
23-
type_visitor = AnnotateAstVisitor(self._source_with_types, ast)
25+
type_visitor = MyAnnotateAstVisitor(self._source_with_types, ast)
2426
type_visitor.visit(node)
2527

2628
def type(self, node) -> Optional[JavaType]:
29+
if hasattr(node, 'resolved_annotation') and (result := self.__cache.get(node.resolved_annotation)):
30+
return result
2731
if isinstance(node, ast.Constant):
2832
if isinstance(node.value, str):
2933
return JavaType.Primitive.String
@@ -45,11 +49,59 @@ def method_invocation_type(self, node) -> Optional[JavaType.Method]:
4549
return self.__map_type(node.func.resolved_type, node) if self.__enabled else None
4650

4751
def __map_type(self, type, node):
48-
if isinstance(type, CallableType):
52+
signature = get_type_string(type)
53+
result = self.__cache.get(signature)
54+
if result:
55+
return result
56+
57+
if isinstance(type, ClassType):
58+
self.__cache[signature] = (result := JavaType.Class())
59+
result._kind = JavaType.FullyQualified.Kind.Class
60+
result._fully_qualified_name = type.name
61+
result._interfaces = [self.__map_type(i, node) for i in type.cls.bases]
62+
elif isinstance(type, CallableType):
4963
if isinstance(node, ast.Name):
5064
name = node.id
5165
elif isinstance(node, ast.Call) and isinstance(node.func, ast.Attribute):
5266
name = node.func.attr
5367
else:
5468
name = ''
5569
return JavaType.Method(_name=name)
70+
elif isinstance(type, GenericType):
71+
self.__cache[signature] = (result := JavaType.Parameterized)
72+
result._type = self.__map_type(type.base_type, node)
73+
result._type_parameters = [self.__map_type(t, node) for t in type.parameters]
74+
elif isinstance(type, NothingType):
75+
self.__cache[signature] = (result := JavaType.Unknown())
76+
return result
77+
78+
79+
def get_type_string(typ):
80+
if typ is None:
81+
return "None"
82+
elif isinstance(typ, ClassType):
83+
return typ.name
84+
elif isinstance(typ, GenericType):
85+
base = get_type_string(typ.base_type)
86+
params = [get_type_string(p) for p in typ.parameters]
87+
return f"{base}[{', '.join(params)}]"
88+
elif isinstance(typ, CallableType):
89+
args = [get_type_string(a) for a in typ.args]
90+
ret = get_type_string(typ.ret)
91+
return f"[{', '.join(args)}] -> {ret}"
92+
elif isinstance(typ, UnionType):
93+
types = [get_type_string(t) for t in typ.type_list]
94+
return '|'.join(types)
95+
elif isinstance(typ, TypeParameter):
96+
types = [get_type_string(t) for t in typ.constraints]
97+
return f"{typ.full_name}{[{', '.join(types)}] if types else ''}"
98+
elif hasattr(typ, "name"):
99+
return typ.name
100+
else:
101+
return str(typ)
102+
103+
104+
class MyAnnotateAstVisitor(AnnotateAstVisitor):
105+
# TODO check if we really should have this
106+
def visit_Call(self, node):
107+
self._maybe_annotate(node)

0 commit comments

Comments
 (0)