You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-11-06 12:20:30 +00:00
Merge pull request #47776 from Razoric480/foreport
Implement LSP didDeleteFiles & make parser aware of sub-nodes
This commit is contained in:
@@ -2998,6 +2998,7 @@ Error GDScriptLanguage::lookup_code(const String &p_code, const String &p_symbol
|
|||||||
is_function = true;
|
is_function = true;
|
||||||
[[fallthrough]];
|
[[fallthrough]];
|
||||||
}
|
}
|
||||||
|
case GDScriptParser::COMPLETION_CALL_ARGUMENTS:
|
||||||
case GDScriptParser::COMPLETION_IDENTIFIER: {
|
case GDScriptParser::COMPLETION_IDENTIFIER: {
|
||||||
GDScriptParser::DataType base_type;
|
GDScriptParser::DataType base_type;
|
||||||
if (context.current_class) {
|
if (context.current_class) {
|
||||||
|
|||||||
@@ -49,8 +49,9 @@ void ExtendGDScriptParser::update_diagnostics() {
|
|||||||
diagnostic.code = -1;
|
diagnostic.code = -1;
|
||||||
lsp::Range range;
|
lsp::Range range;
|
||||||
lsp::Position pos;
|
lsp::Position pos;
|
||||||
int line = LINE_NUMBER_TO_INDEX(error.line);
|
const PackedStringArray lines = get_lines();
|
||||||
const String &line_text = get_lines()[line];
|
int line = CLAMP(LINE_NUMBER_TO_INDEX(error.line), 0, lines.size() - 1);
|
||||||
|
const String &line_text = lines[line];
|
||||||
pos.line = line;
|
pos.line = line;
|
||||||
pos.character = line_text.length() - line_text.strip_edges(true, false).length();
|
pos.character = line_text.length() - line_text.strip_edges(true, false).length();
|
||||||
range.start = pos;
|
range.start = pos;
|
||||||
@@ -361,8 +362,56 @@ void ExtendGDScriptParser::parse_function_symbol(const GDScriptParser::FunctionN
|
|||||||
r_symbol.detail += " -> " + p_func->get_datatype().to_string();
|
r_symbol.detail += " -> " + p_func->get_datatype().to_string();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < p_func->body->locals.size(); i++) {
|
List<GDScriptParser::SuiteNode *> function_nodes;
|
||||||
const SuiteNode::Local &local = p_func->body->locals[i];
|
|
||||||
|
List<GDScriptParser::Node *> node_stack;
|
||||||
|
node_stack.push_back(p_func->body);
|
||||||
|
|
||||||
|
while (!node_stack.is_empty()) {
|
||||||
|
GDScriptParser::Node *node = node_stack[0];
|
||||||
|
node_stack.pop_front();
|
||||||
|
|
||||||
|
switch (node->type) {
|
||||||
|
case GDScriptParser::TypeNode::IF: {
|
||||||
|
GDScriptParser::IfNode *if_node = (GDScriptParser::IfNode *)node;
|
||||||
|
node_stack.push_back(if_node->true_block);
|
||||||
|
if (if_node->false_block) {
|
||||||
|
node_stack.push_back(if_node->false_block);
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case GDScriptParser::TypeNode::FOR: {
|
||||||
|
GDScriptParser::ForNode *for_node = (GDScriptParser::ForNode *)node;
|
||||||
|
node_stack.push_back(for_node->loop);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case GDScriptParser::TypeNode::WHILE: {
|
||||||
|
GDScriptParser::WhileNode *while_node = (GDScriptParser::WhileNode *)node;
|
||||||
|
node_stack.push_back(while_node->loop);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case GDScriptParser::TypeNode::MATCH_BRANCH: {
|
||||||
|
GDScriptParser::MatchBranchNode *match_node = (GDScriptParser::MatchBranchNode *)node;
|
||||||
|
node_stack.push_back(match_node->block);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case GDScriptParser::TypeNode::SUITE: {
|
||||||
|
GDScriptParser::SuiteNode *suite_node = (GDScriptParser::SuiteNode *)node;
|
||||||
|
function_nodes.push_back(suite_node);
|
||||||
|
for (int i = 0; i < suite_node->statements.size(); ++i) {
|
||||||
|
node_stack.push_back(suite_node->statements[i]);
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (List<GDScriptParser::SuiteNode *>::Element *N = function_nodes.front(); N; N = N->next()) {
|
||||||
|
const GDScriptParser::SuiteNode *suite_node = N->get();
|
||||||
|
for (int i = 0; i < suite_node->locals.size(); i++) {
|
||||||
|
const SuiteNode::Local &local = suite_node->locals[i];
|
||||||
lsp::DocumentSymbol symbol;
|
lsp::DocumentSymbol symbol;
|
||||||
symbol.name = local.name;
|
symbol.name = local.name;
|
||||||
symbol.kind = local.type == SuiteNode::Local::CONSTANT ? lsp::SymbolKind::Constant : lsp::SymbolKind::Variable;
|
symbol.kind = local.type == SuiteNode::Local::CONSTANT ? lsp::SymbolKind::Constant : lsp::SymbolKind::Variable;
|
||||||
@@ -372,7 +421,7 @@ void ExtendGDScriptParser::parse_function_symbol(const GDScriptParser::FunctionN
|
|||||||
symbol.range.end.character = LINE_NUMBER_TO_INDEX(local.end_column);
|
symbol.range.end.character = LINE_NUMBER_TO_INDEX(local.end_column);
|
||||||
symbol.uri = uri;
|
symbol.uri = uri;
|
||||||
symbol.script_path = path;
|
symbol.script_path = path;
|
||||||
symbol.detail = SuiteNode::Local::CONSTANT ? "const " : "var ";
|
symbol.detail = local.type == SuiteNode::Local::CONSTANT ? "const " : "var ";
|
||||||
symbol.detail += symbol.name;
|
symbol.detail += symbol.name;
|
||||||
if (local.get_datatype().is_hard_type()) {
|
if (local.get_datatype().is_hard_type()) {
|
||||||
symbol.detail += ": " + local.get_datatype().to_string();
|
symbol.detail += ": " + local.get_datatype().to_string();
|
||||||
@@ -380,6 +429,7 @@ void ExtendGDScriptParser::parse_function_symbol(const GDScriptParser::FunctionN
|
|||||||
symbol.documentation = parse_documentation(LINE_NUMBER_TO_INDEX(local.start_line));
|
symbol.documentation = parse_documentation(LINE_NUMBER_TO_INDEX(local.start_line));
|
||||||
r_symbol.children.push_back(symbol);
|
r_symbol.children.push_back(symbol);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String ExtendGDScriptParser::parse_documentation(int p_line, bool p_docs_down) {
|
String ExtendGDScriptParser::parse_documentation(int p_line, bool p_docs_down) {
|
||||||
|
|||||||
@@ -42,6 +42,7 @@
|
|||||||
#include "scene/resources/packed_scene.h"
|
#include "scene/resources/packed_scene.h"
|
||||||
|
|
||||||
void GDScriptWorkspace::_bind_methods() {
|
void GDScriptWorkspace::_bind_methods() {
|
||||||
|
ClassDB::bind_method(D_METHOD("didDeleteFiles"), &GDScriptWorkspace::did_delete_files);
|
||||||
ClassDB::bind_method(D_METHOD("symbol"), &GDScriptWorkspace::symbol);
|
ClassDB::bind_method(D_METHOD("symbol"), &GDScriptWorkspace::symbol);
|
||||||
ClassDB::bind_method(D_METHOD("parse_script", "path", "content"), &GDScriptWorkspace::parse_script);
|
ClassDB::bind_method(D_METHOD("parse_script", "path", "content"), &GDScriptWorkspace::parse_script);
|
||||||
ClassDB::bind_method(D_METHOD("parse_local_script", "path"), &GDScriptWorkspace::parse_local_script);
|
ClassDB::bind_method(D_METHOD("parse_local_script", "path"), &GDScriptWorkspace::parse_local_script);
|
||||||
@@ -51,6 +52,16 @@ void GDScriptWorkspace::_bind_methods() {
|
|||||||
ClassDB::bind_method(D_METHOD("generate_script_api", "path"), &GDScriptWorkspace::generate_script_api);
|
ClassDB::bind_method(D_METHOD("generate_script_api", "path"), &GDScriptWorkspace::generate_script_api);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GDScriptWorkspace::did_delete_files(const Dictionary &p_params) {
|
||||||
|
Array files = p_params["files"];
|
||||||
|
for (int i = 0; i < files.size(); ++i) {
|
||||||
|
Dictionary file = files[i];
|
||||||
|
String uri = file["uri"];
|
||||||
|
String path = get_file_path(uri);
|
||||||
|
parse_script(path, "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void GDScriptWorkspace::remove_cache_parser(const String &p_path) {
|
void GDScriptWorkspace::remove_cache_parser(const String &p_path) {
|
||||||
Map<String, ExtendGDScriptParser *>::Element *parser = parse_results.find(p_path);
|
Map<String, ExtendGDScriptParser *>::Element *parser = parse_results.find(p_path);
|
||||||
Map<String, ExtendGDScriptParser *>::Element *script = scripts.find(p_path);
|
Map<String, ExtendGDScriptParser *>::Element *script = scripts.find(p_path);
|
||||||
|
|||||||
@@ -89,6 +89,7 @@ public:
|
|||||||
void resolve_document_links(const String &p_uri, List<lsp::DocumentLink> &r_list);
|
void resolve_document_links(const String &p_uri, List<lsp::DocumentLink> &r_list);
|
||||||
Dictionary generate_script_api(const String &p_path);
|
Dictionary generate_script_api(const String &p_path);
|
||||||
Error resolve_signature(const lsp::TextDocumentPositionParams &p_doc_pos, lsp::SignatureHelp &r_signature);
|
Error resolve_signature(const lsp::TextDocumentPositionParams &p_doc_pos, lsp::SignatureHelp &r_signature);
|
||||||
|
void did_delete_files(const Dictionary &p_params);
|
||||||
|
|
||||||
GDScriptWorkspace();
|
GDScriptWorkspace();
|
||||||
~GDScriptWorkspace();
|
~GDScriptWorkspace();
|
||||||
|
|||||||
@@ -1528,6 +1528,114 @@ struct SignatureHelp {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A pattern to describe in which file operation requests or notifications
|
||||||
|
* the server is interested in.
|
||||||
|
*/
|
||||||
|
struct FileOperationPattern {
|
||||||
|
/**
|
||||||
|
* The glob pattern to match.
|
||||||
|
*/
|
||||||
|
String glob = "**/*.gd";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether to match `file`s or `folder`s with this pattern.
|
||||||
|
*
|
||||||
|
* Matches both if undefined.
|
||||||
|
*/
|
||||||
|
String matches = "file";
|
||||||
|
|
||||||
|
Dictionary to_json() const {
|
||||||
|
Dictionary dict;
|
||||||
|
|
||||||
|
dict["glob"] = glob;
|
||||||
|
dict["matches"] = matches;
|
||||||
|
|
||||||
|
return dict;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A filter to describe in which file operation requests or notifications
|
||||||
|
* the server is interested in.
|
||||||
|
*/
|
||||||
|
struct FileOperationFilter {
|
||||||
|
/**
|
||||||
|
* The actual file operation pattern.
|
||||||
|
*/
|
||||||
|
FileOperationPattern pattern;
|
||||||
|
|
||||||
|
Dictionary to_json() const {
|
||||||
|
Dictionary dict;
|
||||||
|
|
||||||
|
dict["pattern"] = pattern.to_json();
|
||||||
|
|
||||||
|
return dict;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The options to register for file operations.
|
||||||
|
*/
|
||||||
|
struct FileOperationRegistrationOptions {
|
||||||
|
/**
|
||||||
|
* The actual filters.
|
||||||
|
*/
|
||||||
|
Vector<FileOperationFilter> filters;
|
||||||
|
|
||||||
|
FileOperationRegistrationOptions() {
|
||||||
|
filters.push_back(FileOperationFilter());
|
||||||
|
}
|
||||||
|
|
||||||
|
Dictionary to_json() const {
|
||||||
|
Dictionary dict;
|
||||||
|
|
||||||
|
Array filts;
|
||||||
|
for (int i = 0; i < filters.size(); i++) {
|
||||||
|
filts.push_back(filters[i].to_json());
|
||||||
|
}
|
||||||
|
dict["filters"] = filts;
|
||||||
|
|
||||||
|
return dict;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The server is interested in file notifications/requests.
|
||||||
|
*/
|
||||||
|
struct FileOperations {
|
||||||
|
/**
|
||||||
|
* The server is interested in receiving didDeleteFiles file notifications.
|
||||||
|
*/
|
||||||
|
FileOperationRegistrationOptions didDelete;
|
||||||
|
|
||||||
|
Dictionary to_json() const {
|
||||||
|
Dictionary dict;
|
||||||
|
|
||||||
|
dict["didDelete"] = didDelete.to_json();
|
||||||
|
|
||||||
|
return dict;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Workspace specific server capabilities
|
||||||
|
*/
|
||||||
|
struct Workspace {
|
||||||
|
/**
|
||||||
|
* The server is interested in file notifications/requests.
|
||||||
|
*/
|
||||||
|
FileOperations fileOperations;
|
||||||
|
|
||||||
|
Dictionary to_json() const {
|
||||||
|
Dictionary dict;
|
||||||
|
|
||||||
|
dict["fileOperations"] = fileOperations.to_json();
|
||||||
|
|
||||||
|
return dict;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
struct ServerCapabilities {
|
struct ServerCapabilities {
|
||||||
/**
|
/**
|
||||||
* Defines how text documents are synced. Is either a detailed structure defining each notification or
|
* Defines how text documents are synced. Is either a detailed structure defining each notification or
|
||||||
@@ -1589,6 +1697,11 @@ struct ServerCapabilities {
|
|||||||
*/
|
*/
|
||||||
bool workspaceSymbolProvider = true;
|
bool workspaceSymbolProvider = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The server supports workspace folder.
|
||||||
|
*/
|
||||||
|
Workspace workspace;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The server provides code actions. The `CodeActionOptions` return type is only
|
* The server provides code actions. The `CodeActionOptions` return type is only
|
||||||
* valid if the client signals code action literal support via the property
|
* valid if the client signals code action literal support via the property
|
||||||
@@ -1676,6 +1789,7 @@ struct ServerCapabilities {
|
|||||||
dict["documentHighlightProvider"] = documentHighlightProvider;
|
dict["documentHighlightProvider"] = documentHighlightProvider;
|
||||||
dict["documentSymbolProvider"] = documentSymbolProvider;
|
dict["documentSymbolProvider"] = documentSymbolProvider;
|
||||||
dict["workspaceSymbolProvider"] = workspaceSymbolProvider;
|
dict["workspaceSymbolProvider"] = workspaceSymbolProvider;
|
||||||
|
dict["workspace"] = workspace.to_json();
|
||||||
dict["codeActionProvider"] = codeActionProvider;
|
dict["codeActionProvider"] = codeActionProvider;
|
||||||
dict["documentFormattingProvider"] = documentFormattingProvider;
|
dict["documentFormattingProvider"] = documentFormattingProvider;
|
||||||
dict["documentRangeFormattingProvider"] = documentRangeFormattingProvider;
|
dict["documentRangeFormattingProvider"] = documentRangeFormattingProvider;
|
||||||
|
|||||||
Reference in New Issue
Block a user