GDScript: Track columns by raw string offsets
This commit is contained in:
@@ -35,95 +35,27 @@
|
||||
#include "gdscript_language_protocol.h"
|
||||
#include "gdscript_workspace.h"
|
||||
|
||||
#include "editor/settings/editor_settings.h"
|
||||
|
||||
int get_indent_size() {
|
||||
if (EditorSettings::get_singleton()) {
|
||||
return EditorSettings::get_singleton()->get_setting("text_editor/behavior/indent/size");
|
||||
} else {
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
|
||||
LSP::Position GodotPosition::to_lsp(const Vector<String> &p_lines) const {
|
||||
LSP::Position GodotPosition::to_lsp() const {
|
||||
LSP::Position res;
|
||||
|
||||
// Special case: `line = 0` -> root class (range covers everything).
|
||||
if (line <= 0) {
|
||||
return res;
|
||||
}
|
||||
// Special case: `line = p_lines.size() + 1` -> root class (range covers everything).
|
||||
if (line >= p_lines.size() + 1) {
|
||||
res.line = p_lines.size();
|
||||
return res;
|
||||
}
|
||||
res.line = line - 1;
|
||||
|
||||
// Special case: `column = 0` -> Starts at beginning of line.
|
||||
if (column <= 0) {
|
||||
return res;
|
||||
}
|
||||
|
||||
// Note: character outside of `pos_line.length()-1` is valid.
|
||||
res.character = column - 1;
|
||||
|
||||
String pos_line = p_lines[res.line];
|
||||
if (pos_line.contains_char('\t')) {
|
||||
int tab_size = get_indent_size();
|
||||
|
||||
int in_col = 1;
|
||||
int res_char = 0;
|
||||
|
||||
while (res_char < pos_line.size() && in_col < column) {
|
||||
if (pos_line[res_char] == '\t') {
|
||||
in_col += tab_size;
|
||||
res_char++;
|
||||
} else {
|
||||
in_col++;
|
||||
res_char++;
|
||||
}
|
||||
}
|
||||
|
||||
res.character = res_char;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
GodotPosition GodotPosition::from_lsp(const LSP::Position p_pos, const Vector<String> &p_lines) {
|
||||
GodotPosition res(p_pos.line + 1, p_pos.character + 1);
|
||||
|
||||
// Line outside of actual text is valid (-> pos/cursor at end of text).
|
||||
if (res.line > p_lines.size()) {
|
||||
return res;
|
||||
}
|
||||
|
||||
String line = p_lines[p_pos.line];
|
||||
int tabs_before_char = 0;
|
||||
for (int i = 0; i < p_pos.character && i < line.length(); i++) {
|
||||
if (line[i] == '\t') {
|
||||
tabs_before_char++;
|
||||
}
|
||||
}
|
||||
|
||||
if (tabs_before_char > 0) {
|
||||
int tab_size = get_indent_size();
|
||||
res.column += tabs_before_char * (tab_size - 1);
|
||||
}
|
||||
|
||||
return res;
|
||||
GodotPosition GodotPosition::from_lsp(const LSP::Position p_pos) {
|
||||
return GodotPosition(p_pos.line + 1, p_pos.character + 1);
|
||||
}
|
||||
|
||||
LSP::Range GodotRange::to_lsp(const Vector<String> &p_lines) const {
|
||||
LSP::Range GodotRange::to_lsp() const {
|
||||
LSP::Range res;
|
||||
res.start = start.to_lsp(p_lines);
|
||||
res.end = end.to_lsp(p_lines);
|
||||
res.start = start.to_lsp();
|
||||
res.end = end.to_lsp();
|
||||
return res;
|
||||
}
|
||||
|
||||
GodotRange GodotRange::from_lsp(const LSP::Range &p_range, const Vector<String> &p_lines) {
|
||||
GodotPosition start = GodotPosition::from_lsp(p_range.start, p_lines);
|
||||
GodotPosition end = GodotPosition::from_lsp(p_range.end, p_lines);
|
||||
GodotRange GodotRange::from_lsp(const LSP::Range &p_range) {
|
||||
GodotPosition start = GodotPosition::from_lsp(p_range.start);
|
||||
GodotPosition end = GodotPosition::from_lsp(p_range.end);
|
||||
return GodotRange(start, end);
|
||||
}
|
||||
|
||||
@@ -141,7 +73,7 @@ void ExtendGDScriptParser::update_diagnostics() {
|
||||
GodotPosition(error.start_line, error.start_column),
|
||||
GodotPosition(error.end_line, error.end_column));
|
||||
|
||||
diagnostic.range = godot_range.to_lsp(get_lines());
|
||||
diagnostic.range = godot_range.to_lsp();
|
||||
diagnostics.push_back(diagnostic);
|
||||
}
|
||||
|
||||
@@ -156,7 +88,7 @@ void ExtendGDScriptParser::update_diagnostics() {
|
||||
GodotPosition(warning.start_line, warning.start_column),
|
||||
GodotPosition(warning.end_line, warning.end_column));
|
||||
|
||||
diagnostic.range = godot_range.to_lsp(get_lines());
|
||||
diagnostic.range = godot_range.to_lsp();
|
||||
diagnostics.push_back(diagnostic);
|
||||
}
|
||||
}
|
||||
@@ -207,7 +139,7 @@ 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(scr_path);
|
||||
link.range = GodotRange(GodotPosition(token.start_line, token.start_column), GodotPosition(token.end_line, token.end_column)).to_lsp(lines);
|
||||
link.range = GodotRange(GodotPosition(token.start_line, token.start_column), GodotPosition(token.end_line, token.end_column)).to_lsp();
|
||||
document_links.push_back(link);
|
||||
}
|
||||
}
|
||||
@@ -218,7 +150,7 @@ void ExtendGDScriptParser::update_document_links(const String &p_code) {
|
||||
LSP::Range ExtendGDScriptParser::range_of_node(const GDScriptParser::Node *p_node) const {
|
||||
GodotPosition start(p_node->start_line, p_node->start_column);
|
||||
GodotPosition end(p_node->end_line, p_node->end_column);
|
||||
return GodotRange(start, end).to_lsp(lines);
|
||||
return GodotRange(start, end).to_lsp();
|
||||
}
|
||||
|
||||
void ExtendGDScriptParser::parse_class_symbol(const GDScriptParser::ClassNode *p_class, LSP::DocumentSymbol &r_symbol) {
|
||||
@@ -394,8 +326,8 @@ void ExtendGDScriptParser::parse_class_symbol(const GDScriptParser::ClassNode *p
|
||||
symbol.name = m.enum_value.identifier->name;
|
||||
symbol.kind = LSP::SymbolKind::EnumMember;
|
||||
symbol.deprecated = false;
|
||||
symbol.range.start = GodotPosition(m.enum_value.line, m.enum_value.start_column).to_lsp(lines);
|
||||
symbol.range.end = GodotPosition(m.enum_value.line, m.enum_value.end_column).to_lsp(lines);
|
||||
symbol.range.start = GodotPosition(m.enum_value.line, m.enum_value.start_column).to_lsp();
|
||||
symbol.range.end = GodotPosition(m.enum_value.line, m.enum_value.end_column).to_lsp();
|
||||
symbol.selectionRange = range_of_node(m.enum_value.identifier);
|
||||
symbol.documentation = m.enum_value.doc_data.description;
|
||||
symbol.uri = uri;
|
||||
@@ -430,8 +362,8 @@ void ExtendGDScriptParser::parse_class_symbol(const GDScriptParser::ClassNode *p
|
||||
child.name = value.identifier->name;
|
||||
child.kind = LSP::SymbolKind::EnumMember;
|
||||
child.deprecated = false;
|
||||
child.range.start = GodotPosition(value.line, value.start_column).to_lsp(lines);
|
||||
child.range.end = GodotPosition(value.line, value.end_column).to_lsp(lines);
|
||||
child.range.start = GodotPosition(value.line, value.start_column).to_lsp();
|
||||
child.range.end = GodotPosition(value.line, value.end_column).to_lsp();
|
||||
child.selectionRange = range_of_node(value.identifier);
|
||||
child.documentation = value.doc_data.description;
|
||||
child.uri = uri;
|
||||
@@ -605,8 +537,8 @@ void ExtendGDScriptParser::parse_function_symbol(const GDScriptParser::FunctionN
|
||||
break;
|
||||
default:
|
||||
// Fallback.
|
||||
symbol.range.start = GodotPosition(local.start_line, local.start_column).to_lsp(get_lines());
|
||||
symbol.range.end = GodotPosition(local.end_line, local.end_column).to_lsp(get_lines());
|
||||
symbol.range.start = GodotPosition(local.start_line, local.start_column).to_lsp();
|
||||
symbol.range.end = GodotPosition(local.end_line, local.end_column).to_lsp();
|
||||
symbol.selectionRange = symbol.range;
|
||||
break;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user