I have a huge library and couple classes planned to be decommissioned.
E.g.:
class [[deprecated]] OldApi {
// details
};
The idea is that everything what uses this class is deprecated. E.g.: a hidden dependency looks like this in header:
// on API we have no old API dependency
void hiddenDependency();
and in compiling unit:
void hiddenDependency()
{
OldApi inst;
// work on it/do something
}
I have really deep dependency graph so manual solution would be a pain. Is there any way/tool to inherit these deprecate attributes?
So after using this tool, the hidden dependencies also would be deprecated:
[[deprecated]]
void hiddenDependency();
Many thanks for help!
I have really deep dependency graph so manual solution would be a pain. Is there any way/tool to inherit these deprecate attributes?
Yes, you can write a tool using a compiler like Clang as a library.
Roughly, you would walk the tree that Clang gives you to find function/method bodies. In each of them, check if there are any references to OldApi
or its members. If so, add the attribute to the function/method and output the resulting tree.
If you need to deprecate users of those functions too, you can apply it recursively as needed.
Conceptually easy, but if you have never written a tool like that, it may take a while. Even with experience, you usually need to have a lot of code to modify to this approach worth the time investment.
Having said that, as others have pointed out, the question is odd. When you deprecate something, you typically need to replace that thing in the callers/users, rather than deprecate all the users.
Strictly speaking, hiddenDependency
is not deprecated, and [[deprecated]]
in OldApi
warns hiddenDependency
that OldApi
is deprecated and it should be updated/replaced, but the body of hiddenDependency
is still valid, unless the code has not been designed properly (and same declaration but different definition in OldApi
affects hiddenDependency
). Nonetheless, if there is some kind of relation between OldApi
and hiddenDependency
, they may or might be scoped in a namespace
(or should have been), so the solution is to deprecate the namespace
instead of the class and trying to "inherit" [[deprecated]]
:
namespace [[deprecated("Use NewFunctionality instead")]] OldFunctionality {
class OldApi {
public:
OldApi(){
}
};
void foo() {
OldApi bar;
}
}
Assuming that you are able to deprecate the caller, what's the limit? Should only be the caller of the deprecated method considered as deprecated? Should be the caller of the caller considered as deprecated as well? How many levels of deprecation are expected? Because the compiler warns that hiddenDependency
is calling a deprecated method, it points out the reason and the affected line in hiddenDependency
. What's the criteria to not move up the warning until the main
? Going further, is the criteria to deprecate all the functions which call OldApi
? (if so, you already have a group, hence you can encapsulate it i.e. namespace) Or is the criteria all the functions which call OldApi
and some extra requirements? (if so, there is not a clear procedure and it has to be done manually).
Even if parsing the whole text looking for the pattern "hiddenDependency
calls OldApi
" is an option (and probably the most valid one considering your example), it doesn't look like a clean and easy to maintain (or even justify/document) solution.
Assuming this is a good idea, my approach would be to temporarily delete or rename OldApi
and attempt to compile. Your IDE or existing language tooling should be able to emit information about every compiler error, whether it be definitions that reference OldApi
, or functions/class declarations that leverage it. Mark every single one as [[deprecated]]
. Then, restore OldApi
with the [[deprecated]]
flag as well.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With