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+ #ifdef 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
@@ -4003,6 +4058,38 @@ void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNod
40034058 StringName name = p_identifier->name ;
40044059
40054060 if (base.kind == GDScriptParser::DataType::ENUM) {
4061+ #ifdef TOOLS_ENABLED
4062+ StringName class_name;
4063+ DocTools *dd = EditorHelp::get_doc_data ();
4064+ // TODO: Is this a proper way of detecting it's from a native class?
4065+ // e.g., "AnimationPlayer.AnimationProcessCallback"
4066+ // User-defined enums also seem to have a "native_type" so we can't
4067+ // detect actual native classes solely based on whether or not that
4068+ // string is defined.
4069+ if (base.native_type && !base.class_type ) {
4070+ class_name = String (base.native_type ).get_slicec (' .' , 0 );
4071+ }
4072+
4073+ else if (base.class_type && base.class_type ->identifier && base.class_type ->identifier ->name ) {
4074+ class_name = base.class_type ->identifier ->name ;
4075+ // It's an inner class, so we need to get the outer class's name
4076+ // as well to construct its full name as found in the doc data.
4077+ if (base.class_type ->outer != nullptr && base.class_type ->outer ->identifier != nullptr ) {
4078+ class_name = String (base.class_type ->outer ->identifier ->name ) + " ." + class_name;
4079+ }
4080+ }
4081+
4082+ if (dd && dd->class_list .has (class_name)) {
4083+ for (const DocData::ConstantDoc &doc : dd->class_list [class_name].constants ) {
4084+ if (doc.enumeration == base.enum_type && doc.name == name) {
4085+ if (doc.is_deprecated ) {
4086+ parser->push_warning (p_identifier, GDScriptWarning::DEPRECATED_IDENTIFIER, " enum value" , vformat (" %s.%s" , base.enum_type , doc.name ));
4087+ }
4088+ break ;
4089+ }
4090+ }
4091+ }
4092+ #endif
40064093 if (base.is_meta_type ) {
40074094 if (base.enum_values .has (name)) {
40084095 p_identifier->set_datatype (type_from_metatype (base));
@@ -4148,6 +4235,11 @@ void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNod
41484235 p_identifier->reduced_value = member.constant ->initializer ->reduced_value ;
41494236 p_identifier->source = GDScriptParser::IdentifierNode::MEMBER_CONSTANT;
41504237 p_identifier->constant_source = member.constant ;
4238+ #ifdef TOOLS_ENABLED
4239+ if (member.constant ->doc_data .is_deprecated ) {
4240+ parser->push_warning (p_identifier, GDScriptWarning::DEPRECATED_IDENTIFIER, " constant" , name);
4241+ }
4242+ #endif
41514243 return ;
41524244 }
41534245
@@ -4156,6 +4248,11 @@ void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNod
41564248 p_identifier->is_constant = true ;
41574249 p_identifier->reduced_value = member.enum_value .value ;
41584250 p_identifier->source = GDScriptParser::IdentifierNode::MEMBER_CONSTANT;
4251+ #ifdef TOOLS_ENABLED
4252+ if (member.enum_value .doc_data .is_deprecated ) {
4253+ parser->push_warning (p_identifier, GDScriptWarning::DEPRECATED_IDENTIFIER, " enum value" , name);
4254+ }
4255+ #endif
41594256 return ;
41604257 }
41614258
@@ -4164,6 +4261,11 @@ void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNod
41644261 p_identifier->is_constant = true ;
41654262 p_identifier->reduced_value = member.m_enum ->dictionary ;
41664263 p_identifier->source = GDScriptParser::IdentifierNode::MEMBER_CONSTANT;
4264+ #ifdef TOOLS_ENABLED
4265+ if (member.m_enum ->doc_data .is_deprecated ) {
4266+ parser->push_warning (p_identifier, GDScriptWarning::DEPRECATED_IDENTIFIER, " enum" , name);
4267+ }
4268+ #endif
41674269 return ;
41684270 }
41694271
@@ -4173,6 +4275,11 @@ void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNod
41734275 p_identifier->source = member.variable ->is_static ? GDScriptParser::IdentifierNode::STATIC_VARIABLE : GDScriptParser::IdentifierNode::MEMBER_VARIABLE;
41744276 p_identifier->variable_source = member.variable ;
41754277 member.variable ->usages += 1 ;
4278+ #ifdef TOOLS_ENABLED
4279+ if (member.variable ->doc_data .is_deprecated ) {
4280+ parser->push_warning (p_identifier, GDScriptWarning::DEPRECATED_IDENTIFIER, " property or variable" , name);
4281+ }
4282+ #endif
41764283 return ;
41774284 }
41784285 } break ;
@@ -4183,6 +4290,12 @@ void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNod
41834290 p_identifier->source = GDScriptParser::IdentifierNode::MEMBER_SIGNAL;
41844291 p_identifier->signal_source = member.signal ;
41854292 member.signal ->usages += 1 ;
4293+
4294+ #ifdef TOOLS_ENABLED
4295+ if (member.signal ->doc_data .is_deprecated ) {
4296+ parser->push_warning (p_identifier, GDScriptWarning::DEPRECATED_IDENTIFIER, " signal" , name);
4297+ }
4298+ #endif
41864299 return ;
41874300 }
41884301 } break ;
@@ -4200,6 +4313,11 @@ void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNod
42004313 case GDScriptParser::ClassNode::Member::CLASS: {
42014314 reduce_identifier_from_base_set_class (p_identifier, member.get_datatype ());
42024315 p_identifier->source = GDScriptParser::IdentifierNode::MEMBER_CLASS;
4316+ #ifdef TOOLS_ENABLED
4317+ if (script_class->get_member (name).m_class ->doc_data .is_deprecated ) {
4318+ parser->push_warning (p_identifier, GDScriptWarning::DEPRECATED_IDENTIFIER, " class" , name);
4319+ }
4320+ #endif
42034321 return ;
42044322 }
42054323
@@ -4289,6 +4407,19 @@ void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNod
42894407 p_identifier->set_datatype (type_from_property (getter->get_return_info (), false , !has_setter));
42904408 p_identifier->source = GDScriptParser::IdentifierNode::INHERITED_VARIABLE;
42914409 }
4410+ #ifdef TOOLS_ENABLED
4411+ DocTools *dd = EditorHelp::get_doc_data ();
4412+ if (dd && dd->class_list .has (native)) {
4413+ for (const DocData::PropertyDoc &doc : dd->class_list [native].properties ) {
4414+ if (doc.name == name) {
4415+ if (doc.is_deprecated ) {
4416+ parser->push_warning (p_identifier, GDScriptWarning::DEPRECATED_IDENTIFIER, " property" , name);
4417+ }
4418+ break ;
4419+ }
4420+ }
4421+ }
4422+ #endif
42924423 return ;
42934424 }
42944425 if (ClassDB::get_method_info (native, name, &method_info)) {
@@ -4301,11 +4432,33 @@ void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNod
43014432 // Signal is a type too.
43024433 p_identifier->set_datatype (make_signal_type (method_info));
43034434 p_identifier->source = GDScriptParser::IdentifierNode::INHERITED_VARIABLE;
4435+ #ifdef TOOLS_ENABLED
4436+ DocTools *dd = EditorHelp::get_doc_data ();
4437+ if (dd && dd->class_list .has (native)) {
4438+ for (const DocData::MethodDoc &doc : dd->class_list [native].signals ) {
4439+ if (doc.name == name) {
4440+ if (doc.is_deprecated ) {
4441+ parser->push_warning (p_identifier, GDScriptWarning::DEPRECATED_IDENTIFIER, " signal" , name);
4442+ }
4443+ break ;
4444+ }
4445+ }
4446+ }
4447+ #endif
43044448 return ;
43054449 }
43064450 if (ClassDB::has_enum (native, name)) {
43074451 p_identifier->set_datatype (make_native_enum_type (name, native));
43084452 p_identifier->source = GDScriptParser::IdentifierNode::MEMBER_CONSTANT;
4453+ #ifdef TOOLS_ENABLED
4454+ DocTools *dd = EditorHelp::get_doc_data ();
4455+ if (dd && dd->class_list .has (native) && dd->class_list [native].enums .has (name)) {
4456+ DocData::EnumDoc doc = dd->class_list [native].enums [name];
4457+ if (doc.is_deprecated ) {
4458+ parser->push_warning (p_identifier, GDScriptWarning::DEPRECATED_IDENTIFIER, " enum" , name);
4459+ }
4460+ }
4461+ #endif
43094462 return ;
43104463 }
43114464 bool valid = false ;
@@ -4316,6 +4469,20 @@ void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNod
43164469 p_identifier->reduced_value = int_constant;
43174470 p_identifier->source = GDScriptParser::IdentifierNode::MEMBER_CONSTANT;
43184471
4472+ #ifdef TOOLS_ENABLED
4473+ DocTools *dd = EditorHelp::get_doc_data ();
4474+ if (dd && dd->class_list .has (native)) {
4475+ for (const DocData::ConstantDoc &doc : dd->class_list [native].constants ) {
4476+ if (doc.name == name) {
4477+ if (doc.is_deprecated ) {
4478+ parser->push_warning (p_identifier, GDScriptWarning::DEPRECATED_IDENTIFIER, " constant" , name);
4479+ }
4480+ break ;
4481+ }
4482+ }
4483+ }
4484+ #endif
4485+
43194486 // Check whether this constant, which exists, belongs to an enum
43204487 StringName enum_name = ClassDB::get_integer_constant_enum (native, name);
43214488 if (enum_name != StringName ()) {
@@ -4368,6 +4535,12 @@ void GDScriptAnalyzer::reduce_identifier(GDScriptParser::IdentifierNode *p_ident
43684535 // TODO: Constant should have a value on the node itself.
43694536 p_identifier->reduced_value = p_identifier->constant_source ->initializer ->reduced_value ;
43704537 found_source = true ;
4538+
4539+ #ifdef TOOLS_ENABLED
4540+ if (p_identifier->constant_source ->doc_data .is_deprecated ) {
4541+ parser->push_warning (p_identifier, GDScriptWarning::DEPRECATED_IDENTIFIER, " constant" , p_identifier->name );
4542+ }
4543+ #endif
43714544 break ;
43724545 case GDScriptParser::IdentifierNode::MEMBER_SIGNAL:
43734546 p_identifier->signal_source ->usages ++;
@@ -4387,6 +4560,11 @@ void GDScriptAnalyzer::reduce_identifier(GDScriptParser::IdentifierNode *p_ident
43874560 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)) {
43884561 parser->push_warning (p_identifier, GDScriptWarning::UNASSIGNED_VARIABLE, p_identifier->name );
43894562 }
4563+ #endif
4564+ #ifdef TOOLS_ENABLED
4565+ if (p_identifier->variable_source ->doc_data .is_deprecated ) {
4566+ parser->push_warning (p_identifier, GDScriptWarning::DEPRECATED_IDENTIFIER, " property or variable" , p_identifier->name );
4567+ }
43904568#endif
43914569 break ;
43924570 case GDScriptParser::IdentifierNode::LOCAL_ITERATOR:
@@ -4504,12 +4682,28 @@ void GDScriptAnalyzer::reduce_identifier(GDScriptParser::IdentifierNode *p_ident
45044682 }
45054683
45064684 if (class_exists (name)) {
4685+ #ifdef TOOLS_ENABLED
4686+ DocTools *dd = EditorHelp::get_doc_data ();
4687+ if (dd && dd->class_list .has (name)) {
4688+ if (dd->class_list [name].is_deprecated ) {
4689+ parser->push_warning (p_identifier, GDScriptWarning::DEPRECATED_IDENTIFIER, " class" , name);
4690+ }
4691+ }
4692+ #endif
45074693 p_identifier->set_datatype (make_native_meta_type (name));
45084694 return ;
45094695 }
45104696
45114697 if (ScriptServer::is_global_class (name)) {
45124698 p_identifier->set_datatype (make_global_class_meta_type (name, p_identifier));
4699+ #ifdef TOOLS_ENABLED
4700+ DocTools *dd = EditorHelp::get_doc_data ();
4701+ if (dd && dd->class_list .has (name)) {
4702+ if (dd->class_list [name].is_deprecated ) {
4703+ parser->push_warning (p_identifier, GDScriptWarning::DEPRECATED_IDENTIFIER, " class" , name);
4704+ }
4705+ }
4706+ #endif
45134707 return ;
45144708 }
45154709
@@ -4550,6 +4744,14 @@ void GDScriptAnalyzer::reduce_identifier(GDScriptParser::IdentifierNode *p_ident
45504744 }
45514745 }
45524746 }
4747+ #ifdef TOOLS_ENABLED
4748+ DocTools *dd = EditorHelp::get_doc_data ();
4749+ if (dd && dd->class_list .has (name)) {
4750+ if (dd->class_list [name].is_deprecated ) {
4751+ parser->push_warning (p_identifier, GDScriptWarning::DEPRECATED_IDENTIFIER, " class" , name);
4752+ }
4753+ }
4754+ #endif
45534755 result.is_constant = true ;
45544756 p_identifier->set_datatype (result);
45554757 return ;
@@ -4567,6 +4769,17 @@ void GDScriptAnalyzer::reduce_identifier(GDScriptParser::IdentifierNode *p_ident
45674769 }
45684770 p_identifier->is_constant = true ;
45694771 p_identifier->reduced_value = value;
4772+
4773+ #ifdef TOOLS_ENABLED
4774+ DocTools *dd = EditorHelp::get_doc_data ();
4775+ if (dd && dd->class_list .has (" @GlobalScope" )) {
4776+ for (const DocData::ConstantDoc &cd : dd->class_list [" @GlobalScope" ].constants ) {
4777+ if (cd.name == name && cd.is_deprecated ) {
4778+ parser->push_warning (p_identifier, GDScriptWarning::DEPRECATED_IDENTIFIER, " constant" , name);
4779+ }
4780+ }
4781+ }
4782+ #endif
45704783 return ;
45714784 }
45724785
@@ -5812,6 +6025,12 @@ bool GDScriptAnalyzer::get_function_signature(GDScriptParser::Node *p_source, bo
58126025 r_return_type.is_meta_type = false ;
58136026 r_return_type.is_coroutine = found_function->is_coroutine ;
58146027
6028+ // For user-defined methods.
6029+ #ifdef TOOLS_ENABLED
6030+ if (found_function->doc_data .is_deprecated ) {
6031+ parser->push_warning (p_source, GDScriptWarning::DEPRECATED_IDENTIFIER, " function" , found_function->identifier ->name );
6032+ }
6033+ #endif
58156034 return true ;
58166035 }
58176036
@@ -5855,6 +6074,19 @@ bool GDScriptAnalyzer::get_function_signature(GDScriptParser::Node *p_source, bo
58556074 if (native_method && r_native_class) {
58566075 *r_native_class = native_method->get_instance_class ();
58576076 }
6077+ #endif
6078+ #ifdef TOOLS_ENABLED
6079+ DocTools *dd = EditorHelp::get_doc_data ();
6080+ if (dd) {
6081+ const Vector<DocData::MethodDoc> &method_list = dd->class_list [base_native].methods ;
6082+ for (int i = 0 ; i < method_list.size (); i++) {
6083+ if (method_list[i].name == function_name && method_list[i].is_deprecated ) {
6084+ parser->push_warning (p_source, GDScriptWarning::DEPRECATED_IDENTIFIER, " function" , function_name);
6085+ break ;
6086+ }
6087+ }
6088+ }
6089+
58586090#endif
58596091 return valid;
58606092 }
0 commit comments