diff options
Diffstat (limited to 'modules')
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 { |