Skip to content

Commit fc9d410

Browse files
committed
LSP: Add support for unreachable code display
Supporting LSP clients can display lines with UNREACHABLE_CODE as faded out
1 parent 944a3c6 commit fc9d410

4 files changed

Lines changed: 61 additions & 1 deletion

File tree

modules/gdscript/gdscript_parser.cpp

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2025,6 +2025,19 @@ GDScriptParser::SuiteNode *GDScriptParser::parse_suite(const String &p_context,
20252025

20262026
} while ((multiline || previous.type == GDScriptTokenizer::Token::SEMICOLON) && !check(GDScriptTokenizer::Token::DEDENT) && !lambda_ended && !is_at_end());
20272027

2028+
#ifdef DEBUG_ENABLED
2029+
if (current_suite->unreachable_code_start) {
2030+
Node *unreachable_start = current_suite->unreachable_code_start;
2031+
Node *unreachable_end = suite->statements[suite->statements.size() - 1];
2032+
push_warning(
2033+
unreachable_start->start_line,
2034+
unreachable_start->start_column,
2035+
unreachable_end->end_line,
2036+
unreachable_end->end_column,
2037+
GDScriptWarning::UNREACHABLE_CODE,
2038+
current_function->identifier ? current_function->identifier->name : "<anonymous lambda>");
2039+
}
2040+
#endif // DEBUG_ENABLED
20282041
complete_extents(suite);
20292042

20302043
if (multiline) {
@@ -2245,7 +2258,12 @@ GDScriptParser::Node *GDScriptParser::parse_statement() {
22452258
if (unreachable && result != nullptr) {
22462259
current_suite->has_unreachable_code = true;
22472260
if (current_function) {
2248-
push_warning(result, GDScriptWarning::UNREACHABLE_CODE, current_function->identifier ? current_function->identifier->name : "<anonymous lambda>");
2261+
// Store where the unreachable code begins for this suite,
2262+
// but hold off on emitting the warning until we also know where
2263+
// the unreachable code ends.
2264+
if (current_suite->unreachable_code_start == nullptr) {
2265+
current_suite->unreachable_code_start = result;
2266+
}
22492267
} else {
22502268
// TODO: Properties setters and getters with unreachable code are not being warned
22512269
}

modules/gdscript/gdscript_parser.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1202,6 +1202,7 @@ class GDScriptParser {
12021202
FunctionNode *parent_function = nullptr;
12031203
IfNode *parent_if = nullptr;
12041204

1205+
Node *unreachable_code_start = nullptr;
12051206
bool has_return = false;
12061207
bool has_continue = false;
12071208
bool has_unreachable_code = false; // Just so warnings aren't given more than once per block.

modules/gdscript/language_server/gdscript_extend_parser.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,10 @@ void ExtendGDScriptParser::update_diagnostics() {
8484
diagnostic.message = "(" + warning.get_name() + "): " + warning.get_message();
8585
diagnostic.source = "gdscript";
8686

87+
if (warning.code == GDScriptWarning::UNREACHABLE_CODE) {
88+
diagnostic.tags.append(LSP::DiagnosticTag::Unnecessary);
89+
}
90+
8791
GodotRange godot_range(
8892
GodotPosition(warning.start_line, warning.start_column),
8993
GodotPosition(warning.end_line, warning.end_column));

modules/gdscript/language_server/godot_lsp.h

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -731,6 +731,27 @@ static const int Information = 3;
731731
static const int Hint = 4;
732732
}; // namespace DiagnosticSeverity
733733

734+
/**
735+
* The diagnostic tags.
736+
*
737+
* @since 3.15.0
738+
*/
739+
namespace DiagnosticTag {
740+
/**
741+
* Unused or unnecessary code.
742+
*
743+
* Clients are allowed to render diagnostics with this tag faded out
744+
* instead of having an error squiggle.
745+
*/
746+
static const int Unnecessary = 1;
747+
/**
748+
* Deprecated or obsolete code.
749+
*
750+
* Clients are allowed to rendered diagnostics with this tag strike through.
751+
*/
752+
static const int Deprecated = 2;
753+
}; // namespace DiagnosticTag
754+
734755
/**
735756
* Represents a related message and source code location for a diagnostic. This should be
736757
* used to point to code locations that cause or related to a diagnostics, e.g when duplicating
@@ -787,6 +808,14 @@ struct Diagnostic {
787808
*/
788809
String message;
789810

811+
/**
812+
* Additional metadata about the diagnostic.
813+
*
814+
* @since 3.15.0
815+
*/
816+
// Note: Uses DiagnosticTag namespace values.
817+
Vector<int> tags;
818+
790819
/**
791820
* An array of related diagnostic information, e.g. when symbol-names within
792821
* a scope collide all definitions can be marked via this property.
@@ -808,6 +837,14 @@ struct Diagnostic {
808837
}
809838
dict["relatedInformation"] = arr;
810839
}
840+
if (!tags.is_empty()) {
841+
Array arr;
842+
arr.resize(tags.size());
843+
for (int i = 0; i < tags.size(); i++) {
844+
arr[i] = tags[i];
845+
}
846+
dict["tags"] = arr;
847+
}
811848
return dict;
812849
}
813850
};

0 commit comments

Comments
 (0)