From ec7fccaa77f9003b6c151108edc5e40ef30b0544 Mon Sep 17 00:00:00 2001 From: feSHt377 Date: Fri, 7 Aug 2026 17:24:13 +0800 Subject: [PATCH 1/3] fix: add missing 'origin' to built-in template entries TypeScriptLanguage::_get_built_in_templates returns template dicts built by make_template_entry, which omitted the 'origin' key. Godot's ScriptLanguageExtension::get_built_in_templates requires it and skips any entry without it. Selecting TypeScript in the New Script dialog therefore produced the '!d.has(origin)' error and dropped all templates. Set origin to TEMPLATE_BUILT_IN (0). --- src/script/typescript_language.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/script/typescript_language.cpp b/src/script/typescript_language.cpp index e2148b3..f9e283a 100644 --- a/src/script/typescript_language.cpp +++ b/src/script/typescript_language.cpp @@ -148,6 +148,7 @@ Dictionary make_template_entry(const String &p_inherit, const String &p_name, co entry["description"] = p_description; entry["content"] = p_content; entry["id"] = p_id; + entry["origin"] = 0; return entry; } From 57d9a064e7f0ac2f0b75caa07368a5fc2f65111a Mon Sep 17 00:00:00 2001 From: moluopro Date: Fri, 7 Aug 2026 20:49:24 +0800 Subject: [PATCH 2/3] fix: name TypeScript template origin --- src/script/typescript_language.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/script/typescript_language.cpp b/src/script/typescript_language.cpp index f9e283a..f5df79c 100644 --- a/src/script/typescript_language.cpp +++ b/src/script/typescript_language.cpp @@ -38,6 +38,10 @@ constexpr const char *TS_CONTROL_FLOW_WORDS[] = { "finally", "for", "if", "return", "switch", "throw", "try", "while", "yield" }; +// Mirrors ScriptLanguage::TemplateLocation::TEMPLATE_BUILT_IN, which godot-cpp +// does not expose as a GDExtension enum. +constexpr int SCRIPT_TEMPLATE_ORIGIN_BUILT_IN = 0; + bool contains_word(const String &p_word, const char *const *p_words, size_t p_count) { const String word = p_word.strip_edges(); for (size_t i = 0; i < p_count; i++) { @@ -148,7 +152,7 @@ Dictionary make_template_entry(const String &p_inherit, const String &p_name, co entry["description"] = p_description; entry["content"] = p_content; entry["id"] = p_id; - entry["origin"] = 0; + entry["origin"] = SCRIPT_TEMPLATE_ORIGIN_BUILT_IN; return entry; } From 3e5e8be6aa33983b6312df396b89653798ab5af5 Mon Sep 17 00:00:00 2001 From: moluopro Date: Fri, 7 Aug 2026 20:49:37 +0800 Subject: [PATCH 3/3] test: cover TypeScript template origin metadata --- test/test_repository_integrity.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/test/test_repository_integrity.py b/test/test_repository_integrity.py index 547e8b5..f2f1f2c 100644 --- a/test/test_repository_integrity.py +++ b/test/test_repository_integrity.py @@ -1103,6 +1103,18 @@ def test_typescript_language_editor_surface_is_not_stubbed(self): self.assertNotIn("script->_get_global_name()", global_class_body) self.assertNotIn("script->get_base_class_name()", global_class_body) + def test_typescript_builtin_template_entries_include_godot_required_fields(self): + source = (ROOT / "src/script/typescript_language.cpp").read_text(encoding="utf-8") + match = re.search(r"Dictionary make_template_entry\(.*?\n\}", source, re.DOTALL) + self.assertIsNotNone(match) + body = match.group(0) + + for key in ("inherit", "name", "description", "content", "id", "origin"): + self.assertIn(f'entry["{key}"]', body) + self.assertIn("SCRIPT_TEMPLATE_ORIGIN_BUILT_IN", source) + self.assertIn('entry["origin"] = SCRIPT_TEMPLATE_ORIGIN_BUILT_IN;', body) + self.assertNotIn('entry["origin"] = 0;', body) + def test_typescript_metadata_parser_resolves_project_imports_like_compiler(self): source = (ROOT / "src/script/typescript_script.cpp").read_text(encoding="utf-8")