From 98128d9fa3b09dabe7c8de706b41c59a98a119f5 Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Wed, 28 Aug 2019 13:04:13 +0300 Subject: [PATCH] - added ability to specify deprecation messages in ZScript It's an optional extension of deprecated keyword: deprecated("2.4", "use ModernFunction instead") int OldFunction(); deprecated("3.5", "use ModernVariable instead") int OldVariable; Usage of such members will produce the following report: Script warning, ":zscript.txt" line 123: Accessing deprecated function OldFunction - deprecated since 2.4.0, use ModernFunction instead Script warning, ":zscript.txt" line 456: Accessing deprecated member variable OldVariable - deprecated since 3.5.0, use ModernVariable instead --- src/scripting/backend/codegen.cpp | 14 ++++++++---- src/scripting/symbols.h | 2 ++ src/scripting/zscript/zcc-parse.lemon | 14 ++++++++++-- src/scripting/zscript/zcc_compile.cpp | 31 +++++++++++++++++++-------- src/scripting/zscript/zcc_parser.h | 3 +++ 5 files changed, 49 insertions(+), 15 deletions(-) diff --git a/src/scripting/backend/codegen.cpp b/src/scripting/backend/codegen.cpp index e88af4b35c..974be598ae 100644 --- a/src/scripting/backend/codegen.cpp +++ b/src/scripting/backend/codegen.cpp @@ -6134,10 +6134,12 @@ FxExpression *FxIdentifier::Resolve(FCompileContext& ctx) // The main motivation here is to keep the deprecated static functions accessing the global level variable as they were. // Print these only if debug output is active and at the highest verbosity level. const bool internal = (ctx.Function->Variants[0].Flags & VARF_Deprecated) && Wads.GetLumpFile(ctx.Lump) == 0; + const FString &deprecationMessage = vsym->DeprecationMessage; ScriptPosition.Message(internal ? MSG_DEBUGMSG : MSG_WARNING, - "%sAccessing deprecated global variable %s - deprecated since %d.%d.%d", internal ? TEXTCOLOR_BLUE : "", - sym->SymbolName.GetChars(), vsym->mVersion.major, vsym->mVersion.minor, vsym->mVersion.revision); + "%sAccessing deprecated global variable %s - deprecated since %d.%d.%d%s%s", internal ? TEXTCOLOR_BLUE : "", + sym->SymbolName.GetChars(), vsym->mVersion.major, vsym->mVersion.minor, vsym->mVersion.revision, + deprecationMessage.IsEmpty() ? "" : ", ", deprecationMessage.GetChars()); } } @@ -6233,7 +6235,9 @@ FxExpression *FxIdentifier::ResolveMember(FCompileContext &ctx, PContainerType * { if (sym->mVersion <= ctx.Version) { - ScriptPosition.Message(MSG_WARNING, "Accessing deprecated member variable %s - deprecated since %d.%d.%d", sym->SymbolName.GetChars(), vsym->mVersion.major, vsym->mVersion.minor, vsym->mVersion.revision); + const FString &deprecationMessage = vsym->DeprecationMessage; + ScriptPosition.Message(MSG_WARNING, "Accessing deprecated member variable %s - deprecated since %d.%d.%d%s%s", sym->SymbolName.GetChars(), vsym->mVersion.major, vsym->mVersion.minor, vsym->mVersion.revision, + deprecationMessage.IsEmpty() ? "" : ", ", deprecationMessage.GetChars()); } } @@ -8773,7 +8777,9 @@ bool FxVMFunctionCall::CheckAccessibility(const VersionInfo &ver) { if (Function->mVersion <= ver) { - ScriptPosition.Message(MSG_WARNING, "Accessing deprecated function %s - deprecated since %d.%d.%d", Function->SymbolName.GetChars(), Function->mVersion.major, Function->mVersion.minor, Function->mVersion.revision); + const FString &deprecationMessage = Function->Variants[0].DeprecationMessage; + ScriptPosition.Message(MSG_WARNING, "Accessing deprecated function %s - deprecated since %d.%d.%d%s%s", Function->SymbolName.GetChars(), Function->mVersion.major, Function->mVersion.minor, Function->mVersion.revision, + deprecationMessage.IsEmpty() ? "" : ", ", deprecationMessage.GetChars()); } } return true; diff --git a/src/scripting/symbols.h b/src/scripting/symbols.h index d211aaabad..bba2ac8d10 100644 --- a/src/scripting/symbols.h +++ b/src/scripting/symbols.h @@ -76,6 +76,7 @@ public: PType *Type; uint32_t Flags; int BitValue; + FString DeprecationMessage; protected: PField(); }; @@ -170,6 +171,7 @@ public: uint32_t Flags; int UseFlags; PContainerType *SelfClass; + FString DeprecationMessage; }; TArray Variants; PContainerType *OwningClass = nullptr; diff --git a/src/scripting/zscript/zcc-parse.lemon b/src/scripting/zscript/zcc-parse.lemon index 83da141005..67506975f9 100644 --- a/src/scripting/zscript/zcc-parse.lemon +++ b/src/scripting/zscript/zcc-parse.lemon @@ -949,6 +949,7 @@ declarator(X) ::= decl_flags(A) type_list_or_void(B) variables_or_function(C). decl->Name = C.FuncName; decl->UseFlags = A == nullptr? nullptr : A->Id; decl->Flags = (A == nullptr? 0 : A->Flags) | C.FuncFlags; + decl->DeprecationMessage = A == nullptr ? nullptr : A->DeprecationMessage; if (A == nullptr) decl->Version = {0,0,0}; else decl->Version = A->Version; @@ -964,11 +965,13 @@ declarator(X) ::= decl_flags(A) type_list_or_void(B) variables_or_function(C). { decl->Flags = 0; decl->Version = {0,0,0}; + decl->DeprecationMessage = nullptr; } else { decl->Flags = A->Flags; decl->Version = A->Version; + decl->DeprecationMessage = A->DeprecationMessage; } X = decl; } @@ -1061,6 +1064,7 @@ decl_flags(X) ::= decl_flags(F) decl_flag(A). X->Id = nullptr; X->Flags = A.Int; X->Version = { 0, 0 }; + X->DeprecationMessage = nullptr; } else { @@ -1079,6 +1083,7 @@ decl_flags(X) ::= decl_flags(F) ACTION(B) states_opts(A). X->Flags = ZCC_Action; X->Id = nullptr; X->Version = { 0, 0 }; + X->DeprecationMessage = nullptr; } else { @@ -1088,8 +1093,11 @@ decl_flags(X) ::= decl_flags(F) ACTION(B) states_opts(A). X->Id = A; } -decl_flags(X) ::= decl_flags(F) DEPRECATED(B) LPAREN STRCONST(A) RPAREN. -{ +opt_deprecation_message(X) ::= . { X.String = nullptr; X.SourceLoc = stat->sc->GetMessageLine(); } +opt_deprecation_message(X) ::= COMMA STRCONST(C). { X = C; } + +decl_flags(X) ::= decl_flags(F) DEPRECATED(B) LPAREN STRCONST(A) opt_deprecation_message(C) RPAREN. +{ if (F == nullptr) { NEW_AST_NODE(DeclFlags,nil_f,B.SourceLoc); @@ -1104,6 +1112,7 @@ decl_flags(X) ::= decl_flags(F) DEPRECATED(B) LPAREN STRCONST(A) RPAREN. X->Flags |= ZCC_Deprecated; } X->Version = A.String->GetChars(); + X->DeprecationMessage = C.String; } decl_flags(X) ::= decl_flags(F) VERSION(B) LPAREN STRCONST(A) RPAREN. @@ -1115,6 +1124,7 @@ decl_flags(X) ::= decl_flags(F) VERSION(B) LPAREN STRCONST(A) RPAREN. X->Flags = ZCC_Version; X->Id = nullptr; X->Version = { 0, 0 }; + X->DeprecationMessage = nullptr; } else { diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 7bb2fbc717..fa39d862be 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -1320,6 +1320,8 @@ bool ZCCCompiler::CompileFields(PContainerType *type, TArrayBitValue != 0) thisfieldtype = fd->FieldSize == 1 ? TypeUInt8 : fd->FieldSize == 2 ? TypeUInt16 : TypeUInt32; - auto f = type->AddNativeField(name->Name, thisfieldtype, fd->FieldOffset, varflags, fd->BitValue); - if (field->Flags & (ZCC_Version | ZCC_Deprecated)) f->mVersion = field->Version; + f = type->AddNativeField(name->Name, thisfieldtype, fd->FieldOffset, varflags, fd->BitValue); } else { // This is a global variable. if (fd->BitValue != 0) thisfieldtype = fd->FieldSize == 1 ? TypeUInt8 : fd->FieldSize == 2 ? TypeUInt16 : TypeUInt32; - PField *f = Create(name->Name, thisfieldtype, varflags | VARF_Native | VARF_Static, fd->FieldOffset, fd->BitValue); - if (field->Flags & (ZCC_Version | ZCC_Deprecated)) - { - f->mVersion = field->Version; - } + f = Create(name->Name, thisfieldtype, varflags | VARF_Native | VARF_Static, fd->FieldOffset, fd->BitValue); if (OutNamespace->Symbols.AddSymbol(f) == nullptr) { // name is already in use @@ -1372,13 +1369,24 @@ bool ZCCCompiler::CompileFields(PContainerType *type, TArrayAddField(name->Name, thisfieldtype, varflags); - if (field->Flags & (ZCC_Version | ZCC_Deprecated)) f->mVersion = field->Version; + f = type->AddField(name->Name, thisfieldtype, varflags); } else { Error(field, "Cannot declare non-native global variables. Tried to declare %s", FName(name->Name).GetChars()); } + + assert(f != nullptr); + + if (field->Flags & (ZCC_Version | ZCC_Deprecated)) + { + f->mVersion = field->Version; + + if (field->DeprecationMessage != nullptr) + { + f->DeprecationMessage = *field->DeprecationMessage; + } + } } name = static_cast(name->SiblingNext); } while (name != field->Names); @@ -2752,6 +2760,11 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool sym->AddVariant(NewPrototype(rets, args), argflags, argnames, afd == nullptr ? nullptr : *(afd->VMPointer), varflags, useflags); c->Type()->Symbols.ReplaceSymbol(sym); + if (f->DeprecationMessage != nullptr) + { + sym->Variants[0].DeprecationMessage = *f->DeprecationMessage; + } + auto vcls = PType::toClass(c->Type()); auto cls = vcls ? vcls->Descriptor : nullptr; PFunction *virtsym = nullptr; diff --git a/src/scripting/zscript/zcc_parser.h b/src/scripting/zscript/zcc_parser.h index 272d7e1413..f09ead5666 100644 --- a/src/scripting/zscript/zcc_parser.h +++ b/src/scripting/zscript/zcc_parser.h @@ -515,6 +515,7 @@ struct ZCC_FuncParamDecl : ZCC_TreeNode struct ZCC_DeclFlags : ZCC_TreeNode { ZCC_Identifier *Id; + FString *DeprecationMessage; VersionInfo Version; int Flags; }; @@ -537,6 +538,7 @@ struct ZCC_Declarator : ZCC_TreeNode struct ZCC_VarDeclarator : ZCC_Declarator { ZCC_VarName *Names; + FString *DeprecationMessage; }; // A function in a class. @@ -546,6 +548,7 @@ struct ZCC_FuncDeclarator : ZCC_Declarator ENamedName Name; ZCC_Statement *Body; ZCC_Identifier *UseFlags; + FString *DeprecationMessage; }; struct ZCC_Default : ZCC_CompoundStmt