Skip to content

Commit

Permalink
fix: Self types as results are translated to class names (#110)
Browse files Browse the repository at this point in the history
Closes #86

### Summary of Changes
`Self`s as result types are now translated to the corresponding class
names.
  • Loading branch information
Masara committed Apr 13, 2024
1 parent c35c6ac commit 4554a56
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 0 deletions.
8 changes: 8 additions & 0 deletions src/safeds_stubgen/api_analyzer/_ast_visitor.py
Original file line number Diff line number Diff line change
Expand Up @@ -502,6 +502,10 @@ def _infer_type_from_return_stmts(func_node: mp_nodes.FuncDef) -> sds_types.Tupl
type_ = mypy_expression_to_sds_type(conditional_branch)
if isinstance(type_, sds_types.NamedType | sds_types.TupleType):
types.add(type_)
elif hasattr(return_stmt.expr, "node") and getattr(return_stmt.expr.node, "is_self", False):
# The result type is an instance of the parent class
expr_type = return_stmt.expr.node.type.type
types.add(sds_types.NamedType(name=expr_type.name, qname=expr_type.fullname))
else:
type_ = mypy_expression_to_sds_type(return_stmt.expr)
if isinstance(type_, sds_types.NamedType | sds_types.TupleType):
Expand Down Expand Up @@ -916,6 +920,10 @@ def mypy_type_to_abstract_type(
if upper_bound.__str__() != "builtins.object":
type_ = self.mypy_type_to_abstract_type(upper_bound)

if mypy_type.name == "Self":
# Special case, where the method returns an instance of its class
return type_

type_var = sds_types.TypeVarType(name=mypy_type.name, upper_bound=type_)
self.type_var_types.add(type_var)
return type_var
Expand Down
15 changes: 15 additions & 0 deletions tests/data/various_modules_package/class_module.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from typing import Self

from tests.data.main_package.another_path.another_module import yetAnotherClass


Expand Down Expand Up @@ -41,3 +43,16 @@ class InheritFromException(ValueError):

class InheritFromException2(Exception, InheritFromException, ClassModuleClassB):
...


class SelfTypes1:
def self_result1(self) -> Self:
pass


class SelfTypes2(SelfTypes1):
def self_result2(self) -> Self:
pass

def infer_self_result2(self):
return self
Original file line number Diff line number Diff line change
Expand Up @@ -6945,6 +6945,8 @@
'tests/data/various_modules_package/class_module/_ClassModulePrivateClassG',
'tests/data/various_modules_package/class_module/InheritFromException',
'tests/data/various_modules_package/class_module/InheritFromException2',
'tests/data/various_modules_package/class_module/SelfTypes1',
'tests/data/various_modules_package/class_module/SelfTypes2',
]),
'docstring': '',
'enums': list([
Expand All @@ -6954,6 +6956,10 @@
'id': 'tests/data/various_modules_package/class_module',
'name': 'class_module',
'qualified_imports': list([
dict({
'alias': None,
'qualified_name': 'typing.Self',
}),
dict({
'alias': None,
'qualified_name': 'tests.data.main_package.another_path.another_module.yetAnotherClass',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,19 @@ class ClassModuleClassD() {
fun classEFunc()
}
}

class SelfTypes1() {
@Pure
@PythonName("self_result1")
fun selfResult1() -> result1: SelfTypes1
}

class SelfTypes2() sub SelfTypes1 {
@Pure
@PythonName("self_result2")
fun selfResult2() -> result1: SelfTypes2

@Pure
@PythonName("infer_self_result2")
fun inferSelfResult2() -> result1: SelfTypes2
}

0 comments on commit 4554a56

Please sign in to comment.