summaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
Diffstat (limited to 'modules')
-rw-r--r--modules/gdscript/gdscript_analyzer.cpp23
-rw-r--r--modules/gdscript/language_server/gdscript_extend_parser.cpp2
-rw-r--r--modules/gdscript/language_server/gdscript_language_protocol.cpp1
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/extend_non_class_constant_1.gd9
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/extend_non_class_constant_1.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/extend_non_class_constant_2.gd12
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/extend_non_class_constant_2.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/extend_variable.gd9
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/extend_variable.out2
-rw-r--r--modules/gltf/gltf_document.cpp8
-rw-r--r--modules/text_server_adv/text_server_adv.cpp137
-rw-r--r--modules/text_server_adv/text_server_adv.h5
-rw-r--r--modules/text_server_fb/text_server_fb.cpp2
13 files changed, 168 insertions, 46 deletions
diff --git a/modules/gdscript/gdscript_analyzer.cpp b/modules/gdscript/gdscript_analyzer.cpp
index c233d51801..b964bbce7e 100644
--- a/modules/gdscript/gdscript_analyzer.cpp
+++ b/modules/gdscript/gdscript_analyzer.cpp
@@ -478,7 +478,24 @@ Error GDScriptAnalyzer::resolve_class_inheritance(GDScriptParser::ClassNode *p_c
}
if (look_class->has_member(name)) {
resolve_class_member(look_class, name, p_class);
- base = look_class->get_member(name).get_datatype();
+ GDScriptParser::ClassNode::Member member = look_class->get_member(name);
+ GDScriptParser::DataType member_datatype = member.get_datatype();
+
+ switch (member.type) {
+ case GDScriptParser::ClassNode::Member::CLASS:
+ break; // OK.
+ case GDScriptParser::ClassNode::Member::CONSTANT:
+ if (member_datatype.kind != GDScriptParser::DataType::SCRIPT && member_datatype.kind != GDScriptParser::DataType::CLASS) {
+ push_error(vformat(R"(Constant "%s" is not a preloaded script or class.)", name), p_class);
+ return ERR_PARSE_ERROR;
+ }
+ break;
+ default:
+ push_error(vformat(R"(Cannot use %s "%s" in extends chain.)", member.get_type_name(), name), p_class);
+ return ERR_PARSE_ERROR;
+ }
+
+ base = member_datatype;
found = true;
break;
}
@@ -506,6 +523,10 @@ Error GDScriptAnalyzer::resolve_class_inheritance(GDScriptParser::ClassNode *p_c
GDScriptParser::DataType id_type = id->get_datatype();
if (!id_type.is_set()) {
push_error(vformat(R"(Could not find type "%s" under base "%s".)", id->name, base.to_string()), p_class);
+ return ERR_PARSE_ERROR;
+ } else if (id_type.kind != GDScriptParser::DataType::SCRIPT && id_type.kind != GDScriptParser::DataType::CLASS) {
+ push_error(vformat(R"(Identifier "%s" is not a preloaded script or class.)", id->name), p_class);
+ return ERR_PARSE_ERROR;
}
base = id_type;
diff --git a/modules/gdscript/language_server/gdscript_extend_parser.cpp b/modules/gdscript/language_server/gdscript_extend_parser.cpp
index 146ed10ceb..1bf9f85831 100644
--- a/modules/gdscript/language_server/gdscript_extend_parser.cpp
+++ b/modules/gdscript/language_server/gdscript_extend_parser.cpp
@@ -337,7 +337,7 @@ void ExtendGDScriptParser::parse_function_symbol(const GDScriptParser::FunctionN
symbol.kind = lsp::SymbolKind::Variable;
symbol.name = parameter->identifier->name;
symbol.range.start.line = LINE_NUMBER_TO_INDEX(parameter->start_line);
- symbol.range.start.character = LINE_NUMBER_TO_INDEX(parameter->start_line);
+ symbol.range.start.character = LINE_NUMBER_TO_INDEX(parameter->start_column);
symbol.range.end.line = LINE_NUMBER_TO_INDEX(parameter->end_line);
symbol.range.end.character = LINE_NUMBER_TO_INDEX(parameter->end_column);
symbol.uri = uri;
diff --git a/modules/gdscript/language_server/gdscript_language_protocol.cpp b/modules/gdscript/language_server/gdscript_language_protocol.cpp
index acd75f039a..0aa53c1dbe 100644
--- a/modules/gdscript/language_server/gdscript_language_protocol.cpp
+++ b/modules/gdscript/language_server/gdscript_language_protocol.cpp
@@ -237,6 +237,7 @@ void GDScriptLanguageProtocol::poll() {
HashMap<int, Ref<LSPeer>>::Iterator E = clients.begin();
while (E != clients.end()) {
Ref<LSPeer> peer = E->value;
+ peer->connection->poll();
StreamPeerTCP::Status status = peer->connection->get_status();
if (status == StreamPeerTCP::STATUS_NONE || status == StreamPeerTCP::STATUS_ERROR) {
on_client_disconnected(E->key);
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/extend_non_class_constant_1.gd b/modules/gdscript/tests/scripts/analyzer/errors/extend_non_class_constant_1.gd
new file mode 100644
index 0000000000..72af099158
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/extend_non_class_constant_1.gd
@@ -0,0 +1,9 @@
+# GH-75870
+
+const A = 1
+
+class B extends A:
+ pass
+
+func test():
+ pass
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/extend_non_class_constant_1.out b/modules/gdscript/tests/scripts/analyzer/errors/extend_non_class_constant_1.out
new file mode 100644
index 0000000000..65d629a35b
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/extend_non_class_constant_1.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Constant "A" is not a preloaded script or class.
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/extend_non_class_constant_2.gd b/modules/gdscript/tests/scripts/analyzer/errors/extend_non_class_constant_2.gd
new file mode 100644
index 0000000000..fe334f8cb7
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/extend_non_class_constant_2.gd
@@ -0,0 +1,12 @@
+# GH-75870
+
+class A:
+ const X = 1
+
+const Y = A.X # A.X is now resolved.
+
+class B extends A.X:
+ pass
+
+func test():
+ pass
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/extend_non_class_constant_2.out b/modules/gdscript/tests/scripts/analyzer/errors/extend_non_class_constant_2.out
new file mode 100644
index 0000000000..951cfb1ea4
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/extend_non_class_constant_2.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Identifier "X" is not a preloaded script or class.
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/extend_variable.gd b/modules/gdscript/tests/scripts/analyzer/errors/extend_variable.gd
new file mode 100644
index 0000000000..6574d4cf31
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/extend_variable.gd
@@ -0,0 +1,9 @@
+# GH-75870
+
+var A = 1
+
+class B extends A:
+ pass
+
+func test():
+ pass
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/extend_variable.out b/modules/gdscript/tests/scripts/analyzer/errors/extend_variable.out
new file mode 100644
index 0000000000..7b39af6979
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/extend_variable.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Cannot use variable "A" in extends chain.
diff --git a/modules/gltf/gltf_document.cpp b/modules/gltf/gltf_document.cpp
index d93485a800..7087c30688 100644
--- a/modules/gltf/gltf_document.cpp
+++ b/modules/gltf/gltf_document.cpp
@@ -2820,7 +2820,13 @@ Error GLTFDocument::_parse_meshes(Ref<GLTFState> p_state) {
if (j == 0) {
const Array &target_names = extras.has("targetNames") ? (Array)extras["targetNames"] : Array();
for (int k = 0; k < targets.size(); k++) {
- import_mesh->add_blend_shape(k < target_names.size() ? (String)target_names[k] : String("morph_") + itos(k));
+ String bs_name;
+ if (k < target_names.size() && ((String)target_names[k]).size() != 0) {
+ bs_name = (String)target_names[k];
+ } else {
+ bs_name = String("morph_") + itos(k);
+ }
+ import_mesh->add_blend_shape(bs_name);
}
}
diff --git a/modules/text_server_adv/text_server_adv.cpp b/modules/text_server_adv/text_server_adv.cpp
index 3cf6288fef..e1aa467fdc 100644
--- a/modules/text_server_adv/text_server_adv.cpp
+++ b/modules/text_server_adv/text_server_adv.cpp
@@ -4105,6 +4105,7 @@ RID TextServerAdvanced::_shaped_text_substr(const RID &p_shaped, int64_t p_start
new_sd->direction = sd->direction;
new_sd->custom_punct = sd->custom_punct;
new_sd->para_direction = sd->para_direction;
+ new_sd->base_para_direction = sd->base_para_direction;
for (int i = 0; i < TextServer::SPACING_MAX; i++) {
new_sd->extra_spacing[i] = sd->extra_spacing[i];
}
@@ -4149,22 +4150,61 @@ bool TextServerAdvanced::_shape_substr(ShapedTextDataAdvanced *p_new_sd, const S
ERR_FAIL_COND_V_MSG((start < 0 || end - start > p_new_sd->utf16.length()), false, "Invalid BiDi override range.");
// Create temporary line bidi & shape.
- UBiDi *bidi_iter = ubidi_openSized(end - start, 0, &err);
- ERR_FAIL_COND_V_MSG(U_FAILURE(err), false, u_errorName(err));
- ubidi_setLine(p_sd->bidi_iter[ov], start, end, bidi_iter, &err);
- if (U_FAILURE(err)) {
- ubidi_close(bidi_iter);
- ERR_FAIL_V_MSG(false, u_errorName(err));
+ UBiDi *bidi_iter = nullptr;
+ if (p_sd->bidi_iter[ov]) {
+ bidi_iter = ubidi_openSized(end - start, 0, &err);
+ if (U_SUCCESS(err)) {
+ ubidi_setLine(p_sd->bidi_iter[ov], start, end, bidi_iter, &err);
+ if (U_FAILURE(err)) {
+ // Line BiDi failed (string contains incompatible control characters), try full paragraph BiDi instead.
+ err = U_ZERO_ERROR;
+ const UChar *data = p_sd->utf16.get_data();
+ switch (static_cast<TextServer::Direction>(p_sd->bidi_override[ov].z)) {
+ case DIRECTION_LTR: {
+ ubidi_setPara(bidi_iter, data + start, end - start, UBIDI_LTR, nullptr, &err);
+ } break;
+ case DIRECTION_RTL: {
+ ubidi_setPara(bidi_iter, data + start, end - start, UBIDI_RTL, nullptr, &err);
+ } break;
+ case DIRECTION_INHERITED: {
+ ubidi_setPara(bidi_iter, data + start, end - start, p_sd->base_para_direction, nullptr, &err);
+ } break;
+ case DIRECTION_AUTO: {
+ UBiDiDirection direction = ubidi_getBaseDirection(data + start, end - start);
+ if (direction != UBIDI_NEUTRAL) {
+ ubidi_setPara(bidi_iter, data + start, end - start, direction, nullptr, &err);
+ } else {
+ ubidi_setPara(bidi_iter, data + start, end - start, p_sd->base_para_direction, nullptr, &err);
+ }
+ } break;
+ }
+ if (U_FAILURE(err)) {
+ ubidi_close(bidi_iter);
+ bidi_iter = nullptr;
+ ERR_PRINT(vformat("BiDi reordering for the line failed: %s", u_errorName(err)));
+ }
+ }
+ } else {
+ bidi_iter = nullptr;
+ ERR_PRINT(vformat("BiDi iterator allocation for the line failed: %s", u_errorName(err)));
+ }
}
p_new_sd->bidi_iter.push_back(bidi_iter);
err = U_ZERO_ERROR;
- int bidi_run_count = ubidi_countRuns(bidi_iter, &err);
- ERR_FAIL_COND_V_MSG(U_FAILURE(err), false, u_errorName(err));
+ int bidi_run_count = 1;
+ if (bidi_iter) {
+ bidi_run_count = ubidi_countRuns(bidi_iter, &err);
+ if (U_FAILURE(err)) {
+ ERR_PRINT(u_errorName(err));
+ }
+ }
for (int i = 0; i < bidi_run_count; i++) {
int32_t _bidi_run_start = 0;
- int32_t _bidi_run_length = 0;
- ubidi_getVisualRun(bidi_iter, i, &_bidi_run_start, &_bidi_run_length);
+ int32_t _bidi_run_length = end - start;
+ if (bidi_iter) {
+ ubidi_getVisualRun(bidi_iter, i, &_bidi_run_start, &_bidi_run_length);
+ }
int32_t bidi_run_start = _convert_pos(p_sd, ov_start + start + _bidi_run_start);
int32_t bidi_run_end = _convert_pos(p_sd, ov_start + start + _bidi_run_start + _bidi_run_length);
@@ -5571,25 +5611,25 @@ bool TextServerAdvanced::_shaped_text_shape(const RID &p_shaped) {
sd->script_iter = memnew(ScriptIterator(sd->text, 0, sd->text.length()));
}
- int base_para_direction = UBIDI_DEFAULT_LTR;
+ sd->base_para_direction = UBIDI_DEFAULT_LTR;
switch (sd->direction) {
case DIRECTION_LTR: {
sd->para_direction = DIRECTION_LTR;
- base_para_direction = UBIDI_LTR;
+ sd->base_para_direction = UBIDI_LTR;
} break;
case DIRECTION_RTL: {
sd->para_direction = DIRECTION_RTL;
- base_para_direction = UBIDI_RTL;
+ sd->base_para_direction = UBIDI_RTL;
} break;
case DIRECTION_INHERITED:
case DIRECTION_AUTO: {
UBiDiDirection direction = ubidi_getBaseDirection(data, sd->utf16.length());
if (direction != UBIDI_NEUTRAL) {
sd->para_direction = (direction == UBIDI_RTL) ? DIRECTION_RTL : DIRECTION_LTR;
- base_para_direction = direction;
+ sd->base_para_direction = direction;
} else {
sd->para_direction = DIRECTION_LTR;
- base_para_direction = UBIDI_DEFAULT_LTR;
+ sd->base_para_direction = UBIDI_DEFAULT_LTR;
}
} break;
}
@@ -5609,38 +5649,53 @@ bool TextServerAdvanced::_shaped_text_shape(const RID &p_shaped) {
UErrorCode err = U_ZERO_ERROR;
UBiDi *bidi_iter = ubidi_openSized(end - start, 0, &err);
- ERR_FAIL_COND_V_MSG(U_FAILURE(err), false, u_errorName(err));
-
- switch (static_cast<TextServer::Direction>(sd->bidi_override[ov].z)) {
- case DIRECTION_LTR: {
- ubidi_setPara(bidi_iter, data + start, end - start, UBIDI_LTR, nullptr, &err);
- } break;
- case DIRECTION_RTL: {
- ubidi_setPara(bidi_iter, data + start, end - start, UBIDI_RTL, nullptr, &err);
- } break;
- case DIRECTION_INHERITED: {
- ubidi_setPara(bidi_iter, data + start, end - start, base_para_direction, nullptr, &err);
- } break;
- case DIRECTION_AUTO: {
- UBiDiDirection direction = ubidi_getBaseDirection(data + start, end - start);
- if (direction != UBIDI_NEUTRAL) {
- ubidi_setPara(bidi_iter, data + start, end - start, direction, nullptr, &err);
- } else {
- ubidi_setPara(bidi_iter, data + start, end - start, base_para_direction, nullptr, &err);
- }
- } break;
+ if (U_SUCCESS(err)) {
+ switch (static_cast<TextServer::Direction>(sd->bidi_override[ov].z)) {
+ case DIRECTION_LTR: {
+ ubidi_setPara(bidi_iter, data + start, end - start, UBIDI_LTR, nullptr, &err);
+ } break;
+ case DIRECTION_RTL: {
+ ubidi_setPara(bidi_iter, data + start, end - start, UBIDI_RTL, nullptr, &err);
+ } break;
+ case DIRECTION_INHERITED: {
+ ubidi_setPara(bidi_iter, data + start, end - start, sd->base_para_direction, nullptr, &err);
+ } break;
+ case DIRECTION_AUTO: {
+ UBiDiDirection direction = ubidi_getBaseDirection(data + start, end - start);
+ if (direction != UBIDI_NEUTRAL) {
+ ubidi_setPara(bidi_iter, data + start, end - start, direction, nullptr, &err);
+ } else {
+ ubidi_setPara(bidi_iter, data + start, end - start, sd->base_para_direction, nullptr, &err);
+ }
+ } break;
+ }
+ if (U_FAILURE(err)) {
+ ubidi_close(bidi_iter);
+ bidi_iter = nullptr;
+ ERR_PRINT(vformat("BiDi reordering for the paragraph failed: %s", u_errorName(err)));
+ }
+ } else {
+ bidi_iter = nullptr;
+ ERR_PRINT(vformat("BiDi iterator allocation for the paragraph failed: %s", u_errorName(err)));
}
- ERR_FAIL_COND_V_MSG(U_FAILURE(err), false, u_errorName(err));
sd->bidi_iter.push_back(bidi_iter);
err = U_ZERO_ERROR;
- int bidi_run_count = ubidi_countRuns(bidi_iter, &err);
- ERR_FAIL_COND_V_MSG(U_FAILURE(err), false, u_errorName(err));
+ int bidi_run_count = 1;
+ if (bidi_iter) {
+ bidi_run_count = ubidi_countRuns(bidi_iter, &err);
+ if (U_FAILURE(err)) {
+ ERR_PRINT(u_errorName(err));
+ }
+ }
for (int i = 0; i < bidi_run_count; i++) {
int32_t _bidi_run_start = 0;
- int32_t _bidi_run_length = 0;
+ int32_t _bidi_run_length = end - start;
+ bool is_rtl = false;
hb_direction_t bidi_run_direction = HB_DIRECTION_INVALID;
- bool is_rtl = (ubidi_getVisualRun(bidi_iter, i, &_bidi_run_start, &_bidi_run_length) == UBIDI_LTR);
+ if (bidi_iter) {
+ is_rtl = (ubidi_getVisualRun(bidi_iter, i, &_bidi_run_start, &_bidi_run_length) == UBIDI_LTR);
+ }
switch (sd->orientation) {
case ORIENTATION_HORIZONTAL: {
if (is_rtl) {
@@ -5697,7 +5752,7 @@ bool TextServerAdvanced::_shaped_text_shape(const RID &p_shaped) {
gl.start = span.start;
gl.end = span.end;
gl.count = 1;
- gl.flags = GRAPHEME_IS_VALID | GRAPHEME_IS_VIRTUAL;
+ gl.flags = GRAPHEME_IS_VALID | GRAPHEME_IS_EMBEDDED_OBJECT;
if (sd->orientation == ORIENTATION_HORIZONTAL) {
gl.advance = sd->objects[span.embedded_key].rect.size.x;
} else {
diff --git a/modules/text_server_adv/text_server_adv.h b/modules/text_server_adv/text_server_adv.h
index ce08cf7694..dff87f3d74 100644
--- a/modules/text_server_adv/text_server_adv.h
+++ b/modules/text_server_adv/text_server_adv.h
@@ -475,6 +475,7 @@ class TextServerAdvanced : public TextServerExtension {
/* Shaped data */
TextServer::Direction para_direction = DIRECTION_LTR; // Detected text direction.
+ int base_para_direction = UBIDI_DEFAULT_LTR;
bool valid = false; // String is shaped.
bool line_breaks_valid = false; // Line and word break flags are populated (and virtual zero width spaces inserted).
bool justification_ops_valid = false; // Virtual elongation glyphs are added to the string.
@@ -514,7 +515,9 @@ class TextServerAdvanced : public TextServerExtension {
~ShapedTextDataAdvanced() {
for (int i = 0; i < bidi_iter.size(); i++) {
- ubidi_close(bidi_iter[i]);
+ if (bidi_iter[i]) {
+ ubidi_close(bidi_iter[i]);
+ }
}
if (script_iter) {
memdelete(script_iter);
diff --git a/modules/text_server_fb/text_server_fb.cpp b/modules/text_server_fb/text_server_fb.cpp
index 8687726287..eac5ba4a07 100644
--- a/modules/text_server_fb/text_server_fb.cpp
+++ b/modules/text_server_fb/text_server_fb.cpp
@@ -3664,7 +3664,7 @@ bool TextServerFallback::_shaped_text_shape(const RID &p_shaped) {
gl.end = span.end;
gl.count = 1;
gl.index = 0;
- gl.flags = GRAPHEME_IS_VALID | GRAPHEME_IS_VIRTUAL;
+ gl.flags = GRAPHEME_IS_VALID | GRAPHEME_IS_EMBEDDED_OBJECT;
if (sd->orientation == ORIENTATION_HORIZONTAL) {
gl.advance = sd->objects[span.embedded_key].rect.size.x;
} else {