Skip to content

Commit 6d8b722

Browse files
committed
[GDScript]: Added strongly typed big-Self type to name the type of little-self.
1 parent 149a4b4 commit 6d8b722

16 files changed

+117
-0
lines changed

modules/gdscript/gdscript_analyzer.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -898,6 +898,17 @@ GDScriptParser::DataType GDScriptAnalyzer::resolve_datatype(GDScriptParser::Type
898898
}
899899
}
900900

901+
if (!result.is_set() && first == SNAME("Self")) {
902+
// Strong type for the `self` identifier. Resolves to the current class
903+
// meta-type so it behaves like using the current class name directly.
904+
if (parser->current_class) {
905+
result = parser->current_class->datatype;
906+
} else {
907+
push_error(R"("Self" can only be used inside a class.)", p_type);
908+
return bad_type;
909+
}
910+
}
911+
901912
if (!result.is_set()) {
902913
push_error(vformat(R"(Could not find type "%s" in the current scope.)", first), p_type);
903914
return bad_type;
@@ -4650,6 +4661,24 @@ void GDScriptAnalyzer::reduce_identifier(GDScriptParser::IdentifierNode *p_ident
46504661
return;
46514662
}
46524663

4664+
// Allow "Self" here, as a value it resolves to the current class meta-type.
4665+
// This enables expressions like `Self.new()` or `Self.my_static()` to work.
4666+
if (name == SNAME("Self")) {
4667+
if (parser->current_class == nullptr) {
4668+
push_error(R"("Self" can only be used inside a class.)", p_identifier);
4669+
} else {
4670+
p_identifier->datatype = parser->current_class->datatype;
4671+
4672+
Error err = OK;
4673+
Ref<GDScript> scr = get_depended_shallow_script(parser->current_class->datatype.script_path, err);
4674+
if (!err && scr.is_valid()) {
4675+
p_identifier->reduced_value = scr->find_class(parser->current_class->datatype.class_type->fqcn);
4676+
p_identifier->is_constant = true;
4677+
}
4678+
}
4679+
return;
4680+
}
4681+
46534682
// Not found.
46544683
#ifdef SUGGEST_GODOT4_RENAMES
46554684
String rename_hint;

modules/gdscript/gdscript_compiler.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -478,6 +478,11 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
478478
} break;
479479
}
480480

481+
// Special-case: `Self` refers to the current class meta-type.
482+
if (identifier == SNAME("Self")) {
483+
return GDScriptCodeGenerator::Address(GDScriptCodeGenerator::Address::CLASS);
484+
}
485+
481486
// Not found, error.
482487
_set_error("Identifier not found: " + String(identifier), p_expression);
483488
r_error = ERR_COMPILATION_FAILED;
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
class Self:
2+
var value := "OK"
3+
4+
class TestClass:
5+
static func make() -> Self:
6+
return Self.new()
7+
8+
func test():
9+
var x := TestClass.make()
10+
prints(x != null, x is Self)
11+
prints(x.value)
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
GDTEST_OK
2+
true true
3+
OK
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
var list: Array[Self] = []
2+
var dict: Dictionary[String, Self] = {}
3+
4+
func test():
5+
list.append(self)
6+
print(list.size() == 1 and list.back() is Self)
7+
list.clear()
8+
9+
dict["self"] = self
10+
print(dict.has("self") and dict["self"] is Self)
11+
dict.clear()
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
GDTEST_OK
2+
true
3+
true
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
enum MyEnum { A, B }
2+
3+
func get_enum() -> Self.MyEnum:
4+
return MyEnum.A
5+
6+
func test():
7+
var e: Self.MyEnum = get_enum()
8+
print(int(e) == 0)
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
GDTEST_OK
2+
true
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
class Inner:
2+
var val := "OK"
3+
4+
func make_inner() -> Self.Inner:
5+
return Self.Inner.new()
6+
7+
func test():
8+
var i: Self.Inner = make_inner()
9+
print(i.val)
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
GDTEST_OK
2+
OK

0 commit comments

Comments
 (0)