4444#include " core/templates/hash_map.h"
4545#include " scene/main/node.h"
4646
47+ #ifdef TOOLS_ENABLED
48+ #include " editor/editor_help.h"
49+ #endif
50+
4751#if defined(TOOLS_ENABLED) && !defined(DISABLE_DEPRECATED)
4852#define SUGGEST_GODOT4_RENAMES
4953#include " editor/renames_map_3_to_4.h"
@@ -1993,6 +1997,57 @@ void GDScriptAnalyzer::resolve_assignable(GDScriptParser::AssignableNode *p_assi
19931997 type = specified_type;
19941998 }
19951999
2000+ #if TOOLS_ENABLED
2001+ DocTools *dd = EditorHelp::get_doc_data ();
2002+ bool is_deprecated = false ;
2003+ String new_value_type = " value" ;
2004+ String value_name = type.native_type ;
2005+ switch (type.kind ) {
2006+ case GDScriptParser::DataType::Kind::BUILTIN: // No built-in datatypes are deprecated.
2007+ break ;
2008+ case GDScriptParser::DataType::Kind::NATIVE:
2009+ is_deprecated = dd && dd->class_list .has (type.native_type ) && dd->class_list [type.native_type ].is_deprecated ;
2010+ new_value_type = " class" ;
2011+ break ;
2012+ case GDScriptParser::DataType::Kind::SCRIPT: {
2013+ StringName class_name = type.script_type ->get_doc_class_name ();
2014+ is_deprecated = dd && dd->class_list .has (class_name) && dd->class_list [class_name].is_deprecated ;
2015+ new_value_type = " class" ;
2016+ break ;
2017+ }
2018+ case GDScriptParser::DataType::Kind::CLASS:
2019+ is_deprecated = type.class_type ->doc_data .is_deprecated ;
2020+ new_value_type = " class" ;
2021+
2022+ // TODO: Not recognizing the autoload name as a class type
2023+ // var my_var: MyAutoload # <--- not getting this name
2024+ if (type.class_type && type.class_type ->identifier ) {
2025+ value_name = type.class_type ->identifier ->name ;
2026+ } else {
2027+ value_name = " " ;
2028+ }
2029+ break ;
2030+ case GDScriptParser::DataType::Kind::ENUM: {
2031+ StringName enum_type = type.enum_type ; // Something like MyEnum.
2032+ GDScriptParser::ClassNode *class_type = type.class_type ;
2033+ StringName class_name = (class_type && class_type->identifier ) ? class_type->identifier ->name : " @GlobalScope" ;
2034+ if (dd && dd->class_list .has (class_name)) {
2035+ DocData::ClassDoc class_doc = dd->class_list [class_name];
2036+ if (class_doc.enums .has (enum_type)) {
2037+ is_deprecated = class_doc.enums [enum_type].is_deprecated ;
2038+ }
2039+ }
2040+ new_value_type = " enum" ;
2041+ break ;
2042+ }
2043+ default :
2044+ break ;
2045+ }
2046+ if (is_deprecated) {
2047+ parser->push_warning (p_assignable, GDScriptWarning::DEPRECATED_IDENTIFIER, new_value_type, value_name);
2048+ }
2049+ #endif
2050+
19962051 if (p_assignable->initializer != nullptr ) {
19972052 reduce_expression (p_assignable->initializer );
19982053
@@ -3998,6 +4053,38 @@ void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNod
39984053 StringName name = p_identifier->name ;
39994054
40004055 if (base.kind == GDScriptParser::DataType::ENUM) {
4056+ #if TOOLS_ENABLED
4057+ StringName class_name;
4058+ DocTools *dd = EditorHelp::get_doc_data ();
4059+ // TODO: Is this a proper way of detecting it's from a native class?
4060+ // e.g., "AnimationPlayer.AnimationProcessCallback"
4061+ // User-defined enums also seem to have a "native_type" so we can't
4062+ // detect actual native classes solely based on whether or not that
4063+ // string is defined.
4064+ if (base.native_type && !base.class_type ) {
4065+ class_name = String (base.native_type ).get_slicec (' .' , 0 );
4066+ }
4067+
4068+ else if (base.class_type && base.class_type ->identifier && base.class_type ->identifier ->name ) {
4069+ class_name = base.class_type ->identifier ->name ;
4070+ // It's an inner class, so we need to get the outer class's name
4071+ // as well to construct its full name as found in the doc data.
4072+ if (base.class_type ->outer != nullptr && base.class_type ->outer ->identifier != nullptr ) {
4073+ class_name = String (base.class_type ->outer ->identifier ->name ) + " ." + class_name;
4074+ }
4075+ }
4076+
4077+ if (dd && dd->class_list .has (class_name)) {
4078+ for (const DocData::ConstantDoc &doc : dd->class_list [class_name].constants ) {
4079+ if (doc.enumeration == base.enum_type && doc.name == name) {
4080+ if (doc.is_deprecated ) {
4081+ parser->push_warning (p_identifier, GDScriptWarning::DEPRECATED_IDENTIFIER, " enum value" , vformat (" %s.%s" , base.enum_type , doc.name ));
4082+ }
4083+ break ;
4084+ }
4085+ }
4086+ }
4087+ #endif
40014088 if (base.is_meta_type ) {
40024089 if (base.enum_values .has (name)) {
40034090 p_identifier->set_datatype (type_from_metatype (base));
@@ -4143,6 +4230,11 @@ void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNod
41434230 p_identifier->reduced_value = member.constant ->initializer ->reduced_value ;
41444231 p_identifier->source = GDScriptParser::IdentifierNode::MEMBER_CONSTANT;
41454232 p_identifier->constant_source = member.constant ;
4233+ #if TOOLS_ENABLED
4234+ if (member.constant ->doc_data .is_deprecated ) {
4235+ parser->push_warning (p_identifier, GDScriptWarning::DEPRECATED_IDENTIFIER, " constant" , name);
4236+ }
4237+ #endif
41464238 return ;
41474239 }
41484240
@@ -4151,6 +4243,11 @@ void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNod
41514243 p_identifier->is_constant = true ;
41524244 p_identifier->reduced_value = member.enum_value .value ;
41534245 p_identifier->source = GDScriptParser::IdentifierNode::MEMBER_CONSTANT;
4246+ #if TOOLS_ENABLED
4247+ if (member.enum_value .doc_data .is_deprecated ) {
4248+ parser->push_warning (p_identifier, GDScriptWarning::DEPRECATED_IDENTIFIER, " enum value" , name);
4249+ }
4250+ #endif
41544251 return ;
41554252 }
41564253
@@ -4159,6 +4256,11 @@ void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNod
41594256 p_identifier->is_constant = true ;
41604257 p_identifier->reduced_value = member.m_enum ->dictionary ;
41614258 p_identifier->source = GDScriptParser::IdentifierNode::MEMBER_CONSTANT;
4259+ #if TOOLS_ENABLED
4260+ if (member.m_enum ->doc_data .is_deprecated ) {
4261+ parser->push_warning (p_identifier, GDScriptWarning::DEPRECATED_IDENTIFIER, " enum" , name);
4262+ }
4263+ #endif
41624264 return ;
41634265 }
41644266
@@ -4168,6 +4270,11 @@ void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNod
41684270 p_identifier->source = member.variable ->is_static ? GDScriptParser::IdentifierNode::STATIC_VARIABLE : GDScriptParser::IdentifierNode::MEMBER_VARIABLE;
41694271 p_identifier->variable_source = member.variable ;
41704272 member.variable ->usages += 1 ;
4273+ #if TOOLS_ENABLED
4274+ if (member.variable ->doc_data .is_deprecated ) {
4275+ parser->push_warning (p_identifier, GDScriptWarning::DEPRECATED_IDENTIFIER, " property or variable" , name);
4276+ }
4277+ #endif
41714278 return ;
41724279 }
41734280 } break ;
@@ -4178,6 +4285,12 @@ void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNod
41784285 p_identifier->source = GDScriptParser::IdentifierNode::MEMBER_SIGNAL;
41794286 p_identifier->signal_source = member.signal ;
41804287 member.signal ->usages += 1 ;
4288+
4289+ #if TOOLS_ENABLED
4290+ if (member.signal ->doc_data .is_deprecated ) {
4291+ parser->push_warning (p_identifier, GDScriptWarning::DEPRECATED_IDENTIFIER, " signal" , name);
4292+ }
4293+ #endif
41814294 return ;
41824295 }
41834296 } break ;
@@ -4195,6 +4308,11 @@ void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNod
41954308 case GDScriptParser::ClassNode::Member::CLASS: {
41964309 reduce_identifier_from_base_set_class (p_identifier, member.get_datatype ());
41974310 p_identifier->source = GDScriptParser::IdentifierNode::MEMBER_CLASS;
4311+ #ifdef TOOLS_ENABLED
4312+ if (script_class->get_member (name).m_class ->doc_data .is_deprecated ) {
4313+ parser->push_warning (p_identifier, GDScriptWarning::DEPRECATED_IDENTIFIER, " class" , name);
4314+ }
4315+ #endif
41984316 return ;
41994317 }
42004318
@@ -4284,6 +4402,19 @@ void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNod
42844402 p_identifier->set_datatype (type_from_property (getter->get_return_info (), false , !has_setter));
42854403 p_identifier->source = GDScriptParser::IdentifierNode::INHERITED_VARIABLE;
42864404 }
4405+ #if TOOLS_ENABLED
4406+ DocTools *dd = EditorHelp::get_doc_data ();
4407+ if (dd && dd->class_list .has (native)) {
4408+ for (const DocData::PropertyDoc &doc : dd->class_list [native].properties ) {
4409+ if (doc.name == name) {
4410+ if (doc.is_deprecated ) {
4411+ parser->push_warning (p_identifier, GDScriptWarning::DEPRECATED_IDENTIFIER, " property" , name);
4412+ }
4413+ break ;
4414+ }
4415+ }
4416+ }
4417+ #endif
42874418 return ;
42884419 }
42894420 if (ClassDB::get_method_info (native, name, &method_info)) {
@@ -4296,11 +4427,33 @@ void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNod
42964427 // Signal is a type too.
42974428 p_identifier->set_datatype (make_signal_type (method_info));
42984429 p_identifier->source = GDScriptParser::IdentifierNode::INHERITED_VARIABLE;
4430+ #if TOOLS_ENABLED
4431+ DocTools *dd = EditorHelp::get_doc_data ();
4432+ if (dd && dd->class_list .has (native)) {
4433+ for (const DocData::MethodDoc &doc : dd->class_list [native].signals ) {
4434+ if (doc.name == name) {
4435+ if (doc.is_deprecated ) {
4436+ parser->push_warning (p_identifier, GDScriptWarning::DEPRECATED_IDENTIFIER, " signal" , name);
4437+ }
4438+ break ;
4439+ }
4440+ }
4441+ }
4442+ #endif
42994443 return ;
43004444 }
43014445 if (ClassDB::has_enum (native, name)) {
43024446 p_identifier->set_datatype (make_native_enum_type (name, native));
43034447 p_identifier->source = GDScriptParser::IdentifierNode::MEMBER_CONSTANT;
4448+ #if TOOLS_ENABLED
4449+ DocTools *dd = EditorHelp::get_doc_data ();
4450+ if (dd && dd->class_list .has (native) && dd->class_list [native].enums .has (name)) {
4451+ DocData::EnumDoc doc = dd->class_list [native].enums [name];
4452+ if (doc.is_deprecated ) {
4453+ parser->push_warning (p_identifier, GDScriptWarning::DEPRECATED_IDENTIFIER, " enum" , name);
4454+ }
4455+ }
4456+ #endif
43044457 return ;
43054458 }
43064459 bool valid = false ;
@@ -4311,6 +4464,20 @@ void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNod
43114464 p_identifier->reduced_value = int_constant;
43124465 p_identifier->source = GDScriptParser::IdentifierNode::MEMBER_CONSTANT;
43134466
4467+ #if TOOLS_ENABLED
4468+ DocTools *dd = EditorHelp::get_doc_data ();
4469+ if (dd && dd->class_list .has (native)) {
4470+ for (const DocData::ConstantDoc &doc : dd->class_list [native].constants ) {
4471+ if (doc.name == name) {
4472+ if (doc.is_deprecated ) {
4473+ parser->push_warning (p_identifier, GDScriptWarning::DEPRECATED_IDENTIFIER, " constant" , name);
4474+ }
4475+ break ;
4476+ }
4477+ }
4478+ }
4479+ #endif
4480+
43144481 // Check whether this constant, which exists, belongs to an enum
43154482 StringName enum_name = ClassDB::get_integer_constant_enum (native, name);
43164483 if (enum_name != StringName ()) {
@@ -4363,6 +4530,12 @@ void GDScriptAnalyzer::reduce_identifier(GDScriptParser::IdentifierNode *p_ident
43634530 // TODO: Constant should have a value on the node itself.
43644531 p_identifier->reduced_value = p_identifier->constant_source ->initializer ->reduced_value ;
43654532 found_source = true ;
4533+
4534+ #ifdef TOOLS_ENABLED
4535+ if (p_identifier->constant_source ->doc_data .is_deprecated ) {
4536+ parser->push_warning (p_identifier, GDScriptWarning::DEPRECATED_IDENTIFIER, " constant" , p_identifier->name );
4537+ }
4538+ #endif
43664539 break ;
43674540 case GDScriptParser::IdentifierNode::MEMBER_SIGNAL:
43684541 p_identifier->signal_source ->usages ++;
@@ -4382,6 +4555,11 @@ void GDScriptAnalyzer::reduce_identifier(GDScriptParser::IdentifierNode *p_ident
43824555 if (p_identifier->variable_source && p_identifier->variable_source ->assignments == 0 && !(p_identifier->get_datatype ().is_hard_type () && p_identifier->get_datatype ().kind == GDScriptParser::DataType::BUILTIN)) {
43834556 parser->push_warning (p_identifier, GDScriptWarning::UNASSIGNED_VARIABLE, p_identifier->name );
43844557 }
4558+ #endif
4559+ #ifdef TOOLS_ENABLED
4560+ if (p_identifier->variable_source ->doc_data .is_deprecated ) {
4561+ parser->push_warning (p_identifier, GDScriptWarning::DEPRECATED_IDENTIFIER, " property or variable" , p_identifier->name );
4562+ }
43854563#endif
43864564 break ;
43874565 case GDScriptParser::IdentifierNode::LOCAL_ITERATOR:
@@ -4499,12 +4677,28 @@ void GDScriptAnalyzer::reduce_identifier(GDScriptParser::IdentifierNode *p_ident
44994677 }
45004678
45014679 if (class_exists (name)) {
4680+ #if TOOLS_ENABLED
4681+ DocTools *dd = EditorHelp::get_doc_data ();
4682+ if (dd && dd->class_list .has (name)) {
4683+ if (dd->class_list [name].is_deprecated ) {
4684+ parser->push_warning (p_identifier, GDScriptWarning::DEPRECATED_IDENTIFIER, " class" , name);
4685+ }
4686+ }
4687+ #endif
45024688 p_identifier->set_datatype (make_native_meta_type (name));
45034689 return ;
45044690 }
45054691
45064692 if (ScriptServer::is_global_class (name)) {
45074693 p_identifier->set_datatype (make_global_class_meta_type (name, p_identifier));
4694+ #if TOOLS_ENABLED
4695+ DocTools *dd = EditorHelp::get_doc_data ();
4696+ if (dd && dd->class_list .has (name)) {
4697+ if (dd->class_list [name].is_deprecated ) {
4698+ parser->push_warning (p_identifier, GDScriptWarning::DEPRECATED_IDENTIFIER, " class" , name);
4699+ }
4700+ }
4701+ #endif
45084702 return ;
45094703 }
45104704
@@ -4545,6 +4739,14 @@ void GDScriptAnalyzer::reduce_identifier(GDScriptParser::IdentifierNode *p_ident
45454739 }
45464740 }
45474741 }
4742+ #if TOOLS_ENABLED
4743+ DocTools *dd = EditorHelp::get_doc_data ();
4744+ if (dd && dd->class_list .has (name)) {
4745+ if (dd->class_list [name].is_deprecated ) {
4746+ parser->push_warning (p_identifier, GDScriptWarning::DEPRECATED_IDENTIFIER, " class" , name);
4747+ }
4748+ }
4749+ #endif
45484750 result.is_constant = true ;
45494751 p_identifier->set_datatype (result);
45504752 return ;
@@ -4562,6 +4764,17 @@ void GDScriptAnalyzer::reduce_identifier(GDScriptParser::IdentifierNode *p_ident
45624764 }
45634765 p_identifier->is_constant = true ;
45644766 p_identifier->reduced_value = value;
4767+
4768+ #if TOOLS_ENABLED
4769+ DocTools *dd = EditorHelp::get_doc_data ();
4770+ if (dd && dd->class_list .has (" @GlobalScope" )) {
4771+ for (const DocData::ConstantDoc &cd : dd->class_list [" @GlobalScope" ].constants ) {
4772+ if (cd.name == name && cd.is_deprecated ) {
4773+ parser->push_warning (p_identifier, GDScriptWarning::DEPRECATED_IDENTIFIER, " constant" , name);
4774+ }
4775+ }
4776+ }
4777+ #endif
45654778 return ;
45664779 }
45674780
@@ -5755,6 +5968,12 @@ bool GDScriptAnalyzer::get_function_signature(GDScriptParser::Node *p_source, bo
57555968 r_return_type.is_meta_type = false ;
57565969 r_return_type.is_coroutine = found_function->is_coroutine ;
57575970
5971+ // For user-defined methods.
5972+ #ifdef TOOLS_ENABLED
5973+ if (found_function->doc_data .is_deprecated ) {
5974+ parser->push_warning (p_source, GDScriptWarning::DEPRECATED_IDENTIFIER, " function" , found_function->identifier ->name );
5975+ }
5976+ #endif
57585977 return true ;
57595978 }
57605979
@@ -5798,6 +6017,19 @@ bool GDScriptAnalyzer::get_function_signature(GDScriptParser::Node *p_source, bo
57986017 if (native_method && r_native_class) {
57996018 *r_native_class = native_method->get_instance_class ();
58006019 }
6020+ #endif
6021+ #ifdef TOOLS_ENABLED
6022+ DocTools *dd = EditorHelp::get_doc_data ();
6023+ if (dd) {
6024+ Vector<DocData::MethodDoc> method_list = dd->class_list [base_native].methods ;
6025+ for (int i = 0 ; i < method_list.size (); i++) {
6026+ if (method_list[i].name == function_name && method_list[i].is_deprecated ) {
6027+ parser->push_warning (p_source, GDScriptWarning::DEPRECATED_IDENTIFIER, " function" , function_name);
6028+ break ;
6029+ }
6030+ }
6031+ }
6032+
58016033#endif
58026034 return valid;
58036035 }
0 commit comments