4444#include " core/templates/hash_map.h"
4545#include " scene/main/node.h"
4646
47+ #ifdef TOOLS_ENABLED
48+ #include " editor/doc/editor_help.h"
49+ #endif
50+
4751#if defined(TOOLS_ENABLED) && !defined(DISABLE_DEPRECATED)
4852#define SUGGEST_GODOT4_RENAMES
4953#include " editor/project_upgrade/renames_map_3_to_4.h"
@@ -2088,6 +2092,57 @@ void GDScriptAnalyzer::resolve_assignable(GDScriptParser::AssignableNode *p_assi
20882092 type = specified_type;
20892093 }
20902094
2095+ #ifdef TOOLS_ENABLED
2096+ DocTools *dd = EditorHelp::get_doc_data ();
2097+ bool is_deprecated = false ;
2098+ String new_value_type = " value" ;
2099+ String value_name = type.native_type ;
2100+ switch (type.kind ) {
2101+ case GDScriptParser::DataType::Kind::BUILTIN: // No built-in datatypes are deprecated.
2102+ break ;
2103+ case GDScriptParser::DataType::Kind::NATIVE:
2104+ is_deprecated = dd && dd->class_list .has (type.native_type ) && dd->class_list [type.native_type ].is_deprecated ;
2105+ new_value_type = " class" ;
2106+ break ;
2107+ case GDScriptParser::DataType::Kind::SCRIPT: {
2108+ StringName class_name = type.script_type ->get_doc_class_name ();
2109+ is_deprecated = dd && dd->class_list .has (class_name) && dd->class_list [class_name].is_deprecated ;
2110+ new_value_type = " class" ;
2111+ break ;
2112+ }
2113+ case GDScriptParser::DataType::Kind::CLASS:
2114+ is_deprecated = type.class_type ->doc_data .is_deprecated ;
2115+ new_value_type = " class" ;
2116+
2117+ // TODO: Not recognizing the autoload name as a class type
2118+ // var my_var: MyAutoload # <--- not getting this name
2119+ if (type.class_type && type.class_type ->identifier ) {
2120+ value_name = type.class_type ->identifier ->name ;
2121+ } else {
2122+ value_name = " " ;
2123+ }
2124+ break ;
2125+ case GDScriptParser::DataType::Kind::ENUM: {
2126+ StringName enum_type = type.enum_type ; // Something like MyEnum.
2127+ GDScriptParser::ClassNode *class_type = type.class_type ;
2128+ StringName class_name = (class_type && class_type->identifier ) ? class_type->identifier ->name : " @GlobalScope" ;
2129+ if (dd && dd->class_list .has (class_name)) {
2130+ DocData::ClassDoc class_doc = dd->class_list [class_name];
2131+ if (class_doc.enums .has (enum_type)) {
2132+ is_deprecated = class_doc.enums [enum_type].is_deprecated ;
2133+ }
2134+ }
2135+ new_value_type = " enum" ;
2136+ break ;
2137+ }
2138+ default :
2139+ break ;
2140+ }
2141+ if (is_deprecated) {
2142+ parser->push_warning (p_assignable, GDScriptWarning::DEPRECATED_IDENTIFIER, new_value_type, value_name);
2143+ }
2144+ #endif
2145+
20912146 if (p_assignable->initializer != nullptr ) {
20922147 reduce_expression (p_assignable->initializer );
20932148
@@ -4040,6 +4095,38 @@ void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNod
40404095 StringName name = p_identifier->name ;
40414096
40424097 if (base.kind == GDScriptParser::DataType::ENUM) {
4098+ #ifdef TOOLS_ENABLED
4099+ StringName class_name;
4100+ DocTools *dd = EditorHelp::get_doc_data ();
4101+ // TODO: Is this a proper way of detecting it's from a native class?
4102+ // e.g., "AnimationPlayer.AnimationProcessCallback"
4103+ // User-defined enums also seem to have a "native_type" so we can't
4104+ // detect actual native classes solely based on whether or not that
4105+ // string is defined.
4106+ if (base.native_type && !base.class_type ) {
4107+ class_name = String (base.native_type ).get_slicec (' .' , 0 );
4108+ }
4109+
4110+ else if (base.class_type && base.class_type ->identifier && base.class_type ->identifier ->name ) {
4111+ class_name = base.class_type ->identifier ->name ;
4112+ // It's an inner class, so we need to get the outer class's name
4113+ // as well to construct its full name as found in the doc data.
4114+ if (base.class_type ->outer != nullptr && base.class_type ->outer ->identifier != nullptr ) {
4115+ class_name = String (base.class_type ->outer ->identifier ->name ) + " ." + class_name;
4116+ }
4117+ }
4118+
4119+ if (dd && dd->class_list .has (class_name)) {
4120+ for (const DocData::ConstantDoc &doc : dd->class_list [class_name].constants ) {
4121+ if (doc.enumeration == base.enum_type && doc.name == name) {
4122+ if (doc.is_deprecated ) {
4123+ parser->push_warning (p_identifier, GDScriptWarning::DEPRECATED_IDENTIFIER, " enum value" , vformat (" %s.%s" , base.enum_type , doc.name ));
4124+ }
4125+ break ;
4126+ }
4127+ }
4128+ }
4129+ #endif
40434130 if (base.is_meta_type ) {
40444131 if (base.enum_values .has (name)) {
40454132 p_identifier->set_datatype (type_from_metatype (base));
@@ -4185,6 +4272,11 @@ void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNod
41854272 p_identifier->reduced_value = member.constant ->initializer ->reduced_value ;
41864273 p_identifier->source = GDScriptParser::IdentifierNode::MEMBER_CONSTANT;
41874274 p_identifier->constant_source = member.constant ;
4275+ #ifdef TOOLS_ENABLED
4276+ if (member.constant ->doc_data .is_deprecated ) {
4277+ parser->push_warning (p_identifier, GDScriptWarning::DEPRECATED_IDENTIFIER, " constant" , name);
4278+ }
4279+ #endif
41884280 return ;
41894281 }
41904282
@@ -4193,6 +4285,11 @@ void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNod
41934285 p_identifier->is_constant = true ;
41944286 p_identifier->reduced_value = member.enum_value .value ;
41954287 p_identifier->source = GDScriptParser::IdentifierNode::MEMBER_CONSTANT;
4288+ #ifdef TOOLS_ENABLED
4289+ if (member.enum_value .doc_data .is_deprecated ) {
4290+ parser->push_warning (p_identifier, GDScriptWarning::DEPRECATED_IDENTIFIER, " enum value" , name);
4291+ }
4292+ #endif
41964293 return ;
41974294 }
41984295
@@ -4201,6 +4298,11 @@ void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNod
42014298 p_identifier->is_constant = true ;
42024299 p_identifier->reduced_value = member.m_enum ->dictionary ;
42034300 p_identifier->source = GDScriptParser::IdentifierNode::MEMBER_CONSTANT;
4301+ #ifdef TOOLS_ENABLED
4302+ if (member.m_enum ->doc_data .is_deprecated ) {
4303+ parser->push_warning (p_identifier, GDScriptWarning::DEPRECATED_IDENTIFIER, " enum" , name);
4304+ }
4305+ #endif
42044306 return ;
42054307 }
42064308
@@ -4210,6 +4312,11 @@ void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNod
42104312 p_identifier->source = member.variable ->is_static ? GDScriptParser::IdentifierNode::STATIC_VARIABLE : GDScriptParser::IdentifierNode::MEMBER_VARIABLE;
42114313 p_identifier->variable_source = member.variable ;
42124314 member.variable ->usages += 1 ;
4315+ #ifdef TOOLS_ENABLED
4316+ if (member.variable ->doc_data .is_deprecated ) {
4317+ parser->push_warning (p_identifier, GDScriptWarning::DEPRECATED_IDENTIFIER, " property or variable" , name);
4318+ }
4319+ #endif
42134320 return ;
42144321 }
42154322 } break ;
@@ -4220,6 +4327,12 @@ void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNod
42204327 p_identifier->source = GDScriptParser::IdentifierNode::MEMBER_SIGNAL;
42214328 p_identifier->signal_source = member.signal ;
42224329 member.signal ->usages += 1 ;
4330+
4331+ #ifdef TOOLS_ENABLED
4332+ if (member.signal ->doc_data .is_deprecated ) {
4333+ parser->push_warning (p_identifier, GDScriptWarning::DEPRECATED_IDENTIFIER, " signal" , name);
4334+ }
4335+ #endif
42234336 return ;
42244337 }
42254338 } break ;
@@ -4237,6 +4350,11 @@ void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNod
42374350 case GDScriptParser::ClassNode::Member::CLASS: {
42384351 reduce_identifier_from_base_set_class (p_identifier, member.get_datatype ());
42394352 p_identifier->source = GDScriptParser::IdentifierNode::MEMBER_CLASS;
4353+ #ifdef TOOLS_ENABLED
4354+ if (script_class->get_member (name).m_class ->doc_data .is_deprecated ) {
4355+ parser->push_warning (p_identifier, GDScriptWarning::DEPRECATED_IDENTIFIER, " class" , name);
4356+ }
4357+ #endif
42404358 return ;
42414359 }
42424360
@@ -4326,6 +4444,19 @@ void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNod
43264444 p_identifier->set_datatype (type_from_property (getter->get_return_info (), false , !has_setter));
43274445 p_identifier->source = GDScriptParser::IdentifierNode::INHERITED_VARIABLE;
43284446 }
4447+ #ifdef TOOLS_ENABLED
4448+ DocTools *dd = EditorHelp::get_doc_data ();
4449+ if (dd && dd->class_list .has (native)) {
4450+ for (const DocData::PropertyDoc &doc : dd->class_list [native].properties ) {
4451+ if (doc.name == name) {
4452+ if (doc.is_deprecated ) {
4453+ parser->push_warning (p_identifier, GDScriptWarning::DEPRECATED_IDENTIFIER, " property" , name);
4454+ }
4455+ break ;
4456+ }
4457+ }
4458+ }
4459+ #endif
43294460 return ;
43304461 }
43314462 if (ClassDB::get_method_info (native, name, &method_info)) {
@@ -4338,11 +4469,33 @@ void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNod
43384469 // Signal is a type too.
43394470 p_identifier->set_datatype (make_signal_type (method_info));
43404471 p_identifier->source = GDScriptParser::IdentifierNode::INHERITED_VARIABLE;
4472+ #ifdef TOOLS_ENABLED
4473+ DocTools *dd = EditorHelp::get_doc_data ();
4474+ if (dd && dd->class_list .has (native)) {
4475+ for (const DocData::MethodDoc &doc : dd->class_list [native].signals ) {
4476+ if (doc.name == name) {
4477+ if (doc.is_deprecated ) {
4478+ parser->push_warning (p_identifier, GDScriptWarning::DEPRECATED_IDENTIFIER, " signal" , name);
4479+ }
4480+ break ;
4481+ }
4482+ }
4483+ }
4484+ #endif
43414485 return ;
43424486 }
43434487 if (ClassDB::has_enum (native, name)) {
43444488 p_identifier->set_datatype (make_native_enum_type (name, native));
43454489 p_identifier->source = GDScriptParser::IdentifierNode::MEMBER_CONSTANT;
4490+ #ifdef TOOLS_ENABLED
4491+ DocTools *dd = EditorHelp::get_doc_data ();
4492+ if (dd && dd->class_list .has (native) && dd->class_list [native].enums .has (name)) {
4493+ DocData::EnumDoc doc = dd->class_list [native].enums [name];
4494+ if (doc.is_deprecated ) {
4495+ parser->push_warning (p_identifier, GDScriptWarning::DEPRECATED_IDENTIFIER, " enum" , name);
4496+ }
4497+ }
4498+ #endif
43464499 return ;
43474500 }
43484501 bool valid = false ;
@@ -4353,6 +4506,20 @@ void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNod
43534506 p_identifier->reduced_value = int_constant;
43544507 p_identifier->source = GDScriptParser::IdentifierNode::MEMBER_CONSTANT;
43554508
4509+ #ifdef TOOLS_ENABLED
4510+ DocTools *dd = EditorHelp::get_doc_data ();
4511+ if (dd && dd->class_list .has (native)) {
4512+ for (const DocData::ConstantDoc &doc : dd->class_list [native].constants ) {
4513+ if (doc.name == name) {
4514+ if (doc.is_deprecated ) {
4515+ parser->push_warning (p_identifier, GDScriptWarning::DEPRECATED_IDENTIFIER, " constant" , name);
4516+ }
4517+ break ;
4518+ }
4519+ }
4520+ }
4521+ #endif
4522+
43564523 // Check whether this constant, which exists, belongs to an enum
43574524 StringName enum_name = ClassDB::get_integer_constant_enum (native, name);
43584525 if (enum_name != StringName ()) {
@@ -4405,6 +4572,12 @@ void GDScriptAnalyzer::reduce_identifier(GDScriptParser::IdentifierNode *p_ident
44054572 // TODO: Constant should have a value on the node itself.
44064573 p_identifier->reduced_value = p_identifier->constant_source ->initializer ->reduced_value ;
44074574 found_source = true ;
4575+
4576+ #ifdef TOOLS_ENABLED
4577+ if (p_identifier->constant_source ->doc_data .is_deprecated ) {
4578+ parser->push_warning (p_identifier, GDScriptWarning::DEPRECATED_IDENTIFIER, " constant" , p_identifier->name );
4579+ }
4580+ #endif
44084581 break ;
44094582 case GDScriptParser::IdentifierNode::MEMBER_SIGNAL:
44104583 p_identifier->signal_source ->usages ++;
@@ -4424,7 +4597,12 @@ void GDScriptAnalyzer::reduce_identifier(GDScriptParser::IdentifierNode *p_ident
44244597 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)) {
44254598 parser->push_warning (p_identifier, GDScriptWarning::UNASSIGNED_VARIABLE, p_identifier->name );
44264599 }
4427- #endif // DEBUG_ENABLED
4600+ #endif
4601+ #ifdef TOOLS_ENABLED
4602+ if (p_identifier->variable_source ->doc_data .is_deprecated ) {
4603+ parser->push_warning (p_identifier, GDScriptWarning::DEPRECATED_IDENTIFIER, " property or variable" , p_identifier->name );
4604+ }
4605+ #endif
44284606 break ;
44294607 case GDScriptParser::IdentifierNode::LOCAL_ITERATOR:
44304608 p_identifier->set_datatype (p_identifier->bind_source ->get_datatype ());
@@ -4543,13 +4721,29 @@ void GDScriptAnalyzer::reduce_identifier(GDScriptParser::IdentifierNode *p_ident
45434721 }
45444722
45454723 if (class_exists (name)) {
4724+ #ifdef TOOLS_ENABLED
4725+ DocTools *dd = EditorHelp::get_doc_data ();
4726+ if (dd && dd->class_list .has (name)) {
4727+ if (dd->class_list [name].is_deprecated ) {
4728+ parser->push_warning (p_identifier, GDScriptWarning::DEPRECATED_IDENTIFIER, " class" , name);
4729+ }
4730+ }
4731+ #endif
45464732 p_identifier->source = GDScriptParser::IdentifierNode::NATIVE_CLASS;
45474733 p_identifier->set_datatype (make_native_meta_type (name));
45484734 return ;
45494735 }
45504736
45514737 if (ScriptServer::is_global_class (name)) {
45524738 p_identifier->set_datatype (make_global_class_meta_type (name, p_identifier));
4739+ #ifdef TOOLS_ENABLED
4740+ DocTools *dd = EditorHelp::get_doc_data ();
4741+ if (dd && dd->class_list .has (name)) {
4742+ if (dd->class_list [name].is_deprecated ) {
4743+ parser->push_warning (p_identifier, GDScriptWarning::DEPRECATED_IDENTIFIER, " class" , name);
4744+ }
4745+ }
4746+ #endif
45534747 return ;
45544748 }
45554749
@@ -4590,6 +4784,14 @@ void GDScriptAnalyzer::reduce_identifier(GDScriptParser::IdentifierNode *p_ident
45904784 }
45914785 }
45924786 }
4787+ #ifdef TOOLS_ENABLED
4788+ DocTools *dd = EditorHelp::get_doc_data ();
4789+ if (dd && dd->class_list .has (name)) {
4790+ if (dd->class_list [name].is_deprecated ) {
4791+ parser->push_warning (p_identifier, GDScriptWarning::DEPRECATED_IDENTIFIER, " class" , name);
4792+ }
4793+ }
4794+ #endif
45934795 result.is_constant = true ;
45944796 p_identifier->set_datatype (result);
45954797 return ;
@@ -4607,6 +4809,17 @@ void GDScriptAnalyzer::reduce_identifier(GDScriptParser::IdentifierNode *p_ident
46074809 }
46084810 p_identifier->is_constant = true ;
46094811 p_identifier->reduced_value = value;
4812+
4813+ #ifdef TOOLS_ENABLED
4814+ DocTools *dd = EditorHelp::get_doc_data ();
4815+ if (dd && dd->class_list .has (" @GlobalScope" )) {
4816+ for (const DocData::ConstantDoc &cd : dd->class_list [" @GlobalScope" ].constants ) {
4817+ if (cd.name == name && cd.is_deprecated ) {
4818+ parser->push_warning (p_identifier, GDScriptWarning::DEPRECATED_IDENTIFIER, " constant" , name);
4819+ }
4820+ }
4821+ }
4822+ #endif
46104823 return ;
46114824 }
46124825
@@ -5858,6 +6071,12 @@ bool GDScriptAnalyzer::get_function_signature(GDScriptParser::Node *p_source, bo
58586071 r_return_type.is_meta_type = false ;
58596072 r_return_type.is_coroutine = found_function->is_coroutine ;
58606073
6074+ // For user-defined methods.
6075+ #ifdef TOOLS_ENABLED
6076+ if (found_function->doc_data .is_deprecated ) {
6077+ parser->push_warning (p_source, GDScriptWarning::DEPRECATED_IDENTIFIER, " function" , found_function->identifier ->name );
6078+ }
6079+ #endif
58616080 return true ;
58626081 }
58636082
@@ -5901,7 +6120,20 @@ bool GDScriptAnalyzer::get_function_signature(GDScriptParser::Node *p_source, bo
59016120 if (native_method && r_native_class) {
59026121 *r_native_class = native_method->get_instance_class ();
59036122 }
5904- #endif // DEBUG_ENABLED
6123+ #endif
6124+ #ifdef TOOLS_ENABLED
6125+ DocTools *dd = EditorHelp::get_doc_data ();
6126+ if (dd) {
6127+ const Vector<DocData::MethodDoc> &method_list = dd->class_list [base_native].methods ;
6128+ for (const DocData::MethodDoc &doc : method_list) {
6129+ if (doc.name == function_name && doc.is_deprecated ) {
6130+ parser->push_warning (p_source, GDScriptWarning::DEPRECATED_IDENTIFIER, " function" , function_name);
6131+ break ;
6132+ }
6133+ }
6134+ }
6135+
6136+ #endif
59056137 return valid;
59066138 }
59076139
0 commit comments