summaryrefslogtreecommitdiffstats
path: root/src/tools
diff options
context:
space:
mode:
authorAlexey Edelev <alexey.edelev@qt.io>2023-07-06 12:01:25 +0200
committerAlexey Edelev <alexey.edelev@qt.io>2023-07-12 21:58:26 +0200
commit4bc0a08bea3c262ebda26163f9271c946c430ff0 (patch)
treee26112d8bd903d4d26c8b39ba1edb80702cc9c68 /src/tools
parentb9b5ed3aa607f644cf32b5798ac742442de9fe3e (diff)
Add the 'version' argument to 'qt_deprecates' pragma
syncqt uses qt_deprecates pragma to generate deprecated header files that might live forever in Qt packages. This adds the version argument to the pragma, that allows specifying the version when the respective header file should be removed. The new pragma format is the following: pragma qt_deprecates(<header>[,<major.minor>]) If deprecation version of the deprecated header file is lower than the current Qt version, syncqt will display the respective warning in the log and skip generating the deprectated header file. Also the user warning message now displays the exact version when the header file will be removed. Task-number: QTBUG-115029 Pick-to: 6.6 Change-Id: Ifd7464b8539b8be93b95690fd1ca70ef0b14e436 Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io> Reviewed-by: Edward Welbourne <edward.welbourne@qt.io> Reviewed-by: Joerg Bornemann <joerg.bornemann@qt.io>
Diffstat (limited to 'src/tools')
-rw-r--r--src/tools/syncqt/main.cpp84
1 files changed, 73 insertions, 11 deletions
diff --git a/src/tools/syncqt/main.cpp b/src/tools/syncqt/main.cpp
index 055f1f4f30..9f4cad6718 100644
--- a/src/tools/syncqt/main.cpp
+++ b/src/tools/syncqt/main.cpp
@@ -28,6 +28,7 @@
#include <regex>
#include <map>
#include <set>
+#include <stdexcept>
#include <array>
enum ErrorCodes {
@@ -90,6 +91,33 @@ std::string asciiToUpper(std::string s)
return s;
}
+bool parseVersion(const std::string &version, int &major, int &minor)
+{
+ const size_t separatorPos = version.find('.');
+ if (separatorPos == std::string::npos || separatorPos == (version.size() - 1)
+ || separatorPos == 0)
+ return false;
+
+ try {
+ size_t pos = 0;
+ major = std::stoi(version.substr(0, separatorPos), &pos);
+ if (pos != separatorPos)
+ return false;
+
+ const size_t nextPart = separatorPos + 1;
+ pos = 0;
+ minor = std::stoi(version.substr(nextPart), &pos);
+ if (pos != (version.size() - nextPart))
+ return false;
+ } catch (const std::invalid_argument &) {
+ return false;
+ } catch (const std::out_of_range &) {
+ return false;
+ }
+
+ return true;
+}
+
class DummyOutputStream : public std::ostream
{
struct : public std::streambuf
@@ -1015,10 +1043,13 @@ public:
// - 'qt_class(<symbol>)' manually declares the 'symbol' that should be used to generate
// the CaMeL case header alias.
//
- // - 'qt_deprecates(<deprecated header file>)' indicates that this header file replaces
- // the 'deprecated header file'. syncqt will create the deprecated header file' with
- // the special deprecation content. See the 'generateDeprecatedHeaders' function
- // for details.
+ // - 'qt_deprecates(<deprecated header file>[,<major.minor>])' indicates that this header
+ // file replaces the 'deprecated header file'. syncqt will create the deprecated header
+ // file' with the special deprecation content. Pragma optionally accepts the Qt version
+ // where file should be removed. If the current Qt version is higher than the
+ // deprecation version, syncqt displays deprecation warning and skips generating the
+ // deprecated header.
+ // See the 'generateDeprecatedHeaders' function for details.
//
// - 'qt_no_master_include' indicates that syncqt should avoid including this header
// files into the module master header file.
@@ -1449,13 +1480,44 @@ public:
{
static std::regex cIdentifierSymbolsRegex("[^a-zA-Z0-9_]");
static std::string guard_base = "DEPRECATED_HEADER_" + m_commandLineArgs->moduleName();
+ bool result = true;
for (auto it = m_deprecatedHeaders.begin(); it != m_deprecatedHeaders.end(); ++it) {
- std::string &replacement = it->second;
+ const std::string &descriptor = it->first;
+ const std::string &replacement = it->second;
+
+ const auto separatorPos = descriptor.find(',');
+ std::string headerName = descriptor.substr(0, separatorPos);
+ std::string versionDisclaimer;
+ if (separatorPos != std::string::npos) {
+ std::string version = descriptor.substr(separatorPos + 1);
+ versionDisclaimer = " and will be removed in Qt " + version;
+ int minor = 0;
+ int major = 0;
+ if (!utils::parseVersion(version, minor, major)) {
+ std::cerr << ErrorMessagePreamble
+ << "Invalid version format specified for the deprecated header file "
+ << headerName << ": '" << version
+ << "'. Expected format: 'major.minor'.\n";
+ result = false;
+ continue;
+ }
+
+ if (QT_VERSION_MAJOR > major
+ || (QT_VERSION_MAJOR == major && QT_VERSION_MINOR >= minor)) {
+ std::cerr << WarningMessagePreamble << headerName
+ << " is marked as deprecated and will not be generated in Qt "
+ << QT_VERSION_STR
+ << ". The respective qt_deprecates pragma needs to be removed.\n";
+ continue;
+ }
+ }
+
std::string qualifiedHeaderName =
- std::regex_replace(it->first, cIdentifierSymbolsRegex, "_");
+ std::regex_replace(headerName, cIdentifierSymbolsRegex, "_");
std::string guard = guard_base + "_" + qualifiedHeaderName;
- std::string warningText = "Header <" + m_commandLineArgs->moduleName() + "/" + it->first
- + "> is deprecated. Please include <" + replacement + "> instead.";
+ std::string warningText = "Header <" + m_commandLineArgs->moduleName() + "/"
+ + headerName + "> is deprecated" + versionDisclaimer + ". Please include <"
+ + replacement + "> instead.";
std::stringstream buffer;
buffer << "#ifndef " << guard << "\n"
<< "#define " << guard << "\n"
@@ -1466,10 +1528,10 @@ public:
<< "#endif\n"
<< "#include <" << replacement << ">\n"
<< "#endif\n";
- writeIfDifferent(m_commandLineArgs->includeDir() + '/' + it->first, buffer.str());
- m_producedHeaders.insert(it->first);
+ writeIfDifferent(m_commandLineArgs->includeDir() + '/' + headerName, buffer.str());
+ m_producedHeaders.insert(headerName);
}
- return true;
+ return result;
}
[[nodiscard]] bool generateHeaderCheckExceptions()