Reenable GDScript LSP server

This commit is contained in:
George Marques 2020-06-12 14:19:29 -03:00
parent dadfcd8aba
commit b6a2628c48
No known key found for this signature in database
GPG Key ID: 046BD46A3201E43D
14 changed files with 353 additions and 342 deletions

View File

@ -149,6 +149,8 @@ T *GDScriptParser::alloc_node() {
// TODO: Properly set positions for all nodes.
node->start_line = previous.start_line;
node->end_line = previous.end_line;
node->start_column = previous.start_column;
node->end_column = previous.end_column;
node->leftmost_column = previous.leftmost_column;
node->rightmost_column = previous.rightmost_column;

View File

@ -232,6 +232,7 @@ public:
Type type = NONE;
int start_line = 0, end_line = 0;
int start_column = 0, end_column = 0;
int leftmost_column = 0, rightmost_column = 0;
Node *next = nullptr;
List<AnnotationNode *> annotations;
@ -855,21 +856,49 @@ public:
type = CONSTANT;
constant = p_constant;
name = p_constant->identifier->name;
start_line = p_constant->start_line;
end_line = p_constant->end_line;
start_column = p_constant->start_column;
end_column = p_constant->end_column;
leftmost_column = p_constant->leftmost_column;
rightmost_column = p_constant->rightmost_column;
}
Local(VariableNode *p_variable) {
type = VARIABLE;
variable = p_variable;
name = p_variable->identifier->name;
start_line = p_variable->start_line;
end_line = p_variable->end_line;
start_column = p_variable->start_column;
end_column = p_variable->end_column;
leftmost_column = p_variable->leftmost_column;
rightmost_column = p_variable->rightmost_column;
}
Local(ParameterNode *p_parameter) {
type = PARAMETER;
parameter = p_parameter;
name = p_parameter->identifier->name;
start_line = p_parameter->start_line;
end_line = p_parameter->end_line;
start_column = p_parameter->start_column;
end_column = p_parameter->end_column;
leftmost_column = p_parameter->leftmost_column;
rightmost_column = p_parameter->rightmost_column;
}
Local(IdentifierNode *p_identifier) {
type = FOR_VARIABLE;
bind = p_identifier;
name = p_identifier->name;
start_line = p_identifier->start_line;
end_line = p_identifier->end_line;
start_column = p_identifier->start_column;
end_column = p_identifier->end_column;
leftmost_column = p_identifier->leftmost_column;
rightmost_column = p_identifier->rightmost_column;
}
};
Local empty;

View File

@ -28,12 +28,10 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
// FIXME: Reenable LSP.
#if 0
#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"
@ -41,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();
@ -70,7 +70,7 @@ void ExtendGDScriptParser::update_diagnostics() {
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();
@ -85,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);
@ -109,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);
@ -129,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();
}
}
@ -147,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;
r_symbol.name = p_class->identifier != nullptr ? String(p_class->identifier->name) : String();
if (r_symbol.name.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);
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->variables.size(); ++i) {
const GDScriptParser::ClassNode::Member &m = p_class->variables[i];
for (int i = 0; i < p_class->members.size(); i++) {
const ClassNode::Member &m = p_class->members[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);
}
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.detail = "const " + symbol.name;
if (c.type.kind != GDScriptParser::DataType::UNRESOLVED) {
symbol.detail += ": " + c.type.to_string();
}
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;
}
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 ";
}
} else {
value_text = JSON::print(node->value);
}
} else {
value_text = JSON::print(node->value);
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);
}
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();
}
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().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;
}
}
} else {
value_text = JSON::print(default_value);
}
} else {
value_text = JSON::print(default_value);
}
if (!value_text.empty()) {
symbol.detail += " = " + value_text;
}
r_symbol.children.push_back(symbol);
} break;
case ClassNode::Member::ENUM_VALUE: {
lsp::DocumentSymbol symbol;
symbol.name = m.constant->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;
}
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 i = 0; i < m.m_enum->values.size(); i++) {
if (i > 0) {
symbol.detail += ", ";
}
symbol.detail += String(m.m_enum->values[i].identifier->name) + " = " + itos(m.m_enum->values[i].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.
}
if (!value_text.empty()) {
symbol.detail += " = " + value_text;
}
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);
}
}
@ -627,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;
}
@ -663,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;
}
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["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]));
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(); i++) {
enum_dict[m.m_enum->values[i].identifier->name] = m.m_enum->values[i].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.
}
}
class_api["sub_classes"] = nested_classes;
class_api["constants"] = constants;
class_api["members"] = members;
class_api["signals"] = signals;
class_api["methods"] = methods;
class_api["static_functions"] = static_functions;
return class_api;
@ -755,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);
}
@ -766,11 +800,13 @@ 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);
return err;
}
#endif

View File

@ -31,9 +31,6 @@
#ifndef GDSCRIPT_EXTEND_PARSER_H
#define GDSCRIPT_EXTEND_PARSER_H
// FIXME: Reenable LSP.
#if 0
#include "../gdscript_parser.h"
#include "core/variant.h"
#include "lsp.hpp"
@ -103,5 +100,3 @@ public:
};
#endif
#endif

View File

@ -28,9 +28,6 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
// FIXME: Reenable LSP.
#if 0
#include "gdscript_language_protocol.h"
#include "core/io/json.h"
@ -306,5 +303,3 @@ GDScriptLanguageProtocol::GDScriptLanguageProtocol() {
set_scope("workspace", workspace.ptr());
workspace->root = ProjectSettings::get_singleton()->get_resource_path();
}
#endif

View File

@ -31,9 +31,6 @@
#ifndef GDSCRIPT_PROTOCAL_SERVER_H
#define GDSCRIPT_PROTOCAL_SERVER_H
// FIXME: Reenable LSP.
#if 0
#include "core/io/stream_peer.h"
#include "core/io/stream_peer_tcp.h"
#include "core/io/tcp_server.h"
@ -112,5 +109,3 @@ public:
};
#endif
#endif

View File

@ -28,9 +28,6 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
// FIXME: Reenable LSP.
#if 0
#include "gdscript_language_server.h"
#include "core/os/file_access.h"
@ -117,5 +114,3 @@ void register_lsp_types() {
ClassDB::register_class<GDScriptTextDocument>();
ClassDB::register_class<GDScriptWorkspace>();
}
#endif

View File

@ -31,9 +31,6 @@
#ifndef GDSCRIPT_LANGUAGE_SERVER_H
#define GDSCRIPT_LANGUAGE_SERVER_H
// FIXME: Reenable LSP.
#if 0
#include "../gdscript_parser.h"
#include "editor/editor_plugin.h"
#include "gdscript_language_protocol.h"
@ -63,6 +60,4 @@ public:
void register_lsp_types();
#endif
#endif // GDSCRIPT_LANGUAGE_SERVER_H

View File

@ -38,9 +38,6 @@
#include "gdscript_language_protocol.h"
#include "servers/display_server.h"
// FIXME: Reenable LSP.
#if 0
void GDScriptTextDocument::_bind_methods() {
ClassDB::bind_method(D_METHOD("didOpen"), &GDScriptTextDocument::didOpen);
ClassDB::bind_method(D_METHOD("didChange"), &GDScriptTextDocument::didChange);
@ -440,5 +437,3 @@ Array GDScriptTextDocument::find_symbols(const lsp::TextDocumentPositionParams &
}
return arr;
}
#endif

View File

@ -31,9 +31,6 @@
#ifndef GDSCRIPT_TEXT_DOCUMENT_H
#define GDSCRIPT_TEXT_DOCUMENT_H
// FIXME: Reenable LSP.
#if 0
#include "core/os/file_access.h"
#include "core/reference.h"
#include "lsp.hpp"
@ -79,5 +76,3 @@ public:
};
#endif
#endif

View File

@ -28,9 +28,6 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
// FIXME: Reenable LSP.
#if 0
#include "gdscript_workspace.h"
#include "../gdscript.h"
@ -121,7 +118,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);
}
@ -621,5 +618,3 @@ GDScriptWorkspace::~GDScriptWorkspace() {
remove_cache_parser(E->get());
}
}
#endif

View File

@ -31,9 +31,6 @@
#ifndef GDSCRIPT_WORKSPACE_H
#define GDSCRIPT_WORKSPACE_H
// FIXME: Reenable LSP.
#if 0
#include "../gdscript_parser.h"
#include "core/variant.h"
#include "editor/editor_file_system.h"
@ -98,5 +95,3 @@ public:
};
#endif
#endif

View File

@ -31,9 +31,6 @@
#ifndef GODOT_LSP_H
#define GODOT_LSP_H
// FIXME: Reenable LSP.
#if 0
#include "core/class_db.h"
#include "core/list.h"
#include "editor/doc_data.h"
@ -1788,5 +1785,3 @@ static String marked_documentation(const String &p_bbcode) {
} // namespace lsp
#endif
#endif

View File

@ -52,13 +52,10 @@ GDScriptCache *gdscript_cache = nullptr;
#include "editor/gdscript_highlighter.h"
#include "editor/gdscript_translation_parser_plugin.h"
// FIXME: Reenable LSP.
#if 0
#ifndef GDSCRIPT_NO_LSP
#include "core/engine.h"
#include "language_server/gdscript_language_server.h"
#endif // !GDSCRIPT_NO_LSP
#endif
Ref<GDScriptEditorTranslationParserPlugin> gdscript_translation_parser_plugin;
@ -97,15 +94,12 @@ static void _editor_init() {
ScriptEditor::get_singleton()->register_syntax_highlighter(gdscript_syntax_highlighter);
#endif
// FIXME: Reenable LSP.
#if 0
#ifndef GDSCRIPT_NO_LSP
register_lsp_types();
GDScriptLanguageServer *lsp_plugin = memnew(GDScriptLanguageServer);
EditorNode::get_singleton()->add_editor_plugin(lsp_plugin);
Engine::get_singleton()->add_singleton(Engine::Singleton("GDScriptLanguageProtocol", GDScriptLanguageProtocol::get_singleton()));
#endif // !GDSCRIPT_NO_LSP
#endif
}
#endif // TOOLS_ENABLED