summaryrefslogtreecommitdiff
path: root/modules/gdscript
diff options
context:
space:
mode:
Diffstat (limited to 'modules/gdscript')
-rw-r--r--modules/gdscript/editor/gdscript_highlighter.cpp4
-rw-r--r--modules/gdscript/editor/gdscript_highlighter.h4
-rw-r--r--modules/gdscript/gdscript.cpp4
-rw-r--r--modules/gdscript/gdscript.h4
-rw-r--r--modules/gdscript/gdscript_compiler.cpp4
-rw-r--r--modules/gdscript/gdscript_compiler.h4
-rw-r--r--modules/gdscript/gdscript_editor.cpp4
-rw-r--r--modules/gdscript/gdscript_function.cpp4
-rw-r--r--modules/gdscript/gdscript_function.h4
-rw-r--r--modules/gdscript/gdscript_functions.cpp11
-rw-r--r--modules/gdscript/gdscript_functions.h4
-rw-r--r--modules/gdscript/gdscript_parser.cpp111
-rw-r--r--modules/gdscript/gdscript_parser.h4
-rw-r--r--modules/gdscript/gdscript_tokenizer.cpp4
-rw-r--r--modules/gdscript/gdscript_tokenizer.h4
-rw-r--r--modules/gdscript/language_server/gdscript_extend_parser.cpp49
-rw-r--r--modules/gdscript/language_server/gdscript_extend_parser.h6
-rw-r--r--modules/gdscript/language_server/gdscript_language_protocol.cpp4
-rw-r--r--modules/gdscript/language_server/gdscript_language_protocol.h4
-rw-r--r--modules/gdscript/language_server/gdscript_language_server.cpp7
-rw-r--r--modules/gdscript/language_server/gdscript_language_server.h4
-rw-r--r--modules/gdscript/language_server/gdscript_text_document.cpp138
-rw-r--r--modules/gdscript/language_server/gdscript_text_document.h7
-rw-r--r--modules/gdscript/language_server/gdscript_workspace.cpp55
-rw-r--r--modules/gdscript/language_server/gdscript_workspace.h5
-rw-r--r--modules/gdscript/language_server/lsp.hpp120
-rw-r--r--modules/gdscript/register_types.cpp4
-rw-r--r--modules/gdscript/register_types.h4
28 files changed, 421 insertions, 160 deletions
diff --git a/modules/gdscript/editor/gdscript_highlighter.cpp b/modules/gdscript/editor/gdscript_highlighter.cpp
index 4d6279074c..687e1785be 100644
--- a/modules/gdscript/editor/gdscript_highlighter.cpp
+++ b/modules/gdscript/editor/gdscript_highlighter.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/modules/gdscript/editor/gdscript_highlighter.h b/modules/gdscript/editor/gdscript_highlighter.h
index 9ba2c80552..e652fb1471 100644
--- a/modules/gdscript/editor/gdscript_highlighter.h
+++ b/modules/gdscript/editor/gdscript_highlighter.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp
index 03b51be27f..5b0210b16d 100644
--- a/modules/gdscript/gdscript.cpp
+++ b/modules/gdscript/gdscript.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/modules/gdscript/gdscript.h b/modules/gdscript/gdscript.h
index a5ad23c75d..cc25c1c313 100644
--- a/modules/gdscript/gdscript.h
+++ b/modules/gdscript/gdscript.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp
index 7ce19f5adc..11e015b473 100644
--- a/modules/gdscript/gdscript_compiler.cpp
+++ b/modules/gdscript/gdscript_compiler.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/modules/gdscript/gdscript_compiler.h b/modules/gdscript/gdscript_compiler.h
index 2cf630ba72..bb3ee881f8 100644
--- a/modules/gdscript/gdscript_compiler.h
+++ b/modules/gdscript/gdscript_compiler.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/modules/gdscript/gdscript_editor.cpp b/modules/gdscript/gdscript_editor.cpp
index 97b8dda6d0..e2f2b7fc3b 100644
--- a/modules/gdscript/gdscript_editor.cpp
+++ b/modules/gdscript/gdscript_editor.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/modules/gdscript/gdscript_function.cpp b/modules/gdscript/gdscript_function.cpp
index 4518a5be4b..a01a7397fe 100644
--- a/modules/gdscript/gdscript_function.cpp
+++ b/modules/gdscript/gdscript_function.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/modules/gdscript/gdscript_function.h b/modules/gdscript/gdscript_function.h
index cefc28d77f..236ca720a2 100644
--- a/modules/gdscript/gdscript_function.h
+++ b/modules/gdscript/gdscript_function.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/modules/gdscript/gdscript_functions.cpp b/modules/gdscript/gdscript_functions.cpp
index 5c0573be3f..01d62a1c62 100644
--- a/modules/gdscript/gdscript_functions.cpp
+++ b/modules/gdscript/gdscript_functions.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -2057,12 +2057,13 @@ MethodInfo GDScriptFunctions::get_info(Function p_func) {
mi.return_val.type = Variant::BOOL;
return mi;
} break;
- case FUNC_MAX: {
+ default: {
ERR_FAIL_V(MethodInfo());
} break;
}
#endif
-
- return MethodInfo();
+ MethodInfo mi;
+ mi.return_val.usage |= PROPERTY_USAGE_NIL_IS_VARIANT;
+ return mi;
}
diff --git a/modules/gdscript/gdscript_functions.h b/modules/gdscript/gdscript_functions.h
index 9ea5dd46cf..1812ddf121 100644
--- a/modules/gdscript/gdscript_functions.h
+++ b/modules/gdscript/gdscript_functions.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp
index 4405393b96..fc35678e65 100644
--- a/modules/gdscript/gdscript_parser.cpp
+++ b/modules/gdscript/gdscript_parser.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -2689,6 +2689,7 @@ void GDScriptParser::_transform_match_statment(MatchNode *p_match_statement) {
op->op = OperatorNode::OP_ASSIGN;
op->arguments.push_back(id2);
op->arguments.push_back(local_var->assign);
+ local_var->assign_op = op;
branch->body->statements.push_front(op);
branch->body->statements.push_front(local_var);
@@ -2866,7 +2867,6 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) {
assigned = _get_default_value_for_type(lv->datatype, var_line);
}
- lv->assign = assigned;
//must be added later, to avoid self-referencing.
p_block->variables.insert(n, lv);
@@ -4045,7 +4045,13 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
if (tokenizer->get_token() == GDScriptTokenizer::TK_PARENTHESIS_OPEN) {
- tokenizer->advance();
+#define _ADVANCE_AND_CONSUME_NEWLINES \
+ do { \
+ tokenizer->advance(); \
+ } while (tokenizer->get_token() == GDScriptTokenizer::TK_NEWLINE)
+
+ _ADVANCE_AND_CONSUME_NEWLINES;
+ parenthesis++;
String hint_prefix = "";
bool is_arrayed = false;
@@ -4075,11 +4081,11 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
}
current_export.type = type;
current_export.usage |= PROPERTY_USAGE_SCRIPT_VARIABLE;
- tokenizer->advance();
+ _ADVANCE_AND_CONSUME_NEWLINES;
if (tokenizer->get_token() == GDScriptTokenizer::TK_COMMA) {
// hint expected next!
- tokenizer->advance();
+ _ADVANCE_AND_CONSUME_NEWLINES;
switch (type) {
@@ -4087,7 +4093,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
if (tokenizer->get_token() == GDScriptTokenizer::TK_IDENTIFIER && tokenizer->get_token_identifier() == "FLAGS") {
- tokenizer->advance();
+ _ADVANCE_AND_CONSUME_NEWLINES;
if (tokenizer->get_token() == GDScriptTokenizer::TK_PARENTHESIS_CLOSE) {
WARN_DEPRECATED_MSG("Exporting bit flags hint requires string constants.");
@@ -4099,7 +4105,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
}
current_export.hint = PROPERTY_HINT_FLAGS;
- tokenizer->advance();
+ _ADVANCE_AND_CONSUME_NEWLINES;
bool first = true;
while (true) {
@@ -4118,7 +4124,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
current_export.hint_string += c.xml_escape();
- tokenizer->advance();
+ _ADVANCE_AND_CONSUME_NEWLINES;
if (tokenizer->get_token() == GDScriptTokenizer::TK_PARENTHESIS_CLOSE)
break;
@@ -4127,7 +4133,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
_set_error("Expected \")\" or \",\" in the named bit flags hint.");
return;
}
- tokenizer->advance();
+ _ADVANCE_AND_CONSUME_NEWLINES;
}
break;
@@ -4135,7 +4141,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
if (tokenizer->get_token() == GDScriptTokenizer::TK_IDENTIFIER && tokenizer->get_token_identifier() == "LAYERS_2D_RENDER") {
- tokenizer->advance();
+ _ADVANCE_AND_CONSUME_NEWLINES;
if (tokenizer->get_token() != GDScriptTokenizer::TK_PARENTHESIS_CLOSE) {
_set_error("Expected \")\" in the layers 2D render hint.");
return;
@@ -4146,7 +4152,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
if (tokenizer->get_token() == GDScriptTokenizer::TK_IDENTIFIER && tokenizer->get_token_identifier() == "LAYERS_2D_PHYSICS") {
- tokenizer->advance();
+ _ADVANCE_AND_CONSUME_NEWLINES;
if (tokenizer->get_token() != GDScriptTokenizer::TK_PARENTHESIS_CLOSE) {
_set_error("Expected \")\" in the layers 2D physics hint.");
return;
@@ -4157,7 +4163,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
if (tokenizer->get_token() == GDScriptTokenizer::TK_IDENTIFIER && tokenizer->get_token_identifier() == "LAYERS_3D_RENDER") {
- tokenizer->advance();
+ _ADVANCE_AND_CONSUME_NEWLINES;
if (tokenizer->get_token() != GDScriptTokenizer::TK_PARENTHESIS_CLOSE) {
_set_error("Expected \")\" in the layers 3D render hint.");
return;
@@ -4168,7 +4174,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
if (tokenizer->get_token() == GDScriptTokenizer::TK_IDENTIFIER && tokenizer->get_token_identifier() == "LAYERS_3D_PHYSICS") {
- tokenizer->advance();
+ _ADVANCE_AND_CONSUME_NEWLINES;
if (tokenizer->get_token() != GDScriptTokenizer::TK_PARENTHESIS_CLOSE) {
_set_error("Expected \")\" in the layers 3D physics hint.");
return;
@@ -4198,7 +4204,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
current_export.hint_string += c.xml_escape();
- tokenizer->advance();
+ _ADVANCE_AND_CONSUME_NEWLINES;
if (tokenizer->get_token() == GDScriptTokenizer::TK_PARENTHESIS_CLOSE)
break;
@@ -4208,7 +4214,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
return;
}
- tokenizer->advance();
+ _ADVANCE_AND_CONSUME_NEWLINES;
}
break;
@@ -4220,7 +4226,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
if (tokenizer->get_token() == GDScriptTokenizer::TK_IDENTIFIER && tokenizer->get_token_identifier() == "EASE") {
current_export.hint = PROPERTY_HINT_EXP_EASING;
- tokenizer->advance();
+ _ADVANCE_AND_CONSUME_NEWLINES;
if (tokenizer->get_token() != GDScriptTokenizer::TK_PARENTHESIS_CLOSE) {
_set_error("Expected \")\" in the hint.");
return;
@@ -4232,7 +4238,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
if (tokenizer->get_token() == GDScriptTokenizer::TK_IDENTIFIER && tokenizer->get_token_identifier() == "EXP") {
current_export.hint = PROPERTY_HINT_EXP_RANGE;
- tokenizer->advance();
+ _ADVANCE_AND_CONSUME_NEWLINES;
if (tokenizer->get_token() == GDScriptTokenizer::TK_PARENTHESIS_CLOSE)
break;
@@ -4240,7 +4246,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
_set_error("Expected \")\" or \",\" in the exponential range hint.");
return;
}
- tokenizer->advance();
+ _ADVANCE_AND_CONSUME_NEWLINES;
} else
current_export.hint = PROPERTY_HINT_RANGE;
@@ -4248,7 +4254,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
if (tokenizer->get_token() == GDScriptTokenizer::TK_OP_SUB) {
sign = -1;
- tokenizer->advance();
+ _ADVANCE_AND_CONSUME_NEWLINES;
}
if (tokenizer->get_token() != GDScriptTokenizer::TK_CONSTANT || !tokenizer->get_token_constant().is_num()) {
@@ -4258,7 +4264,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
}
current_export.hint_string = rtos(sign * double(tokenizer->get_token_constant()));
- tokenizer->advance();
+ _ADVANCE_AND_CONSUME_NEWLINES;
if (tokenizer->get_token() == GDScriptTokenizer::TK_PARENTHESIS_CLOSE) {
current_export.hint_string = "0," + current_export.hint_string;
@@ -4272,12 +4278,12 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
return;
}
- tokenizer->advance();
+ _ADVANCE_AND_CONSUME_NEWLINES;
sign = 1.0;
if (tokenizer->get_token() == GDScriptTokenizer::TK_OP_SUB) {
sign = -1;
- tokenizer->advance();
+ _ADVANCE_AND_CONSUME_NEWLINES;
}
if (tokenizer->get_token() != GDScriptTokenizer::TK_CONSTANT || !tokenizer->get_token_constant().is_num()) {
@@ -4288,7 +4294,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
}
current_export.hint_string += "," + rtos(sign * double(tokenizer->get_token_constant()));
- tokenizer->advance();
+ _ADVANCE_AND_CONSUME_NEWLINES;
if (tokenizer->get_token() == GDScriptTokenizer::TK_PARENTHESIS_CLOSE)
break;
@@ -4300,11 +4306,11 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
return;
}
- tokenizer->advance();
+ _ADVANCE_AND_CONSUME_NEWLINES;
sign = 1.0;
if (tokenizer->get_token() == GDScriptTokenizer::TK_OP_SUB) {
sign = -1;
- tokenizer->advance();
+ _ADVANCE_AND_CONSUME_NEWLINES;
}
if (tokenizer->get_token() != GDScriptTokenizer::TK_CONSTANT || !tokenizer->get_token_constant().is_num()) {
@@ -4315,7 +4321,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
}
current_export.hint_string += "," + rtos(sign * double(tokenizer->get_token_constant()));
- tokenizer->advance();
+ _ADVANCE_AND_CONSUME_NEWLINES;
} break;
case Variant::STRING: {
@@ -4340,7 +4346,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
first = false;
current_export.hint_string += c.xml_escape();
- tokenizer->advance();
+ _ADVANCE_AND_CONSUME_NEWLINES;
if (tokenizer->get_token() == GDScriptTokenizer::TK_PARENTHESIS_CLOSE)
break;
@@ -4349,7 +4355,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
_set_error("Expected \")\" or \",\" in the enumeration hint.");
return;
}
- tokenizer->advance();
+ _ADVANCE_AND_CONSUME_NEWLINES;
}
break;
@@ -4357,13 +4363,13 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
if (tokenizer->get_token() == GDScriptTokenizer::TK_IDENTIFIER && tokenizer->get_token_identifier() == "DIR") {
- tokenizer->advance();
+ _ADVANCE_AND_CONSUME_NEWLINES;
if (tokenizer->get_token() == GDScriptTokenizer::TK_PARENTHESIS_CLOSE)
current_export.hint = PROPERTY_HINT_DIR;
else if (tokenizer->get_token() == GDScriptTokenizer::TK_COMMA) {
- tokenizer->advance();
+ _ADVANCE_AND_CONSUME_NEWLINES;
if (tokenizer->get_token() != GDScriptTokenizer::TK_IDENTIFIER || !(tokenizer->get_token_identifier() == "GLOBAL")) {
_set_error("Expected \"GLOBAL\" after comma in the directory hint.");
@@ -4374,7 +4380,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
return;
}
current_export.hint = PROPERTY_HINT_GLOBAL_DIR;
- tokenizer->advance();
+ _ADVANCE_AND_CONSUME_NEWLINES;
if (tokenizer->get_token() != GDScriptTokenizer::TK_PARENTHESIS_CLOSE) {
_set_error("Expected \")\" in the hint.");
@@ -4390,11 +4396,11 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
if (tokenizer->get_token() == GDScriptTokenizer::TK_IDENTIFIER && tokenizer->get_token_identifier() == "FILE") {
current_export.hint = PROPERTY_HINT_FILE;
- tokenizer->advance();
+ _ADVANCE_AND_CONSUME_NEWLINES;
if (tokenizer->get_token() == GDScriptTokenizer::TK_COMMA) {
- tokenizer->advance();
+ _ADVANCE_AND_CONSUME_NEWLINES;
if (tokenizer->get_token() == GDScriptTokenizer::TK_IDENTIFIER && tokenizer->get_token_identifier() == "GLOBAL") {
@@ -4403,12 +4409,12 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
return;
}
current_export.hint = PROPERTY_HINT_GLOBAL_FILE;
- tokenizer->advance();
+ _ADVANCE_AND_CONSUME_NEWLINES;
if (tokenizer->get_token() == GDScriptTokenizer::TK_PARENTHESIS_CLOSE)
break;
else if (tokenizer->get_token() == GDScriptTokenizer::TK_COMMA)
- tokenizer->advance();
+ _ADVANCE_AND_CONSUME_NEWLINES;
else {
_set_error("Expected \")\" or \",\" in the hint.");
return;
@@ -4424,7 +4430,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
return;
}
current_export.hint_string = tokenizer->get_token_constant();
- tokenizer->advance();
+ _ADVANCE_AND_CONSUME_NEWLINES;
}
if (tokenizer->get_token() != GDScriptTokenizer::TK_PARENTHESIS_CLOSE) {
@@ -4437,7 +4443,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
if (tokenizer->get_token() == GDScriptTokenizer::TK_IDENTIFIER && tokenizer->get_token_identifier() == "MULTILINE") {
current_export.hint = PROPERTY_HINT_MULTILINE_TEXT;
- tokenizer->advance();
+ _ADVANCE_AND_CONSUME_NEWLINES;
if (tokenizer->get_token() != GDScriptTokenizer::TK_PARENTHESIS_CLOSE) {
_set_error("Expected \")\" in the hint.");
return;
@@ -4464,7 +4470,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
_set_error("Color type hint expects RGB or RGBA as hints.");
return;
}
- tokenizer->advance();
+ _ADVANCE_AND_CONSUME_NEWLINES;
} break;
default: {
@@ -4515,11 +4521,11 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
bool is_flags = false;
if (tokenizer->get_token() == GDScriptTokenizer::TK_COMMA) {
- tokenizer->advance();
+ _ADVANCE_AND_CONSUME_NEWLINES;
if (tokenizer->get_token() == GDScriptTokenizer::TK_IDENTIFIER && tokenizer->get_token_identifier() == "FLAGS") {
is_flags = true;
- tokenizer->advance();
+ _ADVANCE_AND_CONSUME_NEWLINES;
} else {
current_export = PropertyInfo();
_set_error("Expected \"FLAGS\" after comma.");
@@ -4563,6 +4569,9 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
return;
}
+ tokenizer->advance();
+ parenthesis--;
+
if (is_arrayed) {
hint_prefix += itos(current_export.type);
if (current_export.hint) {
@@ -4572,8 +4581,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
current_export.hint = PROPERTY_HINT_TYPE_STRING;
current_export.type = Variant::ARRAY;
}
-
- tokenizer->advance();
+#undef _ADVANCE_AND_CONSUME_NEWLINES
}
if (tokenizer->get_token() != GDScriptTokenizer::TK_PR_VAR && tokenizer->get_token() != GDScriptTokenizer::TK_PR_ONREADY && tokenizer->get_token() != GDScriptTokenizer::TK_PR_REMOTE && tokenizer->get_token() != GDScriptTokenizer::TK_PR_MASTER && tokenizer->get_token() != GDScriptTokenizer::TK_PR_PUPPET && tokenizer->get_token() != GDScriptTokenizer::TK_PR_SYNC && tokenizer->get_token() != GDScriptTokenizer::TK_PR_REMOTESYNC && tokenizer->get_token() != GDScriptTokenizer::TK_PR_MASTERSYNC && tokenizer->get_token() != GDScriptTokenizer::TK_PR_PUPPETSYNC && tokenizer->get_token() != GDScriptTokenizer::TK_PR_SLAVE) {
@@ -8039,6 +8047,7 @@ void GDScriptParser::_check_block_types(BlockNode *p_block) {
last_var_assign = lv->assign;
if (lv->assign) {
+ lv->assign_op->arguments[0]->set_datatype(lv->datatype);
DataType assign_type = _reduce_node_type(lv->assign);
#ifdef DEBUG_ENABLED
if (assign_type.has_type && assign_type.kind == DataType::BUILTIN && assign_type.builtin_type == Variant::NIL) {
@@ -8183,11 +8192,14 @@ void GDScriptParser::_check_block_types(BlockNode *p_block) {
if (lh_type.has_type && rh_type.may_yield && op->arguments[1]->type == Node::TYPE_OPERATOR) {
_add_warning(GDScriptWarning::FUNCTION_MAY_YIELD, op->line, _find_function_name(static_cast<OperatorNode *>(op->arguments[1])));
}
-#endif // DEBUG_ENABLED
bool type_match = check_types;
+#endif // DEBUG_ENABLED
if (check_types && !_is_type_compatible(lh_type, rh_type)) {
+#ifdef DEBUG_ENABLED
type_match = false;
+#endif // DEBUG_ENABLED
+
// Try supertype test
if (_is_type_compatible(rh_type, lh_type)) {
_mark_line_as_unsafe(op->line);
@@ -8218,7 +8230,9 @@ void GDScriptParser::_check_block_types(BlockNode *p_block) {
op->arguments.write[1] = convert_call;
+#ifdef DEBUG_ENABLED
type_match = true; // Since we are converting, the type is matching
+#endif // DEBUG_ENABLED
}
#ifdef DEBUG_ENABLED
if (lh_type.builtin_type == Variant::INT && rh_type.builtin_type == Variant::REAL) {
@@ -8231,8 +8245,10 @@ void GDScriptParser::_check_block_types(BlockNode *p_block) {
if (!rh_type.has_type && (op->op != OperatorNode::OP_ASSIGN || lh_type.has_type || op->arguments[0]->type == Node::TYPE_OPERATOR)) {
_mark_line_as_unsafe(op->line);
}
-#endif // DEBUG_ENABLED
op->datatype.has_type = type_match;
+#else
+ op->datatype.has_type = false;
+#endif // DEBUG_ENABLED
} break;
case OperatorNode::OP_CALL:
case OperatorNode::OP_PARENT_CALL: {
@@ -8475,11 +8491,8 @@ Error GDScriptParser::_parse(const String &p_base_path) {
current_class = main_class;
current_function = NULL;
current_block = NULL;
-#ifdef DEBUG_ENABLED
+
if (for_completion) check_types = false;
-#else
- check_types = false;
-#endif
// Resolve all class-level stuff before getting into function blocks
_check_class_level_types(main_class);
diff --git a/modules/gdscript/gdscript_parser.h b/modules/gdscript/gdscript_parser.h
index 93557d745d..c74d7dd856 100644
--- a/modules/gdscript/gdscript_parser.h
+++ b/modules/gdscript/gdscript_parser.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/modules/gdscript/gdscript_tokenizer.cpp b/modules/gdscript/gdscript_tokenizer.cpp
index 761a3de37c..11ffa22906 100644
--- a/modules/gdscript/gdscript_tokenizer.cpp
+++ b/modules/gdscript/gdscript_tokenizer.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/modules/gdscript/gdscript_tokenizer.h b/modules/gdscript/gdscript_tokenizer.h
index 58749012b7..0efc8551cb 100644
--- a/modules/gdscript/gdscript_tokenizer.h
+++ b/modules/gdscript/gdscript_tokenizer.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/modules/gdscript/language_server/gdscript_extend_parser.cpp b/modules/gdscript/language_server/gdscript_extend_parser.cpp
index d63f786fcb..c8ff471401 100644
--- a/modules/gdscript/language_server/gdscript_extend_parser.cpp
+++ b/modules/gdscript/language_server/gdscript_extend_parser.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -522,6 +522,51 @@ 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 {
+
+ ERR_FAIL_INDEX_V(p_position.line, lines.size(), ERR_INVALID_PARAMETER);
+
+ int bracket_stack = 0;
+ int index = 0;
+
+ bool found = false;
+ for (int l = p_position.line; l >= 0; --l) {
+ String line = lines[l];
+ int c = line.length() - 1;
+ if (l == p_position.line) {
+ c = MIN(c, p_position.character - 1);
+ }
+
+ while (c >= 0) {
+ const CharType &charactor = line[c];
+ if (charactor == ')') {
+ ++bracket_stack;
+ } else if (charactor == '(') {
+ --bracket_stack;
+ if (bracket_stack < 0) {
+ found = true;
+ }
+ }
+ if (bracket_stack <= 0 && charactor == ',') {
+ ++index;
+ }
+ --c;
+ if (found) {
+ r_func_pos.character = c;
+ break;
+ }
+ }
+
+ if (found) {
+ r_func_pos.line = l;
+ r_arg_index = index;
+ return OK;
+ }
+ }
+
+ return ERR_METHOD_NOT_FOUND;
+}
+
const lsp::DocumentSymbol *ExtendGDScriptParser::get_symbol_defined_at_line(int p_line) const {
if (p_line <= 0) {
return &class_symbol;
diff --git a/modules/gdscript/language_server/gdscript_extend_parser.h b/modules/gdscript/language_server/gdscript_extend_parser.h
index a6e0ca5534..43dfce994b 100644
--- a/modules/gdscript/language_server/gdscript_extend_parser.h
+++ b/modules/gdscript/language_server/gdscript_extend_parser.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -83,6 +83,8 @@ public:
_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;
+
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_requred = false) const;
String get_identifier_under_position(const lsp::Position &p_position, Vector2i &p_offset) const;
diff --git a/modules/gdscript/language_server/gdscript_language_protocol.cpp b/modules/gdscript/language_server/gdscript_language_protocol.cpp
index 90646f73ba..cff7653d3a 100644
--- a/modules/gdscript/language_server/gdscript_language_protocol.cpp
+++ b/modules/gdscript/language_server/gdscript_language_protocol.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/modules/gdscript/language_server/gdscript_language_protocol.h b/modules/gdscript/language_server/gdscript_language_protocol.h
index 136b45fd78..e45db274e9 100644
--- a/modules/gdscript/language_server/gdscript_language_protocol.h
+++ b/modules/gdscript/language_server/gdscript_language_protocol.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/modules/gdscript/language_server/gdscript_language_server.cpp b/modules/gdscript/language_server/gdscript_language_server.cpp
index 8d58b99e02..9675c07c00 100644
--- a/modules/gdscript/language_server/gdscript_language_server.cpp
+++ b/modules/gdscript/language_server/gdscript_language_server.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -31,13 +31,14 @@
#include "gdscript_language_server.h"
#include "core/os/file_access.h"
#include "core/os/os.h"
+#include "editor/editor_log.h"
#include "editor/editor_node.h"
GDScriptLanguageServer::GDScriptLanguageServer() {
thread = NULL;
thread_exit = false;
_EDITOR_DEF("network/language_server/remote_port", 6008);
- _EDITOR_DEF("network/language_server/enable_smart_resolve", false);
+ _EDITOR_DEF("network/language_server/enable_smart_resolve", true);
_EDITOR_DEF("network/language_server/show_native_symbols_in_editor", false);
}
diff --git a/modules/gdscript/language_server/gdscript_language_server.h b/modules/gdscript/language_server/gdscript_language_server.h
index 83c2320d98..191b8bfa85 100644
--- a/modules/gdscript/language_server/gdscript_language_server.h
+++ b/modules/gdscript/language_server/gdscript_language_server.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/modules/gdscript/language_server/gdscript_text_document.cpp b/modules/gdscript/language_server/gdscript_text_document.cpp
index 1ca2a50c21..33ca4a5d15 100644
--- a/modules/gdscript/language_server/gdscript_text_document.cpp
+++ b/modules/gdscript/language_server/gdscript_text_document.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -49,6 +49,8 @@ void GDScriptTextDocument::_bind_methods() {
ClassDB::bind_method(D_METHOD("colorPresentation"), &GDScriptTextDocument::colorPresentation);
ClassDB::bind_method(D_METHOD("hover"), &GDScriptTextDocument::hover);
ClassDB::bind_method(D_METHOD("definition"), &GDScriptTextDocument::definition);
+ ClassDB::bind_method(D_METHOD("declaration"), &GDScriptTextDocument::declaration);
+ ClassDB::bind_method(D_METHOD("signatureHelp"), &GDScriptTextDocument::signatureHelp);
ClassDB::bind_method(D_METHOD("show_native_symbol_in_editor"), &GDScriptTextDocument::show_native_symbol_in_editor);
}
@@ -340,68 +342,64 @@ Variant GDScriptTextDocument::hover(const Dictionary &p_params) {
}
Array GDScriptTextDocument::definition(const Dictionary &p_params) {
- Array arr;
-
lsp::TextDocumentPositionParams params;
params.load(p_params);
+ List<const lsp::DocumentSymbol *> symbols;
+ Array arr = this->find_symbols(params, symbols);
+ return arr;
+}
- const lsp::DocumentSymbol *symbol = GDScriptLanguageProtocol::get_singleton()->get_workspace()->resolve_symbol(params);
- if (symbol) {
- lsp::Location location;
- location.uri = symbol->uri;
- location.range = symbol->range;
-
- const String &path = GDScriptLanguageProtocol::get_singleton()->get_workspace()->get_file_path(symbol->uri);
- if (file_checker->file_exists(path)) {
- arr.push_back(location.to_json());
- } else if (!symbol->native_class.empty()) {
- if (GDScriptLanguageProtocol::get_singleton()->is_goto_native_symbols_enabled()) {
- String id;
- switch (symbol->kind) {
- case lsp::SymbolKind::Class:
- id = "class_name:" + symbol->name;
- break;
- case lsp::SymbolKind::Constant:
- id = "class_constant:" + symbol->native_class + ":" + symbol->name;
- break;
- case lsp::SymbolKind::Property:
- case lsp::SymbolKind::Variable:
- id = "class_property:" + symbol->native_class + ":" + symbol->name;
- break;
- case lsp::SymbolKind::Enum:
- id = "class_enum:" + symbol->native_class + ":" + symbol->name;
- break;
- case lsp::SymbolKind::Method:
- case lsp::SymbolKind::Function:
- id = "class_method:" + symbol->native_class + ":" + symbol->name;
- break;
- default:
- id = "class_global:" + symbol->native_class + ":" + symbol->name;
- break;
- }
- call_deferred("show_native_symbol_in_editor", id);
- } else {
- notify_client_show_symbol(symbol);
+Variant GDScriptTextDocument::declaration(const Dictionary &p_params) {
+ lsp::TextDocumentPositionParams params;
+ params.load(p_params);
+ List<const lsp::DocumentSymbol *> symbols;
+ Array arr = this->find_symbols(params, symbols);
+ if (arr.empty() && !symbols.empty() && !symbols.front()->get()->native_class.empty()) { // Find a native symbol
+ 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:
+ id = "class_name:" + symbol->name;
+ break;
+ case lsp::SymbolKind::Constant:
+ id = "class_constant:" + symbol->native_class + ":" + symbol->name;
+ break;
+ case lsp::SymbolKind::Property:
+ case lsp::SymbolKind::Variable:
+ id = "class_property:" + symbol->native_class + ":" + symbol->name;
+ break;
+ case lsp::SymbolKind::Enum:
+ id = "class_enum:" + symbol->native_class + ":" + symbol->name;
+ break;
+ case lsp::SymbolKind::Method:
+ case lsp::SymbolKind::Function:
+ id = "class_method:" + symbol->native_class + ":" + symbol->name;
+ break;
+ default:
+ id = "class_global:" + symbol->native_class + ":" + symbol->name;
+ break;
}
+ call_deferred("show_native_symbol_in_editor", id);
+ } else {
+ notify_client_show_symbol(symbol);
}
- } else if (GDScriptLanguageProtocol::get_singleton()->is_smart_resolve_enabled()) {
+ }
+ return arr;
+}
- List<const lsp::DocumentSymbol *> list;
- GDScriptLanguageProtocol::get_singleton()->get_workspace()->resolve_related_symbols(params, list);
- for (List<const lsp::DocumentSymbol *>::Element *E = list.front(); E; E = E->next()) {
+Variant GDScriptTextDocument::signatureHelp(const Dictionary &p_params) {
+ Variant ret;
- if (const lsp::DocumentSymbol *s = E->get()) {
- if (!s->uri.empty()) {
- lsp::Location location;
- location.uri = s->uri;
- location.range = s->range;
- arr.push_back(location.to_json());
- }
- }
- }
+ lsp::TextDocumentPositionParams params;
+ params.load(p_params);
+
+ lsp::SignatureHelp s;
+ if (OK == GDScriptLanguageProtocol::get_singleton()->get_workspace()->resolve_signature(params, s)) {
+ ret = s.to_json();
}
- return arr;
+ return ret;
}
GDScriptTextDocument::GDScriptTextDocument() {
@@ -421,3 +419,33 @@ void GDScriptTextDocument::show_native_symbol_in_editor(const String &p_symbol_i
ScriptEditor::get_singleton()->call_deferred("_help_class_goto", p_symbol_id);
OS::get_singleton()->move_window_to_foreground();
}
+
+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);
+ if (symbol) {
+ lsp::Location location;
+ location.uri = symbol->uri;
+ location.range = symbol->range;
+ const String &path = GDScriptLanguageProtocol::get_singleton()->get_workspace()->get_file_path(symbol->uri);
+ if (file_checker->file_exists(path)) {
+ arr.push_back(location.to_json());
+ }
+ r_list.push_back(symbol);
+ } else if (GDScriptLanguageProtocol::get_singleton()->is_smart_resolve_enabled()) {
+ List<const lsp::DocumentSymbol *> list;
+ GDScriptLanguageProtocol::get_singleton()->get_workspace()->resolve_related_symbols(p_location, list);
+ for (List<const lsp::DocumentSymbol *>::Element *E = list.front(); E; E = E->next()) {
+ if (const lsp::DocumentSymbol *s = E->get()) {
+ if (!s->uri.empty()) {
+ lsp::Location location;
+ location.uri = s->uri;
+ location.range = s->range;
+ arr.push_back(location.to_json());
+ r_list.push_back(s);
+ }
+ }
+ }
+ }
+ return arr;
+}
diff --git a/modules/gdscript/language_server/gdscript_text_document.h b/modules/gdscript/language_server/gdscript_text_document.h
index 235e2c3f6e..b2fd0c31f9 100644
--- a/modules/gdscript/language_server/gdscript_text_document.h
+++ b/modules/gdscript/language_server/gdscript_text_document.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -51,6 +51,7 @@ protected:
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);
@@ -65,6 +66,8 @@ public:
Array colorPresentation(const Dictionary &p_params);
Variant hover(const Dictionary &p_params);
Array definition(const Dictionary &p_params);
+ Variant declaration(const Dictionary &p_params);
+ Variant signatureHelp(const Dictionary &p_params);
void initialize();
diff --git a/modules/gdscript/language_server/gdscript_workspace.cpp b/modules/gdscript/language_server/gdscript_workspace.cpp
index f9a974bad3..1c0590cff1 100644
--- a/modules/gdscript/language_server/gdscript_workspace.cpp
+++ b/modules/gdscript/language_server/gdscript_workspace.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -252,6 +252,12 @@ Error GDScriptWorkspace::initialize() {
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;
+ symbol_arg.name = arg.name;
+ symbol_arg.kind = lsp::SymbolKind::Variable;
+ symbol_arg.detail = arg.type;
+
if (!arg_default_value_started && !arg.default_value.empty()) {
arg_default_value_started = true;
}
@@ -263,6 +269,8 @@ Error GDScriptWorkspace::initialize() {
arg_str += ", ";
}
params += arg_str;
+
+ symbol.children.push_back(symbol_arg);
}
if (data.qualifiers.find("vararg") != -1) {
params += params.empty() ? "..." : ", ...";
@@ -513,6 +521,49 @@ 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) {
+ if (const ExtendGDScriptParser *parser = get_parse_result(get_file_path(p_doc_pos.textDocument.uri))) {
+
+ 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;
+
+ 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 (List<const lsp::DocumentSymbol *>::Element *E = symbols.front(); E; E = E->next()) {
+ const lsp::DocumentSymbol *symbol = E->get();
+ 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;
+ arg_info.label = arg.name;
+ signature_info.parameters.push_back(arg_info);
+ }
+ r_signature.signatures.push_back(signature_info);
+ break;
+ }
+ }
+
+ if (r_signature.signatures.size()) {
+ return OK;
+ }
+ }
+ }
+ return ERR_METHOD_NOT_FOUND;
+}
+
GDScriptWorkspace::GDScriptWorkspace() {
ProjectSettings::get_singleton()->get_resource_path();
}
diff --git a/modules/gdscript/language_server/gdscript_workspace.h b/modules/gdscript/language_server/gdscript_workspace.h
index a416ae1075..146a5cb7c9 100644
--- a/modules/gdscript/language_server/gdscript_workspace.h
+++ b/modules/gdscript/language_server/gdscript_workspace.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -83,6 +83,7 @@ public:
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);
GDScriptWorkspace();
~GDScriptWorkspace();
diff --git a/modules/gdscript/language_server/lsp.hpp b/modules/gdscript/language_server/lsp.hpp
index 35471d63d6..379024844e 100644
--- a/modules/gdscript/language_server/lsp.hpp
+++ b/modules/gdscript/language_server/lsp.hpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -1402,6 +1402,120 @@ struct Hover {
}
};
+/**
+ * Represents a parameter of a callable-signature. A parameter can
+ * have a label and a doc-comment.
+ */
+struct ParameterInformation {
+
+ /**
+ * The label of this parameter information.
+ *
+ * Either a string or an inclusive start and exclusive end offsets within its containing
+ * signature label. (see SignatureInformation.label). The offsets are based on a UTF-16
+ * string representation as `Position` and `Range` does.
+ *
+ * *Note*: a label of type string should be a substring of its containing signature label.
+ * Its intended use case is to highlight the parameter label part in the `SignatureInformation.label`.
+ */
+ String label;
+
+ /**
+ * The human-readable doc-comment of this parameter. Will be shown
+ * in the UI but can be omitted.
+ */
+ MarkupContent documentation;
+
+ Dictionary to_json() const {
+ Dictionary dict;
+ dict["label"] = label;
+ dict["documentation"] = documentation.to_json();
+ return dict;
+ }
+};
+
+/**
+ * Represents the signature of something callable. A signature
+ * can have a label, like a function-name, a doc-comment, and
+ * a set of parameters.
+ */
+struct SignatureInformation {
+ /**
+ * The label of this signature. Will be shown in
+ * the UI.
+ */
+ String label;
+
+ /**
+ * The human-readable doc-comment of this signature. Will be shown
+ * in the UI but can be omitted.
+ */
+ MarkupContent documentation;
+
+ /**
+ * The parameters of this signature.
+ */
+ Vector<ParameterInformation> parameters;
+
+ Dictionary to_json() const {
+ Dictionary dict;
+ dict["label"] = label;
+ dict["documentation"] = documentation.to_json();
+ Array args;
+ for (int i = 0; i < parameters.size(); i++) {
+ args.push_back(parameters[i].to_json());
+ }
+ dict["parameters"] = args;
+ return dict;
+ }
+};
+
+/**
+ * Signature help represents the signature of something
+ * callable. There can be multiple signature but only one
+ * active and only one active parameter.
+ */
+struct SignatureHelp {
+ /**
+ * One or more signatures.
+ */
+ Vector<SignatureInformation> signatures;
+
+ /**
+ * The active signature. If omitted or the value lies outside the
+ * range of `signatures` the value defaults to zero or is ignored if
+ * `signatures.length === 0`. Whenever possible implementors should
+ * make an active decision about the active signature and shouldn't
+ * rely on a default value.
+ * In future version of the protocol this property might become
+ * mandatory to better express this.
+ */
+ int activeSignature = 0;
+
+ /**
+ * The active parameter of the active signature. If omitted or the value
+ * lies outside the range of `signatures[activeSignature].parameters`
+ * defaults to 0 if the active signature has parameters. If
+ * the active signature has no parameters it is ignored.
+ * In future version of the protocol this property might become
+ * mandatory to better express the active parameter if the
+ * active signature does have any.
+ */
+ int activeParameter = 0;
+
+ Dictionary to_json() const {
+ Dictionary dict;
+ Array sigs;
+ for (int i = 0; i < signatures.size(); i++) {
+ sigs.push_back(signatures[i].to_json());
+ }
+ dict["signatures"] = sigs;
+ dict["activeSignature"] = activeSignature;
+ dict["activeParameter"] = activeParameter;
+ return dict;
+ }
+};
+
struct ServerCapabilities {
/**
* Defines how text documents are synced. Is either a detailed structure defining each notification or
@@ -1532,6 +1646,8 @@ struct ServerCapabilities {
Dictionary dict;
dict["textDocumentSync"] = (int)textDocumentSync.change;
dict["completionProvider"] = completionProvider.to_json();
+ signatureHelpProvider.triggerCharacters.push_back(",");
+ signatureHelpProvider.triggerCharacters.push_back("(");
dict["signatureHelpProvider"] = signatureHelpProvider.to_json();
dict["codeLensProvider"] = false; // codeLensProvider.to_json();
dict["documentOnTypeFormattingProvider"] = documentOnTypeFormattingProvider.to_json();
diff --git a/modules/gdscript/register_types.cpp b/modules/gdscript/register_types.cpp
index 94b9e8c2d9..b5eb09d6ba 100644
--- a/modules/gdscript/register_types.cpp
+++ b/modules/gdscript/register_types.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/modules/gdscript/register_types.h b/modules/gdscript/register_types.h
index 0f01a4cdab..55920e8b97 100644
--- a/modules/gdscript/register_types.h
+++ b/modules/gdscript/register_types.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */