Merge pull request #118979 from HolonProduction/lsp/annoation-identifier-crash
LSP: Fix crash in `find_usages_in_file` by correctly resolving annotation names
This commit is contained in:
@@ -632,14 +632,29 @@ String ExtendGDScriptParser::get_text_for_lookup_symbol(const LSP::Position &p_c
|
||||
return longthing;
|
||||
}
|
||||
|
||||
String ExtendGDScriptParser::get_identifier_under_position(const LSP::Position &p_position, LSP::Range &r_range) const {
|
||||
String ExtendGDScriptParser::get_symbol_name_under_position(const LSP::Position &p_position, LSP::Range &r_range) const {
|
||||
r_range = LSP::Range(p_position, p_position); // Default for error macros.
|
||||
ERR_FAIL_INDEX_V(p_position.line, lines.size(), "");
|
||||
|
||||
String line = lines[p_position.line];
|
||||
if (line.is_empty()) {
|
||||
return "";
|
||||
}
|
||||
// Checks against line.size(), which includes a terminating NUL. This is to allow a cursor after the last character.
|
||||
ERR_FAIL_INDEX_V(p_position.character, line.size(), "");
|
||||
|
||||
LSP::Position pos = p_position;
|
||||
|
||||
// Cursor after last character.
|
||||
if (pos.character >= line.length()) {
|
||||
pos.character--;
|
||||
}
|
||||
|
||||
// If on the start of an annotation move the position into the identifier part. We account for "@" at the end.
|
||||
if (line[pos.character] == '@' && pos.character + 1 < line.size() && is_unicode_identifier_start(line[pos.character + 1])) {
|
||||
pos.character++;
|
||||
}
|
||||
|
||||
// `p_position` cursor is BETWEEN chars, not ON chars.
|
||||
// ->
|
||||
// ```gdscript
|
||||
@@ -651,51 +666,54 @@ String ExtendGDScriptParser::get_identifier_under_position(const LSP::Position &
|
||||
// |
|
||||
// | cursor on `member`, pos on ` ` (space)
|
||||
// ```
|
||||
// -> Move position to previous character if:
|
||||
// * Position not on valid identifier char.
|
||||
// * Prev position is valid identifier char.
|
||||
LSP::Position pos = p_position;
|
||||
if (
|
||||
pos.character >= line.length() // Cursor at end of line.
|
||||
|| (!is_unicode_identifier_continue(line[pos.character]) // Not on valid identifier char.
|
||||
&& (pos.character > 0 // Not line start -> there is a prev char.
|
||||
&& is_unicode_identifier_continue(line[pos.character - 1]) // Prev is valid identifier char.
|
||||
))) {
|
||||
if (!is_unicode_identifier_continue(line[pos.character])) {
|
||||
if (pos.character == 0 || !is_unicode_identifier_continue(line[pos.character - 1])) {
|
||||
// In between two non-identifier chars.
|
||||
return "";
|
||||
}
|
||||
// Move position to previous character if not on valid char and the previous char is valid.
|
||||
pos.character--;
|
||||
}
|
||||
|
||||
int start_pos = pos.character;
|
||||
// Iterate forward till we have a start. Symbol starts require lookahead, so we save the latest valid start and track back to it once we can stop looking.
|
||||
// E.g. ?0nly
|
||||
// ^
|
||||
// | could be an identifier start (since 0 can't start identifiers), but if there was another symbol in front of 0 the identifier would be longer.
|
||||
int last_valid_start_pos = -1;
|
||||
for (int c = pos.character; c >= 0; c--) {
|
||||
start_pos = c;
|
||||
char32_t ch = line[c];
|
||||
bool valid_char = is_unicode_identifier_continue(ch);
|
||||
if (!valid_char) {
|
||||
if (is_unicode_identifier_start(ch)) {
|
||||
last_valid_start_pos = c;
|
||||
}
|
||||
if (!is_unicode_identifier_continue(ch)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int end_pos = pos.character;
|
||||
// Iterate backwards till we have an end. No lookahead required. Uses +1 since the end of a range is exclusive.
|
||||
int end_pos = pos.character + 1;
|
||||
for (int c = pos.character; c < line.length(); c++) {
|
||||
char32_t ch = line[c];
|
||||
bool valid_char = is_unicode_identifier_continue(ch);
|
||||
if (!valid_char) {
|
||||
if (!is_unicode_identifier_continue(ch)) {
|
||||
break;
|
||||
}
|
||||
end_pos = c;
|
||||
end_pos = c + 1;
|
||||
}
|
||||
|
||||
if (!is_unicode_identifier_start(line[start_pos + 1])) {
|
||||
if (last_valid_start_pos == -1) {
|
||||
return "";
|
||||
}
|
||||
|
||||
if (start_pos < end_pos) {
|
||||
r_range.start.line = r_range.end.line = pos.line;
|
||||
r_range.start.character = start_pos + 1;
|
||||
r_range.end.character = end_pos + 1;
|
||||
return line.substr(start_pos + 1, end_pos - start_pos);
|
||||
// For annotations we include the @, since it is included in the symbol name used by other parts of the LSP code.
|
||||
int start_pos = last_valid_start_pos;
|
||||
if (start_pos > 0 && line[start_pos - 1] == '@') {
|
||||
start_pos -= 1;
|
||||
}
|
||||
|
||||
return "";
|
||||
r_range.start.character = start_pos;
|
||||
r_range.end.character = end_pos;
|
||||
|
||||
return line.substr(start_pos, end_pos - start_pos);
|
||||
}
|
||||
|
||||
String ExtendGDScriptParser::get_uri() const {
|
||||
|
||||
Reference in New Issue
Block a user