Skip to content

Commit 2f620db

Browse files
LSP: Fix spec violations that break the VSCode outline
1 parent 98ddec4 commit 2f620db

File tree

3 files changed

+43
-1
lines changed

3 files changed

+43
-1
lines changed

modules/gdscript/language_server/gdscript_extend_parser.cpp

+10-1
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,12 @@ lsp::Position GodotPosition::to_lsp(const Vector<String> &p_lines) const {
5757
return res;
5858
}
5959
res.line = line - 1;
60+
61+
// Special case: `column = 0` -> Starts at beginning of line.
62+
if (column <= 0) {
63+
return res;
64+
}
65+
6066
// Note: character outside of `pos_line.length()-1` is valid.
6167
res.character = column - 1;
6268

@@ -238,9 +244,12 @@ void ExtendGDScriptParser::parse_class_symbol(const GDScriptParser::ClassNode *p
238244
r_symbol.kind = lsp::SymbolKind::Class;
239245
r_symbol.deprecated = false;
240246
r_symbol.range = range_of_node(p_class);
241-
r_symbol.range.start.line = MAX(r_symbol.range.start.line, 0);
242247
if (p_class->identifier) {
243248
r_symbol.selectionRange = range_of_node(p_class->identifier);
249+
} else {
250+
// No meaningful `selectionRange`, but we must ensure that it is inside of `range`.
251+
r_symbol.selectionRange.start = r_symbol.range.start;
252+
r_symbol.selectionRange.end = r_symbol.range.start;
244253
}
245254
r_symbol.detail = "class " + r_symbol.name;
246255
{
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# Some comment
2+
extends Node

modules/gdscript/tests/test_lsp.h

+31
Original file line numberDiff line numberDiff line change
@@ -375,6 +375,18 @@ func f():
375375
gd.to_lsp(lines);
376376
}
377377

378+
SUBCASE("special case: zero column for root class") {
379+
GodotPosition gd(1, 0);
380+
lsp::Position expected = lsp_pos(0, 0);
381+
lsp::Position actual = gd.to_lsp(lines);
382+
CHECK_EQ(actual, expected);
383+
}
384+
SUBCASE("special case: zero line and column for root class") {
385+
GodotPosition gd(0, 0);
386+
lsp::Position expected = lsp_pos(0, 0);
387+
lsp::Position actual = gd.to_lsp(lines);
388+
CHECK_EQ(actual, expected);
389+
}
378390
SUBCASE("special case: negative line for root class") {
379391
GodotPosition gd(-1, 0);
380392
lsp::Position expected = lsp_pos(0, 0);
@@ -468,6 +480,25 @@ func f():
468480
test_resolve_symbols(uri, all_test_data, all_test_data);
469481
}
470482

483+
memdelete(proto);
484+
finish_language();
485+
}
486+
TEST_CASE("[workspace][document_symbol]") {
487+
GDScriptLanguageProtocol *proto = initialize(root);
488+
REQUIRE(proto);
489+
490+
SUBCASE("selectionRange of root class must be inside range") {
491+
String path = "res://lsp/first_line_comment.gd";
492+
assert_no_errors_in(path);
493+
GDScriptLanguageProtocol::get_singleton()->get_workspace()->parse_local_script(path);
494+
ExtendGDScriptParser *parser = GDScriptLanguageProtocol::get_singleton()->get_workspace()->parse_results[path];
495+
REQUIRE(parser);
496+
lsp::DocumentSymbol cls = parser->get_symbols();
497+
498+
REQUIRE(((cls.range.start.line == cls.selectionRange.start.line && cls.range.start.character <= cls.selectionRange.start.character) || (cls.range.start.line < cls.selectionRange.start.line)));
499+
REQUIRE(((cls.range.end.line == cls.selectionRange.end.line && cls.range.end.character >= cls.selectionRange.end.character) || (cls.range.end.line > cls.selectionRange.end.line)));
500+
}
501+
471502
memdelete(proto);
472503
finish_language();
473504
}

0 commit comments

Comments
 (0)