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"
@@ -2072,6 +2076,57 @@ void GDScriptAnalyzer::resolve_assignable(GDScriptParser::AssignableNode *p_assi
20722076 type = specified_type;
20732077 }
20742078
2079+ #ifdef TOOLS_ENABLED
2080+ DocTools *dd = EditorHelp::get_doc_data ();
2081+ bool is_deprecated = false ;
2082+ String new_value_type = " value" ;
2083+ String value_name = type.native_type ;
2084+ switch (type.kind ) {
2085+ case GDScriptParser::DataType::Kind::BUILTIN: // No built-in datatypes are deprecated.
2086+ break ;
2087+ case GDScriptParser::DataType::Kind::NATIVE:
2088+ is_deprecated = dd && dd->class_list .has (type.native_type ) && dd->class_list [type.native_type ].is_deprecated ;
2089+ new_value_type = " class" ;
2090+ break ;
2091+ case GDScriptParser::DataType::Kind::SCRIPT: {
2092+ StringName class_name = type.script_type ->get_doc_class_name ();
2093+ is_deprecated = dd && dd->class_list .has (class_name) && dd->class_list [class_name].is_deprecated ;
2094+ new_value_type = " class" ;
2095+ break ;
2096+ }
2097+ case GDScriptParser::DataType::Kind::CLASS:
2098+ is_deprecated = type.class_type ->doc_data .is_deprecated ;
2099+ new_value_type = " class" ;
2100+
2101+ // TODO: Not recognizing the autoload name as a class type
2102+ // var my_var: MyAutoload # <--- not getting this name
2103+ if (type.class_type && type.class_type ->identifier ) {
2104+ value_name = type.class_type ->identifier ->name ;
2105+ } else {
2106+ value_name = " " ;
2107+ }
2108+ break ;
2109+ case GDScriptParser::DataType::Kind::ENUM: {
2110+ StringName enum_type = type.enum_type ; // Something like MyEnum.
2111+ GDScriptParser::ClassNode *class_type = type.class_type ;
2112+ StringName class_name = (class_type && class_type->identifier ) ? class_type->identifier ->name : " @GlobalScope" ;
2113+ if (dd && dd->class_list .has (class_name)) {
2114+ DocData::ClassDoc class_doc = dd->class_list [class_name];
2115+ if (class_doc.enums .has (enum_type)) {
2116+ is_deprecated = class_doc.enums [enum_type].is_deprecated ;
2117+ }
2118+ }
2119+ new_value_type = " enum" ;
2120+ break ;
2121+ }
2122+ default :
2123+ break ;
2124+ }
2125+ if (is_deprecated) {
2126+ parser->push_warning (p_assignable, GDScriptWarning::DEPRECATED_IDENTIFIER, new_value_type, value_name);
2127+ }
2128+ #endif
2129+
20752130 if (p_assignable->initializer != nullptr ) {
20762131 reduce_expression (p_assignable->initializer );
20772132
@@ -4024,6 +4079,38 @@ void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNod
40244079 StringName name = p_identifier->name ;
40254080
40264081 if (base.kind == GDScriptParser::DataType::ENUM) {
4082+ #ifdef TOOLS_ENABLED
4083+ StringName class_name;
4084+ DocTools *dd = EditorHelp::get_doc_data ();
4085+ // TODO: Is this a proper way of detecting it's from a native class?
4086+ // e.g., "AnimationPlayer.AnimationProcessCallback"
4087+ // User-defined enums also seem to have a "native_type" so we can't
4088+ // detect actual native classes solely based on whether or not that
4089+ // string is defined.
4090+ if (base.native_type && !base.class_type ) {
4091+ class_name = String (base.native_type ).get_slicec (' .' , 0 );
4092+ }
4093+
4094+ else if (base.class_type && base.class_type ->identifier && base.class_type ->identifier ->name ) {
4095+ class_name = base.class_type ->identifier ->name ;
4096+ // It's an inner class, so we need to get the outer class's name
4097+ // as well to construct its full name as found in the doc data.
4098+ if (base.class_type ->outer != nullptr && base.class_type ->outer ->identifier != nullptr ) {
4099+ class_name = String (base.class_type ->outer ->identifier ->name ) + " ." + class_name;
4100+ }
4101+ }
4102+
4103+ if (dd && dd->class_list .has (class_name)) {
4104+ for (const DocData::ConstantDoc &doc : dd->class_list [class_name].constants ) {
4105+ if (doc.enumeration == base.enum_type && doc.name == name) {
4106+ if (doc.is_deprecated ) {
4107+ parser->push_warning (p_identifier, GDScriptWarning::DEPRECATED_IDENTIFIER, " enum value" , vformat (" %s.%s" , base.enum_type , doc.name ));
4108+ }
4109+ break ;
4110+ }
4111+ }
4112+ }
4113+ #endif
40274114 if (base.is_meta_type ) {
40284115 if (base.enum_values .has (name)) {
40294116 p_identifier->set_datatype (type_from_metatype (base));
@@ -4169,6 +4256,11 @@ void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNod
41694256 p_identifier->reduced_value = member.constant ->initializer ->reduced_value ;
41704257 p_identifier->source = GDScriptParser::IdentifierNode::MEMBER_CONSTANT;
41714258 p_identifier->constant_source = member.constant ;
4259+ #ifdef TOOLS_ENABLED
4260+ if (member.constant ->doc_data .is_deprecated ) {
4261+ parser->push_warning (p_identifier, GDScriptWarning::DEPRECATED_IDENTIFIER, " constant" , name);
4262+ }
4263+ #endif
41724264 return ;
41734265 }
41744266
@@ -4177,6 +4269,11 @@ void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNod
41774269 p_identifier->is_constant = true ;
41784270 p_identifier->reduced_value = member.enum_value .value ;
41794271 p_identifier->source = GDScriptParser::IdentifierNode::MEMBER_CONSTANT;
4272+ #ifdef TOOLS_ENABLED
4273+ if (member.enum_value .doc_data .is_deprecated ) {
4274+ parser->push_warning (p_identifier, GDScriptWarning::DEPRECATED_IDENTIFIER, " enum value" , name);
4275+ }
4276+ #endif
41804277 return ;
41814278 }
41824279
@@ -4185,6 +4282,11 @@ void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNod
41854282 p_identifier->is_constant = true ;
41864283 p_identifier->reduced_value = member.m_enum ->dictionary ;
41874284 p_identifier->source = GDScriptParser::IdentifierNode::MEMBER_CONSTANT;
4285+ #ifdef TOOLS_ENABLED
4286+ if (member.m_enum ->doc_data .is_deprecated ) {
4287+ parser->push_warning (p_identifier, GDScriptWarning::DEPRECATED_IDENTIFIER, " enum" , name);
4288+ }
4289+ #endif
41884290 return ;
41894291 }
41904292
@@ -4194,6 +4296,11 @@ void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNod
41944296 p_identifier->source = member.variable ->is_static ? GDScriptParser::IdentifierNode::STATIC_VARIABLE : GDScriptParser::IdentifierNode::MEMBER_VARIABLE;
41954297 p_identifier->variable_source = member.variable ;
41964298 member.variable ->usages += 1 ;
4299+ #ifdef TOOLS_ENABLED
4300+ if (member.variable ->doc_data .is_deprecated ) {
4301+ parser->push_warning (p_identifier, GDScriptWarning::DEPRECATED_IDENTIFIER, " property or variable" , name);
4302+ }
4303+ #endif
41974304 return ;
41984305 }
41994306 } break ;
@@ -4204,6 +4311,12 @@ void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNod
42044311 p_identifier->source = GDScriptParser::IdentifierNode::MEMBER_SIGNAL;
42054312 p_identifier->signal_source = member.signal ;
42064313 member.signal ->usages += 1 ;
4314+
4315+ #ifdef TOOLS_ENABLED
4316+ if (member.signal ->doc_data .is_deprecated ) {
4317+ parser->push_warning (p_identifier, GDScriptWarning::DEPRECATED_IDENTIFIER, " signal" , name);
4318+ }
4319+ #endif
42074320 return ;
42084321 }
42094322 } break ;
@@ -4221,6 +4334,11 @@ void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNod
42214334 case GDScriptParser::ClassNode::Member::CLASS: {
42224335 reduce_identifier_from_base_set_class (p_identifier, member.get_datatype ());
42234336 p_identifier->source = GDScriptParser::IdentifierNode::MEMBER_CLASS;
4337+ #ifdef TOOLS_ENABLED
4338+ if (script_class->get_member (name).m_class ->doc_data .is_deprecated ) {
4339+ parser->push_warning (p_identifier, GDScriptWarning::DEPRECATED_IDENTIFIER, " class" , name);
4340+ }
4341+ #endif
42244342 return ;
42254343 }
42264344
@@ -4310,6 +4428,19 @@ void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNod
43104428 p_identifier->set_datatype (type_from_property (getter->get_return_info (), false , !has_setter));
43114429 p_identifier->source = GDScriptParser::IdentifierNode::INHERITED_VARIABLE;
43124430 }
4431+ #ifdef TOOLS_ENABLED
4432+ DocTools *dd = EditorHelp::get_doc_data ();
4433+ if (dd && dd->class_list .has (native)) {
4434+ for (const DocData::PropertyDoc &doc : dd->class_list [native].properties ) {
4435+ if (doc.name == name) {
4436+ if (doc.is_deprecated ) {
4437+ parser->push_warning (p_identifier, GDScriptWarning::DEPRECATED_IDENTIFIER, " property" , name);
4438+ }
4439+ break ;
4440+ }
4441+ }
4442+ }
4443+ #endif
43134444 return ;
43144445 }
43154446 if (ClassDB::get_method_info (native, name, &method_info)) {
@@ -4322,11 +4453,33 @@ void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNod
43224453 // Signal is a type too.
43234454 p_identifier->set_datatype (make_signal_type (method_info));
43244455 p_identifier->source = GDScriptParser::IdentifierNode::INHERITED_VARIABLE;
4456+ #ifdef TOOLS_ENABLED
4457+ DocTools *dd = EditorHelp::get_doc_data ();
4458+ if (dd && dd->class_list .has (native)) {
4459+ for (const DocData::MethodDoc &doc : dd->class_list [native].signals ) {
4460+ if (doc.name == name) {
4461+ if (doc.is_deprecated ) {
4462+ parser->push_warning (p_identifier, GDScriptWarning::DEPRECATED_IDENTIFIER, " signal" , name);
4463+ }
4464+ break ;
4465+ }
4466+ }
4467+ }
4468+ #endif
43254469 return ;
43264470 }
43274471 if (ClassDB::has_enum (native, name)) {
43284472 p_identifier->set_datatype (make_native_enum_type (name, native));
43294473 p_identifier->source = GDScriptParser::IdentifierNode::MEMBER_CONSTANT;
4474+ #ifdef TOOLS_ENABLED
4475+ DocTools *dd = EditorHelp::get_doc_data ();
4476+ if (dd && dd->class_list .has (native) && dd->class_list [native].enums .has (name)) {
4477+ DocData::EnumDoc doc = dd->class_list [native].enums [name];
4478+ if (doc.is_deprecated ) {
4479+ parser->push_warning (p_identifier, GDScriptWarning::DEPRECATED_IDENTIFIER, " enum" , name);
4480+ }
4481+ }
4482+ #endif
43304483 return ;
43314484 }
43324485 bool valid = false ;
@@ -4337,6 +4490,20 @@ void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNod
43374490 p_identifier->reduced_value = int_constant;
43384491 p_identifier->source = GDScriptParser::IdentifierNode::MEMBER_CONSTANT;
43394492
4493+ #ifdef TOOLS_ENABLED
4494+ DocTools *dd = EditorHelp::get_doc_data ();
4495+ if (dd && dd->class_list .has (native)) {
4496+ for (const DocData::ConstantDoc &doc : dd->class_list [native].constants ) {
4497+ if (doc.name == name) {
4498+ if (doc.is_deprecated ) {
4499+ parser->push_warning (p_identifier, GDScriptWarning::DEPRECATED_IDENTIFIER, " constant" , name);
4500+ }
4501+ break ;
4502+ }
4503+ }
4504+ }
4505+ #endif
4506+
43404507 // Check whether this constant, which exists, belongs to an enum
43414508 StringName enum_name = ClassDB::get_integer_constant_enum (native, name);
43424509 if (enum_name != StringName ()) {
@@ -4389,6 +4556,12 @@ void GDScriptAnalyzer::reduce_identifier(GDScriptParser::IdentifierNode *p_ident
43894556 // TODO: Constant should have a value on the node itself.
43904557 p_identifier->reduced_value = p_identifier->constant_source ->initializer ->reduced_value ;
43914558 found_source = true ;
4559+
4560+ #ifdef TOOLS_ENABLED
4561+ if (p_identifier->constant_source ->doc_data .is_deprecated ) {
4562+ parser->push_warning (p_identifier, GDScriptWarning::DEPRECATED_IDENTIFIER, " constant" , p_identifier->name );
4563+ }
4564+ #endif
43924565 break ;
43934566 case GDScriptParser::IdentifierNode::MEMBER_SIGNAL:
43944567 p_identifier->signal_source ->usages ++;
@@ -4408,7 +4581,12 @@ void GDScriptAnalyzer::reduce_identifier(GDScriptParser::IdentifierNode *p_ident
44084581 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)) {
44094582 parser->push_warning (p_identifier, GDScriptWarning::UNASSIGNED_VARIABLE, p_identifier->name );
44104583 }
4411- #endif // DEBUG_ENABLED
4584+ #endif
4585+ #ifdef TOOLS_ENABLED
4586+ if (p_identifier->variable_source ->doc_data .is_deprecated ) {
4587+ parser->push_warning (p_identifier, GDScriptWarning::DEPRECATED_IDENTIFIER, " property or variable" , p_identifier->name );
4588+ }
4589+ #endif
44124590 break ;
44134591 case GDScriptParser::IdentifierNode::LOCAL_ITERATOR:
44144592 p_identifier->set_datatype (p_identifier->bind_source ->get_datatype ());
@@ -4525,12 +4703,28 @@ void GDScriptAnalyzer::reduce_identifier(GDScriptParser::IdentifierNode *p_ident
45254703 }
45264704
45274705 if (class_exists (name)) {
4706+ #ifdef TOOLS_ENABLED
4707+ DocTools *dd = EditorHelp::get_doc_data ();
4708+ if (dd && dd->class_list .has (name)) {
4709+ if (dd->class_list [name].is_deprecated ) {
4710+ parser->push_warning (p_identifier, GDScriptWarning::DEPRECATED_IDENTIFIER, " class" , name);
4711+ }
4712+ }
4713+ #endif
45284714 p_identifier->set_datatype (make_native_meta_type (name));
45294715 return ;
45304716 }
45314717
45324718 if (ScriptServer::is_global_class (name)) {
45334719 p_identifier->set_datatype (make_global_class_meta_type (name, p_identifier));
4720+ #ifdef TOOLS_ENABLED
4721+ DocTools *dd = EditorHelp::get_doc_data ();
4722+ if (dd && dd->class_list .has (name)) {
4723+ if (dd->class_list [name].is_deprecated ) {
4724+ parser->push_warning (p_identifier, GDScriptWarning::DEPRECATED_IDENTIFIER, " class" , name);
4725+ }
4726+ }
4727+ #endif
45344728 return ;
45354729 }
45364730
@@ -4571,6 +4765,14 @@ void GDScriptAnalyzer::reduce_identifier(GDScriptParser::IdentifierNode *p_ident
45714765 }
45724766 }
45734767 }
4768+ #ifdef TOOLS_ENABLED
4769+ DocTools *dd = EditorHelp::get_doc_data ();
4770+ if (dd && dd->class_list .has (name)) {
4771+ if (dd->class_list [name].is_deprecated ) {
4772+ parser->push_warning (p_identifier, GDScriptWarning::DEPRECATED_IDENTIFIER, " class" , name);
4773+ }
4774+ }
4775+ #endif
45744776 result.is_constant = true ;
45754777 p_identifier->set_datatype (result);
45764778 return ;
@@ -4588,6 +4790,17 @@ void GDScriptAnalyzer::reduce_identifier(GDScriptParser::IdentifierNode *p_ident
45884790 }
45894791 p_identifier->is_constant = true ;
45904792 p_identifier->reduced_value = value;
4793+
4794+ #ifdef TOOLS_ENABLED
4795+ DocTools *dd = EditorHelp::get_doc_data ();
4796+ if (dd && dd->class_list .has (" @GlobalScope" )) {
4797+ for (const DocData::ConstantDoc &cd : dd->class_list [" @GlobalScope" ].constants ) {
4798+ if (cd.name == name && cd.is_deprecated ) {
4799+ parser->push_warning (p_identifier, GDScriptWarning::DEPRECATED_IDENTIFIER, " constant" , name);
4800+ }
4801+ }
4802+ }
4803+ #endif
45914804 return ;
45924805 }
45934806
@@ -5839,6 +6052,12 @@ bool GDScriptAnalyzer::get_function_signature(GDScriptParser::Node *p_source, bo
58396052 r_return_type.is_meta_type = false ;
58406053 r_return_type.is_coroutine = found_function->is_coroutine ;
58416054
6055+ // For user-defined methods.
6056+ #ifdef TOOLS_ENABLED
6057+ if (found_function->doc_data .is_deprecated ) {
6058+ parser->push_warning (p_source, GDScriptWarning::DEPRECATED_IDENTIFIER, " function" , found_function->identifier ->name );
6059+ }
6060+ #endif
58426061 return true ;
58436062 }
58446063
@@ -5882,7 +6101,20 @@ bool GDScriptAnalyzer::get_function_signature(GDScriptParser::Node *p_source, bo
58826101 if (native_method && r_native_class) {
58836102 *r_native_class = native_method->get_instance_class ();
58846103 }
5885- #endif // DEBUG_ENABLED
6104+ #endif
6105+ #ifdef TOOLS_ENABLED
6106+ DocTools *dd = EditorHelp::get_doc_data ();
6107+ if (dd) {
6108+ const Vector<DocData::MethodDoc> &method_list = dd->class_list [base_native].methods ;
6109+ for (int i = 0 ; i < method_list.size (); i++) {
6110+ if (method_list[i].name == function_name && method_list[i].is_deprecated ) {
6111+ parser->push_warning (p_source, GDScriptWarning::DEPRECATED_IDENTIFIER, " function" , function_name);
6112+ break ;
6113+ }
6114+ }
6115+ }
6116+
6117+ #endif
58866118 return valid;
58876119 }
58886120
0 commit comments