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