diff options
Diffstat (limited to 'modules/gdscript/language_server')
11 files changed, 398 insertions, 365 deletions
diff --git a/modules/gdscript/language_server/gdscript_extend_parser.cpp b/modules/gdscript/language_server/gdscript_extend_parser.cpp index 330530be80..e63b6ab20e 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-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 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,6 +31,7 @@ #include "gdscript_extend_parser.h" #include "../gdscript.h" +#include "../gdscript_analyzer.h" #include "core/io/json.h" #include "gdscript_language_protocol.h" #include "gdscript_workspace.h" @@ -38,15 +39,17 @@ void ExtendGDScriptParser::update_diagnostics() { diagnostics.clear(); - if (has_error()) { + const List<ParserError> &errors = get_errors(); + for (const List<ParserError>::Element *E = errors.front(); E != nullptr; E = E->next()) { + const ParserError &error = E->get(); lsp::Diagnostic diagnostic; diagnostic.severity = lsp::DiagnosticSeverity::Error; - diagnostic.message = get_error(); + diagnostic.message = error.message; diagnostic.source = "gdscript"; diagnostic.code = -1; lsp::Range range; lsp::Position pos; - int line = LINE_NUMBER_TO_INDEX(get_error_line()); + int line = LINE_NUMBER_TO_INDEX(error.line); const String &line_text = get_lines()[line]; pos.line = line; pos.character = line_text.length() - line_text.strip_edges(true, false).length(); @@ -62,12 +65,12 @@ void ExtendGDScriptParser::update_diagnostics() { const GDScriptWarning &warning = E->get(); lsp::Diagnostic diagnostic; diagnostic.severity = lsp::DiagnosticSeverity::Warning; - diagnostic.message = warning.get_message(); + diagnostic.message = "(" + warning.get_name() + "): " + warning.get_message(); diagnostic.source = "gdscript"; diagnostic.code = warning.code; lsp::Range range; lsp::Position pos; - int line = LINE_NUMBER_TO_INDEX(warning.line); + int line = LINE_NUMBER_TO_INDEX(warning.start_line); const String &line_text = get_lines()[line]; pos.line = line; pos.character = line_text.length() - line_text.strip_edges(true, false).length(); @@ -82,7 +85,7 @@ void ExtendGDScriptParser::update_diagnostics() { void ExtendGDScriptParser::update_symbols() { members.clear(); - const GDScriptParser::Node *head = get_parse_tree(); + const GDScriptParser::Node *head = get_tree(); if (const GDScriptParser::ClassNode *gdclass = dynamic_cast<const GDScriptParser::ClassNode *>(head)) { parse_class_symbol(gdclass, class_symbol); @@ -106,15 +109,15 @@ void ExtendGDScriptParser::update_symbols() { void ExtendGDScriptParser::update_document_links(const String &p_code) { document_links.clear(); - GDScriptTokenizerText tokenizer; + GDScriptTokenizer tokenizer; FileAccessRef fs = FileAccess::create(FileAccess::ACCESS_RESOURCES); - tokenizer.set_code(p_code); + tokenizer.set_source_code(p_code); while (true) { - GDScriptTokenizerText::Token token = tokenizer.get_token(); - if (token == GDScriptTokenizer::TK_EOF || token == GDScriptTokenizer::TK_ERROR) { + GDScriptTokenizer::Token token = tokenizer.scan(); + if (token.type == GDScriptTokenizer::Token::TK_EOF) { break; - } else if (token == GDScriptTokenizer::TK_CONSTANT) { - const Variant &const_val = tokenizer.get_token_constant(); + } else if (token.type == GDScriptTokenizer::Token::LITERAL) { + const Variant &const_val = token.literal; if (const_val.get_type() == Variant::STRING) { String path = const_val; bool exists = fs->file_exists(path); @@ -126,15 +129,14 @@ void ExtendGDScriptParser::update_document_links(const String &p_code) { String value = const_val; lsp::DocumentLink link; link.target = GDScriptLanguageProtocol::get_singleton()->get_workspace()->get_file_uri(path); - link.range.start.line = LINE_NUMBER_TO_INDEX(tokenizer.get_token_line()); - link.range.end.line = link.range.start.line; - link.range.end.character = LINE_NUMBER_TO_INDEX(tokenizer.get_token_column()); - link.range.start.character = link.range.end.character - value.length(); + link.range.start.line = LINE_NUMBER_TO_INDEX(token.start_line); + link.range.end.line = LINE_NUMBER_TO_INDEX(token.end_line); + link.range.start.character = LINE_NUMBER_TO_INDEX(token.start_column); + link.range.end.character = LINE_NUMBER_TO_INDEX(token.end_column); document_links.push_back(link); } } } - tokenizer.advance(); } } @@ -144,219 +146,238 @@ void ExtendGDScriptParser::parse_class_symbol(const GDScriptParser::ClassNode *p r_symbol.uri = uri; r_symbol.script_path = path; r_symbol.children.clear(); - r_symbol.name = p_class->name; - if (r_symbol.name.empty()) { + r_symbol.name = p_class->identifier != nullptr ? String(p_class->identifier->name) : String(); + if (r_symbol.name.is_empty()) { r_symbol.name = path.get_file(); } r_symbol.kind = lsp::SymbolKind::Class; r_symbol.deprecated = false; - r_symbol.range.start.line = LINE_NUMBER_TO_INDEX(p_class->line); - r_symbol.range.start.character = p_class->column; + r_symbol.range.start.line = LINE_NUMBER_TO_INDEX(p_class->start_line); + r_symbol.range.start.character = LINE_NUMBER_TO_INDEX(p_class->start_column); r_symbol.range.end.line = LINE_NUMBER_TO_INDEX(p_class->end_line); r_symbol.selectionRange.start.line = r_symbol.range.start.line; r_symbol.detail = "class " + r_symbol.name; bool is_root_class = &r_symbol == &class_symbol; - r_symbol.documentation = parse_documentation(is_root_class ? 0 : LINE_NUMBER_TO_INDEX(p_class->line), is_root_class); - - for (int i = 0; i < p_class->variables.size(); ++i) { - const GDScriptParser::ClassNode::Member &m = p_class->variables[i]; - - lsp::DocumentSymbol symbol; - symbol.name = m.identifier; - symbol.kind = lsp::SymbolKind::Variable; - symbol.deprecated = false; - const int line = LINE_NUMBER_TO_INDEX(m.line); - symbol.range.start.line = line; - symbol.range.start.character = lines[line].length() - lines[line].strip_edges(true, false).length(); - symbol.range.end.line = line; - symbol.range.end.character = lines[line].length(); - symbol.selectionRange.start.line = symbol.range.start.line; - if (m._export.type != Variant::NIL) { - symbol.detail += "export "; - } - symbol.detail += "var " + m.identifier; - if (m.data_type.kind != GDScriptParser::DataType::UNRESOLVED) { - symbol.detail += ": " + m.data_type.to_string(); - } - if (m.default_value.get_type() != Variant::NIL) { - symbol.detail += " = " + JSON::print(m.default_value); - } - - symbol.documentation = parse_documentation(line); - symbol.uri = uri; - symbol.script_path = path; - - r_symbol.children.push_back(symbol); - } - - for (int i = 0; i < p_class->_signals.size(); ++i) { - const GDScriptParser::ClassNode::Signal &signal = p_class->_signals[i]; - - lsp::DocumentSymbol symbol; - symbol.name = signal.name; - symbol.kind = lsp::SymbolKind::Event; - symbol.deprecated = false; - const int line = LINE_NUMBER_TO_INDEX(signal.line); - symbol.range.start.line = line; - symbol.range.start.character = lines[line].length() - lines[line].strip_edges(true, false).length(); - symbol.range.end.line = symbol.range.start.line; - symbol.range.end.character = lines[line].length(); - symbol.selectionRange.start.line = symbol.range.start.line; - symbol.documentation = parse_documentation(line); - symbol.uri = uri; - symbol.script_path = path; - symbol.detail = "signal " + signal.name + "("; - for (int j = 0; j < signal.arguments.size(); j++) { - if (j > 0) { - symbol.detail += ", "; - } - symbol.detail += signal.arguments[j]; - } - symbol.detail += ")"; - - r_symbol.children.push_back(symbol); - } + r_symbol.documentation = parse_documentation(is_root_class ? 0 : LINE_NUMBER_TO_INDEX(p_class->start_line), is_root_class); + + for (int i = 0; i < p_class->members.size(); i++) { + const ClassNode::Member &m = p_class->members[i]; + + switch (m.type) { + case ClassNode::Member::VARIABLE: { + lsp::DocumentSymbol symbol; + symbol.name = m.variable->identifier->name; + symbol.kind = lsp::SymbolKind::Variable; + symbol.deprecated = false; + symbol.range.start.line = LINE_NUMBER_TO_INDEX(m.variable->start_line); + symbol.range.start.character = LINE_NUMBER_TO_INDEX(m.variable->start_column); + symbol.range.end.line = LINE_NUMBER_TO_INDEX(m.variable->end_line); + symbol.range.end.character = LINE_NUMBER_TO_INDEX(m.variable->end_column); + symbol.selectionRange.start.line = symbol.range.start.line; + if (m.variable->exported) { + symbol.detail += "@export "; + } + symbol.detail += "var " + m.variable->identifier->name; + if (m.get_datatype().is_hard_type()) { + symbol.detail += ": " + m.get_datatype().to_string(); + } + if (m.variable->initializer != nullptr && m.variable->initializer->is_constant) { + symbol.detail += " = " + JSON::print(m.variable->initializer->reduced_value); + } - for (Map<StringName, GDScriptParser::ClassNode::Constant>::Element *E = p_class->constant_expressions.front(); E; E = E->next()) { - lsp::DocumentSymbol symbol; - const GDScriptParser::ClassNode::Constant &c = E->value(); - const GDScriptParser::ConstantNode *node = dynamic_cast<const GDScriptParser::ConstantNode *>(c.expression); - ERR_FAIL_COND(!node); - symbol.name = E->key(); - symbol.kind = lsp::SymbolKind::Constant; - symbol.deprecated = false; - const int line = LINE_NUMBER_TO_INDEX(E->get().expression->line); - symbol.range.start.line = line; - symbol.range.start.character = E->get().expression->column; - symbol.range.end.line = symbol.range.start.line; - symbol.range.end.character = lines[line].length(); - symbol.selectionRange.start.line = symbol.range.start.line; - symbol.documentation = parse_documentation(line); - symbol.uri = uri; - symbol.script_path = path; + symbol.documentation = parse_documentation(LINE_NUMBER_TO_INDEX(m.variable->start_line)); + symbol.uri = uri; + symbol.script_path = path; + + r_symbol.children.push_back(symbol); + } break; + case ClassNode::Member::CONSTANT: { + lsp::DocumentSymbol symbol; + + symbol.name = m.constant->identifier->name; + symbol.kind = lsp::SymbolKind::Constant; + symbol.deprecated = false; + symbol.range.start.line = LINE_NUMBER_TO_INDEX(m.constant->start_line); + symbol.range.start.character = LINE_NUMBER_TO_INDEX(m.constant->start_column); + symbol.range.end.line = LINE_NUMBER_TO_INDEX(m.constant->end_line); + symbol.range.end.character = LINE_NUMBER_TO_INDEX(m.constant->start_column); + symbol.selectionRange.start.line = LINE_NUMBER_TO_INDEX(m.constant->start_line); + symbol.documentation = parse_documentation(LINE_NUMBER_TO_INDEX(m.constant->start_line)); + symbol.uri = uri; + symbol.script_path = path; + + symbol.detail = "const " + symbol.name; + if (m.constant->get_datatype().is_hard_type()) { + symbol.detail += ": " + m.constant->get_datatype().to_string(); + } - symbol.detail = "const " + symbol.name; - if (c.type.kind != GDScriptParser::DataType::UNRESOLVED) { - symbol.detail += ": " + c.type.to_string(); - } + const Variant &default_value = m.constant->initializer->reduced_value; + String value_text; + if (default_value.get_type() == Variant::OBJECT) { + RES res = default_value; + if (res.is_valid() && !res->get_path().is_empty()) { + value_text = "preload(\"" + res->get_path() + "\")"; + if (symbol.documentation.is_empty()) { + if (Map<String, ExtendGDScriptParser *>::Element *S = GDScriptLanguageProtocol::get_singleton()->get_workspace()->scripts.find(res->get_path())) { + symbol.documentation = S->get()->class_symbol.documentation; + } + } + } else { + value_text = JSON::print(default_value); + } + } else { + value_text = JSON::print(default_value); + } + if (!value_text.is_empty()) { + symbol.detail += " = " + value_text; + } - String value_text; - if (node->value.get_type() == Variant::OBJECT) { - RES res = node->value; - if (res.is_valid() && !res->get_path().empty()) { - value_text = "preload(\"" + res->get_path() + "\")"; - if (symbol.documentation.empty()) { - if (Map<String, ExtendGDScriptParser *>::Element *S = GDScriptLanguageProtocol::get_singleton()->get_workspace()->scripts.find(res->get_path())) { - symbol.documentation = S->get()->class_symbol.documentation; + r_symbol.children.push_back(symbol); + } break; + case ClassNode::Member::ENUM_VALUE: { + lsp::DocumentSymbol symbol; + + symbol.name = m.enum_value.identifier->name; + symbol.kind = lsp::SymbolKind::EnumMember; + symbol.deprecated = false; + symbol.range.start.line = LINE_NUMBER_TO_INDEX(m.enum_value.line); + symbol.range.start.character = LINE_NUMBER_TO_INDEX(m.enum_value.leftmost_column); + symbol.range.end.line = LINE_NUMBER_TO_INDEX(m.enum_value.line); + symbol.range.end.character = LINE_NUMBER_TO_INDEX(m.enum_value.rightmost_column); + symbol.selectionRange.start.line = LINE_NUMBER_TO_INDEX(m.enum_value.line); + symbol.documentation = parse_documentation(LINE_NUMBER_TO_INDEX(m.enum_value.line)); + symbol.uri = uri; + symbol.script_path = path; + + symbol.detail = symbol.name + " = " + itos(m.enum_value.value); + + r_symbol.children.push_back(symbol); + } break; + case ClassNode::Member::SIGNAL: { + lsp::DocumentSymbol symbol; + symbol.name = m.signal->identifier->name; + symbol.kind = lsp::SymbolKind::Event; + symbol.deprecated = false; + symbol.range.start.line = LINE_NUMBER_TO_INDEX(m.signal->start_line); + symbol.range.start.character = LINE_NUMBER_TO_INDEX(m.signal->start_column); + symbol.range.end.line = LINE_NUMBER_TO_INDEX(m.signal->end_line); + symbol.range.end.character = LINE_NUMBER_TO_INDEX(m.signal->end_column); + symbol.selectionRange.start.line = symbol.range.start.line; + symbol.documentation = parse_documentation(LINE_NUMBER_TO_INDEX(m.signal->start_line)); + symbol.uri = uri; + symbol.script_path = path; + symbol.detail = "signal " + String(m.signal->identifier->name) + "("; + for (int j = 0; j < m.signal->parameters.size(); j++) { + if (j > 0) { + symbol.detail += ", "; } + symbol.detail += m.signal->parameters[i]->identifier->name; } - } else { - value_text = JSON::print(node->value); - } - } else { - value_text = JSON::print(node->value); - } - if (!value_text.empty()) { - symbol.detail += " = " + value_text; + symbol.detail += ")"; + + r_symbol.children.push_back(symbol); + } break; + case ClassNode::Member::ENUM: { + lsp::DocumentSymbol symbol; + symbol.kind = lsp::SymbolKind::Enum; + symbol.range.start.line = LINE_NUMBER_TO_INDEX(m.m_enum->start_line); + symbol.range.start.character = LINE_NUMBER_TO_INDEX(m.m_enum->start_column); + symbol.range.end.line = LINE_NUMBER_TO_INDEX(m.m_enum->end_line); + symbol.range.end.character = LINE_NUMBER_TO_INDEX(m.m_enum->end_column); + symbol.selectionRange.start.line = symbol.range.start.line; + symbol.documentation = parse_documentation(LINE_NUMBER_TO_INDEX(m.m_enum->start_line)); + symbol.uri = uri; + symbol.script_path = path; + + symbol.detail = "enum " + String(m.m_enum->identifier->name) + "{"; + for (int j = 0; j < m.m_enum->values.size(); j++) { + if (j > 0) { + symbol.detail += ", "; + } + symbol.detail += String(m.m_enum->values[j].identifier->name) + " = " + itos(m.m_enum->values[j].value); + } + symbol.detail += "}"; + r_symbol.children.push_back(symbol); + } break; + case ClassNode::Member::FUNCTION: { + lsp::DocumentSymbol symbol; + parse_function_symbol(m.function, symbol); + r_symbol.children.push_back(symbol); + } break; + case ClassNode::Member::CLASS: { + lsp::DocumentSymbol symbol; + parse_class_symbol(m.m_class, symbol); + r_symbol.children.push_back(symbol); + } break; + case ClassNode::Member::UNDEFINED: + break; // Unreachable. } - - r_symbol.children.push_back(symbol); - } - - for (int i = 0; i < p_class->functions.size(); ++i) { - const GDScriptParser::FunctionNode *func = p_class->functions[i]; - lsp::DocumentSymbol symbol; - parse_function_symbol(func, symbol); - r_symbol.children.push_back(symbol); - } - - for (int i = 0; i < p_class->static_functions.size(); ++i) { - const GDScriptParser::FunctionNode *func = p_class->static_functions[i]; - lsp::DocumentSymbol symbol; - parse_function_symbol(func, symbol); - r_symbol.children.push_back(symbol); - } - - for (int i = 0; i < p_class->subclasses.size(); ++i) { - const GDScriptParser::ClassNode *subclass = p_class->subclasses[i]; - lsp::DocumentSymbol symbol; - parse_class_symbol(subclass, symbol); - r_symbol.children.push_back(symbol); } } void ExtendGDScriptParser::parse_function_symbol(const GDScriptParser::FunctionNode *p_func, lsp::DocumentSymbol &r_symbol) { const String uri = get_uri(); - r_symbol.name = p_func->name; + r_symbol.name = p_func->identifier->name; r_symbol.kind = lsp::SymbolKind::Function; - r_symbol.detail = "func " + p_func->name + "("; + r_symbol.detail = "func " + String(p_func->identifier->name) + "("; r_symbol.deprecated = false; - const int line = LINE_NUMBER_TO_INDEX(p_func->line); - r_symbol.range.start.line = line; - r_symbol.range.start.character = p_func->column; - r_symbol.range.end.line = MAX(p_func->body->end_line - 2, r_symbol.range.start.line); - r_symbol.range.end.character = lines[r_symbol.range.end.line].length(); + r_symbol.range.start.line = LINE_NUMBER_TO_INDEX(p_func->start_line); + r_symbol.range.start.character = LINE_NUMBER_TO_INDEX(p_func->start_column); + r_symbol.range.end.line = LINE_NUMBER_TO_INDEX(p_func->start_line); + r_symbol.range.end.character = LINE_NUMBER_TO_INDEX(p_func->end_column); r_symbol.selectionRange.start.line = r_symbol.range.start.line; - r_symbol.documentation = parse_documentation(line); + r_symbol.documentation = parse_documentation(LINE_NUMBER_TO_INDEX(p_func->start_line)); r_symbol.uri = uri; r_symbol.script_path = path; - String arguments; - for (int i = 0; i < p_func->arguments.size(); i++) { + String parameters; + for (int i = 0; i < p_func->parameters.size(); i++) { + const ParameterNode *parameter = p_func->parameters[i]; lsp::DocumentSymbol symbol; symbol.kind = lsp::SymbolKind::Variable; - symbol.name = p_func->arguments[i]; - symbol.range.start.line = LINE_NUMBER_TO_INDEX(p_func->body->line); - symbol.range.start.character = p_func->body->column; - symbol.range.end = symbol.range.start; + symbol.name = parameter->identifier->name; + symbol.range.start.line = LINE_NUMBER_TO_INDEX(parameter->start_line); + symbol.range.start.character = LINE_NUMBER_TO_INDEX(parameter->start_line); + symbol.range.end.line = LINE_NUMBER_TO_INDEX(parameter->end_line); + symbol.range.end.character = LINE_NUMBER_TO_INDEX(parameter->end_column); symbol.uri = uri; symbol.script_path = path; r_symbol.children.push_back(symbol); if (i > 0) { - arguments += ", "; + parameters += ", "; } - arguments += String(p_func->arguments[i]); - if (p_func->argument_types[i].kind != GDScriptParser::DataType::UNRESOLVED) { - arguments += ": " + p_func->argument_types[i].to_string(); + parameters += String(parameter->identifier->name); + if (parameter->get_datatype().is_hard_type()) { + parameters += ": " + parameter->get_datatype().to_string(); } - int default_value_idx = i - (p_func->arguments.size() - p_func->default_values.size()); - if (default_value_idx >= 0) { - const GDScriptParser::ConstantNode *const_node = dynamic_cast<const GDScriptParser::ConstantNode *>(p_func->default_values[default_value_idx]); - if (const_node == nullptr) { - const GDScriptParser::OperatorNode *operator_node = dynamic_cast<const GDScriptParser::OperatorNode *>(p_func->default_values[default_value_idx]); - if (operator_node) { - const_node = dynamic_cast<const GDScriptParser::ConstantNode *>(operator_node->next); - } - } - - if (const_node) { - String value = JSON::print(const_node->value); - arguments += " = " + value; - } + if (parameter->default_value != nullptr) { + String value = JSON::print(parameter->default_value->reduced_value); + parameters += " = " + value; } } - r_symbol.detail += arguments + ")"; - if (p_func->return_type.kind != GDScriptParser::DataType::UNRESOLVED) { - r_symbol.detail += " -> " + p_func->return_type.to_string(); + r_symbol.detail += parameters + ")"; + if (p_func->get_datatype().is_hard_type()) { + r_symbol.detail += " -> " + p_func->get_datatype().to_string(); } - for (const Map<StringName, LocalVarNode *>::Element *E = p_func->body->variables.front(); E; E = E->next()) { + for (int i = 0; i < p_func->body->locals.size(); i++) { + const SuiteNode::Local &local = p_func->body->locals[i]; lsp::DocumentSymbol symbol; - const GDScriptParser::LocalVarNode *var = E->value(); - symbol.name = E->key(); - symbol.kind = lsp::SymbolKind::Variable; - symbol.range.start.line = LINE_NUMBER_TO_INDEX(E->get()->line); - symbol.range.start.character = E->get()->column; - symbol.range.end.line = symbol.range.start.line; - symbol.range.end.character = lines[symbol.range.end.line].length(); + symbol.name = local.name; + symbol.kind = local.type == SuiteNode::Local::CONSTANT ? lsp::SymbolKind::Constant : lsp::SymbolKind::Variable; + symbol.range.start.line = LINE_NUMBER_TO_INDEX(local.start_line); + symbol.range.start.character = LINE_NUMBER_TO_INDEX(local.start_column); + symbol.range.end.line = LINE_NUMBER_TO_INDEX(local.end_line); + symbol.range.end.character = LINE_NUMBER_TO_INDEX(local.end_column); symbol.uri = uri; symbol.script_path = path; - symbol.detail = "var " + symbol.name; - if (var->datatype.kind != GDScriptParser::DataType::UNRESOLVED) { - symbol.detail += ": " + var->datatype.to_string(); + symbol.detail = SuiteNode::Local::CONSTANT ? "const " : "var "; + symbol.detail += symbol.name; + if (local.get_datatype().is_hard_type()) { + symbol.detail += ": " + local.get_datatype().to_string(); } - symbol.documentation = parse_documentation(line); + symbol.documentation = parse_documentation(LINE_NUMBER_TO_INDEX(local.start_line)); r_symbol.children.push_back(symbol); } } @@ -432,7 +453,7 @@ String ExtendGDScriptParser::get_text_for_lookup_symbol(const lsp::Position &p_c String line = lines[i]; String first_part = line.substr(0, p_cursor.character); String last_part = line.substr(p_cursor.character + 1, lines[i].length()); - if (!p_symbol.empty()) { + if (!p_symbol.is_empty()) { String left_cursor_text; for (int c = p_cursor.character - 1; c >= 0; c--) { left_cursor_text = line.substr(c, p_cursor.character - c); @@ -470,7 +491,7 @@ String ExtendGDScriptParser::get_identifier_under_position(const lsp::Position & int start_pos = p_position.character; for (int c = p_position.character; c >= 0; c--) { start_pos = c; - CharType ch = line[c]; + char32_t ch = line[c]; bool valid_char = (ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || ch == '_'; if (!valid_char) { break; @@ -479,7 +500,7 @@ String ExtendGDScriptParser::get_identifier_under_position(const lsp::Position & int end_pos = p_position.character; for (int c = p_position.character; c < line.length(); c++) { - CharType ch = line[c]; + char32_t ch = line[c]; bool valid_char = (ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || ch == '_'; if (!valid_char) { break; @@ -531,7 +552,7 @@ Error ExtendGDScriptParser::get_left_function_call(const lsp::Position &p_positi } while (c >= 0) { - const CharType &character = line[c]; + const char32_t &character = line[c]; if (character == ')') { ++bracket_stack; } else if (character == '(') { @@ -568,7 +589,7 @@ const lsp::DocumentSymbol *ExtendGDScriptParser::get_symbol_defined_at_line(int } const lsp::DocumentSymbol *ExtendGDScriptParser::get_member_symbol(const String &p_name, const String &p_subclass) const { - if (p_subclass.empty()) { + if (p_subclass.is_empty()) { const lsp::DocumentSymbol *const *ptr = members.getptr(p_name); if (ptr) { return *ptr; @@ -590,7 +611,7 @@ const List<lsp::DocumentLink> &ExtendGDScriptParser::get_document_links() const } const Array &ExtendGDScriptParser::get_member_completions() { - if (member_completions.empty()) { + if (member_completions.is_empty()) { const String *name = members.next(nullptr); while (name) { const lsp::DocumentSymbol *symbol = members.get(*name); @@ -624,34 +645,24 @@ const Array &ExtendGDScriptParser::get_member_completions() { Dictionary ExtendGDScriptParser::dump_function_api(const GDScriptParser::FunctionNode *p_func) const { Dictionary func; ERR_FAIL_NULL_V(p_func, func); - func["name"] = p_func->name; - func["return_type"] = p_func->return_type.to_string(); + func["name"] = p_func->identifier->name; + func["return_type"] = p_func->get_datatype().to_string(); func["rpc_mode"] = p_func->rpc_mode; - Array arguments; - for (int i = 0; i < p_func->arguments.size(); i++) { + Array parameters; + for (int i = 0; i < p_func->parameters.size(); i++) { Dictionary arg; - arg["name"] = p_func->arguments[i]; - arg["type"] = p_func->argument_types[i].to_string(); - int default_value_idx = i - (p_func->arguments.size() - p_func->default_values.size()); - if (default_value_idx >= 0) { - const GDScriptParser::ConstantNode *const_node = dynamic_cast<const GDScriptParser::ConstantNode *>(p_func->default_values[default_value_idx]); - if (const_node == nullptr) { - const GDScriptParser::OperatorNode *operator_node = dynamic_cast<const GDScriptParser::OperatorNode *>(p_func->default_values[default_value_idx]); - if (operator_node) { - const_node = dynamic_cast<const GDScriptParser::ConstantNode *>(operator_node->next); - } - } - if (const_node) { - arg["default_value"] = const_node->value; - } + arg["name"] = p_func->parameters[i]->identifier->name; + arg["type"] = p_func->parameters[i]->get_datatype().to_string(); + if (p_func->parameters[i]->default_value != nullptr) { + arg["default_value"] = p_func->parameters[i]->default_value->reduced_value; } - arguments.push_back(arg); + parameters.push_back(arg); } - if (const lsp::DocumentSymbol *symbol = get_symbol_defined_at_line(LINE_NUMBER_TO_INDEX(p_func->line))) { + if (const lsp::DocumentSymbol *symbol = get_symbol_defined_at_line(LINE_NUMBER_TO_INDEX(p_func->start_line))) { func["signature"] = symbol->detail; func["description"] = symbol->documentation; } - func["arguments"] = arguments; + func["arguments"] = parameters; return func; } @@ -660,91 +671,117 @@ Dictionary ExtendGDScriptParser::dump_class_api(const GDScriptParser::ClassNode ERR_FAIL_NULL_V(p_class, class_api); - class_api["name"] = String(p_class->name); + class_api["name"] = p_class->identifier != nullptr ? String(p_class->identifier->name) : String(); class_api["path"] = path; Array extends_class; - for (int i = 0; i < p_class->extends_class.size(); i++) { - extends_class.append(String(p_class->extends_class[i])); + for (int i = 0; i < p_class->extends.size(); i++) { + extends_class.append(String(p_class->extends[i])); } class_api["extends_class"] = extends_class; - class_api["extends_file"] = String(p_class->extends_file); + class_api["extends_file"] = String(p_class->extends_path); class_api["icon"] = String(p_class->icon_path); - if (const lsp::DocumentSymbol *symbol = get_symbol_defined_at_line(LINE_NUMBER_TO_INDEX(p_class->line))) { + if (const lsp::DocumentSymbol *symbol = get_symbol_defined_at_line(LINE_NUMBER_TO_INDEX(p_class->start_line))) { class_api["signature"] = symbol->detail; class_api["description"] = symbol->documentation; } - Array subclasses; - for (int i = 0; i < p_class->subclasses.size(); i++) { - subclasses.push_back(dump_class_api(p_class->subclasses[i])); - } - class_api["sub_classes"] = subclasses; - + Array nested_classes; Array constants; - for (Map<StringName, GDScriptParser::ClassNode::Constant>::Element *E = p_class->constant_expressions.front(); E; E = E->next()) { - const GDScriptParser::ClassNode::Constant &c = E->value(); - const GDScriptParser::ConstantNode *node = dynamic_cast<const GDScriptParser::ConstantNode *>(c.expression); - ERR_FAIL_COND_V(!node, class_api); - - Dictionary api; - api["name"] = E->key(); - api["value"] = node->value; - api["data_type"] = node->datatype.to_string(); - if (const lsp::DocumentSymbol *symbol = get_symbol_defined_at_line(LINE_NUMBER_TO_INDEX(node->line))) { - api["signature"] = symbol->detail; - api["description"] = symbol->documentation; - } - constants.push_back(api); - } - class_api["constants"] = constants; - Array members; - for (int i = 0; i < p_class->variables.size(); ++i) { - const GDScriptParser::ClassNode::Member &m = p_class->variables[i]; - Dictionary api; - api["name"] = m.identifier; - api["data_type"] = m.data_type.to_string(); - api["default_value"] = m.default_value; - api["setter"] = String(m.setter); - api["getter"] = String(m.getter); - api["export"] = m._export.type != Variant::NIL; - if (const lsp::DocumentSymbol *symbol = get_symbol_defined_at_line(LINE_NUMBER_TO_INDEX(m.line))) { - api["signature"] = symbol->detail; - api["description"] = symbol->documentation; - } - members.push_back(api); - } - class_api["members"] = members; - Array signals; - for (int i = 0; i < p_class->_signals.size(); ++i) { - const GDScriptParser::ClassNode::Signal &signal = p_class->_signals[i]; - Dictionary api; - api["name"] = signal.name; - Array args; - for (int j = 0; j < signal.arguments.size(); j++) { - args.append(signal.arguments[j]); - } - api["arguments"] = args; - if (const lsp::DocumentSymbol *symbol = get_symbol_defined_at_line(LINE_NUMBER_TO_INDEX(signal.line))) { - api["signature"] = symbol->detail; - api["description"] = symbol->documentation; + Array methods; + Array static_functions; + + for (int i = 0; i < p_class->members.size(); i++) { + const ClassNode::Member &m = p_class->members[i]; + switch (m.type) { + case ClassNode::Member::CLASS: + nested_classes.push_back(dump_class_api(m.m_class)); + break; + case ClassNode::Member::CONSTANT: { + Dictionary api; + api["name"] = m.constant->identifier->name; + api["value"] = m.constant->initializer->reduced_value; + api["data_type"] = m.constant->get_datatype().to_string(); + if (const lsp::DocumentSymbol *symbol = get_symbol_defined_at_line(LINE_NUMBER_TO_INDEX(m.constant->start_line))) { + api["signature"] = symbol->detail; + api["description"] = symbol->documentation; + } + constants.push_back(api); + } break; + case ClassNode::Member::ENUM_VALUE: { + Dictionary api; + api["name"] = m.enum_value.identifier->name; + api["value"] = m.enum_value.value; + api["data_type"] = m.get_datatype().to_string(); + if (const lsp::DocumentSymbol *symbol = get_symbol_defined_at_line(LINE_NUMBER_TO_INDEX(m.enum_value.line))) { + api["signature"] = symbol->detail; + api["description"] = symbol->documentation; + } + constants.push_back(api); + } break; + case ClassNode::Member::ENUM: { + Dictionary enum_dict; + for (int j = 0; j < m.m_enum->values.size(); j++) { + enum_dict[m.m_enum->values[j].identifier->name] = m.m_enum->values[j].value; + } + + Dictionary api; + api["name"] = m.m_enum->identifier->name; + api["value"] = enum_dict; + api["data_type"] = m.get_datatype().to_string(); + if (const lsp::DocumentSymbol *symbol = get_symbol_defined_at_line(LINE_NUMBER_TO_INDEX(m.m_enum->start_line))) { + api["signature"] = symbol->detail; + api["description"] = symbol->documentation; + } + constants.push_back(api); + } break; + case ClassNode::Member::VARIABLE: { + Dictionary api; + api["name"] = m.variable->identifier->name; + api["data_type"] = m.variable->get_datatype().to_string(); + api["default_value"] = m.variable->initializer != nullptr ? m.variable->initializer->reduced_value : Variant(); + api["setter"] = m.variable->setter ? ("@" + String(m.variable->identifier->name) + "_setter") : (m.variable->setter_pointer != nullptr ? String(m.variable->setter_pointer->name) : String()); + api["getter"] = m.variable->getter ? ("@" + String(m.variable->identifier->name) + "_getter") : (m.variable->getter_pointer != nullptr ? String(m.variable->getter_pointer->name) : String()); + api["export"] = m.variable->exported; + if (const lsp::DocumentSymbol *symbol = get_symbol_defined_at_line(LINE_NUMBER_TO_INDEX(m.variable->start_line))) { + api["signature"] = symbol->detail; + api["description"] = symbol->documentation; + } + members.push_back(api); + } break; + case ClassNode::Member::SIGNAL: { + Dictionary api; + api["name"] = m.signal->identifier->name; + Array pars; + for (int j = 0; j < m.signal->parameters.size(); j++) { + pars.append(String(m.signal->parameters[i]->identifier->name)); + } + api["arguments"] = pars; + if (const lsp::DocumentSymbol *symbol = get_symbol_defined_at_line(LINE_NUMBER_TO_INDEX(m.signal->start_line))) { + api["signature"] = symbol->detail; + api["description"] = symbol->documentation; + } + signals.push_back(api); + } break; + case ClassNode::Member::FUNCTION: { + if (m.function->is_static) { + static_functions.append(dump_function_api(m.function)); + } else { + methods.append(dump_function_api(m.function)); + } + } break; + case ClassNode::Member::UNDEFINED: + break; // Unreachable. } - signals.push_back(api); } - class_api["signals"] = signals; - Array methods; - for (int i = 0; i < p_class->functions.size(); ++i) { - methods.append(dump_function_api(p_class->functions[i])); - } + class_api["sub_classes"] = nested_classes; + class_api["constants"] = constants; + class_api["members"] = members; + class_api["signals"] = signals; class_api["methods"] = methods; - - Array static_functions; - for (int i = 0; i < p_class->static_functions.size(); ++i) { - static_functions.append(dump_function_api(p_class->static_functions[i])); - } class_api["static_functions"] = static_functions; return class_api; @@ -752,7 +789,7 @@ Dictionary ExtendGDScriptParser::dump_class_api(const GDScriptParser::ClassNode Dictionary ExtendGDScriptParser::generate_api() const { Dictionary api; - const GDScriptParser::Node *head = get_parse_tree(); + const GDScriptParser::Node *head = get_tree(); if (const GDScriptParser::ClassNode *gdclass = dynamic_cast<const GDScriptParser::ClassNode *>(head)) { api = dump_class_api(gdclass); } @@ -763,7 +800,11 @@ Error ExtendGDScriptParser::parse(const String &p_code, const String &p_path) { path = p_path; lines = p_code.split("\n"); - Error err = GDScriptParser::parse(p_code, p_path.get_base_dir(), false, p_path, false, nullptr, false); + Error err = GDScriptParser::parse(p_code, p_path, false); + if (err == OK) { + GDScriptAnalyzer analyzer(this); + err = analyzer.analyze(); + } update_diagnostics(); update_symbols(); update_document_links(p_code); diff --git a/modules/gdscript/language_server/gdscript_extend_parser.h b/modules/gdscript/language_server/gdscript_extend_parser.h index 0c031d7883..28b9b3c82a 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-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 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 */ @@ -32,7 +32,7 @@ #define GDSCRIPT_EXTEND_PARSER_H #include "../gdscript_parser.h" -#include "core/variant.h" +#include "core/variant/variant.h" #include "lsp.hpp" #ifndef LINE_NUMBER_TO_INDEX diff --git a/modules/gdscript/language_server/gdscript_language_protocol.cpp b/modules/gdscript/language_server/gdscript_language_protocol.cpp index 2a67d2ff4f..912c9a174e 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-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 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 */ @@ -30,9 +30,10 @@ #include "gdscript_language_protocol.h" +#include "core/config/project_settings.h" #include "core/io/json.h" #include "core/os/copymem.h" -#include "core/project_settings.h" +#include "editor/doc_tools.h" #include "editor/editor_log.h" #include "editor/editor_node.h" @@ -95,7 +96,7 @@ Error GDScriptLanguageProtocol::LSPeer::handle_data() { // Response String output = GDScriptLanguageProtocol::get_singleton()->process_message(msg); - if (!output.empty()) { + if (!output.is_empty()) { res_queue.push_back(output.utf8()); } } @@ -104,7 +105,7 @@ Error GDScriptLanguageProtocol::LSPeer::handle_data() { Error GDScriptLanguageProtocol::LSPeer::send_data() { int sent = 0; - if (!res_queue.empty()) { + if (!res_queue.is_empty()) { CharString c_res = res_queue[0]; if (res_sent < c_res.size()) { Error err = connection->put_partial_data((const uint8_t *)c_res.get_data() + res_sent, c_res.size() - res_sent - 1, sent); @@ -140,7 +141,7 @@ void GDScriptLanguageProtocol::on_client_disconnected(const int &p_client_id) { String GDScriptLanguageProtocol::process_message(const String &p_text) { String ret = process_string(p_text); - if (ret.empty()) { + if (ret.is_empty()) { return ret; } else { return format_output(ret); @@ -162,7 +163,7 @@ void GDScriptLanguageProtocol::_bind_methods() { ClassDB::bind_method(D_METHOD("initialized", "params"), &GDScriptLanguageProtocol::initialized); ClassDB::bind_method(D_METHOD("on_client_connected"), &GDScriptLanguageProtocol::on_client_connected); ClassDB::bind_method(D_METHOD("on_client_disconnected"), &GDScriptLanguageProtocol::on_client_disconnected); - ClassDB::bind_method(D_METHOD("notify_client", "method", "params"), &GDScriptLanguageProtocol::notify_client, DEFVAL(Variant()), DEFVAL(-1)); + ClassDB::bind_method(D_METHOD("notify_client", "method", "params", "client_id"), &GDScriptLanguageProtocol::notify_client, DEFVAL(Variant()), DEFVAL(-1)); ClassDB::bind_method(D_METHOD("is_smart_resolve_enabled"), &GDScriptLanguageProtocol::is_smart_resolve_enabled); ClassDB::bind_method(D_METHOD("get_text_document"), &GDScriptLanguageProtocol::get_text_document); ClassDB::bind_method(D_METHOD("get_workspace"), &GDScriptLanguageProtocol::get_workspace); @@ -212,7 +213,7 @@ Dictionary GDScriptLanguageProtocol::initialize(const Dictionary &p_params) { void GDScriptLanguageProtocol::initialized(const Variant &p_params) { lsp::GodotCapabilities capabilities; - DocData *doc = EditorHelp::get_doc_data(); + DocTools *doc = EditorHelp::get_doc_data(); for (Map<String, DocData::ClassDoc>::Element *E = doc->class_list.front(); E; E = E->next()) { lsp::GodotNativeClassInfo gdclass; gdclass.name = E->get().name; diff --git a/modules/gdscript/language_server/gdscript_language_protocol.h b/modules/gdscript/language_server/gdscript_language_protocol.h index cf5242e8c5..8b08ae0655 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-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 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 3387d262f8..98ada9de4d 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-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 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 */ @@ -36,12 +36,6 @@ #include "editor/editor_node.h" GDScriptLanguageServer::GDScriptLanguageServer() { - thread = nullptr; - thread_running = false; - started = false; - - use_thread = false; - port = 6008; _EDITOR_DEF("network/language_server/remote_port", port); _EDITOR_DEF("network/language_server/enable_smart_resolve", true); _EDITOR_DEF("network/language_server/show_native_symbols_in_editor", false); @@ -87,9 +81,8 @@ void GDScriptLanguageServer::start() { if (protocol.start(port, IP_Address("127.0.0.1")) == OK) { EditorNode::get_log()->add_message("--- GDScript language server started ---", EditorLog::MSG_TYPE_EDITOR); if (use_thread) { - ERR_FAIL_COND(thread != nullptr); thread_running = true; - thread = Thread::create(GDScriptLanguageServer::thread_main, this); + thread.start(GDScriptLanguageServer::thread_main, this); } set_process_internal(!use_thread); started = true; @@ -98,11 +91,9 @@ void GDScriptLanguageServer::start() { void GDScriptLanguageServer::stop() { if (use_thread) { - ERR_FAIL_COND(nullptr == thread); + ERR_FAIL_COND(!thread.is_started()); thread_running = false; - Thread::wait_to_finish(thread); - memdelete(thread); - thread = nullptr; + thread.wait_to_finish(); } protocol.stop(); started = false; diff --git a/modules/gdscript/language_server/gdscript_language_server.h b/modules/gdscript/language_server/gdscript_language_server.h index 228d29bf42..29c5ddd70e 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-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 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 */ @@ -40,11 +40,11 @@ class GDScriptLanguageServer : public EditorPlugin { GDScriptLanguageProtocol protocol; - Thread *thread; - bool thread_running; - bool started; - bool use_thread; - int port; + Thread thread; + bool thread_running = false; + bool started = false; + bool use_thread = false; + int port = 6008; static void thread_main(void *p_userdata); private: diff --git a/modules/gdscript/language_server/gdscript_text_document.cpp b/modules/gdscript/language_server/gdscript_text_document.cpp index c6fe3169dc..9f2373bf56 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-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 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 */ @@ -147,7 +147,7 @@ Array GDScriptTextDocument::completion(const Dictionary &p_params) { List<ScriptCodeCompletionOption> options; GDScriptLanguageProtocol::get_singleton()->get_workspace()->completion(params, &options); - if (!options.empty()) { + if (!options.is_empty()) { int i = 0; arr.resize(options.size()); @@ -257,7 +257,7 @@ Dictionary GDScriptTextDocument::resolve(const Dictionary &p_params) { if ((item.kind == lsp::CompletionItemKind::Method || item.kind == lsp::CompletionItemKind::Function) && !item.label.ends_with("):")) { item.insertText = item.label + "("; - if (symbol && symbol->children.empty()) { + if (symbol && symbol->children.is_empty()) { item.insertText += ")"; } } else if (item.kind == lsp::CompletionItemKind::Event) { @@ -341,7 +341,7 @@ Variant GDScriptTextDocument::declaration(const Dictionary &p_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 + if (arr.is_empty() && !symbols.is_empty() && !symbols.front()->get()->native_class.is_empty()) { // Find a native symbol const lsp::DocumentSymbol *symbol = symbols.front()->get(); if (GDScriptLanguageProtocol::get_singleton()->is_goto_native_symbols_enabled()) { String id; @@ -425,7 +425,7 @@ Array GDScriptTextDocument::find_symbols(const lsp::TextDocumentPositionParams & 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()) { + if (!s->uri.is_empty()) { lsp::Location location; location.uri = s->uri; location.range = s->range; diff --git a/modules/gdscript/language_server/gdscript_text_document.h b/modules/gdscript/language_server/gdscript_text_document.h index b2fd0c31f9..792e601bc1 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-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 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,8 +31,8 @@ #ifndef GDSCRIPT_TEXT_DOCUMENT_H #define GDSCRIPT_TEXT_DOCUMENT_H +#include "core/object/reference.h" #include "core/os/file_access.h" -#include "core/reference.h" #include "lsp.hpp" class GDScriptTextDocument : public Reference { diff --git a/modules/gdscript/language_server/gdscript_workspace.cpp b/modules/gdscript/language_server/gdscript_workspace.cpp index a203b9bfdb..69cad1a335 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-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 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 */ @@ -32,8 +32,9 @@ #include "../gdscript.h" #include "../gdscript_parser.h" -#include "core/project_settings.h" -#include "core/script_language.h" +#include "core/config/project_settings.h" +#include "core/object/script_language.h" +#include "editor/doc_tools.h" #include "editor/editor_file_system.h" #include "editor/editor_help.h" #include "editor/editor_node.h" @@ -79,7 +80,7 @@ const lsp::DocumentSymbol *GDScriptWorkspace::get_native_symbol(const String &p_ if (const Map<StringName, lsp::DocumentSymbol>::Element *E = native_symbols.find(class_name)) { const lsp::DocumentSymbol &class_symbol = E->value(); - if (p_member.empty()) { + if (p_member.is_empty()) { return &class_symbol; } else { for (int i = 0; i < class_symbol.children.size(); i++) { @@ -118,7 +119,7 @@ void GDScriptWorkspace::reload_all_workspace_scripts() { Map<String, ExtendGDScriptParser *>::Element *S = parse_results.find(path); String err_msg = "Failed parse script " + path; if (S) { - err_msg += "\n" + S->get()->get_error(); + err_msg += "\n" + S->get()->get_errors()[0].message; } ERR_CONTINUE_MSG(err != OK, err_msg); } @@ -170,7 +171,7 @@ ExtendGDScriptParser *GDScriptWorkspace::get_parse_result(const String &p_path) Array GDScriptWorkspace::symbol(const Dictionary &p_params) { String query = p_params["query"]; Array arr; - if (!query.empty()) { + if (!query.is_empty()) { for (Map<String, ExtendGDScriptParser *>::Element *E = scripts.front(); E; E = E->next()) { Vector<lsp::DocumentedSymbolInformation> script_symbols; E->get()->get_symbols().symbol_tree_as_list(E->key(), script_symbols); @@ -189,7 +190,7 @@ Error GDScriptWorkspace::initialize() { return OK; } - DocData *doc = EditorHelp::get_doc_data(); + DocTools *doc = EditorHelp::get_doc_data(); for (Map<String, DocData::ClassDoc>::Element *E = doc->class_list.front(); E; E = E->next()) { const DocData::ClassDoc &class_data = E->value(); lsp::DocumentSymbol class_symbol; @@ -198,7 +199,7 @@ Error GDScriptWorkspace::initialize() { class_symbol.native_class = class_name; class_symbol.kind = lsp::SymbolKind::Class; class_symbol.detail = String("<Native> class ") + class_name; - if (!class_data.inherits.empty()) { + if (!class_data.inherits.is_empty()) { class_symbol.detail += " extends " + class_data.inherits; } class_symbol.documentation = class_data.brief_description + "\n" + class_data.description; @@ -262,7 +263,7 @@ Error GDScriptWorkspace::initialize() { symbol_arg.kind = lsp::SymbolKind::Variable; symbol_arg.detail = arg.type; - if (!arg_default_value_started && !arg.default_value.empty()) { + if (!arg_default_value_started && !arg.default_value.is_empty()) { arg_default_value_started = true; } String arg_str = arg.name + ": " + arg.type; @@ -277,11 +278,11 @@ Error GDScriptWorkspace::initialize() { symbol.children.push_back(symbol_arg); } if (data.qualifiers.find("vararg") != -1) { - params += params.empty() ? "..." : ", ..."; + params += params.is_empty() ? "..." : ", ..."; } String return_type = data.return_type; - if (return_type.empty()) { + if (return_type.is_empty()) { return_type = "void"; } symbol.detail = "func " + class_name + "." + data.name + "(" + params + ") -> " + return_type; @@ -349,7 +350,7 @@ Error GDScriptWorkspace::parse_local_script(const String &p_path) { String GDScriptWorkspace::get_file_path(const String &p_uri) const { String path = p_uri; path = path.replace(root_uri + "/", "res://"); - path = path.http_unescape(); + path = path.uri_decode(); return path; } @@ -447,13 +448,13 @@ const lsp::DocumentSymbol *GDScriptWorkspace::resolve_symbol(const lsp::TextDocu } lsp::Position pos = p_doc_pos.position; - if (symbol_identifier.empty()) { + if (symbol_identifier.is_empty()) { Vector2i offset; symbol_identifier = parser->get_identifier_under_position(p_doc_pos.position, offset); pos.character += offset.y; } - if (!symbol_identifier.empty()) { + if (!symbol_identifier.is_empty()) { if (ScriptServer::is_global_class(symbol_identifier)) { String class_path = ScriptServer::get_global_class_path(symbol_identifier); symbol = get_script_symbol(class_path); @@ -473,7 +474,7 @@ const lsp::DocumentSymbol *GDScriptWorkspace::resolve_symbol(const lsp::TextDocu } else { String member = ret.class_member; - if (member.empty() && symbol_identifier != ret.class_name) { + if (member.is_empty() && symbol_identifier != ret.class_name) { member = symbol_identifier; } symbol = get_native_symbol(ret.class_name, member); @@ -528,7 +529,7 @@ void GDScriptWorkspace::resolve_related_symbols(const lsp::TextDocumentPositionP const lsp::DocumentSymbol *GDScriptWorkspace::resolve_native_symbol(const lsp::NativeSymbolInspectParams &p_params) { if (Map<StringName, lsp::DocumentSymbol>::Element *E = native_symbols.find(p_params.native_class)) { const lsp::DocumentSymbol &symbol = E->get(); - if (p_params.symbol_name.empty() || p_params.symbol_name == symbol.name) { + if (p_params.symbol_name.is_empty() || p_params.symbol_name == symbol.name) { return &symbol; } diff --git a/modules/gdscript/language_server/gdscript_workspace.h b/modules/gdscript/language_server/gdscript_workspace.h index e45b06747d..7fd8bfcf20 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-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 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 */ @@ -32,7 +32,7 @@ #define GDSCRIPT_WORKSPACE_H #include "../gdscript_parser.h" -#include "core/variant.h" +#include "core/variant/variant.h" #include "editor/editor_file_system.h" #include "gdscript_extend_parser.h" #include "lsp.hpp" diff --git a/modules/gdscript/language_server/lsp.hpp b/modules/gdscript/language_server/lsp.hpp index 0075fe9476..6635098be2 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-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 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,9 +31,9 @@ #ifndef GODOT_LSP_H #define GODOT_LSP_H -#include "core/class_db.h" -#include "core/list.h" -#include "editor/doc_data.h" +#include "core/doc_data.h" +#include "core/object/class_db.h" +#include "core/templates/list.h" namespace lsp { @@ -547,7 +547,7 @@ struct TextDocumentItem { * The version number of this document (it will increase after each * change, including undo/redo). */ - int version; + int version = 0; /** * The content of the opened text document. @@ -584,7 +584,7 @@ struct TextDocumentContentChangeEvent { /** * The length of the range that got replaced. */ - int rangeLength; + int rangeLength = 0; /** * The new text of the range/document. @@ -656,12 +656,12 @@ struct Diagnostic { * The diagnostic's severity. Can be omitted. If omitted it is up to the * client to interpret diagnostics as error, warning, info or hint. */ - int severity; + int severity = 0; /** * The diagnostic's code, which might appear in the user interface. */ - int code; + int code = 0; /** * A human-readable string describing the source of this @@ -687,7 +687,7 @@ struct Diagnostic { dict["severity"] = severity; dict["message"] = message; dict["source"] = source; - if (!relatedInformation.empty()) { + if (!relatedInformation.is_empty()) { Array arr; arr.resize(relatedInformation.size()); for (int i = 0; i < relatedInformation.size(); i++) { @@ -833,7 +833,7 @@ struct CompletionItem { * an icon is chosen by the editor. The standardized set * of available values is defined in `CompletionItemKind`. */ - int kind; + int kind = 0; /** * A human-readable string with additional information @@ -891,7 +891,7 @@ struct CompletionItem { * The format of the insert text. The format applies to both the `insertText` property * and the `newText` property of a provided `textEdit`. */ - int insertTextFormat; + int insertTextFormat = 0; /** * An edit which is applied to a document when selecting this completion. When an edit is provided the value of @@ -1003,7 +1003,7 @@ struct CompletionList { * This list it not complete. Further typing should result in recomputing * this list. */ - bool isIncomplete; + bool isIncomplete = false; /** * The completion items. @@ -1191,7 +1191,7 @@ struct DocumentSymbol { void symbol_tree_as_list(const String &p_uri, Vector<DocumentedSymbolInformation> &r_list, const String &p_container = "", bool p_join_name = false) const { DocumentedSymbolInformation si; - if (p_join_name && !p_container.empty()) { + if (p_join_name && !p_container.is_empty()) { si.name = p_container + ">" + name; } else { si.name = name; @@ -1781,7 +1781,6 @@ static String marked_documentation(const String &p_bbcode) { } return markdown; } - } // namespace lsp #endif |