feat: modules moved and engine moved to submodule

This commit is contained in:
Jan van der Weide 2025-04-12 18:40:44 +02:00
parent dfb5e645cd
commit c33d2130cc
5136 changed files with 225275 additions and 64485 deletions

View file

@ -107,7 +107,7 @@
<return type="Dictionary" />
<param index="0" name="instance" type="Object" />
<description>
Returns the passed [param instance] converted to a Dictionary. Can be useful for serializing.
Returns the passed [param instance] converted to a [Dictionary]. Can be useful for serializing.
[codeblock]
var foo = "bar"
func _ready():
@ -133,7 +133,7 @@
- A constant from the [enum Variant.Type] enumeration, for example [constant TYPE_INT].
- An [Object]-derived class which exists in [ClassDB], for example [Node].
- A [Script] (you can use any class, including inner one).
Unlike the right operand of the [code]is[/code] operator, [param type] can be a non-constant value. The [code]is[/code] operator supports more features (such as typed arrays). Use the operator instead of this method if you do not need dynamic type checking.
Unlike the right operand of the [code]is[/code] operator, [param type] can be a non-constant value. The [code]is[/code] operator supports more features (such as typed arrays). Use the operator instead of this method if you do not need to check the type dynamically.
[b]Examples:[/b]
[codeblock]
print(is_instance_of(a, TYPE_INT))

View file

@ -105,7 +105,7 @@ void GDScriptDocGen::_doctype_from_gdtype(const GDType &p_gdtype, String &r_type
return;
case GDType::SCRIPT:
if (p_gdtype.is_meta_type) {
r_type = p_gdtype.script_type.is_valid() ? p_gdtype.script_type->get_class() : Script::get_class_static();
r_type = p_gdtype.script_type.is_valid() ? p_gdtype.script_type->get_class_name() : Script::get_class_static();
return;
}
if (p_gdtype.script_type.is_valid()) {
@ -216,15 +216,15 @@ String GDScriptDocGen::_docvalue_from_variant(const Variant &p_variant, int p_re
} else {
result += "{";
List<Variant> keys;
dict.get_key_list(&keys);
LocalVector<Variant> keys = dict.get_key_list();
keys.sort_custom<StringLikeVariantOrder>();
for (List<Variant>::Element *E = keys.front(); E; E = E->next()) {
if (E->prev()) {
for (uint32_t i = 0; i < keys.size(); i++) {
const Variant &key = keys[i];
if (i > 0) {
result += ", ";
}
result += _docvalue_from_variant(E->get(), p_recursion_level + 1) + ": " + _docvalue_from_variant(dict[E->get()], p_recursion_level + 1);
result += _docvalue_from_variant(key, p_recursion_level + 1) + ": " + _docvalue_from_variant(dict[key], p_recursion_level + 1);
}
result += "}";

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef GDSCRIPT_DOCGEN_H
#define GDSCRIPT_DOCGEN_H
#pragma once
#include "../gdscript_parser.h"
@ -52,5 +51,3 @@ public:
static void doctype_from_gdtype(const GDType &p_gdtype, String &r_type, String &r_enum, bool p_is_return = false);
static String docvalue_from_expression(const GDP::ExpressionNode *p_expression);
};
#endif // GDSCRIPT_DOCGEN_H

View file

@ -150,6 +150,15 @@ Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting_impl(int p_l
break;
}
}
// "#region" and "#endregion" only highlighted if they're the first region on the line.
if (color_regions[c].type == ColorRegion::TYPE_CODE_REGION) {
Vector<String> str_stripped_split = str.strip_edges().split_spaces(1);
if (!str_stripped_split.is_empty() &&
str_stripped_split[0] != "#region" &&
str_stripped_split[0] != "#endregion") {
match = false;
}
}
if (!match) {
continue;
}
@ -777,8 +786,8 @@ void GDScriptSyntaxHighlighter::_update_cache() {
List<String> comments;
gdscript->get_comment_delimiters(&comments);
for (const String &comment : comments) {
String beg = comment.get_slice(" ", 0);
String end = comment.get_slice_count(" ") > 1 ? comment.get_slice(" ", 1) : String();
String beg = comment.get_slicec(' ', 0);
String end = comment.get_slice_count(" ") > 1 ? comment.get_slicec(' ', 1) : String();
add_color_region(ColorRegion::TYPE_COMMENT, beg, end, comment_color, end.is_empty());
}
@ -787,8 +796,8 @@ void GDScriptSyntaxHighlighter::_update_cache() {
List<String> doc_comments;
gdscript->get_doc_comment_delimiters(&doc_comments);
for (const String &doc_comment : doc_comments) {
String beg = doc_comment.get_slice(" ", 0);
String end = doc_comment.get_slice_count(" ") > 1 ? doc_comment.get_slice(" ", 1) : String();
String beg = doc_comment.get_slicec(' ', 0);
String end = doc_comment.get_slice_count(" ") > 1 ? doc_comment.get_slicec(' ', 1) : String();
add_color_region(ColorRegion::TYPE_COMMENT, beg, end, doc_comment_color, end.is_empty());
}

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef GDSCRIPT_HIGHLIGHTER_H
#define GDSCRIPT_HIGHLIGHTER_H
#pragma once
#include "editor/plugins/script_editor_plugin.h"
@ -116,5 +115,3 @@ public:
virtual Ref<EditorSyntaxHighlighter> _create() const override;
};
#endif // GDSCRIPT_HIGHLIGHTER_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef GDSCRIPT_TRANSLATION_PARSER_PLUGIN_H
#define GDSCRIPT_TRANSLATION_PARSER_PLUGIN_H
#pragma once
#include "../gdscript_parser.h"
#include "../gdscript_tokenizer.h"
@ -82,5 +81,3 @@ public:
GDScriptEditorTranslationParserPlugin();
};
#endif // GDSCRIPT_TRANSLATION_PARSER_PLUGIN_H

View file

@ -4,6 +4,16 @@
extends _BASE_
func _enable_plugin() -> void:
# Add autoloads here.
pass
func _disable_plugin() -> void:
# Remove autoloads here.
pass
func _enter_tree() -> void:
# Initialization of the plugin goes here.
pass

View file

@ -59,8 +59,6 @@
#include "editor/editor_paths.h"
#endif
#include <stdint.h>
///////////////////////////
GDScriptNativeClass::GDScriptNativeClass(const StringName &p_name) {
@ -1123,7 +1121,7 @@ Error GDScript::load_source_code(const String &p_path) {
w[len] = 0;
String s;
if (s.parse_utf8((const char *)w, len) != OK) {
if (s.append_utf8((const char *)w, len) != OK) {
ERR_FAIL_V_MSG(ERR_INVALID_DATA, "Script '" + p_path + "' contains invalid unicode (UTF-8), so it was not loaded. Please ensure that scripts are saved in valid UTF-8 unicode.");
}
@ -1625,6 +1623,27 @@ void GDScript::clear(ClearData *p_clear_data) {
}
}
void GDScript::cancel_pending_functions(bool warn) {
MutexLock lock(GDScriptLanguage::get_singleton()->mutex);
while (SelfList<GDScriptFunctionState> *E = pending_func_states.first()) {
// Order matters since clearing the stack may already cause
// the GDScriptFunctionState to be destroyed and thus removed from the list.
pending_func_states.remove(E);
GDScriptFunctionState *state = E->self();
#ifdef DEBUG_ENABLED
if (warn) {
WARN_PRINT("Canceling suspended execution of \"" + state->get_readable_function() + "\" due to a script reload.");
}
#endif
ObjectID state_id = state->get_instance_id();
state->_clear_connections();
if (ObjectDB::get_instance(state_id)) {
state->_clear_stack();
}
}
}
GDScript::~GDScript() {
if (destructing) {
return;
@ -1640,21 +1659,7 @@ GDScript::~GDScript() {
clear();
{
MutexLock lock(GDScriptLanguage::get_singleton()->mutex);
while (SelfList<GDScriptFunctionState> *E = pending_func_states.first()) {
// Order matters since clearing the stack may already cause
// the GDScriptFunctionState to be destroyed and thus removed from the list.
pending_func_states.remove(E);
GDScriptFunctionState *state = E->self();
ObjectID state_id = state->get_instance_id();
state->_clear_connections();
if (ObjectDB::get_instance(state_id)) {
state->_clear_stack();
}
}
}
cancel_pending_functions(false);
{
MutexLock lock(GDScriptLanguage::get_singleton()->mutex);
@ -2249,10 +2254,10 @@ void GDScriptLanguage::init() {
_add_global(StaticCString::create(CoreConstants::get_global_constant_name(i)), CoreConstants::get_global_constant_value(i));
}
_add_global(StaticCString::create("PI"), Math_PI);
_add_global(StaticCString::create("TAU"), Math_TAU);
_add_global(StaticCString::create("INF"), INFINITY);
_add_global(StaticCString::create("NAN"), NAN);
_add_global(StaticCString::create("PI"), Math::PI);
_add_global(StaticCString::create("TAU"), Math::TAU);
_add_global(StaticCString::create("INF"), Math::INF);
_add_global(StaticCString::create("NAN"), Math::NaN);
//populate native classes
@ -2699,8 +2704,7 @@ void GDScriptLanguage::reload_scripts(const Array &p_scripts, bool p_soft_reload
}
void GDScriptLanguage::reload_tool_script(const Ref<Script> &p_script, bool p_soft_reload) {
Array scripts;
scripts.push_back(p_script);
Array scripts = { p_script };
reload_scripts(scripts, p_soft_reload);
}
@ -2849,7 +2853,7 @@ String GDScriptLanguage::get_global_class_name(const String &p_path, String *r_b
while (subclass) {
if (subclass->extends_used) {
if (!subclass->extends_path.is_empty()) {
if (subclass->extends.size() == 0) {
if (subclass->extends.is_empty()) {
get_global_class_name(subclass->extends_path, r_base_type);
subclass = nullptr;
break;
@ -3066,6 +3070,62 @@ void ResourceFormatLoaderGDScript::get_dependencies(const String &p_path, List<S
}
}
void ResourceFormatLoaderGDScript::get_classes_used(const String &p_path, HashSet<StringName> *r_classes) {
Ref<GDScript> scr = ResourceLoader::load(p_path);
if (scr.is_null()) {
return;
}
const String source = scr->get_source_code();
GDScriptTokenizerText tokenizer;
tokenizer.set_source_code(source);
GDScriptTokenizer::Token current = tokenizer.scan();
while (current.type != GDScriptTokenizer::Token::TK_EOF) {
if (!current.is_identifier()) {
current = tokenizer.scan();
continue;
}
int insert_idx = 0;
for (int i = 0; i < current.start_line - 1; i++) {
insert_idx = source.find("\n", insert_idx) + 1;
}
// Insert the "cursor" character, needed for the lookup to work.
const String source_with_cursor = source.insert(insert_idx + current.start_column, String::chr(0xFFFF));
ScriptLanguage::LookupResult result;
if (scr->get_language()->lookup_code(source_with_cursor, current.get_identifier(), p_path, nullptr, result) == OK) {
if (!result.class_name.is_empty() && ClassDB::class_exists(result.class_name)) {
r_classes->insert(result.class_name);
}
if (result.type == ScriptLanguage::LOOKUP_RESULT_CLASS_PROPERTY) {
PropertyInfo prop;
if (ClassDB::get_property_info(result.class_name, result.class_member, &prop)) {
if (!prop.class_name.is_empty() && ClassDB::class_exists(prop.class_name)) {
r_classes->insert(prop.class_name);
}
if (!prop.hint_string.is_empty() && ClassDB::class_exists(prop.hint_string)) {
r_classes->insert(prop.hint_string);
}
}
} else if (result.type == ScriptLanguage::LOOKUP_RESULT_CLASS_METHOD) {
MethodInfo met;
if (ClassDB::get_method_info(result.class_name, result.class_member, &met)) {
if (!met.return_val.class_name.is_empty() && ClassDB::class_exists(met.return_val.class_name)) {
r_classes->insert(met.return_val.class_name);
}
if (!met.return_val.hint_string.is_empty() && ClassDB::class_exists(met.return_val.hint_string)) {
r_classes->insert(met.return_val.hint_string);
}
}
}
}
current = tokenizer.scan();
}
}
Error ResourceFormatSaverGDScript::save(const Ref<Resource> &p_resource, const String &p_path, uint32_t p_flags) {
Ref<GDScript> sqscr = p_resource;
ERR_FAIL_COND_V(sqscr.is_null(), ERR_INVALID_PARAMETER);

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef GDSCRIPT_H
#define GDSCRIPT_H
#pragma once
#include "gdscript_function.h"
@ -244,6 +243,9 @@ public:
void clear(GDScript::ClearData *p_clear_data = nullptr);
// Cancels all functions of the script that are are waiting to be resumed after using await.
void cancel_pending_functions(bool warn);
virtual bool is_valid() const override { return valid; }
virtual bool is_abstract() const override { return false; } // GDScript does not support abstract classes.
@ -655,6 +657,7 @@ public:
virtual bool handles_type(const String &p_type) const override;
virtual String get_resource_type(const String &p_path) const override;
virtual void get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types = false) override;
virtual void get_classes_used(const String &p_path, HashSet<StringName> *r_classes) override;
};
class ResourceFormatSaverGDScript : public ResourceFormatSaver {
@ -663,5 +666,3 @@ public:
virtual void get_recognized_extensions(const Ref<Resource> &p_resource, List<String> *p_extensions) const override;
virtual bool recognize(const Ref<Resource> &p_resource) const override;
};
#endif // GDSCRIPT_H

View file

@ -1640,13 +1640,12 @@ void GDScriptAnalyzer::resolve_annotation(GDScriptParser::AnnotationNode *p_anno
const MethodInfo &annotation_info = parser->valid_annotations[p_annotation->name].info;
const List<PropertyInfo>::Element *E = annotation_info.arguments.front();
for (int i = 0; i < p_annotation->arguments.size(); i++) {
for (int64_t i = 0, j = 0; i < p_annotation->arguments.size(); i++) {
GDScriptParser::ExpressionNode *argument = p_annotation->arguments[i];
const PropertyInfo &argument_info = E->get();
const PropertyInfo &argument_info = annotation_info.arguments[j];
if (E->next() != nullptr) {
E = E->next();
if (j + 1 < annotation_info.arguments.size()) {
++j;
}
reduce_expression(argument);
@ -1715,6 +1714,12 @@ void GDScriptAnalyzer::resolve_function_signature(GDScriptParser::FunctionNode *
static_context = p_function->is_static;
}
MethodInfo method_info;
method_info.name = function_name;
if (p_function->is_static) {
method_info.flags |= MethodFlags::METHOD_FLAG_STATIC;
}
GDScriptParser::DataType prev_datatype = p_function->get_datatype();
GDScriptParser::DataType resolving_datatype;
@ -1734,6 +1739,7 @@ void GDScriptAnalyzer::resolve_function_signature(GDScriptParser::FunctionNode *
for (int i = 0; i < p_function->parameters.size(); i++) {
resolve_parameter(p_function->parameters[i]);
method_info.arguments.push_back(p_function->parameters[i]->get_datatype().to_property_info(p_function->parameters[i]->identifier->name));
#ifdef DEBUG_ENABLED
if (p_function->parameters[i]->usages == 0 && !String(p_function->parameters[i]->identifier->name).begins_with("_")) {
parser->push_warning(p_function->parameters[i]->identifier, GDScriptWarning::UNUSED_PARAMETER, function_visible_name, p_function->parameters[i]->identifier->name);
@ -1797,7 +1803,7 @@ void GDScriptAnalyzer::resolve_function_signature(GDScriptParser::FunctionNode *
GDScriptParser::DataType parent_return_type;
List<GDScriptParser::DataType> parameters_types;
int default_par_count = 0;
BitField<MethodFlags> method_flags;
BitField<MethodFlags> method_flags = {};
StringName native_base;
if (!p_is_lambda && get_function_signature(p_function, false, base_type, function_name, parent_return_type, parameters_types, default_par_count, method_flags, &native_base)) {
bool valid = p_function->is_static == method_flags.has_flag(METHOD_FLAG_STATIC);
@ -1884,6 +1890,10 @@ void GDScriptAnalyzer::resolve_function_signature(GDScriptParser::FunctionNode *
}
#endif
method_info.default_arguments.append_array(p_function->default_arg_values);
method_info.return_val = p_function->get_datatype().to_property_info("");
p_function->info = method_info;
if (p_function->get_datatype().is_resolving()) {
p_function->set_datatype(prev_datatype);
}
@ -2158,7 +2168,7 @@ void GDScriptAnalyzer::resolve_for(GDScriptParser::ForNode *p_for) {
GDScriptParser::IdentifierNode *callee = static_cast<GDScriptParser::IdentifierNode *>(call->callee);
if (callee->name == "range") {
list_resolved = true;
if (call->arguments.size() < 1) {
if (call->arguments.is_empty()) {
push_error(R"*(Invalid call for "range()" function. Expected at least 1 argument, none given.)*", call->callee);
} else if (call->arguments.size() > 3) {
push_error(vformat(R"*(Invalid call for "range()" function. Expected at most 3 arguments, %d given.)*", call->arguments.size()), call->callee);
@ -2266,7 +2276,7 @@ void GDScriptAnalyzer::resolve_for(GDScriptParser::ForNode *p_for) {
GDScriptParser::DataType return_type;
List<GDScriptParser::DataType> par_types;
int default_arg_count = 0;
BitField<MethodFlags> method_flags;
BitField<MethodFlags> method_flags = {};
if (get_function_signature(p_for->list, false, list_type, CoreStringName(_iter_get), return_type, par_types, default_arg_count, method_flags)) {
variable_type = return_type;
variable_type.type_source = list_type.type_source;
@ -3323,28 +3333,24 @@ void GDScriptAnalyzer::reduce_call(GDScriptParser::CallNode *p_call, bool p_is_a
bool types_match = true;
{
List<PropertyInfo>::ConstIterator arg_itr = info.arguments.begin();
for (int i = 0; i < p_call->arguments.size(); ++arg_itr, ++i) {
GDScriptParser::DataType par_type = type_from_property(*arg_itr, true);
GDScriptParser::DataType arg_type = p_call->arguments[i]->get_datatype();
if (!is_type_compatible(par_type, arg_type, true)) {
types_match = false;
break;
for (int64_t i = 0; i < p_call->arguments.size(); ++i) {
GDScriptParser::DataType par_type = type_from_property(info.arguments[i], true);
GDScriptParser::DataType arg_type = p_call->arguments[i]->get_datatype();
if (!is_type_compatible(par_type, arg_type, true)) {
types_match = false;
break;
#ifdef DEBUG_ENABLED
} else {
if (par_type.builtin_type == Variant::INT && arg_type.builtin_type == Variant::FLOAT && builtin_type != Variant::INT) {
parser->push_warning(p_call, GDScriptWarning::NARROWING_CONVERSION, function_name);
}
#endif
} else {
if (par_type.builtin_type == Variant::INT && arg_type.builtin_type == Variant::FLOAT && builtin_type != Variant::INT) {
parser->push_warning(p_call, GDScriptWarning::NARROWING_CONVERSION, function_name);
}
#endif
}
}
if (types_match) {
List<PropertyInfo>::ConstIterator arg_itr = info.arguments.begin();
for (int i = 0; i < p_call->arguments.size(); ++arg_itr, ++i) {
GDScriptParser::DataType par_type = type_from_property(*arg_itr, true);
for (int64_t i = 0; i < p_call->arguments.size(); ++i) {
GDScriptParser::DataType par_type = type_from_property(info.arguments[i], true);
if (p_call->arguments[i]->is_constant) {
update_const_expression_builtin_type(p_call->arguments[i], par_type, "pass");
}
@ -3561,7 +3567,7 @@ void GDScriptAnalyzer::reduce_call(GDScriptParser::CallNode *p_call, bool p_is_a
}
int default_arg_count = 0;
BitField<MethodFlags> method_flags;
BitField<MethodFlags> method_flags = {};
GDScriptParser::DataType return_type;
List<GDScriptParser::DataType> par_types;
@ -5574,7 +5580,7 @@ GDScriptParser::DataType GDScriptAnalyzer::type_from_property(const PropertyInfo
result.set_container_element_type(0, elem_type);
} else if (p_property.type == Variant::DICTIONARY && p_property.hint == PROPERTY_HINT_DICTIONARY_TYPE) {
// Check element type.
StringName key_elem_type_name = p_property.hint_string.get_slice(";", 0);
StringName key_elem_type_name = p_property.hint_string.get_slicec(';', 0);
GDScriptParser::DataType key_elem_type;
key_elem_type.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT;
@ -5599,7 +5605,7 @@ GDScriptParser::DataType GDScriptAnalyzer::type_from_property(const PropertyInfo
}
key_elem_type.is_constant = false;
StringName value_elem_type_name = p_property.hint_string.get_slice(";", 1);
StringName value_elem_type_name = p_property.hint_string.get_slicec(';', 1);
GDScriptParser::DataType value_elem_type;
value_elem_type.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT;

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef GDSCRIPT_ANALYZER_H
#define GDSCRIPT_ANALYZER_H
#pragma once
#include "gdscript_cache.h"
#include "gdscript_parser.h"
@ -167,5 +166,3 @@ public:
GDScriptAnalyzer(GDScriptParser *p_parser);
};
#endif // GDSCRIPT_ANALYZER_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef GDSCRIPT_BYTE_CODEGEN_H
#define GDSCRIPT_BYTE_CODEGEN_H
#pragma once
#include "gdscript_codegen.h"
#include "gdscript_function.h"
@ -552,5 +551,3 @@ public:
virtual ~GDScriptByteCodeGenerator();
};
#endif // GDSCRIPT_BYTE_CODEGEN_H

View file

@ -189,7 +189,7 @@ void GDScriptCache::remove_script(const String &p_path) {
if (HashMap<String, Vector<ObjectID>>::Iterator E = singleton->abandoned_parser_map.find(p_path)) {
for (ObjectID parser_ref_id : E->value) {
Ref<GDScriptParserRef> parser_ref{ ObjectDB::get_instance(parser_ref_id) };
Ref<GDScriptParserRef> parser_ref = { ObjectDB::get_instance(parser_ref_id) };
if (parser_ref.is_valid()) {
parser_ref->clear();
}
@ -275,7 +275,7 @@ String GDScriptCache::get_source_code(const String &p_path) {
source_file.write[len] = 0;
String source;
if (source.parse_utf8((const char *)source_file.ptr(), len) != OK) {
if (source.append_utf8((const char *)source_file.ptr(), len) != OK) {
ERR_FAIL_V_MSG("", "Script '" + p_path + "' contains invalid unicode (UTF-8), so it was not loaded. Please ensure that scripts are saved in valid UTF-8 unicode.");
}
return source;
@ -460,7 +460,7 @@ void GDScriptCache::clear() {
for (const KeyValue<String, Vector<ObjectID>> &KV : singleton->abandoned_parser_map) {
for (ObjectID parser_ref_id : KV.value) {
Ref<GDScriptParserRef> parser_ref{ ObjectDB::get_instance(parser_ref_id) };
Ref<GDScriptParserRef> parser_ref = { ObjectDB::get_instance(parser_ref_id) };
if (parser_ref.is_valid()) {
parser_ref->clear();
}
@ -485,6 +485,7 @@ void GDScriptCache::clear() {
parser_map_refs.clear();
singleton->shallow_gdscript_cache.clear();
singleton->full_gdscript_cache.clear();
singleton->static_gdscript_cache.clear();
}
GDScriptCache::GDScriptCache() {

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef GDSCRIPT_CACHE_H
#define GDSCRIPT_CACHE_H
#pragma once
#include "gdscript.h"
@ -42,6 +41,8 @@ class GDScriptAnalyzer;
class GDScriptParser;
class GDScriptParserRef : public RefCounted {
GDSOFTCLASS(GDScriptParserRef, RefCounted);
public:
enum Status {
EMPTY,
@ -122,5 +123,3 @@ public:
GDScriptCache();
~GDScriptCache();
};
#endif // GDSCRIPT_CACHE_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef GDSCRIPT_CODEGEN_H
#define GDSCRIPT_CODEGEN_H
#pragma once
#include "gdscript_function.h"
#include "gdscript_utility_functions.h"
@ -165,5 +164,3 @@ public:
virtual ~GDScriptCodeGenerator() {}
};
#endif // GDSCRIPT_CODEGEN_H

View file

@ -129,7 +129,7 @@ GDScriptDataType GDScriptCompiler::_gdtype_from_datatype(const GDScriptParser::D
if (p_handle_metatype && p_datatype.is_meta_type) {
result.kind = GDScriptDataType::NATIVE;
result.builtin_type = Variant::OBJECT;
result.native_type = p_datatype.script_type.is_valid() ? p_datatype.script_type->get_class() : Script::get_class_static();
result.native_type = p_datatype.script_type.is_valid() ? p_datatype.script_type->get_class_name() : Script::get_class_static();
break;
}
@ -243,9 +243,8 @@ static bool _can_use_validate_call(const MethodBind *p_method, const Vector<GDSc
}
MethodInfo info;
ClassDB::get_method_info(p_method->get_instance_class(), p_method->get_name(), &info);
int i = 0;
for (List<PropertyInfo>::ConstIterator itr = info.arguments.begin(); itr != info.arguments.end(); ++itr, ++i) {
if (!_is_exact_type(*itr, p_arguments[i].type)) {
for (int64_t i = 0; i < info.arguments.size(); ++i) {
if (!_is_exact_type(info.arguments[i], p_arguments[i].type)) {
return false;
}
}
@ -2660,6 +2659,8 @@ Error GDScriptCompiler::_prepare_compilation(GDScript *p_script, const GDScriptP
p_script->clearing = true;
p_script->cancel_pending_functions(true);
p_script->native = Ref<GDScriptNativeClass>();
p_script->base = Ref<GDScript>();
p_script->_base = nullptr;

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef GDSCRIPT_COMPILER_H
#define GDSCRIPT_COMPILER_H
#pragma once
#include "gdscript.h"
#include "gdscript_codegen.h"
@ -186,5 +185,3 @@ public:
GDScriptCompiler();
};
#endif // GDSCRIPT_COMPILER_H

View file

@ -488,22 +488,22 @@ void GDScriptLanguage::get_public_functions(List<MethodInfo> *p_functions) const
void GDScriptLanguage::get_public_constants(List<Pair<String, Variant>> *p_constants) const {
Pair<String, Variant> pi;
pi.first = "PI";
pi.second = Math_PI;
pi.second = Math::PI;
p_constants->push_back(pi);
Pair<String, Variant> tau;
tau.first = "TAU";
tau.second = Math_TAU;
tau.second = Math::TAU;
p_constants->push_back(tau);
Pair<String, Variant> infinity;
infinity.first = "INF";
infinity.second = INFINITY;
infinity.second = Math::INF;
p_constants->push_back(infinity);
Pair<String, Variant> nan;
nan.first = "NAN";
nan.second = NAN;
nan.second = Math::NaN;
p_constants->push_back(nan);
}
@ -530,9 +530,9 @@ String GDScriptLanguage::make_function(const String &p_class, const String &p_na
if (i > 0) {
s += ", ";
}
s += p_args[i].get_slice(":", 0);
s += p_args[i].get_slicec(':', 0);
if (th) {
String type = p_args[i].get_slice(":", 1);
String type = p_args[i].get_slicec(':', 1);
if (!type.is_empty()) {
s += ": " + type;
}
@ -722,8 +722,8 @@ static String _get_visual_datatype(const PropertyInfo &p_info, bool p_is_arg, co
} else if (p_info.type == Variant::ARRAY && p_info.hint == PROPERTY_HINT_ARRAY_TYPE && !p_info.hint_string.is_empty()) {
return "Array[" + _trim_parent_class(p_info.hint_string, p_base_class) + "]";
} else if (p_info.type == Variant::DICTIONARY && p_info.hint == PROPERTY_HINT_DICTIONARY_TYPE && !p_info.hint_string.is_empty()) {
const String key = p_info.hint_string.get_slice(";", 0);
const String value = p_info.hint_string.get_slice(";", 1);
const String key = p_info.hint_string.get_slicec(';', 0);
const String value = p_info.hint_string.get_slicec(';', 1);
return "Dictionary[" + _trim_parent_class(key, p_base_class) + ", " + _trim_parent_class(value, p_base_class) + "]";
} else if (p_info.type == Variant::NIL) {
if (p_is_arg || (p_info.usage & PROPERTY_USAGE_NIL_IS_VARIANT)) {
@ -921,8 +921,8 @@ static void _find_annotation_arguments(const GDScriptParser::AnnotationNode *p_a
node.insert_text = node.display.quote(p_quote_style);
r_result.insert(node.display, node);
List<StringName> native_classes;
ClassDB::get_inheriters_from_class("Node", &native_classes);
LocalVector<StringName> native_classes;
ClassDB::get_inheriters_from_class("Node", native_classes);
for (const StringName &E : native_classes) {
if (!ClassDB::is_class_exposed(E)) {
continue;
@ -1091,9 +1091,9 @@ static void _find_identifiers_in_suite(const GDScriptParser::SuiteNode *p_suite,
}
}
static void _find_identifiers_in_base(const GDScriptCompletionIdentifier &p_base, bool p_only_functions, bool p_types_only, HashMap<String, ScriptLanguage::CodeCompletionOption> &r_result, int p_recursion_depth);
static void _find_identifiers_in_base(const GDScriptCompletionIdentifier &p_base, bool p_only_functions, bool p_types_only, bool p_add_braces, HashMap<String, ScriptLanguage::CodeCompletionOption> &r_result, int p_recursion_depth);
static void _find_identifiers_in_class(const GDScriptParser::ClassNode *p_class, bool p_only_functions, bool p_types_only, bool p_static, bool p_parent_only, HashMap<String, ScriptLanguage::CodeCompletionOption> &r_result, int p_recursion_depth) {
static void _find_identifiers_in_class(const GDScriptParser::ClassNode *p_class, bool p_only_functions, bool p_types_only, bool p_static, bool p_parent_only, bool p_add_braces, HashMap<String, ScriptLanguage::CodeCompletionOption> &r_result, int p_recursion_depth) {
ERR_FAIL_COND(p_recursion_depth > COMPLETION_RECURSION_LIMIT);
if (!p_parent_only) {
@ -1147,12 +1147,14 @@ static void _find_identifiers_in_class(const GDScriptParser::ClassNode *p_class,
continue;
}
option = ScriptLanguage::CodeCompletionOption(member.function->identifier->name, ScriptLanguage::CODE_COMPLETION_KIND_FUNCTION, location);
if (member.function->parameters.size() > 0 || (member.function->info.flags & METHOD_FLAG_VARARG)) {
option.insert_text += "(";
option.display += U"(\u2026)";
} else {
option.insert_text += "()";
option.display += "()";
if (p_add_braces) {
if (member.function->parameters.size() > 0 || (member.function->info.flags & METHOD_FLAG_VARARG)) {
option.insert_text += "(";
option.display += U"(\u2026)";
} else {
option.insert_text += "()";
option.display += "()";
}
}
break;
case GDScriptParser::ClassNode::Member::SIGNAL:
@ -1183,25 +1185,27 @@ static void _find_identifiers_in_class(const GDScriptParser::ClassNode *p_class,
base_type.type = p_class->base_type;
base_type.type.is_meta_type = p_static;
_find_identifiers_in_base(base_type, p_only_functions, p_types_only, r_result, p_recursion_depth + 1);
_find_identifiers_in_base(base_type, p_only_functions, p_types_only, p_add_braces, r_result, p_recursion_depth + 1);
}
static void _find_identifiers_in_base(const GDScriptCompletionIdentifier &p_base, bool p_only_functions, bool p_types_only, HashMap<String, ScriptLanguage::CodeCompletionOption> &r_result, int p_recursion_depth) {
static void _find_identifiers_in_base(const GDScriptCompletionIdentifier &p_base, bool p_only_functions, bool p_types_only, bool p_add_braces, HashMap<String, ScriptLanguage::CodeCompletionOption> &r_result, int p_recursion_depth) {
ERR_FAIL_COND(p_recursion_depth > COMPLETION_RECURSION_LIMIT);
GDScriptParser::DataType base_type = p_base.type;
if (!p_types_only && base_type.is_meta_type && base_type.kind != GDScriptParser::DataType::BUILTIN && base_type.kind != GDScriptParser::DataType::ENUM) {
ScriptLanguage::CodeCompletionOption option("new", ScriptLanguage::CODE_COMPLETION_KIND_FUNCTION, ScriptLanguage::LOCATION_LOCAL);
option.insert_text += "(";
option.display += U"(\u2026)";
if (p_add_braces) {
option.insert_text += "(";
option.display += U"(\u2026)";
}
r_result.insert(option.display, option);
}
while (!base_type.has_no_type()) {
switch (base_type.kind) {
case GDScriptParser::DataType::CLASS: {
_find_identifiers_in_class(base_type.class_type, p_only_functions, p_types_only, base_type.is_meta_type, false, r_result, p_recursion_depth);
_find_identifiers_in_class(base_type.class_type, p_only_functions, p_types_only, base_type.is_meta_type, false, p_add_braces, r_result, p_recursion_depth);
// This already finds all parent identifiers, so we are done.
base_type = GDScriptParser::DataType();
} break;
@ -1252,12 +1256,14 @@ static void _find_identifiers_in_base(const GDScriptCompletionIdentifier &p_base
}
int location = p_recursion_depth + _get_method_location(scr->get_class_name(), E.name);
ScriptLanguage::CodeCompletionOption option(E.name, ScriptLanguage::CODE_COMPLETION_KIND_FUNCTION, location);
if (E.arguments.size() || (E.flags & METHOD_FLAG_VARARG)) {
option.insert_text += "(";
option.display += U"(\u2026)";
} else {
option.insert_text += "()";
option.display += "()";
if (p_add_braces) {
if (E.arguments.size() || (E.flags & METHOD_FLAG_VARARG)) {
option.insert_text += "(";
option.display += U"(\u2026)";
} else {
option.insert_text += "()";
option.display += "()";
}
}
r_result.insert(option.display, option);
}
@ -1340,12 +1346,14 @@ static void _find_identifiers_in_base(const GDScriptCompletionIdentifier &p_base
}
int location = p_recursion_depth + _get_method_location(type, E.name);
ScriptLanguage::CodeCompletionOption option(E.name, ScriptLanguage::CODE_COMPLETION_KIND_FUNCTION, location);
if (E.arguments.size() || (E.flags & METHOD_FLAG_VARARG)) {
option.insert_text += "(";
option.display += U"(\u2026)";
} else {
option.insert_text += "()";
option.display += "()";
if (p_add_braces) {
if (E.arguments.size() || (E.flags & METHOD_FLAG_VARARG)) {
option.insert_text += "(";
option.display += U"(\u2026)";
} else {
option.insert_text += "()";
option.display += "()";
}
}
r_result.insert(option.display, option);
}
@ -1413,12 +1421,14 @@ static void _find_identifiers_in_base(const GDScriptCompletionIdentifier &p_base
continue;
}
ScriptLanguage::CodeCompletionOption option(E.name, ScriptLanguage::CODE_COMPLETION_KIND_FUNCTION, location);
if (E.arguments.size() || (E.flags & METHOD_FLAG_VARARG)) {
option.insert_text += "(";
option.display += U"(\u2026)";
} else {
option.insert_text += "()";
option.display += "()";
if (p_add_braces) {
if (E.arguments.size() || (E.flags & METHOD_FLAG_VARARG)) {
option.insert_text += "(";
option.display += U"(\u2026)";
} else {
option.insert_text += "()";
option.display += "()";
}
}
r_result.insert(option.display, option);
}
@ -1432,14 +1442,14 @@ static void _find_identifiers_in_base(const GDScriptCompletionIdentifier &p_base
}
}
static void _find_identifiers(const GDScriptParser::CompletionContext &p_context, bool p_only_functions, HashMap<String, ScriptLanguage::CodeCompletionOption> &r_result, int p_recursion_depth) {
static void _find_identifiers(const GDScriptParser::CompletionContext &p_context, bool p_only_functions, bool p_add_braces, HashMap<String, ScriptLanguage::CodeCompletionOption> &r_result, int p_recursion_depth) {
if (!p_only_functions && p_context.current_suite) {
// This includes function parameters, since they are also locals.
_find_identifiers_in_suite(p_context.current_suite, r_result);
}
if (p_context.current_class) {
_find_identifiers_in_class(p_context.current_class, p_only_functions, false, (!p_context.current_function || p_context.current_function->is_static), false, r_result, p_recursion_depth);
_find_identifiers_in_class(p_context.current_class, p_only_functions, false, (!p_context.current_function || p_context.current_function->is_static), false, p_add_braces, r_result, p_recursion_depth);
}
List<StringName> functions;
@ -1448,12 +1458,14 @@ static void _find_identifiers(const GDScriptParser::CompletionContext &p_context
for (const StringName &E : functions) {
MethodInfo function = GDScriptUtilityFunctions::get_function_info(E);
ScriptLanguage::CodeCompletionOption option(String(E), ScriptLanguage::CODE_COMPLETION_KIND_FUNCTION);
if (function.arguments.size() || (function.flags & METHOD_FLAG_VARARG)) {
option.insert_text += "(";
option.display += U"(\u2026)";
} else {
option.insert_text += "()";
option.display += "()";
if (p_add_braces) {
if (function.arguments.size() || (function.flags & METHOD_FLAG_VARARG)) {
option.insert_text += "(";
option.display += U"(\u2026)";
} else {
option.insert_text += "()";
option.display += "()";
}
}
r_result.insert(option.display, option);
}
@ -1499,8 +1511,10 @@ static void _find_identifiers(const GDScriptParser::CompletionContext &p_context
const char **kwa = _keywords_with_args;
while (*kwa) {
ScriptLanguage::CodeCompletionOption option(*kwa, ScriptLanguage::CODE_COMPLETION_KIND_FUNCTION);
option.insert_text += "(";
option.display += U"(\u2026)";
if (p_add_braces) {
option.insert_text += "(";
option.display += U"(\u2026)";
}
r_result.insert(option.display, option);
kwa++;
}
@ -1508,10 +1522,13 @@ static void _find_identifiers(const GDScriptParser::CompletionContext &p_context
List<StringName> utility_func_names;
Variant::get_utility_function_list(&utility_func_names);
for (List<StringName>::Element *E = utility_func_names.front(); E; E = E->next()) {
ScriptLanguage::CodeCompletionOption option(E->get(), ScriptLanguage::CODE_COMPLETION_KIND_FUNCTION);
for (const StringName &util_func_name : utility_func_names) {
ScriptLanguage::CodeCompletionOption option(util_func_name, ScriptLanguage::CODE_COMPLETION_KIND_FUNCTION);
option.insert_text += "(";
option.display += U"(\u2026)"; // As all utility functions contain an argument or more, this is hardcoded here.
if (p_add_braces) {
option.insert_text += "(";
option.display += U"(\u2026)"; // As all utility functions contain an argument or more, this is hardcoded here.
}
r_result.insert(option.display, option);
}
@ -1621,6 +1638,16 @@ static GDScriptCompletionIdentifier _type_from_property(const PropertyInfo &p_pr
return ci;
}
static GDScriptCompletionIdentifier _callable_type_from_method_info(const MethodInfo &p_method) {
GDScriptCompletionIdentifier ci;
ci.type.kind = GDScriptParser::DataType::BUILTIN;
ci.type.builtin_type = Variant::CALLABLE;
ci.type.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT;
ci.type.is_constant = true;
ci.type.method_info = p_method;
return ci;
}
#define MAX_COMPLETION_RECURSION 100
struct RecursionCheck {
int *counter;
@ -1866,7 +1893,7 @@ static bool _guess_expression_type(GDScriptParser::CompletionContext &p_context,
if (all_is_const && call->function_name == SNAME("get_node") && ClassDB::is_parent_class(native_type.native_type, SNAME("Node")) && args.size()) {
String arg1 = args[0];
if (arg1.begins_with("/root/")) {
String which = arg1.get_slice("/", 2);
String which = arg1.get_slicec('/', 2);
if (!which.is_empty()) {
// Try singletons first
if (GDScriptLanguage::get_singleton()->get_named_globals_map().has(which)) {
@ -2458,14 +2485,13 @@ static bool _guess_identifier_type_from_base(GDScriptParser::CompletionContext &
r_type.type.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT;
r_type.type.kind = GDScriptParser::DataType::BUILTIN;
r_type.type.builtin_type = Variant::SIGNAL;
r_type.type.method_info = member.signal->method_info;
return true;
case GDScriptParser::ClassNode::Member::FUNCTION:
if (is_static && !member.function->is_static) {
return false;
}
r_type.type.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT;
r_type.type.kind = GDScriptParser::DataType::BUILTIN;
r_type.type.builtin_type = Variant::CALLABLE;
r_type = _callable_type_from_method_info(member.function->info);
return true;
case GDScriptParser::ClassNode::Member::CLASS:
r_type.type.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT;
@ -2505,6 +2531,12 @@ static bool _guess_identifier_type_from_base(GDScriptParser::CompletionContext &
}
}
if (scr->has_method(p_identifier)) {
MethodInfo mi = scr->get_method_info(p_identifier);
r_type = _callable_type_from_method_info(mi);
return true;
}
Ref<Script> parent = scr->get_base_script();
if (parent.is_valid()) {
base_type.script_type = parent;
@ -2539,23 +2571,35 @@ static bool _guess_identifier_type_from_base(GDScriptParser::CompletionContext &
return true;
}
}
MethodInfo method;
if (ClassDB::get_method_info(class_name, p_identifier, &method)) {
r_type = _callable_type_from_method_info(method);
return true;
}
return false;
} break;
case GDScriptParser::DataType::BUILTIN: {
Callable::CallError err;
Variant tmp;
Variant::construct(base_type.builtin_type, tmp, nullptr, 0, err);
if (err.error != Callable::CallError::CALL_OK) {
return false;
}
bool valid = false;
Variant res = tmp.get(p_identifier, &valid);
if (valid) {
r_type = _type_from_variant(res, p_context);
r_type.value = Variant();
r_type.type.is_constant = false;
if (Variant::has_builtin_method(base_type.builtin_type, p_identifier)) {
r_type = _callable_type_from_method_info(Variant::get_builtin_method_info(base_type.builtin_type, p_identifier));
return true;
} else {
Callable::CallError err;
Variant tmp;
Variant::construct(base_type.builtin_type, tmp, nullptr, 0, err);
if (err.error != Callable::CallError::CALL_OK) {
return false;
}
bool valid = false;
Variant res = tmp.get(p_identifier, &valid);
if (valid) {
r_type = _type_from_variant(res, p_context);
r_type.value = Variant();
r_type.type.is_constant = false;
return true;
}
}
return false;
} break;
@ -2726,6 +2770,22 @@ static bool _guess_method_return_type_from_base(GDScriptParser::CompletionContex
return false;
}
static bool _guess_expecting_callable(GDScriptParser::CompletionContext &p_context) {
if (p_context.call.call != nullptr && p_context.call.call->type == GDScriptParser::Node::CALL) {
GDScriptParser::CallNode *call_node = static_cast<GDScriptParser::CallNode *>(p_context.call.call);
GDScriptCompletionIdentifier ci;
if (_guess_expression_type(p_context, call_node->callee, ci)) {
if (ci.type.kind == GDScriptParser::DataType::BUILTIN && ci.type.builtin_type == Variant::CALLABLE) {
if (p_context.call.argument >= 0 && p_context.call.argument < ci.type.method_info.arguments.size()) {
return ci.type.method_info.arguments.get(p_context.call.argument).type == Variant::CALLABLE;
}
}
}
}
return false;
}
static void _find_enumeration_candidates(GDScriptParser::CompletionContext &p_context, const String &p_enum_hint, HashMap<String, ScriptLanguage::CodeCompletionOption> &r_result) {
if (!p_enum_hint.contains_char('.')) {
// Global constant or in the current class.
@ -2745,8 +2805,8 @@ static void _find_enumeration_candidates(GDScriptParser::CompletionContext &p_co
}
}
} else {
String class_name = p_enum_hint.get_slice(".", 0);
String enum_name = p_enum_hint.get_slice(".", 1);
String class_name = p_enum_hint.get_slicec('.', 0);
String enum_name = p_enum_hint.get_slicec('.', 1);
if (!ClassDB::class_exists(class_name)) {
return;
@ -2839,9 +2899,9 @@ static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, c
// Handle user preference.
if (opt.is_quoted()) {
opt = opt.unquote().quote(quote_style);
if (use_string_names && info.arguments.get(p_argidx).type == Variant::STRING_NAME) {
if (use_string_names && info.arguments[p_argidx].type == Variant::STRING_NAME) {
opt = "&" + opt;
} else if (use_node_paths && info.arguments.get(p_argidx).type == Variant::NODE_PATH) {
} else if (use_node_paths && info.arguments[p_argidx].type == Variant::NODE_PATH) {
opt = "^" + opt;
}
}
@ -2852,7 +2912,7 @@ static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, c
}
if (p_argidx < method_args) {
const PropertyInfo &arg_info = info.arguments.get(p_argidx);
const PropertyInfo &arg_info = info.arguments[p_argidx];
if (arg_info.usage & (PROPERTY_USAGE_CLASS_IS_ENUM | PROPERTY_USAGE_CLASS_IS_BITFIELD)) {
_find_enumeration_candidates(p_context, arg_info.class_name, r_result);
}
@ -2949,7 +3009,7 @@ static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, c
if (!s.begins_with("autoload/")) {
continue;
}
String name = s.get_slice("/", 1);
String name = s.get_slicec('/', 1);
String path = ("/root/" + name).quote(quote_style);
if (use_node_paths) {
path = "^" + path;
@ -2968,7 +3028,7 @@ static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, c
if (!s.begins_with("input/")) {
continue;
}
String name = s.get_slice("/", 1).quote(quote_style);
String name = s.get_slicec('/', 1).quote(quote_style);
if (use_string_names) {
name = "&" + name;
}
@ -3267,10 +3327,12 @@ static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, c
for (const StringName &E : methods) {
if (Variant::is_builtin_method_static(completion_context.builtin_type, E)) {
ScriptLanguage::CodeCompletionOption option(E, ScriptLanguage::CODE_COMPLETION_KIND_FUNCTION);
if (Variant::get_builtin_method_argument_count(completion_context.builtin_type, E) > 0 || Variant::is_builtin_method_vararg(completion_context.builtin_type, E)) {
option.insert_text += "(";
} else {
option.insert_text += "()";
if (!_guess_expecting_callable(completion_context)) {
if (Variant::get_builtin_method_argument_count(completion_context.builtin_type, E) > 0 || Variant::is_builtin_method_vararg(completion_context.builtin_type, E)) {
option.insert_text += "(";
} else {
option.insert_text += "()";
}
}
options.insert(option.display, option);
}
@ -3328,7 +3390,7 @@ static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, c
break;
}
if (!_guess_expression_type(completion_context, static_cast<const GDScriptParser::AssignmentNode *>(completion_context.node)->assignee, type)) {
_find_identifiers(completion_context, false, options, 0);
_find_identifiers(completion_context, false, true, options, 0);
r_forced = true;
break;
}
@ -3337,7 +3399,7 @@ static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, c
_find_enumeration_candidates(completion_context, type.enumeration, options);
r_forced = options.size() > 0;
} else {
_find_identifiers(completion_context, false, options, 0);
_find_identifiers(completion_context, false, true, options, 0);
r_forced = true;
}
} break;
@ -3345,7 +3407,7 @@ static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, c
is_function = true;
[[fallthrough]];
case GDScriptParser::COMPLETION_IDENTIFIER: {
_find_identifiers(completion_context, is_function, options, 0);
_find_identifiers(completion_context, is_function, !_guess_expecting_callable(completion_context), options, 0);
} break;
case GDScriptParser::COMPLETION_ATTRIBUTE_METHOD:
is_function = true;
@ -3360,7 +3422,7 @@ static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, c
break;
}
_find_identifiers_in_base(base, is_function, false, options, 0);
_find_identifiers_in_base(base, is_function, false, !_guess_expecting_callable(completion_context), options, 0);
}
} break;
case GDScriptParser::COMPLETION_SUBSCRIPT: {
@ -3380,20 +3442,20 @@ static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, c
}
}
if (!subscript->index || subscript->index->type != GDScriptParser::Node::LITERAL) {
_find_identifiers(completion_context, false, options, 0);
_find_identifiers(completion_context, false, !_guess_expecting_callable(completion_context), options, 0);
}
} else if (res) {
if (!subscript->is_attribute) {
// Quote the options if they are not accessed as attribute.
HashMap<String, ScriptLanguage::CodeCompletionOption> opt;
_find_identifiers_in_base(base, false, false, opt, 0);
_find_identifiers_in_base(base, false, false, false, opt, 0);
for (const KeyValue<String, CodeCompletionOption> &E : opt) {
ScriptLanguage::CodeCompletionOption option(E.value.insert_text.quote(quote_style), E.value.kind, E.value.location);
options.insert(option.display, option);
}
} else {
_find_identifiers_in_base(base, false, false, options, 0);
_find_identifiers_in_base(base, false, false, !_guess_expecting_callable(completion_context), options, 0);
}
}
} break;
@ -3437,7 +3499,7 @@ static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, c
}
if (found) {
_find_identifiers_in_base(base, false, true, options, 0);
_find_identifiers_in_base(base, false, true, true, options, 0);
}
r_forced = true;
} break;
@ -3491,21 +3553,21 @@ static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, c
for (const MethodInfo &mi : virtual_methods) {
String method_hint = mi.name;
if (method_hint.contains_char(':')) {
method_hint = method_hint.get_slice(":", 0);
method_hint = method_hint.get_slicec(':', 0);
}
method_hint += "(";
for (List<PropertyInfo>::ConstIterator arg_itr = mi.arguments.begin(); arg_itr != mi.arguments.end(); ++arg_itr) {
if (arg_itr != mi.arguments.begin()) {
for (int64_t i = 0; i < mi.arguments.size(); ++i) {
if (i > 0) {
method_hint += ", ";
}
String arg = arg_itr->name;
String arg = mi.arguments[i].name;
if (arg.contains_char(':')) {
arg = arg.substr(0, arg.find_char(':'));
}
method_hint += arg;
if (use_type_hint) {
method_hint += ": " + _get_visual_datatype(*arg_itr, true, class_name);
method_hint += ": " + _get_visual_datatype(mi.arguments[i], true, class_name);
}
}
method_hint += ")";
@ -3578,7 +3640,7 @@ static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, c
if (!completion_context.current_class) {
break;
}
_find_identifiers_in_class(completion_context.current_class, true, false, false, true, options, 0);
_find_identifiers_in_class(completion_context.current_class, true, false, false, true, !_guess_expecting_callable(completion_context), options, 0);
} break;
}
@ -3630,7 +3692,7 @@ void GDScriptLanguage::auto_indent_code(String &p_code, int p_from_line, int p_t
}
}
String st = l.substr(tc, l.length()).strip_edges();
String st = l.substr(tc).strip_edges();
if (st.is_empty() || st.begins_with("#")) {
continue; //ignore!
}

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef GDSCRIPT_FUNCTION_H
#define GDSCRIPT_FUNCTION_H
#pragma once
#include "gdscript_utility_functions.h"
@ -616,11 +615,16 @@ public:
bool is_valid(bool p_extended_check = false) const;
Variant resume(const Variant &p_arg = Variant());
#ifdef DEBUG_ENABLED
// Returns a human-readable representation of the function.
String get_readable_function() {
return state.function_name;
}
#endif
void _clear_stack();
void _clear_connections();
GDScriptFunctionState();
~GDScriptFunctionState();
};
#endif // GDSCRIPT_FUNCTION_H

View file

@ -45,7 +45,9 @@ bool GDScriptLambdaCallable::compare_less(const CallableCustom *p_a, const Calla
}
bool GDScriptLambdaCallable::is_valid() const {
return CallableCustom::is_valid() && function != nullptr;
// Don't need to call CallableCustom::is_valid():
// It just verifies our script exists, which we know to be true because it is RefCounted.
return function != nullptr;
}
uint32_t GDScriptLambdaCallable::hash() const {

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef GDSCRIPT_LAMBDA_CALLABLE_H
#define GDSCRIPT_LAMBDA_CALLABLE_H
#pragma once
#include "gdscript.h"
@ -97,5 +96,3 @@ public:
GDScriptLambdaSelfCallable(Object *p_self, GDScriptFunction *p_function, const Vector<Variant> &p_captures);
virtual ~GDScriptLambdaSelfCallable() = default;
};
#endif // GDSCRIPT_LAMBDA_CALLABLE_H

View file

@ -269,6 +269,9 @@ void GDScriptParser::override_completion_context(const Node *p_for_node, Complet
context.current_argument = p_argument;
context.node = p_node;
context.parser = this;
if (!completion_call_stack.is_empty()) {
context.call = completion_call_stack.back()->get();
}
completion_context = context;
}
@ -288,6 +291,9 @@ void GDScriptParser::make_completion_context(CompletionType p_type, Node *p_node
context.current_argument = p_argument;
context.node = p_node;
context.parser = this;
if (!completion_call_stack.is_empty()) {
context.call = completion_call_stack.back()->get();
}
completion_context = context;
}
@ -306,6 +312,9 @@ void GDScriptParser::make_completion_context(CompletionType p_type, Variant::Typ
context.current_line = tokenizer->get_cursor_line();
context.builtin_type = p_builtin_type;
context.parser = this;
if (!completion_call_stack.is_empty()) {
context.call = completion_call_stack.back()->get();
}
completion_context = context;
}
@ -317,9 +326,6 @@ void GDScriptParser::push_completion_call(Node *p_call) {
call.call = p_call;
call.argument = 0;
completion_call_stack.push_back(call);
if (previous.cursor_place == GDScriptTokenizerText::CURSOR_MIDDLE || previous.cursor_place == GDScriptTokenizerText::CURSOR_END || current.cursor_place == GDScriptTokenizerText::CURSOR_BEGINNING) {
completion_call = call;
}
}
void GDScriptParser::pop_completion_call() {
@ -331,7 +337,7 @@ void GDScriptParser::pop_completion_call() {
}
void GDScriptParser::set_last_completion_call_arg(int p_argument) {
if (!for_completion || passed_cursor) {
if (!for_completion) {
return;
}
ERR_FAIL_COND_MSG(completion_call_stack.is_empty(), "Trying to set argument on empty completion call stack");
@ -477,12 +483,6 @@ GDScriptTokenizer::Token GDScriptParser::advance() {
if (current.type == GDScriptTokenizer::Token::TK_EOF) {
ERR_FAIL_COND_V_MSG(current.type == GDScriptTokenizer::Token::TK_EOF, current, "GDScript parser bug: Trying to advance past the end of stream.");
}
if (for_completion && !completion_call_stack.is_empty()) {
if (completion_call.call == nullptr && tokenizer->is_past_cursor()) {
completion_call = completion_call_stack.back()->get();
passed_cursor = true;
}
}
previous = current;
current = tokenizer->scan();
while (current.type == GDScriptTokenizer::Token::ERROR) {
@ -613,12 +613,12 @@ void GDScriptParser::parse_program() {
current_class = head;
bool can_have_class_or_extends = true;
#define PUSH_PENDING_ANNOTATIONS_TO_HEAD \
if (!annotation_stack.is_empty()) { \
for (AnnotationNode * annot : annotation_stack) { \
head->annotations.push_back(annot); \
} \
annotation_stack.clear(); \
#define PUSH_PENDING_ANNOTATIONS_TO_HEAD \
if (!annotation_stack.is_empty()) { \
for (AnnotationNode *annot : annotation_stack) { \
head->annotations.push_back(annot); \
} \
annotation_stack.clear(); \
}
while (!check(GDScriptTokenizer::Token::TK_EOF)) {
@ -672,14 +672,16 @@ void GDScriptParser::parse_program() {
}
}
if (current.type == GDScriptTokenizer::Token::CLASS_NAME || current.type == GDScriptTokenizer::Token::EXTENDS) {
// Set range of the class to only start at extends or class_name if present.
reset_extents(head, current);
}
while (can_have_class_or_extends) {
// Order here doesn't matter, but there should be only one of each at most.
switch (current.type) {
case GDScriptTokenizer::Token::CLASS_NAME:
PUSH_PENDING_ANNOTATIONS_TO_HEAD;
if (head->start_line == 1) {
reset_extents(head, current);
}
advance();
if (head->identifier != nullptr) {
push_error(R"("class_name" can only be used once.)");
@ -689,9 +691,6 @@ void GDScriptParser::parse_program() {
break;
case GDScriptTokenizer::Token::EXTENDS:
PUSH_PENDING_ANNOTATIONS_TO_HEAD;
if (head->start_line == 1) {
reset_extents(head, current);
}
advance();
if (head->extends_used) {
push_error(R"("extends" can only be used once.)");
@ -2721,16 +2720,16 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_builtin_constant(Expressio
switch (op_type) {
case GDScriptTokenizer::Token::CONST_PI:
constant->value = Math_PI;
constant->value = Math::PI;
break;
case GDScriptTokenizer::Token::CONST_TAU:
constant->value = Math_TAU;
constant->value = Math::TAU;
break;
case GDScriptTokenizer::Token::CONST_INF:
constant->value = INFINITY;
constant->value = Math::INF;
break;
case GDScriptTokenizer::Token::CONST_NAN:
constant->value = NAN;
constant->value = Math::NaN;
break;
default:
return nullptr; // Unreachable.
@ -3302,7 +3301,11 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_call(ExpressionNode *p_pre
IdentifierNode *identifier = parse_identifier();
call->callee = identifier;
call->function_name = identifier->name;
consume(GDScriptTokenizer::Token::PARENTHESIS_OPEN, R"(Expected "(" after function name.)");
if (!consume(GDScriptTokenizer::Token::PARENTHESIS_OPEN, R"(Expected "(" after function name.)")) {
pop_multiline();
complete_extents(call);
return nullptr;
}
}
} else {
call->callee = p_previous_operand;
@ -3337,6 +3340,7 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_call(ExpressionNode *p_pre
int argument_index = 0;
do {
make_completion_context(ct, call, argument_index);
set_last_completion_call_arg(argument_index);
if (check(GDScriptTokenizer::Token::PARENTHESIS_CLOSE)) {
// Allow for trailing comma.
break;
@ -4131,7 +4135,7 @@ GDScriptParser::ParseRule *GDScriptParser::get_rule(GDScriptTokenizer::Token::Ty
};
/* clang-format on */
// Avoid desync.
static_assert(sizeof(rules) / sizeof(rules[0]) == GDScriptTokenizer::Token::TK_MAX, "Amount of parse rules don't match the amount of token types.");
static_assert(std::size(rules) == GDScriptTokenizer::Token::TK_MAX, "Amount of parse rules don't match the amount of token types.");
// Let's assume this is never invalid, since nothing generates a TK_MAX.
return &rules[p_token_type];
@ -4354,7 +4358,7 @@ static StringName _find_narrowest_native_or_global_class(const GDScriptParser::D
}
if (p_type.is_meta_type) {
return script.is_valid() ? script->get_class() : Script::get_class_static();
return script.is_valid() ? script->get_class_name() : Script::get_class_static();
}
if (script.is_null()) {
return p_type.native_type;
@ -5254,7 +5258,7 @@ PropertyInfo GDScriptParser::DataType::to_property_info(const String &p_name) co
case SCRIPT:
result.type = Variant::OBJECT;
if (is_meta_type) {
result.class_name = script_type.is_valid() ? script_type->get_class() : Script::get_class_static();
result.class_name = script_type.is_valid() ? script_type->get_class_name() : Script::get_class_static();
} else if (script_type.is_valid() && script_type->get_global_name() != StringName()) {
result.class_name = script_type->get_global_name();
} else {

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef GDSCRIPT_PARSER_H
#define GDSCRIPT_PARSER_H
#pragma once
#include "gdscript_cache.h"
#include "gdscript_tokenizer.h"
@ -1311,6 +1310,11 @@ public:
COMPLETION_TYPE_NAME_OR_VOID, // Same as TYPE_NAME, but allows void (in function return type).
};
struct CompletionCall {
Node *call = nullptr;
int argument = -1;
};
struct CompletionContext {
CompletionType type = COMPLETION_NONE;
ClassNode *current_class = nullptr;
@ -1322,11 +1326,7 @@ public:
Node *node = nullptr;
Object *base = nullptr;
GDScriptParser *parser = nullptr;
};
struct CompletionCall {
Node *call = nullptr;
int argument = -1;
CompletionCall call;
};
private:
@ -1373,9 +1373,7 @@ private:
SuiteNode *current_suite = nullptr;
CompletionContext completion_context;
CompletionCall completion_call;
List<CompletionCall> completion_call_stack;
bool passed_cursor = false;
bool in_lambda = false;
bool lambda_ended = false; // Marker for when a lambda ends, to apply an end of statement if needed.
@ -1587,7 +1585,6 @@ public:
static Variant::Type get_builtin_type(const StringName &p_type); // Excluding `Variant::NIL` and `Variant::OBJECT`.
CompletionContext get_completion_context() const { return completion_context; }
CompletionCall get_completion_call() const { return completion_call; }
void get_annotation_list(List<MethodInfo> *r_annotations) const;
bool annotation_exists(const String &p_annotation_name) const;
@ -1667,5 +1664,3 @@ public:
#endif // DEBUG_ENABLED
static void cleanup();
};
#endif // GDSCRIPT_PARSER_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef GDSCRIPT_RPC_CALLABLE_H
#define GDSCRIPT_RPC_CALLABLE_H
#pragma once
#include "core/variant/callable.h"
#include "core/variant/variant.h"
@ -59,5 +58,3 @@ public:
GDScriptRPCCallable(Object *p_object, const StringName &p_method);
virtual ~GDScriptRPCCallable() = default;
};
#endif // GDSCRIPT_RPC_CALLABLE_H

View file

@ -157,7 +157,7 @@ static const char *token_names[] = {
};
// Avoid desync.
static_assert(sizeof(token_names) / sizeof(token_names[0]) == GDScriptTokenizer::Token::TK_MAX, "Amount of token names don't match the amount of token types.");
static_assert(std::size(token_names) == GDScriptTokenizer::Token::TK_MAX, "Amount of token names don't match the amount of token types.");
const char *GDScriptTokenizer::Token::get_name() const {
ERR_FAIL_INDEX_V_MSG(type, TK_MAX, "<error>", "Using token type out of the enum.");
@ -366,7 +366,7 @@ GDScriptTokenizer::Token GDScriptTokenizerText::make_token(Token::Type p_type) {
token.end_column = column;
token.leftmost_column = leftmost_column;
token.rightmost_column = rightmost_column;
token.source = String(_start, _current - _start);
token.source = String::utf32(Span(_start, _current - _start));
if (p_type != Token::ERROR && cursor_line > -1) {
// Also count whitespace after token.
@ -588,7 +588,7 @@ GDScriptTokenizer::Token GDScriptTokenizerText::potential_identifier() {
return token;
}
String name(_start, len);
String name = String::utf32(Span(_start, len));
if (len < MIN_KEYWORD_LENGTH || len > MAX_KEYWORD_LENGTH) {
// Cannot be a keyword, as the length doesn't match any.
return make_identifier(name);
@ -863,7 +863,7 @@ GDScriptTokenizer::Token GDScriptTokenizerText::number() {
// Create a string with the whole number.
int len = _current - _start;
String number = String(_start, len).replace("_", "");
String number = String::utf32(Span(_start, len)).remove_char('_');
// Convert to the appropriate literal type.
if (base == 16) {
@ -1337,7 +1337,7 @@ void GDScriptTokenizerText::check_indent() {
}
String GDScriptTokenizerText::_get_indent_char_name(char32_t ch) {
ERR_FAIL_COND_V(ch != ' ' && ch != '\t', String(&ch, 1).c_escape());
ERR_FAIL_COND_V(ch != ' ' && ch != '\t', String::chr(ch).c_escape());
return ch == ' ' ? "space" : "tab";
}

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef GDSCRIPT_TOKENIZER_H
#define GDSCRIPT_TOKENIZER_H
#pragma once
#include "core/templates/hash_map.h"
#include "core/templates/list.h"
@ -312,5 +311,3 @@ public:
GDScriptTokenizerText();
};
#endif // GDSCRIPT_TOKENIZER_H

View file

@ -182,7 +182,7 @@ Error GDScriptTokenizerBuffer::set_code_buffer(const Vector<uint8_t> &p_buffer)
cs.write[j] = decode_uint32(tmp);
}
String s(reinterpret_cast<const char32_t *>(cs.ptr()), len);
String s = String::utf32(Span(reinterpret_cast<const char32_t *>(cs.ptr()), len));
b += len * 4;
total_len -= len * 4;
identifiers.write[i] = s;

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef GDSCRIPT_TOKENIZER_BUFFER_H
#define GDSCRIPT_TOKENIZER_BUFFER_H
#pragma once
#include "gdscript_tokenizer.h"
@ -89,5 +88,3 @@ public:
virtual Token scan() override;
};
#endif // GDSCRIPT_TOKENIZER_BUFFER_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef GDSCRIPT_UTILITY_CALLABLE_H
#define GDSCRIPT_UTILITY_CALLABLE_H
#pragma once
#include "gdscript_utility_functions.h"
@ -62,5 +61,3 @@ public:
GDScriptUtilityCallable(const StringName &p_function_name);
};
#endif // GDSCRIPT_UTILITY_CALLABLE_H

View file

@ -624,8 +624,8 @@ StringName GDScriptUtilityFunctions::get_function_return_class(const StringName
Variant::Type GDScriptUtilityFunctions::get_function_argument_type(const StringName &p_function, int p_arg) {
GDScriptUtilityFunctionInfo *info = utility_function_table.lookup_ptr(p_function);
ERR_FAIL_NULL_V(info, Variant::NIL);
ERR_FAIL_COND_V(p_arg >= info->info.arguments.size(), Variant::NIL);
return info->info.arguments.get(p_arg).type;
ERR_FAIL_INDEX_V(p_arg, info->info.arguments.size(), Variant::NIL);
return info->info.arguments[p_arg].type;
}
int GDScriptUtilityFunctions::get_function_argument_count(const StringName &p_function) {

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef GDSCRIPT_UTILITY_FUNCTIONS_H
#define GDSCRIPT_UTILITY_FUNCTIONS_H
#pragma once
#include "core/string/string_name.h"
#include "core/variant/variant.h"
@ -57,5 +56,3 @@ public:
static void register_functions();
static void unregister_functions();
};
#endif // GDSCRIPT_UTILITY_FUNCTIONS_H

View file

@ -387,7 +387,7 @@ void (*type_init_function_table[])(Variant *) = {
&&OPCODE_LINE, \
&&OPCODE_END \
}; \
static_assert((sizeof(switch_table_ops) / sizeof(switch_table_ops[0]) == (OPCODE_END + 1)), "Opcodes in jump table aren't the same as opcodes in enum.");
static_assert(std::size(switch_table_ops) == (OPCODE_END + 1), "Opcodes in jump table aren't the same as opcodes in enum.");
#define OPCODE(m_op) \
m_op:
@ -3246,7 +3246,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
ip += 5; \
} else { \
int jumpto = _code_ptr[ip + 4]; \
GD_ERR_BREAK(jumpto<0 || jumpto> _code_size); \
GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size); \
ip = jumpto; \
} \
} \
@ -3284,9 +3284,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
#endif
*counter = Variant();
Array ref;
ref.push_back(*counter);
Array ref = { *counter };
Variant vref;
VariantInternal::initialize(&vref, Variant::ARRAY);
*VariantInternal::get_array(&vref) = ref;
@ -3578,7 +3576,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
(*idx)++; \
if (*idx >= array->size()) { \
int jumpto = _code_ptr[ip + 4]; \
GD_ERR_BREAK(jumpto<0 || jumpto> _code_size); \
GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size); \
ip = jumpto; \
} else { \
GET_VARIANT_PTR(iterator, 2); \
@ -3619,8 +3617,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
Object *obj = *VariantInternal::get_object(container);
#endif
Array ref;
ref.push_back(*counter);
Array ref = { *counter };
Variant vref;
VariantInternal::initialize(&vref, Variant::ARRAY);
*VariantInternal::get_array(&vref) = ref;

View file

@ -245,7 +245,7 @@ String GDScriptWarning::get_name_from_code(Code p_code) {
#endif
};
static_assert((sizeof(names) / sizeof(*names)) == WARNING_MAX, "Amount of warning types don't match the amount of warning names.");
static_assert(std::size(names) == WARNING_MAX, "Amount of warning types don't match the amount of warning names.");
return names[(int)p_code];
}

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef GDSCRIPT_WARNING_H
#define GDSCRIPT_WARNING_H
#pragma once
#ifdef DEBUG_ENABLED
@ -154,7 +153,7 @@ public:
#endif
};
static_assert((sizeof(default_warning_levels) / sizeof(default_warning_levels[0])) == WARNING_MAX, "Amount of default levels does not match the amount of warnings.");
static_assert(std::size(default_warning_levels) == WARNING_MAX, "Amount of default levels does not match the amount of warnings.");
Code code = WARNING_MAX;
int start_line = -1, end_line = -1;
@ -171,5 +170,3 @@ public:
};
#endif // DEBUG_ENABLED
#endif // GDSCRIPT_WARNING_H

View file

@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path fill="#e0e0e0" d="m7 1-.565 2.258a5 5 0 0 0-.689.28L3.758 2.343 2.344 3.758l1.195 1.994a5 5 0 0 0-.285.685L1 7v2l2.258.564a5 5 0 0 0 .279.688l-1.193 1.99 1.414 1.414 1.994-1.195a5 5 0 0 0 .685.285L7 15h2l.564-2.258a5 5 0 0 0 .688-.28l1.99 1.194 1.414-1.414-1.195-1.994a5 5 0 0 0 .285-.685L15 9V7l-2.258-.564a5 5 0 0 0-.28-.688l1.194-1.99-1.414-1.414-1.994 1.195a5 5 0 0 0-.686-.285L9 1H7zm1 5a2 2 0 0 1 0 4 2 2 0 0 1 0-4z"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path fill="#e0e0e0" d="m7 1-.565 2.258a5 5 0 0 0-.689.28L3.758 2.343 2.344 3.758l1.195 1.994a5 5 0 0 0-.285.685L1 7v2l2.258.564a5 5 0 0 0 .279.688l-1.193 1.99 1.414 1.414 1.994-1.195a5 5 0 0 0 .685.285L7 15h2l.564-2.258a5 5 0 0 0 .688-.28l1.99 1.194 1.414-1.414-1.195-1.994a5 5 0 0 0 .285-.685L15 9V7l-2.258-.564a5 5 0 0 0-.28-.688l1.194-1.99-1.414-1.414-1.994 1.195a5 5 0 0 0-.686-.285L9 1H7zm1 5a2 2 0 0 1 0 4 2 2 0 0 1 0-4z"/></svg>

Before

Width:  |  Height:  |  Size: 499 B

After

Width:  |  Height:  |  Size: 500 B

Before After
Before After

View file

@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path fill="none" stroke="#e0e0e0" d="m7 1-.565 2.258a5 5 0 0 0-.689.28L3.758 2.343 2.344 3.758l1.195 1.994a5 5 0 0 0-.285.685L1 7v2l2.258.564a5 5 0 0 0 .279.688l-1.193 1.99 1.414 1.414 1.994-1.195a5 5 0 0 0 .685.285L7 15h2l.564-2.258a5 5 0 0 0 .688-.28l1.99 1.194 1.414-1.414-1.195-1.994a5 5 0 0 0 .285-.685L15 9V7l-2.258-.564a5 5 0 0 0-.28-.688l1.194-1.99-1.414-1.414-1.994 1.195a5 5 0 0 0-.686-.285L9 1H7zm1 5a2 2 0 0 1 0 4 2 2 0 0 1 0-4z"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path fill="none" stroke="#e0e0e0" d="m7 1-.565 2.258a5 5 0 0 0-.689.28L3.758 2.343 2.344 3.758l1.195 1.994a5 5 0 0 0-.285.685L1 7v2l2.258.564a5 5 0 0 0 .279.688l-1.193 1.99 1.414 1.414 1.994-1.195a5 5 0 0 0 .685.285L7 15h2l.564-2.258a5 5 0 0 0 .688-.28l1.99 1.194 1.414-1.414-1.195-1.994a5 5 0 0 0 .285-.685L15 9V7l-2.258-.564a5 5 0 0 0-.28-.688l1.194-1.99-1.414-1.414-1.994 1.195a5 5 0 0 0-.686-.285L9 1H7zm1 5a2 2 0 0 1 0 4 2 2 0 0 1 0-4z"/></svg>

Before

Width:  |  Height:  |  Size: 513 B

After

Width:  |  Height:  |  Size: 514 B

Before After
Before After

View file

@ -44,8 +44,8 @@ int get_indent_size() {
}
}
lsp::Position GodotPosition::to_lsp(const Vector<String> &p_lines) const {
lsp::Position res;
LSP::Position GodotPosition::to_lsp(const Vector<String> &p_lines) const {
LSP::Position res;
// Special case: `line = 0` -> root class (range covers everything).
if (line <= 0) {
@ -89,7 +89,7 @@ lsp::Position GodotPosition::to_lsp(const Vector<String> &p_lines) const {
return res;
}
GodotPosition GodotPosition::from_lsp(const lsp::Position p_pos, const Vector<String> &p_lines) {
GodotPosition GodotPosition::from_lsp(const LSP::Position p_pos, const Vector<String> &p_lines) {
GodotPosition res(p_pos.line + 1, p_pos.character + 1);
// Line outside of actual text is valid (-> pos/cursor at end of text).
@ -113,14 +113,14 @@ GodotPosition GodotPosition::from_lsp(const lsp::Position p_pos, const Vector<St
return res;
}
lsp::Range GodotRange::to_lsp(const Vector<String> &p_lines) const {
lsp::Range res;
LSP::Range GodotRange::to_lsp(const Vector<String> &p_lines) const {
LSP::Range res;
res.start = start.to_lsp(p_lines);
res.end = end.to_lsp(p_lines);
return res;
}
GodotRange GodotRange::from_lsp(const lsp::Range &p_range, const Vector<String> &p_lines) {
GodotRange GodotRange::from_lsp(const LSP::Range &p_range, const Vector<String> &p_lines) {
GodotPosition start = GodotPosition::from_lsp(p_range.start, p_lines);
GodotPosition end = GodotPosition::from_lsp(p_range.end, p_lines);
return GodotRange(start, end);
@ -131,13 +131,13 @@ void ExtendGDScriptParser::update_diagnostics() {
const List<ParserError> &parser_errors = get_errors();
for (const ParserError &error : parser_errors) {
lsp::Diagnostic diagnostic;
diagnostic.severity = lsp::DiagnosticSeverity::Error;
LSP::Diagnostic diagnostic;
diagnostic.severity = LSP::DiagnosticSeverity::Error;
diagnostic.message = error.message;
diagnostic.source = "gdscript";
diagnostic.code = -1;
lsp::Range range;
lsp::Position pos;
LSP::Range range;
LSP::Position pos;
const PackedStringArray line_array = get_lines();
int line = CLAMP(LINE_NUMBER_TO_INDEX(error.line), 0, line_array.size() - 1);
const String &line_text = line_array[line];
@ -152,13 +152,13 @@ void ExtendGDScriptParser::update_diagnostics() {
const List<GDScriptWarning> &parser_warnings = get_warnings();
for (const GDScriptWarning &warning : parser_warnings) {
lsp::Diagnostic diagnostic;
diagnostic.severity = lsp::DiagnosticSeverity::Warning;
LSP::Diagnostic diagnostic;
diagnostic.severity = LSP::DiagnosticSeverity::Warning;
diagnostic.message = "(" + warning.get_name() + "): " + warning.get_message();
diagnostic.source = "gdscript";
diagnostic.code = warning.code;
lsp::Range range;
lsp::Position pos;
LSP::Range range;
LSP::Position pos;
int line = LINE_NUMBER_TO_INDEX(warning.start_line);
const String &line_text = get_lines()[line];
pos.line = line;
@ -178,14 +178,14 @@ void ExtendGDScriptParser::update_symbols() {
parse_class_symbol(gdclass, class_symbol);
for (int i = 0; i < class_symbol.children.size(); i++) {
const lsp::DocumentSymbol &symbol = class_symbol.children[i];
const LSP::DocumentSymbol &symbol = class_symbol.children[i];
members.insert(symbol.name, &symbol);
// Cache level one inner classes.
if (symbol.kind == lsp::SymbolKind::Class) {
if (symbol.kind == LSP::SymbolKind::Class) {
ClassMembers inner_class;
for (int j = 0; j < symbol.children.size(); j++) {
const lsp::DocumentSymbol &s = symbol.children[j];
const LSP::DocumentSymbol &s = symbol.children[j];
inner_class.insert(s.name, &s);
}
inner_classes.insert(symbol.name, inner_class);
@ -208,14 +208,14 @@ void ExtendGDScriptParser::update_document_links(const String &p_code) {
const Variant &const_val = token.literal;
if (const_val.get_type() == Variant::STRING) {
String scr_path = const_val;
bool exists = fs->file_exists(scr_path);
if (!exists) {
scr_path = get_path().get_base_dir() + "/" + scr_path;
exists = fs->file_exists(scr_path);
if (scr_path.is_relative_path()) {
scr_path = get_path().get_base_dir().path_join(scr_path).simplify_path();
}
bool exists = fs->file_exists(scr_path);
if (exists) {
String value = const_val;
lsp::DocumentLink link;
LSP::DocumentLink link;
link.target = GDScriptLanguageProtocol::get_singleton()->get_workspace()->get_file_uri(scr_path);
link.range = GodotRange(GodotPosition(token.start_line, token.start_column), GodotPosition(token.end_line, token.end_column)).to_lsp(lines);
document_links.push_back(link);
@ -225,13 +225,13 @@ void ExtendGDScriptParser::update_document_links(const String &p_code) {
}
}
lsp::Range ExtendGDScriptParser::range_of_node(const GDScriptParser::Node *p_node) const {
LSP::Range ExtendGDScriptParser::range_of_node(const GDScriptParser::Node *p_node) const {
GodotPosition start(p_node->start_line, p_node->start_column);
GodotPosition end(p_node->end_line, p_node->end_column);
return GodotRange(start, end).to_lsp(lines);
}
void ExtendGDScriptParser::parse_class_symbol(const GDScriptParser::ClassNode *p_class, lsp::DocumentSymbol &r_symbol) {
void ExtendGDScriptParser::parse_class_symbol(const GDScriptParser::ClassNode *p_class, LSP::DocumentSymbol &r_symbol) {
const String uri = get_uri();
r_symbol.uri = uri;
@ -241,7 +241,7 @@ void ExtendGDScriptParser::parse_class_symbol(const GDScriptParser::ClassNode *p
if (r_symbol.name.is_empty()) {
r_symbol.name = path.get_file();
}
r_symbol.kind = lsp::SymbolKind::Class;
r_symbol.kind = LSP::SymbolKind::Class;
r_symbol.deprecated = false;
r_symbol.range = range_of_node(p_class);
if (p_class->identifier) {
@ -276,9 +276,9 @@ void ExtendGDScriptParser::parse_class_symbol(const GDScriptParser::ClassNode *p
switch (m.type) {
case ClassNode::Member::VARIABLE: {
lsp::DocumentSymbol symbol;
LSP::DocumentSymbol symbol;
symbol.name = m.variable->identifier->name;
symbol.kind = m.variable->property == VariableNode::PROP_NONE ? lsp::SymbolKind::Variable : lsp::SymbolKind::Property;
symbol.kind = m.variable->property == VariableNode::PROP_NONE ? LSP::SymbolKind::Variable : LSP::SymbolKind::Property;
symbol.deprecated = false;
symbol.range = range_of_node(m.variable);
symbol.selectionRange = range_of_node(m.variable->identifier);
@ -299,20 +299,20 @@ void ExtendGDScriptParser::parse_class_symbol(const GDScriptParser::ClassNode *p
if (m.variable->initializer && m.variable->initializer->type == GDScriptParser::Node::LAMBDA) {
GDScriptParser::LambdaNode *lambda_node = (GDScriptParser::LambdaNode *)m.variable->initializer;
lsp::DocumentSymbol lambda;
LSP::DocumentSymbol lambda;
parse_function_symbol(lambda_node->function, lambda);
// Merge lambda into current variable.
symbol.children.append_array(lambda.children);
}
if (m.variable->getter && m.variable->getter->type == GDScriptParser::Node::FUNCTION) {
lsp::DocumentSymbol get_symbol;
LSP::DocumentSymbol get_symbol;
parse_function_symbol(m.variable->getter, get_symbol);
get_symbol.local = true;
symbol.children.push_back(get_symbol);
}
if (m.variable->setter && m.variable->setter->type == GDScriptParser::Node::FUNCTION) {
lsp::DocumentSymbol set_symbol;
LSP::DocumentSymbol set_symbol;
parse_function_symbol(m.variable->setter, set_symbol);
set_symbol.local = true;
symbol.children.push_back(set_symbol);
@ -321,10 +321,10 @@ void ExtendGDScriptParser::parse_class_symbol(const GDScriptParser::ClassNode *p
r_symbol.children.push_back(symbol);
} break;
case ClassNode::Member::CONSTANT: {
lsp::DocumentSymbol symbol;
LSP::DocumentSymbol symbol;
symbol.name = m.constant->identifier->name;
symbol.kind = lsp::SymbolKind::Constant;
symbol.kind = LSP::SymbolKind::Constant;
symbol.deprecated = false;
symbol.range = range_of_node(m.constant);
symbol.selectionRange = range_of_node(m.constant->identifier);
@ -361,9 +361,9 @@ void ExtendGDScriptParser::parse_class_symbol(const GDScriptParser::ClassNode *p
r_symbol.children.push_back(symbol);
} break;
case ClassNode::Member::SIGNAL: {
lsp::DocumentSymbol symbol;
LSP::DocumentSymbol symbol;
symbol.name = m.signal->identifier->name;
symbol.kind = lsp::SymbolKind::Event;
symbol.kind = LSP::SymbolKind::Event;
symbol.deprecated = false;
symbol.range = range_of_node(m.signal);
symbol.selectionRange = range_of_node(m.signal->identifier);
@ -380,9 +380,9 @@ void ExtendGDScriptParser::parse_class_symbol(const GDScriptParser::ClassNode *p
symbol.detail += ")";
for (GDScriptParser::ParameterNode *param : m.signal->parameters) {
lsp::DocumentSymbol param_symbol;
LSP::DocumentSymbol param_symbol;
param_symbol.name = param->identifier->name;
param_symbol.kind = lsp::SymbolKind::Variable;
param_symbol.kind = LSP::SymbolKind::Variable;
param_symbol.deprecated = false;
param_symbol.local = true;
param_symbol.range = range_of_node(param);
@ -398,10 +398,10 @@ void ExtendGDScriptParser::parse_class_symbol(const GDScriptParser::ClassNode *p
r_symbol.children.push_back(symbol);
} break;
case ClassNode::Member::ENUM_VALUE: {
lsp::DocumentSymbol symbol;
LSP::DocumentSymbol symbol;
symbol.name = m.enum_value.identifier->name;
symbol.kind = lsp::SymbolKind::EnumMember;
symbol.kind = LSP::SymbolKind::EnumMember;
symbol.deprecated = false;
symbol.range.start = GodotPosition(m.enum_value.line, m.enum_value.leftmost_column).to_lsp(lines);
symbol.range.end = GodotPosition(m.enum_value.line, m.enum_value.rightmost_column).to_lsp(lines);
@ -415,9 +415,9 @@ void ExtendGDScriptParser::parse_class_symbol(const GDScriptParser::ClassNode *p
r_symbol.children.push_back(symbol);
} break;
case ClassNode::Member::ENUM: {
lsp::DocumentSymbol symbol;
LSP::DocumentSymbol symbol;
symbol.name = m.m_enum->identifier->name;
symbol.kind = lsp::SymbolKind::Enum;
symbol.kind = LSP::SymbolKind::Enum;
symbol.range = range_of_node(m.m_enum);
symbol.selectionRange = range_of_node(m.m_enum->identifier);
symbol.documentation = m.m_enum->doc_data.description;
@ -434,10 +434,10 @@ void ExtendGDScriptParser::parse_class_symbol(const GDScriptParser::ClassNode *p
symbol.detail += "}";
for (GDScriptParser::EnumNode::Value value : m.m_enum->values) {
lsp::DocumentSymbol child;
LSP::DocumentSymbol child;
child.name = value.identifier->name;
child.kind = lsp::SymbolKind::EnumMember;
child.kind = LSP::SymbolKind::EnumMember;
child.deprecated = false;
child.range.start = GodotPosition(value.line, value.leftmost_column).to_lsp(lines);
child.range.end = GodotPosition(value.line, value.rightmost_column).to_lsp(lines);
@ -454,12 +454,12 @@ void ExtendGDScriptParser::parse_class_symbol(const GDScriptParser::ClassNode *p
r_symbol.children.push_back(symbol);
} break;
case ClassNode::Member::FUNCTION: {
lsp::DocumentSymbol symbol;
LSP::DocumentSymbol symbol;
parse_function_symbol(m.function, symbol);
r_symbol.children.push_back(symbol);
} break;
case ClassNode::Member::CLASS: {
lsp::DocumentSymbol symbol;
LSP::DocumentSymbol symbol;
parse_class_symbol(m.m_class, symbol);
r_symbol.children.push_back(symbol);
} break;
@ -471,13 +471,13 @@ void ExtendGDScriptParser::parse_class_symbol(const GDScriptParser::ClassNode *p
}
}
void ExtendGDScriptParser::parse_function_symbol(const GDScriptParser::FunctionNode *p_func, lsp::DocumentSymbol &r_symbol) {
void ExtendGDScriptParser::parse_function_symbol(const GDScriptParser::FunctionNode *p_func, LSP::DocumentSymbol &r_symbol) {
const String uri = get_uri();
bool is_named = p_func->identifier != nullptr;
r_symbol.name = is_named ? p_func->identifier->name : "";
r_symbol.kind = (p_func->is_static || p_func->source_lambda != nullptr) ? lsp::SymbolKind::Function : lsp::SymbolKind::Method;
r_symbol.kind = (p_func->is_static || p_func->source_lambda != nullptr) ? LSP::SymbolKind::Function : LSP::SymbolKind::Method;
r_symbol.detail = "func";
if (is_named) {
r_symbol.detail += " " + String(p_func->identifier->name);
@ -570,9 +570,9 @@ void ExtendGDScriptParser::parse_function_symbol(const GDScriptParser::FunctionN
const GDScriptParser::SuiteNode *suite_node = N->get();
for (int i = 0; i < suite_node->locals.size(); i++) {
const SuiteNode::Local &local = suite_node->locals[i];
lsp::DocumentSymbol symbol;
LSP::DocumentSymbol symbol;
symbol.name = local.name;
symbol.kind = local.type == SuiteNode::Local::CONSTANT ? lsp::SymbolKind::Constant : lsp::SymbolKind::Variable;
symbol.kind = local.type == SuiteNode::Local::CONSTANT ? LSP::SymbolKind::Constant : LSP::SymbolKind::Variable;
switch (local.type) {
case SuiteNode::Local::CONSTANT:
symbol.range = range_of_node(local.constant);
@ -583,7 +583,7 @@ void ExtendGDScriptParser::parse_function_symbol(const GDScriptParser::FunctionN
symbol.selectionRange = range_of_node(local.variable->identifier);
if (local.variable->initializer && local.variable->initializer->type == GDScriptParser::Node::LAMBDA) {
GDScriptParser::LambdaNode *lambda_node = (GDScriptParser::LambdaNode *)local.variable->initializer;
lsp::DocumentSymbol lambda;
LSP::DocumentSymbol lambda;
parse_function_symbol(lambda_node->function, lambda);
// Merge lambda into current variable.
// -> Only interested in new variables, not lambda itself.
@ -629,14 +629,14 @@ void ExtendGDScriptParser::parse_function_symbol(const GDScriptParser::FunctionN
}
}
String ExtendGDScriptParser::get_text_for_completion(const lsp::Position &p_cursor) const {
String ExtendGDScriptParser::get_text_for_completion(const LSP::Position &p_cursor) const {
String longthing;
int len = lines.size();
for (int i = 0; i < len; i++) {
if (i == p_cursor.line) {
longthing += lines[i].substr(0, p_cursor.character);
longthing += String::chr(0xFFFF); // Not unicode, represents the cursor.
longthing += lines[i].substr(p_cursor.character, lines[i].size());
longthing += lines[i].substr(p_cursor.character);
} else {
longthing += lines[i];
}
@ -649,7 +649,7 @@ String ExtendGDScriptParser::get_text_for_completion(const lsp::Position &p_curs
return longthing;
}
String ExtendGDScriptParser::get_text_for_lookup_symbol(const lsp::Position &p_cursor, const String &p_symbol, bool p_func_required) const {
String ExtendGDScriptParser::get_text_for_lookup_symbol(const LSP::Position &p_cursor, const String &p_symbol, bool p_func_required) const {
String longthing;
int len = lines.size();
for (int i = 0; i < len; i++) {
@ -687,7 +687,7 @@ String ExtendGDScriptParser::get_text_for_lookup_symbol(const lsp::Position &p_c
return longthing;
}
String ExtendGDScriptParser::get_identifier_under_position(const lsp::Position &p_position, lsp::Range &r_range) const {
String ExtendGDScriptParser::get_identifier_under_position(const LSP::Position &p_position, LSP::Range &r_range) const {
ERR_FAIL_INDEX_V(p_position.line, lines.size(), "");
String line = lines[p_position.line];
if (line.is_empty()) {
@ -709,7 +709,7 @@ String ExtendGDScriptParser::get_identifier_under_position(const lsp::Position &
// -> Move position to previous character if:
// * Position not on valid identifier char.
// * Prev position is valid identifier char.
lsp::Position pos = p_position;
LSP::Position pos = p_position;
if (
pos.character >= line.length() // Cursor at end of line.
|| (!is_ascii_identifier_char(line[pos.character]) // Not on valid identifier char.
@ -753,8 +753,8 @@ String ExtendGDScriptParser::get_uri() const {
return GDScriptLanguageProtocol::get_singleton()->get_workspace()->get_file_uri(path);
}
const lsp::DocumentSymbol *ExtendGDScriptParser::search_symbol_defined_at_line(int p_line, const lsp::DocumentSymbol &p_parent, const String &p_symbol_name) const {
const lsp::DocumentSymbol *ret = nullptr;
const LSP::DocumentSymbol *ExtendGDScriptParser::search_symbol_defined_at_line(int p_line, const LSP::DocumentSymbol &p_parent, const String &p_symbol_name) const {
const LSP::DocumentSymbol *ret = nullptr;
if (p_line < p_parent.range.start.line) {
return ret;
} else if (p_parent.range.start.line == p_line && (p_symbol_name.is_empty() || p_parent.name == p_symbol_name)) {
@ -770,7 +770,7 @@ const lsp::DocumentSymbol *ExtendGDScriptParser::search_symbol_defined_at_line(i
return ret;
}
Error ExtendGDScriptParser::get_left_function_call(const lsp::Position &p_position, lsp::Position &r_func_pos, int &r_arg_index) const {
Error ExtendGDScriptParser::get_left_function_call(const LSP::Position &p_position, LSP::Position &r_func_pos, int &r_arg_index) const {
ERR_FAIL_INDEX_V(p_position.line, lines.size(), ERR_INVALID_PARAMETER);
int bracket_stack = 0;
@ -814,22 +814,22 @@ Error ExtendGDScriptParser::get_left_function_call(const lsp::Position &p_positi
return ERR_METHOD_NOT_FOUND;
}
const lsp::DocumentSymbol *ExtendGDScriptParser::get_symbol_defined_at_line(int p_line, const String &p_symbol_name) const {
const LSP::DocumentSymbol *ExtendGDScriptParser::get_symbol_defined_at_line(int p_line, const String &p_symbol_name) const {
if (p_line <= 0) {
return &class_symbol;
}
return search_symbol_defined_at_line(p_line, class_symbol, p_symbol_name);
}
const lsp::DocumentSymbol *ExtendGDScriptParser::get_member_symbol(const String &p_name, const String &p_subclass) const {
const LSP::DocumentSymbol *ExtendGDScriptParser::get_member_symbol(const String &p_name, const String &p_subclass) const {
if (p_subclass.is_empty()) {
const lsp::DocumentSymbol *const *ptr = members.getptr(p_name);
const LSP::DocumentSymbol *const *ptr = members.getptr(p_name);
if (ptr) {
return *ptr;
}
} else {
if (const ClassMembers *_class = inner_classes.getptr(p_subclass)) {
const lsp::DocumentSymbol *const *ptr = _class->getptr(p_name);
const LSP::DocumentSymbol *const *ptr = _class->getptr(p_name);
if (ptr) {
return *ptr;
}
@ -839,15 +839,15 @@ const lsp::DocumentSymbol *ExtendGDScriptParser::get_member_symbol(const String
return nullptr;
}
const List<lsp::DocumentLink> &ExtendGDScriptParser::get_document_links() const {
const List<LSP::DocumentLink> &ExtendGDScriptParser::get_document_links() const {
return document_links;
}
const Array &ExtendGDScriptParser::get_member_completions() {
if (member_completions.is_empty()) {
for (const KeyValue<String, const lsp::DocumentSymbol *> &E : members) {
const lsp::DocumentSymbol *symbol = E.value;
lsp::CompletionItem item = symbol->make_completion_item();
for (const KeyValue<String, const LSP::DocumentSymbol *> &E : members) {
const LSP::DocumentSymbol *symbol = E.value;
LSP::CompletionItem item = symbol->make_completion_item();
item.data = JOIN_SYMBOLS(path, E.key);
member_completions.push_back(item.to_json());
}
@ -855,9 +855,9 @@ const Array &ExtendGDScriptParser::get_member_completions() {
for (const KeyValue<String, ClassMembers> &E : inner_classes) {
const ClassMembers *inner_class = &E.value;
for (const KeyValue<String, const lsp::DocumentSymbol *> &F : *inner_class) {
const lsp::DocumentSymbol *symbol = F.value;
lsp::CompletionItem item = symbol->make_completion_item();
for (const KeyValue<String, const LSP::DocumentSymbol *> &F : *inner_class) {
const LSP::DocumentSymbol *symbol = F.value;
LSP::CompletionItem item = symbol->make_completion_item();
item.data = JOIN_SYMBOLS(path, JOIN_SYMBOLS(E.key, F.key));
member_completions.push_back(item.to_json());
}
@ -883,7 +883,7 @@ Dictionary ExtendGDScriptParser::dump_function_api(const GDScriptParser::Functio
}
parameters.push_back(arg);
}
if (const lsp::DocumentSymbol *symbol = get_symbol_defined_at_line(LINE_NUMBER_TO_INDEX(p_func->start_line))) {
if (const LSP::DocumentSymbol *symbol = get_symbol_defined_at_line(LINE_NUMBER_TO_INDEX(p_func->start_line))) {
func["signature"] = symbol->detail;
func["description"] = symbol->documentation;
}
@ -906,7 +906,7 @@ Dictionary ExtendGDScriptParser::dump_class_api(const GDScriptParser::ClassNode
class_api["extends_file"] = String(p_class->extends_path);
class_api["icon"] = String(p_class->icon_path);
if (const lsp::DocumentSymbol *symbol = get_symbol_defined_at_line(LINE_NUMBER_TO_INDEX(p_class->start_line))) {
if (const LSP::DocumentSymbol *symbol = get_symbol_defined_at_line(LINE_NUMBER_TO_INDEX(p_class->start_line))) {
class_api["signature"] = symbol->detail;
class_api["description"] = symbol->documentation;
}
@ -929,7 +929,7 @@ Dictionary ExtendGDScriptParser::dump_class_api(const GDScriptParser::ClassNode
api["name"] = m.constant->identifier->name;
api["value"] = m.constant->initializer->reduced_value;
api["data_type"] = m.constant->get_datatype().to_string();
if (const lsp::DocumentSymbol *symbol = get_symbol_defined_at_line(LINE_NUMBER_TO_INDEX(m.constant->start_line))) {
if (const LSP::DocumentSymbol *symbol = get_symbol_defined_at_line(LINE_NUMBER_TO_INDEX(m.constant->start_line))) {
api["signature"] = symbol->detail;
api["description"] = symbol->documentation;
}
@ -940,7 +940,7 @@ Dictionary ExtendGDScriptParser::dump_class_api(const GDScriptParser::ClassNode
api["name"] = m.enum_value.identifier->name;
api["value"] = m.enum_value.value;
api["data_type"] = m.get_datatype().to_string();
if (const lsp::DocumentSymbol *symbol = get_symbol_defined_at_line(LINE_NUMBER_TO_INDEX(m.enum_value.line))) {
if (const LSP::DocumentSymbol *symbol = get_symbol_defined_at_line(LINE_NUMBER_TO_INDEX(m.enum_value.line))) {
api["signature"] = symbol->detail;
api["description"] = symbol->documentation;
}
@ -956,7 +956,7 @@ Dictionary ExtendGDScriptParser::dump_class_api(const GDScriptParser::ClassNode
api["name"] = m.m_enum->identifier->name;
api["value"] = enum_dict;
api["data_type"] = m.get_datatype().to_string();
if (const lsp::DocumentSymbol *symbol = get_symbol_defined_at_line(LINE_NUMBER_TO_INDEX(m.m_enum->start_line))) {
if (const LSP::DocumentSymbol *symbol = get_symbol_defined_at_line(LINE_NUMBER_TO_INDEX(m.m_enum->start_line))) {
api["signature"] = symbol->detail;
api["description"] = symbol->documentation;
}
@ -970,7 +970,7 @@ Dictionary ExtendGDScriptParser::dump_class_api(const GDScriptParser::ClassNode
api["setter"] = m.variable->setter ? ("@" + String(m.variable->identifier->name) + "_setter") : (m.variable->setter_pointer != nullptr ? String(m.variable->setter_pointer->name) : String());
api["getter"] = m.variable->getter ? ("@" + String(m.variable->identifier->name) + "_getter") : (m.variable->getter_pointer != nullptr ? String(m.variable->getter_pointer->name) : String());
api["export"] = m.variable->exported;
if (const lsp::DocumentSymbol *symbol = get_symbol_defined_at_line(LINE_NUMBER_TO_INDEX(m.variable->start_line))) {
if (const LSP::DocumentSymbol *symbol = get_symbol_defined_at_line(LINE_NUMBER_TO_INDEX(m.variable->start_line))) {
api["signature"] = symbol->detail;
api["description"] = symbol->documentation;
}
@ -984,7 +984,7 @@ Dictionary ExtendGDScriptParser::dump_class_api(const GDScriptParser::ClassNode
pars.append(String(m.signal->parameters[j]->identifier->name));
}
api["arguments"] = pars;
if (const lsp::DocumentSymbol *symbol = get_symbol_defined_at_line(LINE_NUMBER_TO_INDEX(m.signal->start_line))) {
if (const LSP::DocumentSymbol *symbol = get_symbol_defined_at_line(LINE_NUMBER_TO_INDEX(m.signal->start_line))) {
api["signature"] = symbol->detail;
api["description"] = symbol->documentation;
}

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef GDSCRIPT_EXTEND_PARSER_H
#define GDSCRIPT_EXTEND_PARSER_H
#pragma once
#include "../gdscript_parser.h"
#include "godot_lsp.h"
@ -51,12 +50,12 @@
#define JOIN_SYMBOLS(p_path, name) ((p_path) + SYMBOL_SEPARATOR + (name))
#endif
typedef HashMap<String, const lsp::DocumentSymbol *> ClassMembers;
typedef HashMap<String, const LSP::DocumentSymbol *> ClassMembers;
/**
* Represents a Position as used by GDScript Parser. Used for conversion to and from `lsp::Position`.
* Represents a Position as used by GDScript Parser. Used for conversion to and from `LSP::Position`.
*
* Difference to `lsp::Position`:
* Difference to `LSP::Position`:
* * Line & Char/column: 1-based
* * LSP: both 0-based
* * Tabs are expanded to columns using tab size (`text_editor/behavior/indent/size`).
@ -80,8 +79,8 @@ struct GodotPosition {
GodotPosition(int p_line, int p_column) :
line(p_line), column(p_column) {}
lsp::Position to_lsp(const Vector<String> &p_lines) const;
static GodotPosition from_lsp(const lsp::Position p_pos, const Vector<String> &p_lines);
LSP::Position to_lsp(const Vector<String> &p_lines) const;
static GodotPosition from_lsp(const LSP::Position p_pos, const Vector<String> &p_lines);
bool operator==(const GodotPosition &p_other) const {
return line == p_other.line && column == p_other.column;
@ -99,8 +98,8 @@ struct GodotRange {
GodotRange(GodotPosition p_start, GodotPosition p_end) :
start(p_start), end(p_end) {}
lsp::Range to_lsp(const Vector<String> &p_lines) const;
static GodotRange from_lsp(const lsp::Range &p_range, const Vector<String> &p_lines);
LSP::Range to_lsp(const Vector<String> &p_lines) const;
static GodotRange from_lsp(const LSP::Range &p_range, const Vector<String> &p_lines);
bool operator==(const GodotRange &p_other) const {
return start == p_other.start && end == p_other.end;
@ -115,41 +114,41 @@ class ExtendGDScriptParser : public GDScriptParser {
String path;
Vector<String> lines;
lsp::DocumentSymbol class_symbol;
Vector<lsp::Diagnostic> diagnostics;
List<lsp::DocumentLink> document_links;
LSP::DocumentSymbol class_symbol;
Vector<LSP::Diagnostic> diagnostics;
List<LSP::DocumentLink> document_links;
ClassMembers members;
HashMap<String, ClassMembers> inner_classes;
lsp::Range range_of_node(const GDScriptParser::Node *p_node) const;
LSP::Range range_of_node(const GDScriptParser::Node *p_node) const;
void update_diagnostics();
void update_symbols();
void update_document_links(const String &p_code);
void parse_class_symbol(const GDScriptParser::ClassNode *p_class, lsp::DocumentSymbol &r_symbol);
void parse_function_symbol(const GDScriptParser::FunctionNode *p_func, lsp::DocumentSymbol &r_symbol);
void parse_class_symbol(const GDScriptParser::ClassNode *p_class, LSP::DocumentSymbol &r_symbol);
void parse_function_symbol(const GDScriptParser::FunctionNode *p_func, LSP::DocumentSymbol &r_symbol);
Dictionary dump_function_api(const GDScriptParser::FunctionNode *p_func) const;
Dictionary dump_class_api(const GDScriptParser::ClassNode *p_class) const;
const lsp::DocumentSymbol *search_symbol_defined_at_line(int p_line, const lsp::DocumentSymbol &p_parent, const String &p_symbol_name = "") const;
const LSP::DocumentSymbol *search_symbol_defined_at_line(int p_line, const LSP::DocumentSymbol &p_parent, const String &p_symbol_name = "") const;
Array member_completions;
public:
_FORCE_INLINE_ const String &get_path() const { return path; }
_FORCE_INLINE_ const Vector<String> &get_lines() const { return lines; }
_FORCE_INLINE_ const lsp::DocumentSymbol &get_symbols() const { return class_symbol; }
_FORCE_INLINE_ const Vector<lsp::Diagnostic> &get_diagnostics() const { return diagnostics; }
_FORCE_INLINE_ const LSP::DocumentSymbol &get_symbols() const { return class_symbol; }
_FORCE_INLINE_ const Vector<LSP::Diagnostic> &get_diagnostics() const { return diagnostics; }
_FORCE_INLINE_ const ClassMembers &get_members() const { return members; }
_FORCE_INLINE_ const HashMap<String, ClassMembers> &get_inner_classes() const { return inner_classes; }
Error get_left_function_call(const lsp::Position &p_position, lsp::Position &r_func_pos, int &r_arg_index) const;
Error get_left_function_call(const LSP::Position &p_position, LSP::Position &r_func_pos, int &r_arg_index) const;
String get_text_for_completion(const lsp::Position &p_cursor) const;
String get_text_for_lookup_symbol(const lsp::Position &p_cursor, const String &p_symbol = "", bool p_func_required = false) const;
String get_identifier_under_position(const lsp::Position &p_position, lsp::Range &r_range) const;
String get_text_for_completion(const LSP::Position &p_cursor) const;
String get_text_for_lookup_symbol(const LSP::Position &p_cursor, const String &p_symbol = "", bool p_func_required = false) const;
String get_identifier_under_position(const LSP::Position &p_position, LSP::Range &r_range) const;
String get_uri() const;
/**
@ -160,14 +159,12 @@ public:
* -> Without `p_symbol_name`: returns `handle_arg`. Even if parameter (`arg`) is wanted.
* With `p_symbol_name`: symbol name MUST match `p_symbol_name`: returns `arg`.
*/
const lsp::DocumentSymbol *get_symbol_defined_at_line(int p_line, const String &p_symbol_name = "") const;
const lsp::DocumentSymbol *get_member_symbol(const String &p_name, const String &p_subclass = "") const;
const List<lsp::DocumentLink> &get_document_links() const;
const LSP::DocumentSymbol *get_symbol_defined_at_line(int p_line, const String &p_symbol_name = "") const;
const LSP::DocumentSymbol *get_member_symbol(const String &p_name, const String &p_subclass = "") const;
const List<LSP::DocumentLink> &get_document_links() const;
const Array &get_member_completions();
Dictionary generate_api() const;
Error parse(const String &p_code, const String &p_path);
};
#endif // GDSCRIPT_EXTEND_PARSER_H

View file

@ -60,8 +60,7 @@ Error GDScriptLanguageProtocol::LSPeer::handle_data() {
// End of headers
if (l > 3 && r[l] == '\n' && r[l - 1] == '\r' && r[l - 2] == '\n' && r[l - 3] == '\r') {
r[l - 3] = '\0'; // Null terminate to read string
String header;
header.parse_utf8(r);
String header = String::utf8(r);
content_length = header.substr(16).to_int();
has_header = true;
req_pos = 0;
@ -87,8 +86,7 @@ Error GDScriptLanguageProtocol::LSPeer::handle_data() {
}
// Parse data
String msg;
msg.parse_utf8((const char *)req_buf, req_pos);
String msg = String::utf8((const char *)req_buf, req_pos);
// Reset to read again
req_pos = 0;
@ -171,7 +169,7 @@ void GDScriptLanguageProtocol::_bind_methods() {
}
Dictionary GDScriptLanguageProtocol::initialize(const Dictionary &p_params) {
lsp::InitializeResult ret;
LSP::InitializeResult ret;
String root_uri = p_params["rootUri"];
String root = p_params["rootPath"];
@ -179,7 +177,7 @@ Dictionary GDScriptLanguageProtocol::initialize(const Dictionary &p_params) {
#ifndef WINDOWS_ENABLED
is_same_workspace = root.to_lower() == workspace->root.to_lower();
#else
is_same_workspace = root.replace("\\", "/").to_lower() == workspace->root.to_lower();
is_same_workspace = root.replace_char('\\', '/').to_lower() == workspace->root.to_lower();
#endif
if (root_uri.length() && is_same_workspace) {
@ -213,11 +211,11 @@ Dictionary GDScriptLanguageProtocol::initialize(const Dictionary &p_params) {
}
void GDScriptLanguageProtocol::initialized(const Variant &p_params) {
lsp::GodotCapabilities capabilities;
LSP::GodotCapabilities capabilities;
DocTools *doc = EditorHelp::get_doc_data();
for (const KeyValue<String, DocData::ClassDoc> &E : doc->class_list) {
lsp::GodotNativeClassInfo gdclass;
LSP::GodotNativeClassInfo gdclass;
gdclass.name = E.value.name;
gdclass.class_doc = &(E.value);
if (ClassDB::ClassInfo *ptr = ClassDB::classes.getptr(StringName(E.value.name))) {
@ -336,13 +334,50 @@ bool GDScriptLanguageProtocol::is_goto_native_symbols_enabled() const {
return bool(_EDITOR_GET("network/language_server/show_native_symbols_in_editor"));
}
// clang-format off
#define SET_DOCUMENT_METHOD(m_method) set_method(_STR(textDocument/m_method), callable_mp(text_document.ptr(), &GDScriptTextDocument::m_method))
#define SET_COMPLETION_METHOD(m_method) set_method(_STR(completionItem/m_method), callable_mp(text_document.ptr(), &GDScriptTextDocument::m_method))
#define SET_WORKSPACE_METHOD(m_method) set_method(_STR(workspace/m_method), callable_mp(workspace.ptr(), &GDScriptWorkspace::m_method))
// clang-format on
GDScriptLanguageProtocol::GDScriptLanguageProtocol() {
server.instantiate();
singleton = this;
workspace.instantiate();
text_document.instantiate();
set_scope("textDocument", text_document.ptr());
set_scope("completionItem", text_document.ptr());
set_scope("workspace", workspace.ptr());
SET_DOCUMENT_METHOD(didOpen);
SET_DOCUMENT_METHOD(didClose);
SET_DOCUMENT_METHOD(didChange);
SET_DOCUMENT_METHOD(willSaveWaitUntil);
SET_DOCUMENT_METHOD(didSave);
SET_DOCUMENT_METHOD(documentSymbol);
SET_DOCUMENT_METHOD(completion);
SET_DOCUMENT_METHOD(rename);
SET_DOCUMENT_METHOD(prepareRename);
SET_DOCUMENT_METHOD(references);
SET_DOCUMENT_METHOD(foldingRange);
SET_DOCUMENT_METHOD(codeLens);
SET_DOCUMENT_METHOD(documentLink);
SET_DOCUMENT_METHOD(colorPresentation);
SET_DOCUMENT_METHOD(hover);
SET_DOCUMENT_METHOD(definition);
SET_DOCUMENT_METHOD(declaration);
SET_DOCUMENT_METHOD(signatureHelp);
SET_DOCUMENT_METHOD(nativeSymbol); // Custom method.
SET_COMPLETION_METHOD(resolve);
SET_WORKSPACE_METHOD(didDeleteFiles);
set_method("initialize", callable_mp(this, &GDScriptLanguageProtocol::initialize));
set_method("initialized", callable_mp(this, &GDScriptLanguageProtocol::initialized));
workspace->root = ProjectSettings::get_singleton()->get_resource_path();
}
#undef SET_DOCUMENT_METHOD
#undef SET_COMPLETION_METHOD
#undef SET_WORKSPACE_METHOD

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef GDSCRIPT_LANGUAGE_PROTOCOL_H
#define GDSCRIPT_LANGUAGE_PROTOCOL_H
#pragma once
#include "gdscript_text_document.h"
#include "gdscript_workspace.h"
@ -37,12 +36,7 @@
#include "core/io/stream_peer_tcp.h"
#include "core/io/tcp_server.h"
#include "modules/modules_enabled.gen.h" // For jsonrpc.
#ifdef MODULE_JSONRPC_ENABLED
#include "modules/jsonrpc/jsonrpc.h"
#else
#error "Can't build GDScript LSP without JSONRPC module."
#endif
#define LSP_MAX_BUFFER_SIZE 4194304
#define LSP_MAX_CLIENTS 8
@ -115,5 +109,3 @@ public:
GDScriptLanguageProtocol();
};
#endif // GDSCRIPT_LANGUAGE_PROTOCOL_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef GDSCRIPT_LANGUAGE_SERVER_H
#define GDSCRIPT_LANGUAGE_SERVER_H
#pragma once
#include "gdscript_language_protocol.h"
@ -60,5 +59,3 @@ public:
};
void register_lsp_types();
#endif // GDSCRIPT_LANGUAGE_SERVER_H

View file

@ -63,7 +63,7 @@ void GDScriptTextDocument::_bind_methods() {
}
void GDScriptTextDocument::didOpen(const Variant &p_param) {
lsp::TextDocumentItem doc = load_document_item(p_param);
LSP::TextDocumentItem doc = load_document_item(p_param);
sync_script_content(doc.uri, doc.text);
}
@ -73,11 +73,11 @@ void GDScriptTextDocument::didClose(const Variant &p_param) {
}
void GDScriptTextDocument::didChange(const Variant &p_param) {
lsp::TextDocumentItem doc = load_document_item(p_param);
LSP::TextDocumentItem doc = load_document_item(p_param);
Dictionary dict = p_param;
Array contentChanges = dict["contentChanges"];
for (int i = 0; i < contentChanges.size(); ++i) {
lsp::TextDocumentContentChangeEvent evt;
LSP::TextDocumentContentChangeEvent evt;
evt.load(contentChanges[i]);
doc.text = evt.text;
}
@ -85,7 +85,7 @@ void GDScriptTextDocument::didChange(const Variant &p_param) {
}
void GDScriptTextDocument::willSaveWaitUntil(const Variant &p_param) {
lsp::TextDocumentItem doc = load_document_item(p_param);
LSP::TextDocumentItem doc = load_document_item(p_param);
String path = GDScriptLanguageProtocol::get_singleton()->get_workspace()->get_file_path(doc.uri);
Ref<Script> scr = ResourceLoader::load(path);
@ -95,7 +95,7 @@ void GDScriptTextDocument::willSaveWaitUntil(const Variant &p_param) {
}
void GDScriptTextDocument::didSave(const Variant &p_param) {
lsp::TextDocumentItem doc = load_document_item(p_param);
LSP::TextDocumentItem doc = load_document_item(p_param);
Dictionary dict = p_param;
String text = dict["text"];
@ -126,14 +126,14 @@ void GDScriptTextDocument::reload_script(Ref<GDScript> p_to_reload_script) {
ScriptEditor::get_singleton()->trigger_live_script_reload(p_to_reload_script->get_path());
}
lsp::TextDocumentItem GDScriptTextDocument::load_document_item(const Variant &p_param) {
lsp::TextDocumentItem doc;
LSP::TextDocumentItem GDScriptTextDocument::load_document_item(const Variant &p_param) {
LSP::TextDocumentItem doc;
Dictionary params = p_param;
doc.load(params["textDocument"]);
return doc;
}
void GDScriptTextDocument::notify_client_show_symbol(const lsp::DocumentSymbol *symbol) {
void GDScriptTextDocument::notify_client_show_symbol(const LSP::DocumentSymbol *symbol) {
ERR_FAIL_NULL(symbol);
GDScriptLanguageProtocol::get_singleton()->notify_client("gdscript/show_native_symbol", symbol->to_json(true));
}
@ -143,9 +143,9 @@ void GDScriptTextDocument::initialize() {
for (const KeyValue<StringName, ClassMembers> &E : GDScriptLanguageProtocol::get_singleton()->get_workspace()->native_members) {
const ClassMembers &members = E.value;
for (const KeyValue<String, const lsp::DocumentSymbol *> &F : members) {
const lsp::DocumentSymbol *symbol = members.get(F.key);
lsp::CompletionItem item = symbol->make_completion_item();
for (const KeyValue<String, const LSP::DocumentSymbol *> &F : members) {
const LSP::DocumentSymbol *symbol = members.get(F.key);
LSP::CompletionItem item = symbol->make_completion_item();
item.data = JOIN_SYMBOLS(String(E.key), F.key);
native_member_completions.push_back(item.to_json());
}
@ -156,10 +156,10 @@ void GDScriptTextDocument::initialize() {
Variant GDScriptTextDocument::nativeSymbol(const Dictionary &p_params) {
Variant ret;
lsp::NativeSymbolInspectParams params;
LSP::NativeSymbolInspectParams params;
params.load(p_params);
if (const lsp::DocumentSymbol *symbol = GDScriptLanguageProtocol::get_singleton()->get_workspace()->resolve_native_symbol(params)) {
if (const LSP::DocumentSymbol *symbol = GDScriptLanguageProtocol::get_singleton()->get_workspace()->resolve_native_symbol(params)) {
ret = symbol->to_json(true);
notify_client_show_symbol(symbol);
}
@ -173,7 +173,7 @@ Array GDScriptTextDocument::documentSymbol(const Dictionary &p_params) {
String path = GDScriptLanguageProtocol::get_singleton()->get_workspace()->get_file_path(uri);
Array arr;
if (HashMap<String, ExtendGDScriptParser *>::ConstIterator parser = GDScriptLanguageProtocol::get_singleton()->get_workspace()->scripts.find(path)) {
lsp::DocumentSymbol symbol = parser->value->get_symbols();
LSP::DocumentSymbol symbol = parser->value->get_symbols();
arr.push_back(symbol.to_json(true));
}
return arr;
@ -182,7 +182,7 @@ Array GDScriptTextDocument::documentSymbol(const Dictionary &p_params) {
Array GDScriptTextDocument::completion(const Dictionary &p_params) {
Array arr;
lsp::CompletionParams params;
LSP::CompletionParams params;
params.load(p_params);
Dictionary request_data = params.to_json();
@ -194,41 +194,41 @@ Array GDScriptTextDocument::completion(const Dictionary &p_params) {
arr.resize(options.size());
for (const ScriptLanguage::CodeCompletionOption &option : options) {
lsp::CompletionItem item;
LSP::CompletionItem item;
item.label = option.display;
item.data = request_data;
item.insertText = option.insert_text;
switch (option.kind) {
case ScriptLanguage::CODE_COMPLETION_KIND_ENUM:
item.kind = lsp::CompletionItemKind::Enum;
item.kind = LSP::CompletionItemKind::Enum;
break;
case ScriptLanguage::CODE_COMPLETION_KIND_CLASS:
item.kind = lsp::CompletionItemKind::Class;
item.kind = LSP::CompletionItemKind::Class;
break;
case ScriptLanguage::CODE_COMPLETION_KIND_MEMBER:
item.kind = lsp::CompletionItemKind::Property;
item.kind = LSP::CompletionItemKind::Property;
break;
case ScriptLanguage::CODE_COMPLETION_KIND_FUNCTION:
item.kind = lsp::CompletionItemKind::Method;
item.kind = LSP::CompletionItemKind::Method;
break;
case ScriptLanguage::CODE_COMPLETION_KIND_SIGNAL:
item.kind = lsp::CompletionItemKind::Event;
item.kind = LSP::CompletionItemKind::Event;
break;
case ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT:
item.kind = lsp::CompletionItemKind::Constant;
item.kind = LSP::CompletionItemKind::Constant;
break;
case ScriptLanguage::CODE_COMPLETION_KIND_VARIABLE:
item.kind = lsp::CompletionItemKind::Variable;
item.kind = LSP::CompletionItemKind::Variable;
break;
case ScriptLanguage::CODE_COMPLETION_KIND_FILE_PATH:
item.kind = lsp::CompletionItemKind::File;
item.kind = LSP::CompletionItemKind::File;
break;
case ScriptLanguage::CODE_COMPLETION_KIND_NODE_PATH:
item.kind = lsp::CompletionItemKind::Snippet;
item.kind = LSP::CompletionItemKind::Snippet;
break;
case ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT:
item.kind = lsp::CompletionItemKind::Text;
item.kind = LSP::CompletionItemKind::Text;
break;
default: {
}
@ -242,7 +242,7 @@ Array GDScriptTextDocument::completion(const Dictionary &p_params) {
}
Dictionary GDScriptTextDocument::rename(const Dictionary &p_params) {
lsp::TextDocumentPositionParams params;
LSP::TextDocumentPositionParams params;
params.load(p_params);
String new_name = p_params["newName"];
@ -250,11 +250,11 @@ Dictionary GDScriptTextDocument::rename(const Dictionary &p_params) {
}
Variant GDScriptTextDocument::prepareRename(const Dictionary &p_params) {
lsp::TextDocumentPositionParams params;
LSP::TextDocumentPositionParams params;
params.load(p_params);
lsp::DocumentSymbol symbol;
lsp::Range range;
LSP::DocumentSymbol symbol;
LSP::Range range;
if (GDScriptLanguageProtocol::get_singleton()->get_workspace()->can_rename(params, symbol, range)) {
return Variant(range.to_json());
}
@ -266,16 +266,16 @@ Variant GDScriptTextDocument::prepareRename(const Dictionary &p_params) {
Array GDScriptTextDocument::references(const Dictionary &p_params) {
Array res;
lsp::ReferenceParams params;
LSP::ReferenceParams params;
params.load(p_params);
const lsp::DocumentSymbol *symbol = GDScriptLanguageProtocol::get_singleton()->get_workspace()->resolve_symbol(params);
const LSP::DocumentSymbol *symbol = GDScriptLanguageProtocol::get_singleton()->get_workspace()->resolve_symbol(params);
if (symbol) {
Vector<lsp::Location> usages = GDScriptLanguageProtocol::get_singleton()->get_workspace()->find_all_usages(*symbol);
Vector<LSP::Location> usages = GDScriptLanguageProtocol::get_singleton()->get_workspace()->find_all_usages(*symbol);
res.resize(usages.size());
int declaration_adjustment = 0;
for (int i = 0; i < usages.size(); i++) {
lsp::Location usage = usages[i];
LSP::Location usage = usages[i];
if (!params.context.includeDeclaration && usage.range == symbol->range) {
declaration_adjustment++;
continue;
@ -292,17 +292,17 @@ Array GDScriptTextDocument::references(const Dictionary &p_params) {
}
Dictionary GDScriptTextDocument::resolve(const Dictionary &p_params) {
lsp::CompletionItem item;
LSP::CompletionItem item;
item.load(p_params);
lsp::CompletionParams params;
LSP::CompletionParams params;
Variant data = p_params["data"];
const lsp::DocumentSymbol *symbol = nullptr;
const LSP::DocumentSymbol *symbol = nullptr;
if (data.get_type() == Variant::DICTIONARY) {
params.load(p_params["data"]);
symbol = GDScriptLanguageProtocol::get_singleton()->get_workspace()->resolve_symbol(params, item.label, item.kind == lsp::CompletionItemKind::Method || item.kind == lsp::CompletionItemKind::Function);
symbol = GDScriptLanguageProtocol::get_singleton()->get_workspace()->resolve_symbol(params, item.label, item.kind == LSP::CompletionItemKind::Method || item.kind == LSP::CompletionItemKind::Function);
} else if (data.is_string()) {
String query = data;
@ -318,7 +318,7 @@ Dictionary GDScriptTextDocument::resolve(const Dictionary &p_params) {
}
if (const ClassMembers *members = GDScriptLanguageProtocol::get_singleton()->get_workspace()->native_members.getptr(class_name)) {
if (const lsp::DocumentSymbol *const *member = members->getptr(member_name)) {
if (const LSP::DocumentSymbol *const *member = members->getptr(member_name)) {
symbol = *member;
}
}
@ -335,15 +335,15 @@ Dictionary GDScriptTextDocument::resolve(const Dictionary &p_params) {
item.documentation = symbol->render();
}
if (item.kind == lsp::CompletionItemKind::Event) {
if (params.context.triggerKind == lsp::CompletionTriggerKind::TriggerCharacter && (params.context.triggerCharacter == "(")) {
if (item.kind == LSP::CompletionItemKind::Event) {
if (params.context.triggerKind == LSP::CompletionTriggerKind::TriggerCharacter && (params.context.triggerCharacter == "(")) {
const String quote_style = EDITOR_GET("text_editor/completion/use_single_quotes") ? "'" : "\"";
item.insertText = item.label.quote(quote_style);
}
}
if (item.kind == lsp::CompletionItemKind::Method) {
bool is_trigger_character = params.context.triggerKind == lsp::CompletionTriggerKind::TriggerCharacter;
if (item.kind == LSP::CompletionItemKind::Method) {
bool is_trigger_character = params.context.triggerKind == LSP::CompletionTriggerKind::TriggerCharacter;
bool is_quote_character = params.context.triggerCharacter == "\"" || params.context.triggerCharacter == "'";
if (is_trigger_character && is_quote_character && item.insertText.is_quoted()) {
@ -367,12 +367,12 @@ Array GDScriptTextDocument::codeLens(const Dictionary &p_params) {
Array GDScriptTextDocument::documentLink(const Dictionary &p_params) {
Array ret;
lsp::DocumentLinkParams params;
LSP::DocumentLinkParams params;
params.load(p_params);
List<lsp::DocumentLink> links;
List<LSP::DocumentLink> links;
GDScriptLanguageProtocol::get_singleton()->get_workspace()->resolve_document_links(params.textDocument.uri, links);
for (const lsp::DocumentLink &E : links) {
for (const LSP::DocumentLink &E : links) {
ret.push_back(E.to_json());
}
return ret;
@ -384,12 +384,12 @@ Array GDScriptTextDocument::colorPresentation(const Dictionary &p_params) {
}
Variant GDScriptTextDocument::hover(const Dictionary &p_params) {
lsp::TextDocumentPositionParams params;
LSP::TextDocumentPositionParams params;
params.load(p_params);
const lsp::DocumentSymbol *symbol = GDScriptLanguageProtocol::get_singleton()->get_workspace()->resolve_symbol(params);
const LSP::DocumentSymbol *symbol = GDScriptLanguageProtocol::get_singleton()->get_workspace()->resolve_symbol(params);
if (symbol) {
lsp::Hover hover;
LSP::Hover hover;
hover.contents = symbol->render();
hover.range.start = params.position;
hover.range.end = params.position;
@ -398,10 +398,10 @@ Variant GDScriptTextDocument::hover(const Dictionary &p_params) {
} else if (GDScriptLanguageProtocol::get_singleton()->is_smart_resolve_enabled()) {
Dictionary ret;
Array contents;
List<const lsp::DocumentSymbol *> list;
List<const LSP::DocumentSymbol *> list;
GDScriptLanguageProtocol::get_singleton()->get_workspace()->resolve_related_symbols(params, list);
for (const lsp::DocumentSymbol *&E : list) {
if (const lsp::DocumentSymbol *s = E) {
for (const LSP::DocumentSymbol *&E : list) {
if (const LSP::DocumentSymbol *s = E) {
contents.push_back(s->render().value);
}
}
@ -413,38 +413,38 @@ Variant GDScriptTextDocument::hover(const Dictionary &p_params) {
}
Array GDScriptTextDocument::definition(const Dictionary &p_params) {
lsp::TextDocumentPositionParams params;
LSP::TextDocumentPositionParams params;
params.load(p_params);
List<const lsp::DocumentSymbol *> symbols;
List<const LSP::DocumentSymbol *> symbols;
Array arr = find_symbols(params, symbols);
return arr;
}
Variant GDScriptTextDocument::declaration(const Dictionary &p_params) {
lsp::TextDocumentPositionParams params;
LSP::TextDocumentPositionParams params;
params.load(p_params);
List<const lsp::DocumentSymbol *> symbols;
List<const LSP::DocumentSymbol *> symbols;
Array arr = find_symbols(params, symbols);
if (arr.is_empty() && !symbols.is_empty() && !symbols.front()->get()->native_class.is_empty()) { // Find a native symbol
const lsp::DocumentSymbol *symbol = symbols.front()->get();
const LSP::DocumentSymbol *symbol = symbols.front()->get();
if (GDScriptLanguageProtocol::get_singleton()->is_goto_native_symbols_enabled()) {
String id;
switch (symbol->kind) {
case lsp::SymbolKind::Class:
case LSP::SymbolKind::Class:
id = "class_name:" + symbol->name;
break;
case lsp::SymbolKind::Constant:
case LSP::SymbolKind::Constant:
id = "class_constant:" + symbol->native_class + ":" + symbol->name;
break;
case lsp::SymbolKind::Property:
case lsp::SymbolKind::Variable:
case LSP::SymbolKind::Property:
case LSP::SymbolKind::Variable:
id = "class_property:" + symbol->native_class + ":" + symbol->name;
break;
case lsp::SymbolKind::Enum:
case LSP::SymbolKind::Enum:
id = "class_enum:" + symbol->native_class + ":" + symbol->name;
break;
case lsp::SymbolKind::Method:
case lsp::SymbolKind::Function:
case LSP::SymbolKind::Method:
case LSP::SymbolKind::Function:
id = "class_method:" + symbol->native_class + ":" + symbol->name;
break;
default:
@ -462,10 +462,10 @@ Variant GDScriptTextDocument::declaration(const Dictionary &p_params) {
Variant GDScriptTextDocument::signatureHelp(const Dictionary &p_params) {
Variant ret;
lsp::TextDocumentPositionParams params;
LSP::TextDocumentPositionParams params;
params.load(p_params);
lsp::SignatureHelp s;
LSP::SignatureHelp s;
if (OK == GDScriptLanguageProtocol::get_singleton()->get_workspace()->resolve_signature(params, s)) {
ret = s.to_json();
}
@ -488,11 +488,11 @@ void GDScriptTextDocument::show_native_symbol_in_editor(const String &p_symbol_i
DisplayServer::get_singleton()->window_move_to_foreground();
}
Array GDScriptTextDocument::find_symbols(const lsp::TextDocumentPositionParams &p_location, List<const lsp::DocumentSymbol *> &r_list) {
Array GDScriptTextDocument::find_symbols(const LSP::TextDocumentPositionParams &p_location, List<const LSP::DocumentSymbol *> &r_list) {
Array arr;
const lsp::DocumentSymbol *symbol = GDScriptLanguageProtocol::get_singleton()->get_workspace()->resolve_symbol(p_location);
const LSP::DocumentSymbol *symbol = GDScriptLanguageProtocol::get_singleton()->get_workspace()->resolve_symbol(p_location);
if (symbol) {
lsp::Location location;
LSP::Location location;
location.uri = symbol->uri;
location.range = symbol->selectionRange;
const String &path = GDScriptLanguageProtocol::get_singleton()->get_workspace()->get_file_path(symbol->uri);
@ -501,12 +501,12 @@ Array GDScriptTextDocument::find_symbols(const lsp::TextDocumentPositionParams &
}
r_list.push_back(symbol);
} else if (GDScriptLanguageProtocol::get_singleton()->is_smart_resolve_enabled()) {
List<const lsp::DocumentSymbol *> list;
List<const LSP::DocumentSymbol *> list;
GDScriptLanguageProtocol::get_singleton()->get_workspace()->resolve_related_symbols(p_location, list);
for (const lsp::DocumentSymbol *&E : list) {
if (const lsp::DocumentSymbol *s = E) {
for (const LSP::DocumentSymbol *&E : list) {
if (const LSP::DocumentSymbol *s = E) {
if (!s->uri.is_empty()) {
lsp::Location location;
LSP::Location location;
location.uri = s->uri;
location.range = s->selectionRange;
arr.push_back(location.to_json());

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef GDSCRIPT_TEXT_DOCUMENT_H
#define GDSCRIPT_TEXT_DOCUMENT_H
#pragma once
#include "godot_lsp.h"
@ -45,6 +44,14 @@ protected:
Ref<FileAccess> file_checker;
Array native_member_completions;
private:
Array find_symbols(const LSP::TextDocumentPositionParams &p_location, List<const LSP::DocumentSymbol *> &r_list);
LSP::TextDocumentItem load_document_item(const Variant &p_param);
void notify_client_show_symbol(const LSP::DocumentSymbol *symbol);
public:
void didOpen(const Variant &p_param);
void didClose(const Variant &p_param);
void didChange(const Variant &p_param);
@ -55,14 +62,6 @@ protected:
void sync_script_content(const String &p_path, const String &p_content);
void show_native_symbol_in_editor(const String &p_symbol_id);
Array native_member_completions;
private:
Array find_symbols(const lsp::TextDocumentPositionParams &p_location, List<const lsp::DocumentSymbol *> &r_list);
lsp::TextDocumentItem load_document_item(const Variant &p_param);
void notify_client_show_symbol(const lsp::DocumentSymbol *symbol);
public:
Variant nativeSymbol(const Dictionary &p_params);
Array documentSymbol(const Dictionary &p_params);
Array completion(const Dictionary &p_params);
@ -83,5 +82,3 @@ public:
GDScriptTextDocument();
};
#endif // GDSCRIPT_TEXT_DOCUMENT_H

View file

@ -45,7 +45,7 @@
void GDScriptWorkspace::_bind_methods() {
ClassDB::bind_method(D_METHOD("apply_new_signal"), &GDScriptWorkspace::apply_new_signal);
ClassDB::bind_method(D_METHOD("didDeleteFiles"), &GDScriptWorkspace::did_delete_files);
ClassDB::bind_method(D_METHOD("didDeleteFiles"), &GDScriptWorkspace::didDeleteFiles);
ClassDB::bind_method(D_METHOD("parse_script", "path", "content"), &GDScriptWorkspace::parse_script);
ClassDB::bind_method(D_METHOD("parse_local_script", "path"), &GDScriptWorkspace::parse_local_script);
ClassDB::bind_method(D_METHOD("get_file_path", "uri"), &GDScriptWorkspace::get_file_path);
@ -89,7 +89,7 @@ void GDScriptWorkspace::apply_new_signal(Object *obj, String function, PackedStr
}
function_body += ":\n\tpass # Replace with function body.\n";
lsp::TextEdit text_edit;
LSP::TextEdit text_edit;
if (first_class != -1) {
function_body += "\n\n";
@ -100,13 +100,13 @@ void GDScriptWorkspace::apply_new_signal(Object *obj, String function, PackedStr
String uri = get_file_uri(scr->get_path());
lsp::ApplyWorkspaceEditParams params;
LSP::ApplyWorkspaceEditParams params;
params.edit.add_edit(uri, text_edit);
GDScriptLanguageProtocol::get_singleton()->request_client("workspace/applyEdit", params.to_json());
}
void GDScriptWorkspace::did_delete_files(const Dictionary &p_params) {
void GDScriptWorkspace::didDeleteFiles(const Dictionary &p_params) {
Array files = p_params["files"];
for (int i = 0; i < files.size(); ++i) {
Dictionary file = files[i];
@ -137,19 +137,19 @@ void GDScriptWorkspace::remove_cache_parser(const String &p_path) {
}
}
const lsp::DocumentSymbol *GDScriptWorkspace::get_native_symbol(const String &p_class, const String &p_member) const {
const LSP::DocumentSymbol *GDScriptWorkspace::get_native_symbol(const String &p_class, const String &p_member) const {
StringName class_name = p_class;
StringName empty;
while (class_name != empty) {
if (HashMap<StringName, lsp::DocumentSymbol>::ConstIterator E = native_symbols.find(class_name)) {
const lsp::DocumentSymbol &class_symbol = E->value;
if (HashMap<StringName, LSP::DocumentSymbol>::ConstIterator E = native_symbols.find(class_name)) {
const LSP::DocumentSymbol &class_symbol = E->value;
if (p_member.is_empty()) {
return &class_symbol;
} else {
for (int i = 0; i < class_symbol.children.size(); i++) {
const lsp::DocumentSymbol &symbol = class_symbol.children[i];
const LSP::DocumentSymbol &symbol = class_symbol.children[i];
if (symbol.name == p_member) {
return &symbol;
}
@ -162,7 +162,7 @@ const lsp::DocumentSymbol *GDScriptWorkspace::get_native_symbol(const String &p_
return nullptr;
}
const lsp::DocumentSymbol *GDScriptWorkspace::get_script_symbol(const String &p_path) const {
const LSP::DocumentSymbol *GDScriptWorkspace::get_script_symbol(const String &p_path) const {
HashMap<String, ExtendGDScriptParser *>::ConstIterator S = scripts.find(p_path);
if (S) {
return &(S->value->get_symbols());
@ -170,9 +170,9 @@ const lsp::DocumentSymbol *GDScriptWorkspace::get_script_symbol(const String &p_
return nullptr;
}
const lsp::DocumentSymbol *GDScriptWorkspace::get_parameter_symbol(const lsp::DocumentSymbol *p_parent, const String &symbol_identifier) {
const LSP::DocumentSymbol *GDScriptWorkspace::get_parameter_symbol(const LSP::DocumentSymbol *p_parent, const String &symbol_identifier) {
for (int i = 0; i < p_parent->children.size(); ++i) {
const lsp::DocumentSymbol *parameter_symbol = &p_parent->children[i];
const LSP::DocumentSymbol *parameter_symbol = &p_parent->children[i];
if (!parameter_symbol->detail.is_empty() && parameter_symbol->name == symbol_identifier) {
return parameter_symbol;
}
@ -181,11 +181,11 @@ const lsp::DocumentSymbol *GDScriptWorkspace::get_parameter_symbol(const lsp::Do
return nullptr;
}
const lsp::DocumentSymbol *GDScriptWorkspace::get_local_symbol_at(const ExtendGDScriptParser *p_parser, const String &p_symbol_identifier, const lsp::Position p_position) {
const LSP::DocumentSymbol *GDScriptWorkspace::get_local_symbol_at(const ExtendGDScriptParser *p_parser, const String &p_symbol_identifier, const LSP::Position p_position) {
// Go down and pick closest `DocumentSymbol` with `p_symbol_identifier`.
const lsp::DocumentSymbol *current = &p_parser->get_symbols();
const lsp::DocumentSymbol *best_match = nullptr;
const LSP::DocumentSymbol *current = &p_parser->get_symbols();
const LSP::DocumentSymbol *best_match = nullptr;
while (current) {
if (current->name == p_symbol_identifier) {
@ -197,9 +197,9 @@ const lsp::DocumentSymbol *GDScriptWorkspace::get_local_symbol_at(const ExtendGD
best_match = current;
}
const lsp::DocumentSymbol *parent = current;
const LSP::DocumentSymbol *parent = current;
current = nullptr;
for (const lsp::DocumentSymbol &child : parent->children) {
for (const LSP::DocumentSymbol &child : parent->children) {
if (child.range.contains(p_position)) {
current = &child;
break;
@ -287,11 +287,11 @@ Error GDScriptWorkspace::initialize() {
DocTools *doc = EditorHelp::get_doc_data();
for (const KeyValue<String, DocData::ClassDoc> &E : doc->class_list) {
const DocData::ClassDoc &class_data = E.value;
lsp::DocumentSymbol class_symbol;
LSP::DocumentSymbol class_symbol;
String class_name = E.key;
class_symbol.name = class_name;
class_symbol.native_class = class_name;
class_symbol.kind = lsp::SymbolKind::Class;
class_symbol.kind = LSP::SymbolKind::Class;
class_symbol.detail = String("<Native> class ") + class_name;
if (!class_data.inherits.is_empty()) {
class_symbol.detail += " extends " + class_data.inherits;
@ -300,10 +300,10 @@ Error GDScriptWorkspace::initialize() {
for (int i = 0; i < class_data.constants.size(); i++) {
const DocData::ConstantDoc &const_data = class_data.constants[i];
lsp::DocumentSymbol symbol;
LSP::DocumentSymbol symbol;
symbol.name = const_data.name;
symbol.native_class = class_name;
symbol.kind = lsp::SymbolKind::Constant;
symbol.kind = LSP::SymbolKind::Constant;
symbol.detail = "const " + class_name + "." + const_data.name;
if (const_data.enumeration.length()) {
symbol.detail += ": " + const_data.enumeration;
@ -315,10 +315,10 @@ Error GDScriptWorkspace::initialize() {
for (int i = 0; i < class_data.properties.size(); i++) {
const DocData::PropertyDoc &data = class_data.properties[i];
lsp::DocumentSymbol symbol;
LSP::DocumentSymbol symbol;
symbol.name = data.name;
symbol.native_class = class_name;
symbol.kind = lsp::SymbolKind::Property;
symbol.kind = LSP::SymbolKind::Property;
symbol.detail = "var " + class_name + "." + data.name;
if (data.enumeration.length()) {
symbol.detail += ": " + data.enumeration;
@ -331,10 +331,10 @@ Error GDScriptWorkspace::initialize() {
for (int i = 0; i < class_data.theme_properties.size(); i++) {
const DocData::ThemeItemDoc &data = class_data.theme_properties[i];
lsp::DocumentSymbol symbol;
LSP::DocumentSymbol symbol;
symbol.name = data.name;
symbol.native_class = class_name;
symbol.kind = lsp::SymbolKind::Property;
symbol.kind = LSP::SymbolKind::Property;
symbol.detail = "<Theme> var " + class_name + "." + data.name + ": " + data.type;
symbol.documentation = data.description;
class_symbol.children.push_back(symbol);
@ -350,19 +350,19 @@ Error GDScriptWorkspace::initialize() {
for (int i = 0; i < methods_signals.size(); i++) {
const DocData::MethodDoc &data = methods_signals[i];
lsp::DocumentSymbol symbol;
LSP::DocumentSymbol symbol;
symbol.name = data.name;
symbol.native_class = class_name;
symbol.kind = i >= signal_start_idx ? lsp::SymbolKind::Event : lsp::SymbolKind::Method;
symbol.kind = i >= signal_start_idx ? LSP::SymbolKind::Event : LSP::SymbolKind::Method;
String params = "";
bool arg_default_value_started = false;
for (int j = 0; j < data.arguments.size(); j++) {
const DocData::ArgumentDoc &arg = data.arguments[j];
lsp::DocumentSymbol symbol_arg;
LSP::DocumentSymbol symbol_arg;
symbol_arg.name = arg.name;
symbol_arg.kind = lsp::SymbolKind::Variable;
symbol_arg.kind = LSP::SymbolKind::Variable;
symbol_arg.detail = arg.type;
if (!arg_default_value_started && !arg.default_value.is_empty()) {
@ -398,11 +398,11 @@ Error GDScriptWorkspace::initialize() {
reload_all_workspace_scripts();
if (GDScriptLanguageProtocol::get_singleton()->is_smart_resolve_enabled()) {
for (const KeyValue<StringName, lsp::DocumentSymbol> &E : native_symbols) {
for (const KeyValue<StringName, LSP::DocumentSymbol> &E : native_symbols) {
ClassMembers members;
const lsp::DocumentSymbol &class_symbol = E.value;
const LSP::DocumentSymbol &class_symbol = E.value;
for (int i = 0; i < class_symbol.children.size(); i++) {
const lsp::DocumentSymbol &symbol = class_symbol.children[i];
const LSP::DocumentSymbol &symbol = class_symbol.children[i];
members.insert(symbol.name, &symbol);
}
native_members.insert(E.key, members);
@ -443,7 +443,7 @@ Error GDScriptWorkspace::parse_script(const String &p_path, const String &p_cont
return err;
}
static bool is_valid_rename_target(const lsp::DocumentSymbol *p_symbol) {
static bool is_valid_rename_target(const LSP::DocumentSymbol *p_symbol) {
// Must be valid symbol.
if (!p_symbol) {
return false;
@ -462,14 +462,14 @@ static bool is_valid_rename_target(const lsp::DocumentSymbol *p_symbol) {
return true;
}
Dictionary GDScriptWorkspace::rename(const lsp::TextDocumentPositionParams &p_doc_pos, const String &new_name) {
lsp::WorkspaceEdit edit;
Dictionary GDScriptWorkspace::rename(const LSP::TextDocumentPositionParams &p_doc_pos, const String &new_name) {
LSP::WorkspaceEdit edit;
const lsp::DocumentSymbol *reference_symbol = resolve_symbol(p_doc_pos);
const LSP::DocumentSymbol *reference_symbol = resolve_symbol(p_doc_pos);
if (is_valid_rename_target(reference_symbol)) {
Vector<lsp::Location> usages = find_all_usages(*reference_symbol);
Vector<LSP::Location> usages = find_all_usages(*reference_symbol);
for (int i = 0; i < usages.size(); ++i) {
lsp::Location loc = usages[i];
LSP::Location loc = usages[i];
edit.add_change(loc.uri, loc.range.start.line, loc.range.start.character, loc.range.end.character, new_name);
}
@ -478,8 +478,8 @@ Dictionary GDScriptWorkspace::rename(const lsp::TextDocumentPositionParams &p_do
return edit.to_json();
}
bool GDScriptWorkspace::can_rename(const lsp::TextDocumentPositionParams &p_doc_pos, lsp::DocumentSymbol &r_symbol, lsp::Range &r_range) {
const lsp::DocumentSymbol *reference_symbol = resolve_symbol(p_doc_pos);
bool GDScriptWorkspace::can_rename(const LSP::TextDocumentPositionParams &p_doc_pos, LSP::DocumentSymbol &r_symbol, LSP::Range &r_range) {
const LSP::DocumentSymbol *reference_symbol = resolve_symbol(p_doc_pos);
if (!is_valid_rename_target(reference_symbol)) {
return false;
}
@ -494,8 +494,8 @@ bool GDScriptWorkspace::can_rename(const lsp::TextDocumentPositionParams &p_doc_
return false;
}
Vector<lsp::Location> GDScriptWorkspace::find_usages_in_file(const lsp::DocumentSymbol &p_symbol, const String &p_file_path) {
Vector<lsp::Location> usages;
Vector<LSP::Location> GDScriptWorkspace::find_usages_in_file(const LSP::DocumentSymbol &p_symbol, const String &p_file_path) {
Vector<LSP::Location> usages;
String identifier = p_symbol.name;
if (const ExtendGDScriptParser *parser = get_parse_result(p_file_path)) {
@ -505,19 +505,19 @@ Vector<lsp::Location> GDScriptWorkspace::find_usages_in_file(const lsp::Document
int character = line.find(identifier);
while (character > -1) {
lsp::TextDocumentPositionParams params;
LSP::TextDocumentPositionParams params;
lsp::TextDocumentIdentifier text_doc;
LSP::TextDocumentIdentifier text_doc;
text_doc.uri = get_file_uri(p_file_path);
params.textDocument = text_doc;
params.position.line = i;
params.position.character = character;
const lsp::DocumentSymbol *other_symbol = resolve_symbol(params);
const LSP::DocumentSymbol *other_symbol = resolve_symbol(params);
if (other_symbol == &p_symbol) {
lsp::Location loc;
LSP::Location loc;
loc.uri = text_doc.uri;
loc.range.start = params.position;
loc.range.end.line = params.position.line;
@ -533,7 +533,7 @@ Vector<lsp::Location> GDScriptWorkspace::find_usages_in_file(const lsp::Document
return usages;
}
Vector<lsp::Location> GDScriptWorkspace::find_all_usages(const lsp::DocumentSymbol &p_symbol) {
Vector<LSP::Location> GDScriptWorkspace::find_all_usages(const LSP::DocumentSymbol &p_symbol) {
if (p_symbol.local) {
// Only search in current document.
return find_usages_in_file(p_symbol, p_symbol.script_path);
@ -542,9 +542,9 @@ Vector<lsp::Location> GDScriptWorkspace::find_all_usages(const lsp::DocumentSymb
List<String> paths;
list_script_files("res://", paths);
Vector<lsp::Location> usages;
for (List<String>::Element *PE = paths.front(); PE; PE = PE->next()) {
usages.append_array(find_usages_in_file(p_symbol, PE->get()));
Vector<LSP::Location> usages;
for (const String &path : paths) {
usages.append_array(find_usages_in_file(p_symbol, path));
}
return usages;
}
@ -559,8 +559,8 @@ Error GDScriptWorkspace::parse_local_script(const String &p_path) {
}
String GDScriptWorkspace::get_file_path(const String &p_uri) const {
String path = p_uri.uri_decode();
String base_uri = root_uri.uri_decode();
String path = p_uri.uri_file_decode();
String base_uri = root_uri.uri_file_decode();
path = path.replacen(base_uri + "/", "res://");
return path;
}
@ -576,7 +576,7 @@ void GDScriptWorkspace::publish_diagnostics(const String &p_path) {
Array errors;
HashMap<String, ExtendGDScriptParser *>::ConstIterator ele = parse_results.find(p_path);
if (ele) {
const Vector<lsp::Diagnostic> &list = ele->value->get_diagnostics();
const Vector<LSP::Diagnostic> &list = ele->value->get_diagnostics();
errors.resize(list.size());
for (int i = 0; i < list.size(); ++i) {
errors[i] = list[i].to_json();
@ -632,7 +632,7 @@ Node *GDScriptWorkspace::_get_owner_scene_node(String p_path) {
return owner_scene_node;
}
void GDScriptWorkspace::completion(const lsp::CompletionParams &p_params, List<ScriptLanguage::CodeCompletionOption> *r_options) {
void GDScriptWorkspace::completion(const LSP::CompletionParams &p_params, List<ScriptLanguage::CodeCompletionOption> *r_options) {
String path = get_file_path(p_params.textDocument.uri);
String call_hint;
bool forced = false;
@ -670,8 +670,8 @@ void GDScriptWorkspace::completion(const lsp::CompletionParams &p_params, List<S
}
}
const lsp::DocumentSymbol *GDScriptWorkspace::resolve_symbol(const lsp::TextDocumentPositionParams &p_doc_pos, const String &p_symbol_name, bool p_func_required) {
const lsp::DocumentSymbol *symbol = nullptr;
const LSP::DocumentSymbol *GDScriptWorkspace::resolve_symbol(const LSP::TextDocumentPositionParams &p_doc_pos, const String &p_symbol_name, bool p_func_required) {
const LSP::DocumentSymbol *symbol = nullptr;
String path = get_file_path(p_doc_pos.textDocument.uri);
if (const ExtendGDScriptParser *parser = get_parse_result(path)) {
@ -681,9 +681,9 @@ const lsp::DocumentSymbol *GDScriptWorkspace::resolve_symbol(const lsp::TextDocu
symbol_identifier = identifier_parts[0];
}
lsp::Position pos = p_doc_pos.position;
LSP::Position pos = p_doc_pos.position;
if (symbol_identifier.is_empty()) {
lsp::Range range;
LSP::Range range;
symbol_identifier = parser->get_identifier_under_position(p_doc_pos.position, range);
pos.character = range.end.character;
}
@ -695,7 +695,7 @@ const lsp::DocumentSymbol *GDScriptWorkspace::resolve_symbol(const lsp::TextDocu
} else {
ScriptLanguage::LookupResult ret;
if (symbol_identifier == "new" && parser->get_lines()[p_doc_pos.position.line].replace(" ", "").replace("\t", "").contains("new(")) {
if (symbol_identifier == "new" && parser->get_lines()[p_doc_pos.position.line].remove_chars(" \t").contains("new(")) {
symbol_identifier = "_init";
}
if (OK == GDScriptLanguage::get_singleton()->lookup_code(parser->get_text_for_lookup_symbol(pos, symbol_identifier, p_func_required), symbol_identifier, path, nullptr, ret)) {
@ -712,7 +712,7 @@ const lsp::DocumentSymbol *GDScriptWorkspace::resolve_symbol(const lsp::TextDocu
if (symbol) {
switch (symbol->kind) {
case lsp::SymbolKind::Function: {
case LSP::SymbolKind::Function: {
if (symbol->name != symbol_identifier) {
symbol = get_parameter_symbol(symbol, symbol_identifier);
}
@ -740,16 +740,16 @@ const lsp::DocumentSymbol *GDScriptWorkspace::resolve_symbol(const lsp::TextDocu
return symbol;
}
void GDScriptWorkspace::resolve_related_symbols(const lsp::TextDocumentPositionParams &p_doc_pos, List<const lsp::DocumentSymbol *> &r_list) {
void GDScriptWorkspace::resolve_related_symbols(const LSP::TextDocumentPositionParams &p_doc_pos, List<const LSP::DocumentSymbol *> &r_list) {
String path = get_file_path(p_doc_pos.textDocument.uri);
if (const ExtendGDScriptParser *parser = get_parse_result(path)) {
String symbol_identifier;
lsp::Range range;
LSP::Range range;
symbol_identifier = parser->get_identifier_under_position(p_doc_pos.position, range);
for (const KeyValue<StringName, ClassMembers> &E : native_members) {
const ClassMembers &members = native_members.get(E.key);
if (const lsp::DocumentSymbol *const *symbol = members.getptr(symbol_identifier)) {
if (const LSP::DocumentSymbol *const *symbol = members.getptr(symbol_identifier)) {
r_list.push_back(*symbol);
}
}
@ -757,13 +757,13 @@ void GDScriptWorkspace::resolve_related_symbols(const lsp::TextDocumentPositionP
for (const KeyValue<String, ExtendGDScriptParser *> &E : scripts) {
const ExtendGDScriptParser *scr = E.value;
const ClassMembers &members = scr->get_members();
if (const lsp::DocumentSymbol *const *symbol = members.getptr(symbol_identifier)) {
if (const LSP::DocumentSymbol *const *symbol = members.getptr(symbol_identifier)) {
r_list.push_back(*symbol);
}
for (const KeyValue<String, ClassMembers> &F : scr->get_inner_classes()) {
const ClassMembers *inner_class = &F.value;
if (const lsp::DocumentSymbol *const *symbol = inner_class->getptr(symbol_identifier)) {
if (const LSP::DocumentSymbol *const *symbol = inner_class->getptr(symbol_identifier)) {
r_list.push_back(*symbol);
}
}
@ -771,9 +771,9 @@ void GDScriptWorkspace::resolve_related_symbols(const lsp::TextDocumentPositionP
}
}
const lsp::DocumentSymbol *GDScriptWorkspace::resolve_native_symbol(const lsp::NativeSymbolInspectParams &p_params) {
if (HashMap<StringName, lsp::DocumentSymbol>::Iterator E = native_symbols.find(p_params.native_class)) {
const lsp::DocumentSymbol &symbol = E->value;
const LSP::DocumentSymbol *GDScriptWorkspace::resolve_native_symbol(const LSP::NativeSymbolInspectParams &p_params) {
if (HashMap<StringName, LSP::DocumentSymbol>::Iterator E = native_symbols.find(p_params.native_class)) {
const LSP::DocumentSymbol &symbol = E->value;
if (p_params.symbol_name.is_empty() || p_params.symbol_name == symbol.name) {
return &symbol;
}
@ -788,10 +788,10 @@ const lsp::DocumentSymbol *GDScriptWorkspace::resolve_native_symbol(const lsp::N
return nullptr;
}
void GDScriptWorkspace::resolve_document_links(const String &p_uri, List<lsp::DocumentLink> &r_list) {
void GDScriptWorkspace::resolve_document_links(const String &p_uri, List<LSP::DocumentLink> &r_list) {
if (const ExtendGDScriptParser *parser = get_parse_successed_script(get_file_path(p_uri))) {
const List<lsp::DocumentLink> &links = parser->get_document_links();
for (const lsp::DocumentLink &E : links) {
const List<LSP::DocumentLink> &links = parser->get_document_links();
for (const LSP::DocumentLink &E : links) {
r_list.push_back(E);
}
}
@ -805,29 +805,29 @@ Dictionary GDScriptWorkspace::generate_script_api(const String &p_path) {
return api;
}
Error GDScriptWorkspace::resolve_signature(const lsp::TextDocumentPositionParams &p_doc_pos, lsp::SignatureHelp &r_signature) {
Error GDScriptWorkspace::resolve_signature(const LSP::TextDocumentPositionParams &p_doc_pos, LSP::SignatureHelp &r_signature) {
if (const ExtendGDScriptParser *parser = get_parse_result(get_file_path(p_doc_pos.textDocument.uri))) {
lsp::TextDocumentPositionParams text_pos;
LSP::TextDocumentPositionParams text_pos;
text_pos.textDocument = p_doc_pos.textDocument;
if (parser->get_left_function_call(p_doc_pos.position, text_pos.position, r_signature.activeParameter) == OK) {
List<const lsp::DocumentSymbol *> symbols;
List<const LSP::DocumentSymbol *> symbols;
if (const lsp::DocumentSymbol *symbol = resolve_symbol(text_pos)) {
if (const LSP::DocumentSymbol *symbol = resolve_symbol(text_pos)) {
symbols.push_back(symbol);
} else if (GDScriptLanguageProtocol::get_singleton()->is_smart_resolve_enabled()) {
GDScriptLanguageProtocol::get_singleton()->get_workspace()->resolve_related_symbols(text_pos, symbols);
}
for (const lsp::DocumentSymbol *const &symbol : symbols) {
if (symbol->kind == lsp::SymbolKind::Method || symbol->kind == lsp::SymbolKind::Function) {
lsp::SignatureInformation signature_info;
for (const LSP::DocumentSymbol *const &symbol : symbols) {
if (symbol->kind == LSP::SymbolKind::Method || symbol->kind == LSP::SymbolKind::Function) {
LSP::SignatureInformation signature_info;
signature_info.label = symbol->detail;
signature_info.documentation = symbol->render();
for (int i = 0; i < symbol->children.size(); i++) {
const lsp::DocumentSymbol &arg = symbol->children[i];
lsp::ParameterInformation arg_info;
const LSP::DocumentSymbol &arg = symbol->children[i];
LSP::ParameterInformation arg_info;
arg_info.label = arg.name;
signature_info.parameters.push_back(arg_info);
}

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef GDSCRIPT_WORKSPACE_H
#define GDSCRIPT_WORKSPACE_H
#pragma once
#include "../gdscript_parser.h"
#include "gdscript_extend_parser.h"
@ -49,12 +48,12 @@ protected:
static void _bind_methods();
void remove_cache_parser(const String &p_path);
bool initialized = false;
HashMap<StringName, lsp::DocumentSymbol> native_symbols;
HashMap<StringName, LSP::DocumentSymbol> native_symbols;
const lsp::DocumentSymbol *get_native_symbol(const String &p_class, const String &p_member = "") const;
const lsp::DocumentSymbol *get_script_symbol(const String &p_path) const;
const lsp::DocumentSymbol *get_parameter_symbol(const lsp::DocumentSymbol *p_parent, const String &symbol_identifier);
const lsp::DocumentSymbol *get_local_symbol_at(const ExtendGDScriptParser *p_parser, const String &p_symbol_identifier, const lsp::Position p_position);
const LSP::DocumentSymbol *get_native_symbol(const String &p_class, const String &p_member = "") const;
const LSP::DocumentSymbol *get_script_symbol(const String &p_path) const;
const LSP::DocumentSymbol *get_parameter_symbol(const LSP::DocumentSymbol *p_parent, const String &symbol_identifier);
const LSP::DocumentSymbol *get_local_symbol_at(const ExtendGDScriptParser *p_parser, const String &p_symbol_identifier, const LSP::Position p_position);
void reload_all_workspace_scripts();
@ -83,22 +82,20 @@ public:
String get_file_uri(const String &p_path) const;
void publish_diagnostics(const String &p_path);
void completion(const lsp::CompletionParams &p_params, List<ScriptLanguage::CodeCompletionOption> *r_options);
void completion(const LSP::CompletionParams &p_params, List<ScriptLanguage::CodeCompletionOption> *r_options);
const lsp::DocumentSymbol *resolve_symbol(const lsp::TextDocumentPositionParams &p_doc_pos, const String &p_symbol_name = "", bool p_func_required = false);
void resolve_related_symbols(const lsp::TextDocumentPositionParams &p_doc_pos, List<const lsp::DocumentSymbol *> &r_list);
const lsp::DocumentSymbol *resolve_native_symbol(const lsp::NativeSymbolInspectParams &p_params);
void resolve_document_links(const String &p_uri, List<lsp::DocumentLink> &r_list);
const LSP::DocumentSymbol *resolve_symbol(const LSP::TextDocumentPositionParams &p_doc_pos, const String &p_symbol_name = "", bool p_func_required = false);
void resolve_related_symbols(const LSP::TextDocumentPositionParams &p_doc_pos, List<const LSP::DocumentSymbol *> &r_list);
const LSP::DocumentSymbol *resolve_native_symbol(const LSP::NativeSymbolInspectParams &p_params);
void resolve_document_links(const String &p_uri, List<LSP::DocumentLink> &r_list);
Dictionary generate_script_api(const String &p_path);
Error resolve_signature(const lsp::TextDocumentPositionParams &p_doc_pos, lsp::SignatureHelp &r_signature);
void did_delete_files(const Dictionary &p_params);
Dictionary rename(const lsp::TextDocumentPositionParams &p_doc_pos, const String &new_name);
bool can_rename(const lsp::TextDocumentPositionParams &p_doc_pos, lsp::DocumentSymbol &r_symbol, lsp::Range &r_range);
Vector<lsp::Location> find_usages_in_file(const lsp::DocumentSymbol &p_symbol, const String &p_file_path);
Vector<lsp::Location> find_all_usages(const lsp::DocumentSymbol &p_symbol);
Error resolve_signature(const LSP::TextDocumentPositionParams &p_doc_pos, LSP::SignatureHelp &r_signature);
void didDeleteFiles(const Dictionary &p_params);
Dictionary rename(const LSP::TextDocumentPositionParams &p_doc_pos, const String &new_name);
bool can_rename(const LSP::TextDocumentPositionParams &p_doc_pos, LSP::DocumentSymbol &r_symbol, LSP::Range &r_range);
Vector<LSP::Location> find_usages_in_file(const LSP::DocumentSymbol &p_symbol, const String &p_file_path);
Vector<LSP::Location> find_all_usages(const LSP::DocumentSymbol &p_symbol);
GDScriptWorkspace();
~GDScriptWorkspace();
};
#endif // GDSCRIPT_WORKSPACE_H

View file

@ -28,14 +28,13 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef GODOT_LSP_H
#define GODOT_LSP_H
#pragma once
#include "core/doc_data.h"
#include "core/object/class_db.h"
#include "core/templates/list.h"
namespace lsp {
namespace LSP {
typedef String DocumentUri;
@ -384,7 +383,7 @@ struct Command {
};
// Use namespace instead of enumeration to follow the LSP specifications.
// `lsp::EnumName::EnumValue` is OK but `lsp::EnumValue` is not.
// `LSP::EnumName::EnumValue` is OK but `LSP::EnumValue` is not.
namespace TextDocumentSyncKind {
/**
@ -861,7 +860,7 @@ struct MarkupContent {
};
// Use namespace instead of enumeration to follow the LSP specifications
// `lsp::EnumName::EnumValue` is OK but `lsp::EnumValue` is not.
// `LSP::EnumName::EnumValue` is OK but `LSP::EnumValue` is not.
// And here C++ compilers are unhappy with our enumeration name like `Color`, `File`, `RefCounted` etc.
/**
* The kind of a completion entry.
@ -1118,7 +1117,7 @@ struct CompletionList {
};
// Use namespace instead of enumeration to follow the LSP specifications
// `lsp::EnumName::EnumValue` is OK but `lsp::EnumValue` is not
// `LSP::EnumName::EnumValue` is OK but `LSP::EnumValue` is not
// And here C++ compilers are unhappy with our enumeration name like `String`, `Array`, `Object` etc
/**
* A symbol kind.
@ -1259,7 +1258,7 @@ struct DocumentSymbol {
}
_FORCE_INLINE_ CompletionItem make_completion_item(bool resolved = false) const {
lsp::CompletionItem item;
LSP::CompletionItem item;
item.label = name;
if (resolved) {
@ -1267,33 +1266,33 @@ struct DocumentSymbol {
}
switch (kind) {
case lsp::SymbolKind::Enum:
item.kind = lsp::CompletionItemKind::Enum;
case LSP::SymbolKind::Enum:
item.kind = LSP::CompletionItemKind::Enum;
break;
case lsp::SymbolKind::Class:
item.kind = lsp::CompletionItemKind::Class;
case LSP::SymbolKind::Class:
item.kind = LSP::CompletionItemKind::Class;
break;
case lsp::SymbolKind::Property:
item.kind = lsp::CompletionItemKind::Property;
case LSP::SymbolKind::Property:
item.kind = LSP::CompletionItemKind::Property;
break;
case lsp::SymbolKind::Method:
case lsp::SymbolKind::Function:
item.kind = lsp::CompletionItemKind::Method;
case LSP::SymbolKind::Method:
case LSP::SymbolKind::Function:
item.kind = LSP::CompletionItemKind::Method;
break;
case lsp::SymbolKind::Event:
item.kind = lsp::CompletionItemKind::Event;
case LSP::SymbolKind::Event:
item.kind = LSP::CompletionItemKind::Event;
break;
case lsp::SymbolKind::Constant:
item.kind = lsp::CompletionItemKind::Constant;
case LSP::SymbolKind::Constant:
item.kind = LSP::CompletionItemKind::Constant;
break;
case lsp::SymbolKind::Variable:
item.kind = lsp::CompletionItemKind::Variable;
case LSP::SymbolKind::Variable:
item.kind = LSP::CompletionItemKind::Variable;
break;
case lsp::SymbolKind::File:
item.kind = lsp::CompletionItemKind::File;
case LSP::SymbolKind::File:
item.kind = LSP::CompletionItemKind::File;
break;
default:
item.kind = lsp::CompletionItemKind::Text;
item.kind = LSP::CompletionItemKind::Text;
break;
}
@ -1753,7 +1752,7 @@ struct ServerCapabilities {
/**
* The server provides workspace symbol support.
*/
bool workspaceSymbolProvider = true;
bool workspaceSymbolProvider = false;
/**
* The server supports workspace folder.
@ -1874,7 +1873,7 @@ struct GodotNativeClassInfo {
const DocData::ClassDoc *class_doc = nullptr;
const ClassDB::ClassInfo *class_info = nullptr;
Dictionary to_json() {
Dictionary to_json() const {
Dictionary dict;
dict["name"] = name;
dict["inherits"] = class_doc->inherits;
@ -1889,11 +1888,11 @@ struct GodotCapabilities {
*/
List<GodotNativeClassInfo> native_classes;
Dictionary to_json() {
Dictionary to_json() const {
Dictionary dict;
Array classes;
for (List<GodotNativeClassInfo>::Element *E = native_classes.front(); E; E = E->next()) {
classes.push_back(E->get().to_json());
for (const GodotNativeClassInfo &native_class : native_classes) {
classes.push_back(native_class.to_json());
}
dict["native_classes"] = classes;
return dict;
@ -1917,7 +1916,7 @@ static String marked_documentation(const String &p_bbcode) {
in_code_block = true;
line = "\n";
} else if (in_code_block) {
line = "\t" + line.substr(code_block_indent, line.length());
line = "\t" + line.substr(code_block_indent);
}
if (in_code_block && line.contains("[/codeblock]")) {
@ -1940,8 +1939,7 @@ static String marked_documentation(const String &p_bbcode) {
line = line.replace("[signal ", "`");
line = line.replace("[enum ", "`");
line = line.replace("[constant ", "`");
line = line.replace("[", "`");
line = line.replace("]", "`");
line = line.replace_chars("[]", '`');
}
if (!in_code_block && i < lines.size() - 1) {
@ -1953,6 +1951,4 @@ static String marked_documentation(const String &p_bbcode) {
}
return markdown;
}
} // namespace lsp
#endif // GODOT_LSP_H
} // namespace LSP

View file

@ -101,8 +101,7 @@ protected:
return;
}
String source;
source.parse_utf8(reinterpret_cast<const char *>(file.ptr()), file.size());
String source = String::utf8(reinterpret_cast<const char *>(file.ptr()), file.size());
GDScriptTokenizerBuffer::CompressMode compress_mode = script_mode == EditorExportPreset::MODE_SCRIPT_BINARY_TOKENS_COMPRESSED ? GDScriptTokenizerBuffer::COMPRESS_ZSTD : GDScriptTokenizerBuffer::COMPRESS_NONE;
file = GDScriptTokenizerBuffer::parse_code_string(source, compress_mode);
if (file.is_empty()) {
@ -162,12 +161,7 @@ void initialize_gdscript_module(ModuleInitializationLevel p_level) {
gdscript_translation_parser_plugin.instantiate();
EditorTranslationParser::get_singleton()->add_parser(gdscript_translation_parser_plugin, EditorTranslationParser::STANDARD);
} else if (p_level == MODULE_INITIALIZATION_LEVEL_EDITOR) {
ClassDB::APIType prev_api = ClassDB::get_current_api();
ClassDB::set_current_api(ClassDB::API_EDITOR);
GDREGISTER_CLASS(GDScriptSyntaxHighlighter);
ClassDB::set_current_api(prev_api);
}
#endif // TOOLS_ENABLED
}

View file

@ -28,12 +28,9 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef GDSCRIPT_REGISTER_TYPES_H
#define GDSCRIPT_REGISTER_TYPES_H
#pragma once
#include "modules/register_module_types.h"
void initialize_gdscript_module(ModuleInitializationLevel p_level);
void uninitialize_gdscript_module(ModuleInitializationLevel p_level);
#endif // GDSCRIPT_REGISTER_TYPES_H

View file

@ -478,7 +478,7 @@ void GDScriptTest::error_handler(void *p_this, const char *p_function, const cha
if (include_source_info) {
header += vformat(" at %s:%d on %s()",
String::utf8(p_file).trim_prefix(self->base_dir).replace("\\", "/"),
String::utf8(p_file).trim_prefix(self->base_dir).replace_char('\\', '/'),
p_line,
String::utf8(p_function));
}

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef GDSCRIPT_TEST_RUNNER_H
#define GDSCRIPT_TEST_RUNNER_H
#pragma once
#include "../gdscript.h"
@ -136,5 +135,3 @@ public:
};
} // namespace GDScriptTests
#endif // GDSCRIPT_TEST_RUNNER_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef GDSCRIPT_TEST_RUNNER_SUITE_H
#define GDSCRIPT_TEST_RUNNER_SUITE_H
#pragma once
#include "gdscript_test_runner.h"
@ -81,9 +80,8 @@ TEST_CASE("[Modules][GDScript] Validate built-in API") {
SUBCASE("[Modules][GDScript] Validate built-in methods") {
for (const MethodInfo &mi : builtin_methods) {
int i = 0;
for (List<PropertyInfo>::ConstIterator itr = mi.arguments.begin(); itr != mi.arguments.end(); ++itr, ++i) {
TEST_COND((itr->name.is_empty() || itr->name.begins_with("_unnamed_arg")),
for (int64_t i = 0; i < mi.arguments.size(); ++i) {
TEST_COND((mi.arguments[i].name.is_empty() || mi.arguments[i].name.begins_with("_unnamed_arg")),
vformat("Unnamed argument in position %d of built-in method '%s'.", i, mi.name));
}
}
@ -95,9 +93,8 @@ TEST_CASE("[Modules][GDScript] Validate built-in API") {
SUBCASE("[Modules][GDScript] Validate built-in annotations") {
for (const MethodInfo &ai : builtin_annotations) {
int i = 0;
for (List<PropertyInfo>::ConstIterator itr = ai.arguments.begin(); itr != ai.arguments.end(); ++itr, ++i) {
TEST_COND((itr->name.is_empty() || itr->name.begins_with("_unnamed_arg")),
for (int64_t i = 0; i < ai.arguments.size(); ++i) {
TEST_COND((ai.arguments[i].name.is_empty() || ai.arguments[i].name.begins_with("_unnamed_arg")),
vformat("Unnamed argument in position %d of built-in annotation '%s'.", i, ai.name));
}
}
@ -105,5 +102,3 @@ TEST_CASE("[Modules][GDScript] Validate built-in API") {
}
} // namespace GDScriptTests
#endif // GDSCRIPT_TEST_RUNNER_SUITE_H

View file

@ -1,3 +1,5 @@
extends Node
@onready var anim := $AnimationPlayer
func test():

View file

@ -1,3 +1,5 @@
extends Node
@onready var anim: AnimationPlayer = $AnimationPlayer
func test():

View file

@ -1,3 +1,5 @@
extends Node
@onready var anim = $AnimationPlayer
func test():

View file

@ -0,0 +1,5 @@
[output]
include=[
; GDScript: class_a.notest.gd
{"display": "func_of_a()"},
]

View file

@ -0,0 +1,7 @@
extends "res://completion/class_a.notest.gd"
func test():
super.
if true:
pass

View file

@ -0,0 +1,5 @@
[output]
include=[
; GDScript: class_a.notest.gd
{"display": "func_of_a()"},
]

View file

@ -0,0 +1,7 @@
extends "res://completion/class_a.notest.gd"
func test():
super.f
if true:
pass

View file

@ -1,5 +1,5 @@
extends Node
func a():
%AnimationPlayer.
$UniqueAnimationPlayer.
pass

View file

@ -1,5 +1,5 @@
extends Node
func a():
$UniqueAnimationPlayer.
%AnimationPlayer.
pass

View file

@ -1,6 +1,6 @@
extends Node
var test = $A
@onready var test = $A
func a():
test.

View file

@ -1,6 +1,6 @@
extends Node
var test = $AnimationPlayer
@onready var test = $AnimationPlayer
func a():
test.

View file

@ -1,6 +1,6 @@
extends Node
var test: AnimationPlayer = $AnimationPlayer
@onready var test: AnimationPlayer = $AnimationPlayer
func a():
test.

View file

@ -1,6 +1,6 @@
extends Node
var test: Node = $A
@onready var test: Node = $A
func a():
test.

View file

@ -1,6 +1,6 @@
extends Node
var test: Node = $AnimationPlayer
@onready var test: Node = $AnimationPlayer
func a():
test.

View file

@ -1,6 +1,6 @@
extends Node
var test: Area2D = $A
@onready var test: Area2D = $A
func a():
test.

View file

@ -1,6 +1,6 @@
extends Node
var test: Area2D = $AnimationPlayer
@onready var test: Area2D = $AnimationPlayer
func a():
test.

View file

@ -0,0 +1,8 @@
[output]
include=[
{"display": "hello_world", "insert_text": "hello_world"},
]
exclude=[
{"insert_text": "hello_world()"},
{"insert_text": "hello_world("},
]

View file

@ -0,0 +1,8 @@
signal test
func _init() -> void:
test.connect(h)
pass
func hello_world():
pass

View file

@ -0,0 +1,8 @@
[output]
include=[
{"display": "hello_world", "insert_text": "hello_world"},
]
exclude=[
{"insert_text": "hello_world()"},
{"insert_text": "hello_world("},
]

View file

@ -0,0 +1,8 @@
var arr: Array
func _init() -> void:
arr.sort_custom(h
pass
func hello_world():
pass

View file

@ -0,0 +1,8 @@
[output]
include=[
{"display": "hello_world", "insert_text": "hello_world"},
]
exclude=[
{"insert_text": "hello_world()"},
{"insert_text": "hello_world("},
]

View file

@ -0,0 +1,9 @@
func test(a: Callable, b):
pass
func _init() -> void:
test(h)
pass
func hello_world():
pass

View file

@ -0,0 +1,8 @@
[output]
include=[
{"display": "hello_world", "insert_text": "hello_world"},
]
exclude=[
{"insert_text": "hello_world()"},
{"insert_text": "hello_world("},
]

View file

@ -0,0 +1,9 @@
func test(a, b: Callable):
pass
func _init() -> void:
test(hello_world(), h)
pass
func hello_world():
pass

View file

@ -0,0 +1,8 @@
[output]
include=[
{"display": "hello_world()", "insert_text": "hello_world()"},
]
exclude=[
{"insert_text": "hello_world"},
{"insert_text": "hello_world("},
]

View file

@ -0,0 +1,9 @@
func test(a, b: Callable):
pass
func _init() -> void:
test(h)
pass
func hello_world():
pass

View file

@ -0,0 +1,8 @@
[output]
include=[
{"display": "hello_world", "insert_text": "hello_world"},
]
exclude=[
{"display": "hello_world", "insert_text": "hello_world()"},
{"display": "hello_world", "insert_text": "hello_world("},
]

View file

@ -0,0 +1,8 @@
extends Node
func _init() -> void:
create_tween().tween_callback(h)
pass
func hello_world():
pass

View file

@ -0,0 +1,5 @@
class_name Test
extends Node
func _init():
pass

View file

@ -0,0 +1,12 @@
# TODO: This test is currently disabled since it triggers some complex memory leaks. Try enabling it again once GH-101830 is fixed.
signal finished
const scr: GDScript = preload("reload_suspended_function_helper.notest.gd")
func test():
@warning_ignore("UNSAFE_METHOD_ACCESS")
scr.test(self)
@warning_ignore("RETURN_VALUE_DISCARDED")
scr.reload(true)
finished.emit()

View file

@ -0,0 +1,2 @@
GDTEST_RUNTIME_ERROR
>> WARNING: Canceling suspended execution of "test" due to a script reload.

View file

@ -0,0 +1,3 @@
static func test(a):
await a.finished
pass

View file

@ -0,0 +1,26 @@
var array_var: Array = ["one", "two", "three", "four"]
const array_const: Array = ["one", "two", "three", "four"]
var array_nested_var: Array = [["one"], ["two"], ["three"], ["four"]]
const array_nested_const: Array = [["one"], ["two"], ["three"], ["four"]]
func test():
Utils.check(array_const.is_read_only() == true)
Utils.check(array_nested_const.is_read_only() == true)
print("TEST Callable::callv")
print_four_variants.callv(array_var)
print_four_variants.callv(array_const)
print_four_variants.callv(array_nested_var)
print_four_variants.callv(array_nested_const)
print("TEST Object::callv")
self.callv("print_four_variants", array_var)
self.callv("print_four_variants", array_const)
self.callv("print_four_variants", array_nested_var)
self.callv("print_four_variants", array_nested_const)
func print_four_variants(v1, v2, v3, v4):
print("%s %s %s %s" % [v1, v2, v3, v4])

Some files were not shown because too many files have changed in this diff Show more