forked from qt-creator/qt-creator
Merge remote-tracking branch 'origin/10.0'
Conflicts: src/plugins/debugger/watchhandler.cpp Change-Id: If759b6260dfa008738d3a0ce543eb0eead8a8bba
This commit is contained in:
2
.github/workflows/build_cmake.yml
vendored
2
.github/workflows/build_cmake.yml
vendored
@@ -9,7 +9,7 @@ on:
|
||||
env:
|
||||
QT_VERSION: 6.4.2
|
||||
MACOS_DEPLOYMENT_TARGET: 10.14
|
||||
CLANG_VERSION: 15.0.0
|
||||
CLANG_VERSION: 16.0.0-rc2
|
||||
ELFUTILS_VERSION: 0.175
|
||||
CMAKE_VERSION: 3.21.1
|
||||
NINJA_VERSION: 1.10.2
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
function(create_python_xy PythonExe PythonZipFilePath)
|
||||
get_filename_component(python_lib_dir "${PythonExe}" DIRECTORY)
|
||||
get_filename_component(python_lib_dir "${python_lib_dir}/Lib" ABSOLUTE)
|
||||
foreach(dir collections encodings importlib json urllib)
|
||||
foreach(dir collections encodings importlib json urllib re)
|
||||
file(COPY ${python_lib_dir}/${dir}
|
||||
DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/python-lib
|
||||
FILES_MATCHING PATTERN "*.py"
|
||||
|
||||
@@ -124,7 +124,7 @@ else()
|
||||
set(yaml-cpp_FOUND 1)
|
||||
set_package_properties(yaml-cpp PROPERTIES DESCRIPTION "using internal src/libs/3rdparty/yaml-cpp")
|
||||
if(MSVC)
|
||||
target_compile_options(yaml-cpp PUBLIC /wd4251 /wd4275)
|
||||
target_compile_options(yaml-cpp PUBLIC /wd4251 /wd4275 /EHsc)
|
||||
endif()
|
||||
endif()
|
||||
unset(YAML_SOURCE_DIR)
|
||||
|
||||
@@ -7,7 +7,7 @@ instructions:
|
||||
variableValue: "RelWithDebInfo"
|
||||
- type: EnvironmentVariable
|
||||
variableName: LLVM_BASE_URL
|
||||
variableValue: http://master.qt.io/development_releases/prebuilt/libclang/libclang-release_15.0.0-based
|
||||
variableValue: http://master.qt.io/development_releases/prebuilt/libclang/libclang-release_16.0.0-rc2-based
|
||||
- type: EnvironmentVariable
|
||||
variableName: QTC_QT_BASE_URL
|
||||
variableValue: "http://ci-files02-hki.intra.qt.io/packages/jenkins/archive/qt/6.4/6.4.2-released/Qt"
|
||||
|
||||
BIN
doc/qtcreator/images/qtcreator-python-interpreter-edit-mode.webp
Normal file
BIN
doc/qtcreator/images/qtcreator-python-interpreter-edit-mode.webp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.7 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 5.8 KiB |
BIN
doc/qtcreator/images/qtcreator-qml-js-editing.webp
Normal file
BIN
doc/qtcreator/images/qtcreator-qml-js-editing.webp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.8 KiB |
@@ -729,8 +729,16 @@
|
||||
To automatically format QML/JS files upon saving, select \uicontrol Edit >
|
||||
\uicontrol Preferences > \uicontrol {Qt Quick} > \uicontrol {QML/JS Editing} >
|
||||
\uicontrol {Enable auto format on file save}.
|
||||
To only format files that belong to the current project, select
|
||||
\uicontrol {Restrict to files contained in the current project}.
|
||||
|
||||
\image qtcreator-qml-js-editing.png "QML/JS Editing preferences"
|
||||
To use an external tool, such as \l {qmlformat}, which automatically
|
||||
formats QML files according to QML coding conventions, select
|
||||
\uicontrol {Use custom command instead of built-in formatter}. In
|
||||
the \uicontrol Command field, enter the path to the tool. In the
|
||||
\uicontrol Arguments field, enter options for running the tool.
|
||||
|
||||
\image qtcreator-qml-js-editing.webp {QML/JS Editing preferences}
|
||||
|
||||
\if defined(qtcreator)
|
||||
\section1 Inspecting Preprocessed C++ Code
|
||||
|
||||
@@ -149,14 +149,14 @@
|
||||
|
||||
\section2 QML Language Server
|
||||
|
||||
Qt 6.4 ships with the \c qmlls language server that offers completion and
|
||||
issues warnings for QML. To set it up as a \l {Generic StdIO Language Server},
|
||||
select \c {text/x-qml} and \c {application/x-qt.ui+qml} as MIME types, and
|
||||
\c {<Qt Installation>/bin/qmlls} as executable.
|
||||
Since Qt 6.4, the \c qmlls language server offers code completion and
|
||||
issues warnings for QML. To enable QML language server support, select
|
||||
\uicontrol Edit > \uicontrol Preferences > \uicontrol {Qt Quick} >
|
||||
\uicontrol {QML/JS Editing} > \uicontrol {Use qmlls (EXPERIMENTAL!)}.
|
||||
To use the latest version of the language server installed on your
|
||||
system, select the \uicontrol {Always use latest qmlls} check box.
|
||||
|
||||
If the language server is used together with the \c QmlJSEditor plugin,
|
||||
duplicate suggestions and warnings might be shown. To avoid this, disable
|
||||
the editor plugin as described in \l {Enabling and Disabling Plugins}.
|
||||
\image qtcreator-qml-js-editing.webp {QML/JS Editing preferences}
|
||||
|
||||
\section1 Supported Locator Filters
|
||||
|
||||
|
||||
@@ -17,10 +17,17 @@
|
||||
such as code completion and annotations. Select \uicontrol Install to install
|
||||
PySide6 and the language server.
|
||||
|
||||
To view and manage the available Python interpreters, select \uicontrol Edit
|
||||
> \uicontrol Preferences > \uicontrol Python > \uicontrol Interpreters.
|
||||
You can see the current Python interpreter on the \uicontrol Edit mode
|
||||
toolbar.
|
||||
|
||||
\image qtcreator-python-interpreters.png "Python Interpreters in Preferences"
|
||||
\image qtcreator-python-interpreter-edit-mode.webp {Python interpreter on the Edit mode toolbar}
|
||||
|
||||
To see the available interpreters and change their paths, select
|
||||
the interpreter, and then select \uicontrol {Manage Python Interpreters}.
|
||||
Or, select \uicontrol Edit > \uicontrol Preferences > \uicontrol Python >
|
||||
\uicontrol Interpreters.
|
||||
|
||||
\image qtcreator-python-interpreters.png {Python Interpreters in Preferences}
|
||||
|
||||
You can add and remove interpreters and clean up references to interpreters
|
||||
that you uninstalled, but that still appear in the list. In addition, you
|
||||
@@ -42,7 +49,7 @@
|
||||
the PySide version, class name, base class, and source file for the
|
||||
class.
|
||||
|
||||
\image qtcreator-python-wizard-app-window.png "Qt for Python wizard for creating a widget-based UI"
|
||||
\image qtcreator-python-wizard-app-window.png {Qt for Python wizard for creating a widget-based UI}
|
||||
|
||||
The wizard adds the imports to the source file for
|
||||
access to the QApplication, the base class you selected in the Qt
|
||||
@@ -150,7 +157,7 @@
|
||||
you to create a Python project that has a main QML file. Specify the
|
||||
minimum PySide version to run the application.
|
||||
|
||||
\image qtcreator-python-wizard-qml.png "Qt for Python wizard for creating an empty Qt Quick application"
|
||||
\image qtcreator-python-wizard-qml.png {Qt for Python wizard for creating an empty Qt Quick application}
|
||||
|
||||
The wizard adds the following imports to the source file for access
|
||||
to QGuiApplication and QQmlApplicationEngine:
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
\uicontrol Edit > \uicontrol Preferences > \uicontrol {Qt Quick} >
|
||||
\uicontrol {QML/JS Editing} > \uicontrol {Always show Qt Quick Toolbar}.
|
||||
|
||||
\image qtcreator-qml-js-editing.png "QML/JS Editing preferences"
|
||||
\image qtcreator-qml-js-editing.webp {QML/JS Editing preferences}
|
||||
|
||||
Drag the toolbar to pin it to another location. Select
|
||||
\inlineimage icons/pin.png
|
||||
|
||||
@@ -741,43 +741,28 @@
|
||||
|
||||
\section3 Lambdas
|
||||
|
||||
When using lambdas, note the following:
|
||||
|
||||
\list
|
||||
\li You do not have to explicitly specify the return type. If you are not using one
|
||||
of the previously mentioned compilers, do note that this is a C++14 feature and you
|
||||
might need to enable C++14 support in your compiler.
|
||||
\code
|
||||
[]() {
|
||||
Foo *foo = activeFoo();
|
||||
return foo ? foo->displayName() : QString();
|
||||
});
|
||||
\endcode
|
||||
|
||||
\li If you use static functions from the class that the lambda is located in, you have to
|
||||
explicitly capture \c this. Otherwise it does not compile with g++ 4.7 and earlier.
|
||||
\code
|
||||
void Foo::something()
|
||||
{
|
||||
...
|
||||
[this]() { Foo::someStaticFunction(); }
|
||||
...
|
||||
}
|
||||
|
||||
-NOT-
|
||||
|
||||
void Foo::something()
|
||||
{
|
||||
...
|
||||
[]() { Foo::someStaticFunction(); }
|
||||
...
|
||||
}
|
||||
\endcode
|
||||
\endlist
|
||||
|
||||
Format the lambda according to the following rules:
|
||||
|
||||
\list
|
||||
\li When the lambda neither takes arguments nor specifies a return type,
|
||||
drop round brackets.
|
||||
\code
|
||||
[] { ... lambda body ... }
|
||||
|
||||
-NOT-
|
||||
|
||||
[]() { ... lambda body ... }
|
||||
\endcode
|
||||
|
||||
\li Glue square brackets with round brackets when defining a lambda.
|
||||
\code
|
||||
[](int a) { ... lambda body ... }
|
||||
|
||||
-NOT-
|
||||
|
||||
[] (int a) { ... lambda body ... }
|
||||
\endcode
|
||||
|
||||
\li Place the capture-list, parameter list, return type, and opening brace on the first line,
|
||||
the body indented on the following lines, and the closing brace on a new line.
|
||||
\code
|
||||
@@ -795,7 +780,7 @@
|
||||
\li Place a closing parenthesis and semicolon of an enclosing function call on the same line
|
||||
as the closing brace of the lambda.
|
||||
\code
|
||||
foo([]() {
|
||||
foo([] {
|
||||
something();
|
||||
});
|
||||
\endcode
|
||||
@@ -866,7 +851,7 @@
|
||||
Use initializer lists to initialize containers, for example:
|
||||
|
||||
\code
|
||||
const QVector<int> values = {1, 2, 3, 4, 5};
|
||||
const QList<int> values = {1, 2, 3, 4, 5};
|
||||
\endcode
|
||||
|
||||
\section3 Initialization with Curly Brackets
|
||||
@@ -878,7 +863,7 @@
|
||||
class Values // the following code is quite useful for test fixtures
|
||||
{
|
||||
float floatValue = 4; // prefer that for simple types
|
||||
QVector<int> values = {1, 2, 3, 4, integerValue}; // prefer that syntax for initializer lists
|
||||
QList<int> values = {1, 2, 3, 4, integerValue}; // prefer that syntax for initializer lists
|
||||
SomeValues someValues{"One", 2, 3.4}; // not an initializer_list
|
||||
SomeValues &someValuesReference = someValues;
|
||||
ComplexType complexType{values, otherValues} // constructor call
|
||||
@@ -914,6 +899,29 @@
|
||||
container is const or unshared, use \c{std::cref()} to ensure that the container
|
||||
is not unnecessarily detached.
|
||||
|
||||
\section3 std::optional
|
||||
|
||||
Avoid the throwing function \c{value()}. Check the availability of the value first, and then use
|
||||
the non-throwing functions for accessing values, like \c{operator*} and \c{operator->}.
|
||||
In very simple cases, you can also use \c{value_or()}.
|
||||
|
||||
\code
|
||||
|
||||
if (optionalThing) {
|
||||
val = optionalThing->member;
|
||||
other = doSomething(*optionalThing);
|
||||
}
|
||||
|
||||
-NOT-
|
||||
|
||||
if (optionalThing) {
|
||||
val = optionalThing.value().member;
|
||||
other = doSomething(optionalThing.value());
|
||||
}
|
||||
|
||||
\endcode
|
||||
|
||||
|
||||
\section2 Using QObject
|
||||
|
||||
\list
|
||||
|
||||
2
src/libs/3rdparty/span/span.hpp
vendored
2
src/libs/3rdparty/span/span.hpp
vendored
@@ -27,6 +27,8 @@ http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/n4820.pdf
|
||||
#ifndef TCB_SPAN_NO_EXCEPTIONS
|
||||
#include <cstdio>
|
||||
#include <stdexcept>
|
||||
#else
|
||||
#include <exception> // for std::terminate
|
||||
#endif
|
||||
|
||||
// Various feature test macros
|
||||
|
||||
@@ -54,6 +54,7 @@ qtc_library_enabled(_library_enabled qtcreatorcdbext)
|
||||
if (_library_enabled)
|
||||
# statically link MSVC runtime
|
||||
set_property(TARGET qtcreatorcdbext PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
|
||||
target_compile_options(qtcreatorcdbext PUBLIC /EHsc)
|
||||
|
||||
find_package(Python3 3.8 COMPONENTS Development)
|
||||
|
||||
|
||||
@@ -152,45 +152,43 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void considerItems(int column, QModelIndex start, int *minimum, bool single) const
|
||||
int suggestedColumnSize(int column) const
|
||||
{
|
||||
const QHeaderView *h = q->header();
|
||||
QTC_ASSERT(h, return -1);
|
||||
const QAbstractItemModel *m = q->model();
|
||||
QTC_ASSERT(m, return -1);
|
||||
|
||||
const QFontMetrics fm = q->fontMetrics();
|
||||
const int ind = q->indentation();
|
||||
const int avg = fm.averageCharWidth();
|
||||
int minimum = fm.horizontalAdvance(m->headerData(column, Qt::Horizontal).toString())
|
||||
+ 2 * avg;
|
||||
|
||||
auto considerItems = [&](const QModelIndex &start, bool single) {
|
||||
QModelIndex a = start;
|
||||
a = a.sibling(a.row(), column);
|
||||
QFontMetrics fm = q->fontMetrics();
|
||||
const int ind = q->indentation();
|
||||
QAbstractItemModel *m = q->model();
|
||||
for (int i = 0; i < 100 && a.isValid(); ++i) {
|
||||
const QString s = m->data(a).toString();
|
||||
int w = fm.horizontalAdvance(s) + 10;
|
||||
int w = avg * s.size() + 20;
|
||||
if (column == 0) {
|
||||
for (QModelIndex b = a.parent(); b.isValid(); b = b.parent())
|
||||
w += ind;
|
||||
}
|
||||
if (w > *minimum)
|
||||
*minimum = w;
|
||||
if (w > minimum)
|
||||
minimum = w;
|
||||
if (single)
|
||||
break;
|
||||
a = q->indexBelow(a);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
int suggestedColumnSize(int column) const
|
||||
{
|
||||
QHeaderView *h = q->header();
|
||||
QTC_ASSERT(h, return -1);
|
||||
QAbstractItemModel *m = q->model();
|
||||
QTC_ASSERT(m, return -1);
|
||||
|
||||
QFontMetrics fm = q->fontMetrics();
|
||||
int minimum = fm.horizontalAdvance(m->headerData(column, Qt::Horizontal).toString())
|
||||
+ 2 * fm.horizontalAdvance(QLatin1Char('m'));
|
||||
considerItems(column, q->indexAt(QPoint(1, 1)), &minimum, false);
|
||||
considerItems(q->indexAt(QPoint(1, 1)), false);
|
||||
|
||||
const QVariant extraIndices = m->data(QModelIndex(), BaseTreeView::ExtraIndicesForColumnWidth);
|
||||
const QList<QModelIndex> values = extraIndices.value<QModelIndexList>();
|
||||
for (const QModelIndex &a : values)
|
||||
considerItems(column, a, &minimum, true);
|
||||
considerItems(a, true);
|
||||
|
||||
return minimum;
|
||||
}
|
||||
|
||||
@@ -87,9 +87,7 @@ RunResult DeviceShell::run(const CommandLine &cmd, const QByteArray &stdInData)
|
||||
qCDebug(deviceShellLog) << "Running fallback:" << fallbackCmd;
|
||||
proc.setCommand(fallbackCmd);
|
||||
proc.setWriteData(stdInData);
|
||||
|
||||
proc.start();
|
||||
proc.waitForFinished();
|
||||
proc.runBlocking();
|
||||
|
||||
return RunResult{
|
||||
proc.exitCode(),
|
||||
|
||||
@@ -1878,7 +1878,7 @@ expected_str<FilePath> FilePath::localSource() const
|
||||
return *this;
|
||||
|
||||
QTC_ASSERT(s_deviceHooks.localSource,
|
||||
return make_unexpected(Tr::tr("No 'localSource' device hook set.")));
|
||||
return make_unexpected(Tr::tr("No \"localSource\" device hook set.")));
|
||||
return s_deviceHooks.localSource(*this);
|
||||
}
|
||||
|
||||
|
||||
@@ -175,6 +175,7 @@ public:
|
||||
~RuntimeData();
|
||||
|
||||
static QList<int> createStorages(const TaskContainer::ConstData &constData);
|
||||
void callStorageDoneHandlers();
|
||||
bool updateSuccessBit(bool success);
|
||||
int currentLimit() const;
|
||||
|
||||
@@ -384,6 +385,15 @@ QList<int> TaskContainer::RuntimeData::createStorages(const TaskContainer::Const
|
||||
return storageIdList;
|
||||
}
|
||||
|
||||
void TaskContainer::RuntimeData::callStorageDoneHandlers()
|
||||
{
|
||||
for (int i = m_constData.m_storageList.size() - 1; i >= 0; --i) { // iterate in reverse order
|
||||
const TreeStorageBase storage = m_constData.m_storageList[i];
|
||||
const int storageId = m_storageIdList.value(i);
|
||||
m_constData.m_taskTreePrivate->callDoneHandler(storage, storageId);
|
||||
}
|
||||
}
|
||||
|
||||
TaskContainer::RuntimeData::RuntimeData(const ConstData &constData)
|
||||
: m_constData(constData)
|
||||
, m_storageIdList(createStorages(constData))
|
||||
@@ -397,7 +407,6 @@ TaskContainer::RuntimeData::~RuntimeData()
|
||||
for (int i = m_constData.m_storageList.size() - 1; i >= 0; --i) { // iterate in reverse order
|
||||
const TreeStorageBase storage = m_constData.m_storageList[i];
|
||||
const int storageId = m_storageIdList.value(i);
|
||||
m_constData.m_taskTreePrivate->callDoneHandler(storage, storageId);
|
||||
storage.deleteStorage(storageId);
|
||||
}
|
||||
}
|
||||
@@ -527,6 +536,7 @@ void TaskContainer::invokeEndHandler()
|
||||
invokeHandler(this, groupHandler.m_doneHandler);
|
||||
else if (!m_runtimeData->m_successBit && groupHandler.m_errorHandler)
|
||||
invokeHandler(this, groupHandler.m_errorHandler);
|
||||
m_runtimeData->callStorageDoneHandlers();
|
||||
m_runtimeData.reset();
|
||||
}
|
||||
|
||||
|
||||
@@ -59,5 +59,6 @@ extend_qtc_plugin(Android
|
||||
CONDITION WITH_TESTS
|
||||
SOURCES
|
||||
androidsdkmanager_test.cpp androidsdkmanager_test.h
|
||||
sdkmanageroutputparser_test.cpp sdkmanageroutputparser_test.h
|
||||
android_tst.qrc
|
||||
)
|
||||
|
||||
@@ -123,6 +123,8 @@ Project {
|
||||
"android_tst.qrc",
|
||||
"androidsdkmanager_test.cpp",
|
||||
"androidsdkmanager_test.h",
|
||||
"sdkmanageroutputparser_test.cpp",
|
||||
"sdkmanageroutputparser_test.h",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -533,15 +533,7 @@ bool AndroidBuildApkStep::init()
|
||||
|
||||
m_openPackageLocationForRun = m_openPackageLocation;
|
||||
const FilePath outputDir = AndroidManager::androidBuildDirectory(target());
|
||||
|
||||
if (m_buildAAB) {
|
||||
const QString bt = buildType() == BuildConfiguration::Release ? QLatin1String("release")
|
||||
: QLatin1String("debug");
|
||||
m_packagePath = outputDir.pathAppended(
|
||||
QString("build/outputs/bundle/%1/android-build-%1.aab").arg(bt));
|
||||
} else {
|
||||
m_packagePath = AndroidManager::apkPath(target());
|
||||
}
|
||||
m_packagePath = AndroidManager::packagePath(target());
|
||||
|
||||
qCDebug(buildapkstepLog).noquote() << "APK or AAB path:" << m_packagePath.toUserOutput();
|
||||
|
||||
|
||||
@@ -251,7 +251,7 @@ bool AndroidDeployQtStep::init()
|
||||
} else {
|
||||
m_uninstallPreviousPackageRun = true;
|
||||
m_command = AndroidConfigurations::currentConfig().adbToolPath();
|
||||
m_apkPath = AndroidManager::apkPath(target());
|
||||
m_apkPath = AndroidManager::packagePath(target());
|
||||
m_workingDirectory = bc ? AndroidManager::buildDirectory(target()): FilePath();
|
||||
}
|
||||
m_environment = bc ? bc->environment() : Utils::Environment();
|
||||
|
||||
@@ -268,7 +268,31 @@ FilePath AndroidManager::buildDirectory(const Target *target)
|
||||
return {};
|
||||
}
|
||||
|
||||
FilePath AndroidManager::apkPath(const Target *target)
|
||||
enum PackageFormat {
|
||||
Apk,
|
||||
Aab
|
||||
};
|
||||
|
||||
QString packageSubPath(PackageFormat format, BuildConfiguration::BuildType buildType, bool sig)
|
||||
{
|
||||
const bool deb = (buildType == BuildConfiguration::Debug);
|
||||
|
||||
if (format == Apk) {
|
||||
if (deb)
|
||||
return sig ? packageSubPath(Apk, BuildConfiguration::Release, true) // Intentional
|
||||
: QLatin1String("apk/debug/android-build-debug.apk");
|
||||
else
|
||||
return QLatin1String(sig ? "apk/release/android-build-release-signed.apk"
|
||||
: "apk/release/android-build-release-unsigned.apk");
|
||||
} else {
|
||||
return QLatin1String(deb ? "bundle/debug/android-build-debug.aab"
|
||||
: "bundle/release/android-build-release.aab");
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
FilePath AndroidManager::packagePath(const Target *target)
|
||||
{
|
||||
QTC_ASSERT(target, return {});
|
||||
|
||||
@@ -279,13 +303,10 @@ FilePath AndroidManager::apkPath(const Target *target)
|
||||
if (!buildApkStep)
|
||||
return {};
|
||||
|
||||
QString apkPath("build/outputs/apk/android-build-");
|
||||
if (buildApkStep->signPackage())
|
||||
apkPath += QLatin1String("release.apk");
|
||||
else
|
||||
apkPath += QLatin1String("debug.apk");
|
||||
const QString subPath = packageSubPath(buildApkStep->buildAAB() ? Aab : Apk,
|
||||
bc->buildType(), buildApkStep->signPackage());
|
||||
|
||||
return androidBuildDirectory(target) / apkPath;
|
||||
return androidBuildDirectory(target) / "build/outputs" / subPath;
|
||||
}
|
||||
|
||||
bool AndroidManager::matchedAbis(const QStringList &deviceAbis, const QStringList &appAbis)
|
||||
|
||||
@@ -78,7 +78,7 @@ public:
|
||||
static Utils::FilePath manifestPath(const ProjectExplorer::Target *target);
|
||||
static void setManifestPath(ProjectExplorer::Target *target, const Utils::FilePath &path);
|
||||
static Utils::FilePath manifestSourcePath(const ProjectExplorer::Target *target);
|
||||
static Utils::FilePath apkPath(const ProjectExplorer::Target *target);
|
||||
static Utils::FilePath packagePath(const ProjectExplorer::Target *target);
|
||||
static bool matchedAbis(const QStringList &deviceAbis, const QStringList &appAbis);
|
||||
static QString devicePreferredAbi(const QStringList &deviceAbis, const QStringList &appAbis);
|
||||
static ProjectExplorer::Abi androidAbi2Abi(const QString &androidAbi);
|
||||
|
||||
@@ -17,11 +17,15 @@
|
||||
#include "androidqtversion.h"
|
||||
#include "androidrunconfiguration.h"
|
||||
#include "androidruncontrol.h"
|
||||
#include "androidsdkmanager_test.h"
|
||||
#include "androidsettingswidget.h"
|
||||
#include "androidtoolchain.h"
|
||||
#include "androidtr.h"
|
||||
|
||||
#ifdef WITH_TESTS
|
||||
# include "androidsdkmanager_test.h"
|
||||
# include "sdkmanageroutputparser_test.h"
|
||||
#endif
|
||||
|
||||
#include "javaeditor.h"
|
||||
#include "javalanguageserver.h"
|
||||
|
||||
@@ -118,6 +122,7 @@ void AndroidPlugin::initialize()
|
||||
|
||||
#ifdef WITH_TESTS
|
||||
addTest<AndroidSdkManagerTest>();
|
||||
addTest<SdkManagerOutputParserTest>();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
// Copyright (C) 2022 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||
|
||||
|
||||
@@ -3,8 +3,9 @@
|
||||
|
||||
#include "sdkmanageroutputparser.h"
|
||||
|
||||
#include "avdmanageroutputparser.h"
|
||||
#include "androidconstants.h"
|
||||
#include "androidsdkpackage.h"
|
||||
#include "avdmanageroutputparser.h"
|
||||
|
||||
#include <utils/algorithm.h>
|
||||
|
||||
@@ -440,8 +441,8 @@ SdkManagerOutputParser::MarkerTag SdkManagerOutputParser::parseMarkers(const QSt
|
||||
if (line.startsWith(QLatin1String(pair.second)))
|
||||
return pair.first;
|
||||
}
|
||||
|
||||
QRegularExpressionMatch match = QRegularExpression("^[a-zA-Z]+[A-Za-z0-9;._-]+").match(line);
|
||||
static const QRegularExpression reg("^[a-zA-Z]+[A-Za-z0-9;._-]+");
|
||||
const QRegularExpressionMatch match = reg.match(line);
|
||||
if (match.hasMatch() && match.captured(0) == line)
|
||||
return GenericToolMarker;
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||
#pragma once
|
||||
|
||||
#include "androidconstants.h"
|
||||
#include "androidsdkpackage.h"
|
||||
|
||||
#include <utils/filepath.h>
|
||||
@@ -74,6 +73,7 @@ private:
|
||||
|
||||
MarkerTag m_currentSection = MarkerTag::None;
|
||||
QHash<AndroidSdkPackage *, int> m_systemImages;
|
||||
friend class SdkManagerOutputParserTest;
|
||||
};
|
||||
} // namespace Internal
|
||||
} // namespace Android
|
||||
|
||||
793
src/plugins/android/sdkmanageroutputparser_test.cpp
Normal file
793
src/plugins/android/sdkmanageroutputparser_test.cpp
Normal file
@@ -0,0 +1,793 @@
|
||||
// Copyright (C) 2022 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||
|
||||
#include "sdkmanageroutputparser_test.h"
|
||||
#include "sdkmanageroutputparser.h"
|
||||
|
||||
#include "androidsdkpackage.h"
|
||||
|
||||
#include <QMap>
|
||||
#include <QString>
|
||||
#include <QTest>
|
||||
#include <QVersionNumber>
|
||||
#include <QtGlobal>
|
||||
#include <qtestcase.h>
|
||||
#include <QVersionNumber>
|
||||
|
||||
namespace Android::Internal {
|
||||
|
||||
SdkManagerOutputParserTest::SdkManagerOutputParserTest(QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_parser(std::make_unique<SdkManagerOutputParser>(m_packages))
|
||||
{}
|
||||
|
||||
SdkManagerOutputParserTest::~SdkManagerOutputParserTest() = default;
|
||||
|
||||
void SdkManagerOutputParserTest::testParseMarkers_data()
|
||||
{
|
||||
QTest::addColumn<QString>("output");
|
||||
QTest::addColumn<SdkManagerOutputParser::MarkerTag>("markerTag");
|
||||
|
||||
QMap<SdkManagerOutputParser::MarkerTag, QString> testData
|
||||
= {{SdkManagerOutputParser::MarkerTag::InstalledPackagesMarker, "Installed packages:"},
|
||||
{SdkManagerOutputParser::MarkerTag::AvailablePackagesMarkers, "Available Packages:"},
|
||||
{SdkManagerOutputParser::MarkerTag::AvailableUpdatesMarker, "Available Updates:"},
|
||||
{SdkManagerOutputParser::MarkerTag::EmptyMarker, ""},
|
||||
{SdkManagerOutputParser::MarkerTag::PlatformMarker, "platforms"},
|
||||
{SdkManagerOutputParser::MarkerTag::SystemImageMarker, "system-images"},
|
||||
{SdkManagerOutputParser::MarkerTag::BuildToolsMarker, "build-tools"},
|
||||
{SdkManagerOutputParser::MarkerTag::SdkToolsMarker, "tools"},
|
||||
{SdkManagerOutputParser::MarkerTag::PlatformToolsMarker, "platform-tools"},
|
||||
{SdkManagerOutputParser::MarkerTag::EmulatorToolsMarker, "emulator"},
|
||||
{SdkManagerOutputParser::MarkerTag::NdkMarker, "ndk"},
|
||||
{SdkManagerOutputParser::MarkerTag::ExtrasMarker, "extras"},
|
||||
{SdkManagerOutputParser::MarkerTag::CmdlineSdkToolsMarker, "cmdline-tools"},
|
||||
{SdkManagerOutputParser::MarkerTag::GenericToolMarker, "sources;android-32"}};
|
||||
|
||||
for (const SdkManagerOutputParser::MarkerTag data : testData.keys())
|
||||
QTest::newRow(testData.value(data).toLatin1().constData()) << testData.value(data) << data;
|
||||
|
||||
QTest::newRow("Installed packages")
|
||||
<< "Installed packages:" << SdkManagerOutputParser::MarkerTag::InstalledPackagesMarker;
|
||||
}
|
||||
|
||||
void SdkManagerOutputParserTest::testParseMarkers()
|
||||
{
|
||||
QFETCH(QString, output);
|
||||
QFETCH(SdkManagerOutputParser::MarkerTag, markerTag);
|
||||
|
||||
SdkManagerOutputParser::MarkerTag actualMarkerTag = m_parser->parseMarkers(output);
|
||||
|
||||
QCOMPARE(actualMarkerTag, markerTag);
|
||||
}
|
||||
|
||||
// BuildTools
|
||||
void SdkManagerOutputParserTest::testParseBuildToolsPackage_data()
|
||||
{
|
||||
QTest::addColumn<QStringList>("output");
|
||||
|
||||
QTest::addColumn<QString>("description");
|
||||
QTest::addColumn<QString>("displayText");
|
||||
QTest::addColumn<QVersionNumber>("revision");
|
||||
|
||||
QTest::newRow("build-tools;33.0.1")
|
||||
<< QStringList({"build-tools;33.0.1",
|
||||
" Description: Android SDK Build-Tools 33.0.1",
|
||||
" Version: 33.0.1"})
|
||||
<< "Android SDK Build-Tools 33.0.1"
|
||||
<< "Android SDK Build-Tools 33.0.1" << QVersionNumber({33, 0, 1});
|
||||
|
||||
QTest::newRow("build-tools;33.0.3")
|
||||
<< QStringList({"build-tools;33.0.3",
|
||||
" Description: Android SDK Build-Tools 33.0.3",
|
||||
" Version: 33.0.3"})
|
||||
<< "Android SDK Build-Tools 33.0.3"
|
||||
<< "Android SDK Build-Tools 33.0.3" << QVersionNumber({33, 0, 3});
|
||||
}
|
||||
|
||||
void SdkManagerOutputParserTest::testParseBuildToolsPackage()
|
||||
{
|
||||
QFETCH(QStringList, output);
|
||||
QFETCH(QString, description);
|
||||
QFETCH(QString, displayText);
|
||||
QFETCH(QVersionNumber, revision);
|
||||
|
||||
BuildTools *actualBuildTools = m_parser->parseBuildToolsPackage(output);
|
||||
|
||||
QVERIFY(actualBuildTools != nullptr);
|
||||
QCOMPARE(actualBuildTools->descriptionText(), description);
|
||||
QCOMPARE(actualBuildTools->displayText(), displayText);
|
||||
QCOMPARE(actualBuildTools->revision(), revision);
|
||||
}
|
||||
|
||||
void SdkManagerOutputParserTest::testParseBuildToolsPackageEmpty()
|
||||
{
|
||||
BuildTools *actualBuildTools = m_parser->parseBuildToolsPackage({""});
|
||||
|
||||
QVERIFY(actualBuildTools == nullptr);
|
||||
}
|
||||
|
||||
// SdkTools
|
||||
void SdkManagerOutputParserTest::testParseSdkToolsPackage_data()
|
||||
{
|
||||
QTest::addColumn<QStringList>("output");
|
||||
|
||||
QTest::addColumn<QString>("description");
|
||||
QTest::addColumn<QString>("displayText");
|
||||
QTest::addColumn<QVersionNumber>("revision");
|
||||
|
||||
QTest::newRow("cmdline-tools;latest")
|
||||
<< QStringList({"cmdline-tools;latest",
|
||||
" Description: Android SDK Command-line Tools (latest)",
|
||||
" Version: 9.0"})
|
||||
<< "Android SDK Command-line Tools (latest)"
|
||||
<< "Android SDK Command-line Tools (latest)" << QVersionNumber({9, 0});
|
||||
|
||||
QTest::newRow("cmdline-tools;8.0")
|
||||
<< QStringList({"cmdline-tools;8.0",
|
||||
" Description: Android SDK Command-line Tools",
|
||||
" Version: 8.0"})
|
||||
<< "Android SDK Command-line Tools"
|
||||
<< "Android SDK Command-line Tools" << QVersionNumber({8, 0});
|
||||
}
|
||||
|
||||
void SdkManagerOutputParserTest::testParseSdkToolsPackage()
|
||||
{
|
||||
QFETCH(QStringList, output);
|
||||
QFETCH(QString, description);
|
||||
QFETCH(QString, displayText);
|
||||
QFETCH(QVersionNumber, revision);
|
||||
|
||||
std::unique_ptr<SdkTools> actualSdkTool(m_parser->parseSdkToolsPackage(output));
|
||||
|
||||
QVERIFY(actualSdkTool != nullptr);
|
||||
QCOMPARE(actualSdkTool->descriptionText(), description);
|
||||
QCOMPARE(actualSdkTool->displayText(), displayText);
|
||||
QCOMPARE(actualSdkTool->revision(), revision);
|
||||
}
|
||||
|
||||
void SdkManagerOutputParserTest::testParseSdkToolsPackageEmpty()
|
||||
{
|
||||
std::unique_ptr<SdkTools> actualSdkTool(m_parser->parseSdkToolsPackage({""}));
|
||||
|
||||
QVERIFY(actualSdkTool == nullptr);
|
||||
}
|
||||
|
||||
// PlatformTools
|
||||
void SdkManagerOutputParserTest::testParsePlatformToolsPackage_data()
|
||||
{
|
||||
QTest::addColumn<QStringList>("output");
|
||||
|
||||
QTest::addColumn<QString>("description");
|
||||
QTest::addColumn<QString>("displayText");
|
||||
QTest::addColumn<QVersionNumber>("revision");
|
||||
|
||||
QTest::newRow("platform-tools")
|
||||
<< QStringList({"platform-tools",
|
||||
" Description: Android SDK Platform-Tools",
|
||||
" Version: 33.0.3"})
|
||||
<< "Android SDK Platform-Tools"
|
||||
<< "Android SDK Platform-Tools" << QVersionNumber({33, 0, 3});
|
||||
}
|
||||
|
||||
void SdkManagerOutputParserTest::testParsePlatformToolsPackage()
|
||||
{
|
||||
QFETCH(QStringList, output);
|
||||
QFETCH(QString, description);
|
||||
QFETCH(QString, displayText);
|
||||
QFETCH(QVersionNumber, revision);
|
||||
|
||||
std::unique_ptr<PlatformTools> actualPlatformTool(
|
||||
m_parser->parsePlatformToolsPackage(output));
|
||||
|
||||
QVERIFY(actualPlatformTool != nullptr);
|
||||
QCOMPARE(actualPlatformTool->descriptionText(), description);
|
||||
QCOMPARE(actualPlatformTool->displayText(), displayText);
|
||||
QCOMPARE(actualPlatformTool->revision(), revision);
|
||||
}
|
||||
|
||||
void SdkManagerOutputParserTest::testParsePlatformToolsPackageEmpty()
|
||||
{
|
||||
std::unique_ptr<PlatformTools> actualPlatformTool(
|
||||
m_parser->parsePlatformToolsPackage({""}));
|
||||
|
||||
QVERIFY(actualPlatformTool == nullptr);
|
||||
}
|
||||
|
||||
// EmulatorTools
|
||||
void SdkManagerOutputParserTest::testParseEmulatorToolsPackage_data()
|
||||
{
|
||||
QTest::addColumn<QStringList>("output");
|
||||
|
||||
QTest::addColumn<QString>("description");
|
||||
QTest::addColumn<QString>("displayText");
|
||||
QTest::addColumn<QVersionNumber>("revision");
|
||||
|
||||
QTest::newRow("emulator") << QStringList(
|
||||
{"emulator", " Description: Android Emulator", " Version: 30.0.12"})
|
||||
<< "Android Emulator"
|
||||
<< "Android Emulator" << QVersionNumber({30, 0, 12});
|
||||
}
|
||||
|
||||
void SdkManagerOutputParserTest::testParseEmulatorToolsPackage()
|
||||
{
|
||||
QFETCH(QStringList, output);
|
||||
QFETCH(QString, description);
|
||||
QFETCH(QString, displayText);
|
||||
QFETCH(QVersionNumber, revision);
|
||||
|
||||
std::unique_ptr<EmulatorTools> actualEmulatorTools(
|
||||
m_parser->parseEmulatorToolsPackage(output));
|
||||
|
||||
QVERIFY(actualEmulatorTools != nullptr);
|
||||
QCOMPARE(actualEmulatorTools->descriptionText(), description);
|
||||
QCOMPARE(actualEmulatorTools->displayText(), displayText);
|
||||
QCOMPARE(actualEmulatorTools->revision(), revision);
|
||||
}
|
||||
|
||||
void SdkManagerOutputParserTest::testParseEmulatorToolsPackageEmpty()
|
||||
{
|
||||
std::unique_ptr<EmulatorTools> actualEmulatorTools(
|
||||
m_parser->parseEmulatorToolsPackage({""}));
|
||||
|
||||
QVERIFY(actualEmulatorTools == nullptr);
|
||||
}
|
||||
|
||||
// NDK
|
||||
void SdkManagerOutputParserTest::testParseNdkPackage_data()
|
||||
{
|
||||
QTest::addColumn<QStringList>("output");
|
||||
|
||||
QTest::addColumn<QString>("description");
|
||||
QTest::addColumn<QString>("displayText");
|
||||
QTest::addColumn<QVersionNumber>("revision");
|
||||
|
||||
QTest::newRow("ndk;21.0.6113669") << QStringList({"ndk;21.0.6113669",
|
||||
" Description: Android NDK",
|
||||
" Version: 21.0.6113669"})
|
||||
<< "Android NDK"
|
||||
<< "Android NDK" << QVersionNumber({21, 0, 6113669});
|
||||
}
|
||||
|
||||
void SdkManagerOutputParserTest::testParseNdkPackage()
|
||||
{
|
||||
QFETCH(QStringList, output);
|
||||
QFETCH(QString, description);
|
||||
QFETCH(QString, displayText);
|
||||
QFETCH(QVersionNumber, revision);
|
||||
|
||||
std::unique_ptr<Ndk> actualNdkPackage(m_parser->parseNdkPackage(output));
|
||||
|
||||
QVERIFY(actualNdkPackage != nullptr);
|
||||
QCOMPARE(actualNdkPackage->descriptionText(), description);
|
||||
QCOMPARE(actualNdkPackage->displayText(), displayText);
|
||||
QCOMPARE(actualNdkPackage->revision(), revision);
|
||||
}
|
||||
|
||||
void SdkManagerOutputParserTest::testParseNdkPackageEmpty()
|
||||
{
|
||||
std::unique_ptr<Ndk> actualNdkPackage(m_parser->parseNdkPackage({""}));
|
||||
|
||||
QVERIFY(actualNdkPackage == nullptr);
|
||||
}
|
||||
|
||||
// ExtraTools
|
||||
void SdkManagerOutputParserTest::testParseExtraToolsPackage_data()
|
||||
{
|
||||
QTest::addColumn<QStringList>("output");
|
||||
|
||||
QTest::addColumn<QString>("description");
|
||||
QTest::addColumn<QString>("displayText");
|
||||
QTest::addColumn<QVersionNumber>("revision");
|
||||
|
||||
QTest::newRow(
|
||||
"extras;m2repository;com;android;support;constraint;constraint-layout;1.0.0-beta5")
|
||||
<< QStringList(
|
||||
{"extras;m2repository;com;android;support;constraint;constraint-layout;1.0.1",
|
||||
" Description: ConstraintLayout for Android 1.0.1",
|
||||
" Version: 1",
|
||||
" Dependencies:"})
|
||||
<< "ConstraintLayout for Android 1.0.1"
|
||||
<< "ConstraintLayout for Android 1.0.1" << QVersionNumber({1});
|
||||
}
|
||||
|
||||
void SdkManagerOutputParserTest::testParseExtraToolsPackage()
|
||||
{
|
||||
QFETCH(QStringList, output);
|
||||
QFETCH(QString, description);
|
||||
QFETCH(QString, displayText);
|
||||
QFETCH(QVersionNumber, revision);
|
||||
|
||||
std::unique_ptr<ExtraTools> actualExtraTools(
|
||||
m_parser->parseExtraToolsPackage(output));
|
||||
|
||||
QVERIFY(actualExtraTools != nullptr);
|
||||
QCOMPARE(actualExtraTools->descriptionText(), description);
|
||||
QCOMPARE(actualExtraTools->displayText(), displayText);
|
||||
QCOMPARE(actualExtraTools->revision(), revision);
|
||||
}
|
||||
|
||||
void SdkManagerOutputParserTest::testParseExtraToolsPackageEmpty()
|
||||
{
|
||||
std::unique_ptr<ExtraTools> actualExtraTools(
|
||||
m_parser->parseExtraToolsPackage({""}));
|
||||
|
||||
QVERIFY(actualExtraTools == nullptr);
|
||||
}
|
||||
|
||||
// GenericTools
|
||||
void SdkManagerOutputParserTest::testParseGenericToolsPackage_data()
|
||||
{
|
||||
QTest::addColumn<QStringList>("output");
|
||||
|
||||
QTest::addColumn<QString>("description");
|
||||
QTest::addColumn<QString>("displayText");
|
||||
QTest::addColumn<QVersionNumber>("revision");
|
||||
|
||||
QTest::newRow("sources;android-33")
|
||||
<< QStringList({"sources;android-33",
|
||||
" Description: Sources for Android 33",
|
||||
" Version: 1"})
|
||||
<< "Sources for Android 33"
|
||||
<< "Sources for Android 33" << QVersionNumber({1});
|
||||
}
|
||||
|
||||
void SdkManagerOutputParserTest::testParseGenericToolsPackage()
|
||||
{
|
||||
QFETCH(QStringList, output);
|
||||
QFETCH(QString, description);
|
||||
QFETCH(QString, displayText);
|
||||
QFETCH(QVersionNumber, revision);
|
||||
|
||||
std::unique_ptr<GenericSdkPackage> actualGenericTools(
|
||||
m_parser->parseGenericTools(output));
|
||||
|
||||
QVERIFY(actualGenericTools != nullptr);
|
||||
QCOMPARE(actualGenericTools->descriptionText(), description);
|
||||
QCOMPARE(actualGenericTools->displayText(), displayText);
|
||||
QCOMPARE(actualGenericTools->revision(), revision);
|
||||
}
|
||||
|
||||
void SdkManagerOutputParserTest::testParseGenericToolsPackageEmpty()
|
||||
{
|
||||
std::unique_ptr<GenericSdkPackage> actualGenericTools(
|
||||
m_parser->parseGenericTools({""}));
|
||||
|
||||
QVERIFY(actualGenericTools == nullptr);
|
||||
}
|
||||
|
||||
// Platform
|
||||
void SdkManagerOutputParserTest::testParsePlatformPackage_data()
|
||||
{
|
||||
QTest::addColumn<QStringList>("output");
|
||||
|
||||
QTest::addColumn<QString>("description");
|
||||
QTest::addColumn<QString>("installLocation");
|
||||
QTest::addColumn<QVersionNumber>("revision");
|
||||
QTest::addColumn<QString>("extension");
|
||||
|
||||
QTest::newRow("platforms;android-31")
|
||||
<< QStringList({"platforms;android-31",
|
||||
" Description: Android SDK Platform 31",
|
||||
" Version: 5",
|
||||
" Installed Location: /home/name/Android/Sdk/platforms/android-31"})
|
||||
<< "Android SDK Platform 31"
|
||||
<< "/home/name/Android/Sdk/platforms/android-31" << QVersionNumber({5}) << "";
|
||||
|
||||
QTest::newRow("platforms;android-33-ext4")
|
||||
<< QStringList({"platforms;android-33-ext4",
|
||||
" Description: Android SDK Platform 33",
|
||||
" Version: 1",
|
||||
" Installed Location: /home/name/Android/Sdk/platforms/android-33"})
|
||||
<< "Android SDK Platform 33"
|
||||
<< "/home/name/Android/Sdk/platforms/android-33" << QVersionNumber({1}) << " Extension 4";
|
||||
}
|
||||
|
||||
void SdkManagerOutputParserTest::testParsePlatformPackage()
|
||||
{
|
||||
QFETCH(QStringList, output);
|
||||
QFETCH(QString, description);
|
||||
QFETCH(QString, installLocation);
|
||||
QFETCH(QVersionNumber, revision);
|
||||
QFETCH(QString, extension);
|
||||
|
||||
std::unique_ptr<AndroidSdkPackage> actualPlatform(m_parser->parsePlatform(output));
|
||||
|
||||
QVERIFY(actualPlatform != nullptr);
|
||||
QCOMPARE(actualPlatform->descriptionText(), description);
|
||||
QCOMPARE(actualPlatform->installedLocation().path(), installLocation);
|
||||
QCOMPARE(actualPlatform->revision(), revision);
|
||||
QCOMPARE(actualPlatform->extension(), extension);
|
||||
}
|
||||
|
||||
void SdkManagerOutputParserTest::testParsePlatformPackageEmpty()
|
||||
{
|
||||
std::unique_ptr<AndroidSdkPackage> actualPlatform(m_parser->parsePlatform({""}));
|
||||
|
||||
QVERIFY(actualPlatform == nullptr);
|
||||
}
|
||||
|
||||
// SystemImage
|
||||
void SdkManagerOutputParserTest::testParseSystemImagePackage_data()
|
||||
{
|
||||
QTest::addColumn<QStringList>("output");
|
||||
|
||||
QTest::addColumn<QString>("description");
|
||||
QTest::addColumn<QString>("installLocation");
|
||||
QTest::addColumn<QVersionNumber>("revision");
|
||||
|
||||
QTest::newRow("system-images;android-31;google_apis;x86")
|
||||
<< QStringList({"system-images;android-31;google_apis;x86",
|
||||
" Description: Google APIs Intel x86 Atom System Image",
|
||||
" Version: 7",
|
||||
" Installed Location: /home/name/Android/Sdk/system-images/android-31/"
|
||||
"google_apis/x86"})
|
||||
<< "Google APIs Intel x86 Atom System Image"
|
||||
<< "/home/name/Android/Sdk/system-images/android-31/google_apis/x86"
|
||||
<< QVersionNumber({7});
|
||||
}
|
||||
|
||||
void SdkManagerOutputParserTest::testParseSystemImagePackage()
|
||||
{
|
||||
QFETCH(QStringList, output);
|
||||
QFETCH(QString, description);
|
||||
QFETCH(QString, installLocation);
|
||||
QFETCH(QVersionNumber, revision);
|
||||
|
||||
QPair<SystemImage *, int> actualSystemImagePair(m_parser->parseSystemImage(output));
|
||||
|
||||
SystemImage *actualSystemImage = actualSystemImagePair.first;
|
||||
|
||||
QVERIFY(actualSystemImage != nullptr);
|
||||
QCOMPARE(actualSystemImage->descriptionText(), description);
|
||||
QCOMPARE(actualSystemImage->installedLocation().path(), installLocation);
|
||||
QCOMPARE(actualSystemImage->revision(), revision);
|
||||
delete actualSystemImage;
|
||||
}
|
||||
|
||||
void SdkManagerOutputParserTest::testParseSystemImagePackageEmpty()
|
||||
{
|
||||
QPair<SystemImage *, int> actualSystemImagePair(m_parser->parseSystemImage({""}));
|
||||
SystemImage *actualSystemImage = actualSystemImagePair.first;
|
||||
|
||||
QVERIFY(actualSystemImage == nullptr);
|
||||
delete actualSystemImage;
|
||||
}
|
||||
void SdkManagerOutputParserTest::testParsePackageListing()
|
||||
{
|
||||
QFETCH(QString, sdkManagerOutput);
|
||||
QFETCH(QList<AndroidSdkPackage::PackageType>, packageTypes);
|
||||
QFETCH(int, sdkManagerOutputPackagesNumber);
|
||||
|
||||
m_parser->parsePackageListing(sdkManagerOutput);
|
||||
|
||||
QCOMPARE(m_packages.length(), sdkManagerOutputPackagesNumber);
|
||||
|
||||
for (int i = 0; i < m_packages.length(); ++i)
|
||||
QCOMPARE(m_packages.at(i)->type(), packageTypes.at(i));
|
||||
}
|
||||
|
||||
void SdkManagerOutputParserTest::testParsePackageListing_data()
|
||||
{
|
||||
QTest::addColumn<int>("sdkManagerOutputPackagesNumber");
|
||||
QTest::addColumn<QList<AndroidSdkPackage::PackageType>>("packageTypes");
|
||||
QTest::addColumn<QString>("sdkManagerOutput");
|
||||
|
||||
const QList<AndroidSdkPackage::PackageType> packageTypes = {
|
||||
AndroidSdkPackage::PackageType::BuildToolsPackage,
|
||||
AndroidSdkPackage::PackageType::SdkToolsPackage,
|
||||
AndroidSdkPackage::PackageType::EmulatorToolsPackage,
|
||||
AndroidSdkPackage::PackageType::NDKPackage,
|
||||
AndroidSdkPackage::PackageType::GenericSdkPackage,
|
||||
AndroidSdkPackage::PackageType::SdkPlatformPackage,
|
||||
AndroidSdkPackage::PackageType::GenericSdkPackage,
|
||||
|
||||
AndroidSdkPackage::PackageType::BuildToolsPackage,
|
||||
AndroidSdkPackage::PackageType::GenericSdkPackage,
|
||||
AndroidSdkPackage::PackageType::SdkToolsPackage,
|
||||
AndroidSdkPackage::PackageType::SdkToolsPackage,
|
||||
AndroidSdkPackage::PackageType::ExtraToolsPackage,
|
||||
AndroidSdkPackage::PackageType::NDKPackage,
|
||||
AndroidSdkPackage::PackageType::NDKPackage,
|
||||
AndroidSdkPackage::PackageType::PlatformToolsPackage,
|
||||
AndroidSdkPackage::PackageType::SdkPlatformPackage,
|
||||
AndroidSdkPackage::PackageType::SdkPlatformPackage,
|
||||
AndroidSdkPackage::PackageType::SdkPlatformPackage,
|
||||
AndroidSdkPackage::PackageType::SdkPlatformPackage,
|
||||
AndroidSdkPackage::PackageType::GenericSdkPackage,
|
||||
AndroidSdkPackage::PackageType::GenericSdkPackage,
|
||||
};
|
||||
|
||||
QTest::newRow("sdkmanager --list --verbose") // version 8.0
|
||||
<< 21
|
||||
<< packageTypes
|
||||
<< QString(R"(
|
||||
Loading package information...
|
||||
Loading local repository...
|
||||
Info: Parsing /home/artem/Android/Sdk/build-tools/31.0.0/package.xml
|
||||
Info: Parsing /home/artem/Android/Sdk/cmdline-tools/latest/package.xml
|
||||
Info: Parsing /home/artem/Android/Sdk/emulator/package.xml
|
||||
Info: Parsing /home/artem/Android/Sdk/ndk/21.3.6528147/package.xml
|
||||
Info: Parsing /home/artem/Android/Sdk/ndk/23.1.7779620/package.xml
|
||||
Info: Parsing /home/artem/Android/Sdk/ndk/25.1.8937393/package.xml
|
||||
Info: Parsing /home/artem/Android/Sdk/patcher/v4/package.xml
|
||||
Info: Parsing /home/artem/Android/Sdk/platform-tools/package.xml
|
||||
Info: Parsing /home/artem/Android/Sdk/platforms/android-31/package.xml
|
||||
Info: Parsing
|
||||
/home/artem/Android/Sdk/system-images/android-25/google_apis/armeabi-v7a
|
||||
package.xml
|
||||
Info: Parsing
|
||||
/home/artem/Android/Sdk/system-images/android-27/default/arm64-v8a/package.xml
|
||||
Info: Parsing
|
||||
/home/artem/Android/Sdk/system-images/android-29/google_apis/x86/package.xml
|
||||
Info: Parsing
|
||||
/home/artem/Android/Sdk/system-images/android-31/android-tv/arm64-v8a/package.xml
|
||||
Info: Parsing
|
||||
/home/artem/Android/Sdk/system-images/android-31/android-tv/x86/package.xml
|
||||
Info: Parsing
|
||||
/home/artem/Android/Sdk/system-images/android-31/default/x86_64/package.xml
|
||||
Info: Parsing
|
||||
/home/artem/Android/Sdk/system-images/android-31/google_apis/x86_64/package.xml
|
||||
Info: Parsing
|
||||
/home/artem/Android/Sdk/system-images/android-32/google_apis/arm64-v8a/package.xml
|
||||
Info: Parsing
|
||||
/home/artem/Android/Sdk/system-images/android-32/google_apis/x86_64/package.xml
|
||||
Info: Parsing
|
||||
/home/artem/Android/Sdk/system-images/android-33/google_apis/arm64-v8a/package.xml
|
||||
[========= ] 25% Loading local repository...
|
||||
[========= ] 25% Fetch remote repository...
|
||||
[========== ] 26% Fetch remote repository...
|
||||
[============ ] 31% Fetch remote repository...
|
||||
[============= ] 33% Fetch remote repository...
|
||||
[============= ] 34% Fetch remote repository...
|
||||
[============== ] 36% Fetch remote repository...
|
||||
[============== ] 37% Fetch remote repository...
|
||||
[=============== ] 38% Fetch remote repository...
|
||||
[=============== ] 40% Fetch remote repository...
|
||||
[================ ] 41% Fetch remote repository...
|
||||
[================= ] 43% Fetch remote repository...
|
||||
[================= ] 44% Fetch remote repository...
|
||||
[================== ] 45% Fetch remote repository...
|
||||
[================== ] 47% Fetch remote repository...
|
||||
[=================== ] 48% Fetch remote repository...
|
||||
[=================== ] 50% Fetch remote repository...
|
||||
[==================== ] 51% Fetch remote repository...
|
||||
[==================== ] 53% Fetch remote repository...
|
||||
[===================== ] 54% Fetch remote repository...
|
||||
[====================== ] 55% Fetch remote repository...
|
||||
[====================== ] 57% Fetch remote repository...
|
||||
[======================= ] 58% Fetch remote repository...
|
||||
[======================= ] 60% Fetch remote repository...
|
||||
[======================== ] 61% Fetch remote repository...
|
||||
[======================== ] 62% Fetch remote repository...
|
||||
[========================= ] 64% Fetch remote repository...
|
||||
[========================== ] 65% Fetch remote repository...
|
||||
[========================== ] 67% Fetch remote repository...
|
||||
[=========================== ] 68% Fetch remote repository...
|
||||
[=========================== ] 69% Fetch remote repository...
|
||||
[============================ ] 71% Fetch remote repository...
|
||||
[============================ ] 72% Fetch remote repository...
|
||||
[============================= ] 74% Fetch remote repository...
|
||||
[============================= ] 75% Fetch remote repository...
|
||||
[============================= ] 75% Computing updates...
|
||||
[=======================================] 100% Computing updates...
|
||||
Installed packages:
|
||||
--------------------------------------
|
||||
build-tools;31.0.0
|
||||
Description: Android SDK Build-Tools 31
|
||||
Version: 31.0.0
|
||||
Installed Location: /home/artem/Android/Sdk/build-tools/31.0.0
|
||||
|
||||
cmdline-tools;latest
|
||||
Description: Android SDK Command-line Tools (latest)
|
||||
Version: 8.0
|
||||
Installed Location: /home/artem/Android/Sdk/cmdline-tools/latest
|
||||
|
||||
emulator
|
||||
Description: Android Emulator
|
||||
Version: 31.3.14
|
||||
Installed Location: /home/artem/Android/Sdk/emulator
|
||||
|
||||
ndk;25.1.8937393
|
||||
Description: NDK (Side by side) 25.1.8937393
|
||||
Version: 25.1.8937393
|
||||
Installed Location: /home/artem/Android/Sdk/ndk/25.1.8937393
|
||||
|
||||
patcher;v4
|
||||
Description: SDK Patch Applier v4
|
||||
Version: 1
|
||||
Installed Location: /home/artem/Android/Sdk/patcher/v4
|
||||
|
||||
platforms;android-31
|
||||
Description: Android SDK Platform 31
|
||||
Version: 1
|
||||
Installed Location: /home/artem/Android/Sdk/platforms/android-31
|
||||
|
||||
system-images;android-33;google_apis;arm64-v8a
|
||||
Description: Google APIs ARM 64 v8a System Image
|
||||
Version: 8
|
||||
Installed Location:
|
||||
/home/artem/Android/Sdk/system-images/android-33/google_apis/arm64-v8a
|
||||
|
||||
Available Packages:
|
||||
--------------------------------------
|
||||
add-ons;addon-google_apis-google-24
|
||||
Description: Google APIs
|
||||
Version: 1
|
||||
|
||||
build-tools;33.0.1
|
||||
Description: Android SDK Build-Tools 33.0.1
|
||||
Version: 33.0.1
|
||||
|
||||
cmake;3.22.1
|
||||
Description: CMake 3.22.1
|
||||
Version: 3.22.1
|
||||
|
||||
cmdline-tools;9.0
|
||||
Description: Android SDK Command-line Tools
|
||||
Version: 9.0
|
||||
|
||||
cmdline-tools;latest
|
||||
Description: Android SDK Command-line Tools (latest)
|
||||
Version: 9.0
|
||||
|
||||
emulator
|
||||
Description: Android Emulator
|
||||
Version: 31.3.14
|
||||
Dependencies:
|
||||
patcher;v4
|
||||
|
||||
extras;android;m2repository
|
||||
Description: Android Support Repository
|
||||
Version: 47.0.0
|
||||
|
||||
ndk-bundle
|
||||
Description: NDK
|
||||
Version: 22.1.7171670
|
||||
Dependencies:
|
||||
patcher;v4
|
||||
|
||||
ndk;25.0.8775105
|
||||
Description: NDK (Side by side) 25.0.8775105
|
||||
Version: 25.0.8775105
|
||||
Dependencies:
|
||||
patcher;v4
|
||||
|
||||
ndk;25.1.8937393
|
||||
Description: NDK (Side by side) 25.1.8937393
|
||||
Version: 25.1.8937393
|
||||
Dependencies:
|
||||
patcher;v4
|
||||
|
||||
patcher;v4
|
||||
Description: SDK Patch Applier v4
|
||||
Version: 1
|
||||
|
||||
platform-tools
|
||||
Description: Android SDK Platform-Tools
|
||||
Version: 33.0.3
|
||||
|
||||
platforms;android-33
|
||||
Description: Android SDK Platform 33
|
||||
Version: 2
|
||||
|
||||
platforms;android-33-ext4
|
||||
Description: Android SDK Platform 33
|
||||
Version: 1
|
||||
|
||||
platforms;android-9
|
||||
Description: Android SDK Platform 9
|
||||
Version: 2
|
||||
|
||||
platforms;android-TiramisuPrivacySandbox
|
||||
Description: Android SDK Platform TiramisuPrivacySandbox
|
||||
Version: 8
|
||||
|
||||
sources;android-32
|
||||
Description: Sources for Android 32
|
||||
Version: 1
|
||||
|
||||
sources;android-33
|
||||
Description: Sources for Android 33
|
||||
Version: 1
|
||||
|
||||
system-images;android-10;default;armeabi-v7a
|
||||
Description: ARM EABI v7a System Image
|
||||
Version: 5
|
||||
Dependencies:
|
||||
patcher;v4
|
||||
|
||||
system-images;android-33-ext4;google_apis_playstore;arm64-v8a
|
||||
Description: Google Play ARM 64 v8a System Image
|
||||
Version: 1
|
||||
Dependencies:
|
||||
patcher;v4
|
||||
emulator Revision 30.7.3
|
||||
|
||||
system-images;android-33-ext4;google_apis_playstore;x86_64
|
||||
Description: Google Play Intel x86 Atom_64 System Image
|
||||
Version: 1
|
||||
Dependencies:
|
||||
patcher;v4
|
||||
emulator Revision 30.7.3
|
||||
|
||||
system-images;android-33;android-tv;arm64-v8a
|
||||
Description: Android TV ARM 64 v8a System Image
|
||||
Version: 5
|
||||
Dependencies:
|
||||
patcher;v4
|
||||
emulator Revision 28.1.6
|
||||
|
||||
system-images;android-33;android-tv;x86
|
||||
Description: Android TV Intel x86 Atom System Image
|
||||
Version: 5
|
||||
Dependencies:
|
||||
patcher;v4
|
||||
emulator Revision 28.1.6
|
||||
|
||||
system-images;android-33;google-tv;arm64-v8a
|
||||
Description: Google TV ARM 64 v8a System Image
|
||||
Version: 5
|
||||
Dependencies:
|
||||
patcher;v4
|
||||
emulator Revision 28.1.6
|
||||
|
||||
system-images;android-33;google-tv;x86
|
||||
Description: Google TV Intel x86 Atom System Image
|
||||
Version: 5
|
||||
Dependencies:
|
||||
patcher;v4
|
||||
emulator Revision 28.1.6
|
||||
|
||||
system-images;android-33;google_apis;arm64-v8a
|
||||
Description: Google APIs ARM 64 v8a System Image
|
||||
Version: 8
|
||||
Dependencies:
|
||||
patcher;v4
|
||||
emulator Revision 30.7.3
|
||||
|
||||
system-images;android-33;google_apis;x86_64
|
||||
Description: Google APIs Intel x86 Atom_64 System Image
|
||||
Version: 8
|
||||
Dependencies:
|
||||
patcher;v4
|
||||
emulator Revision 30.7.3
|
||||
|
||||
system-images;android-33;google_apis_playstore;arm64-v8a
|
||||
Description: Google Play ARM 64 v8a System Image
|
||||
Version: 7
|
||||
Dependencies:
|
||||
patcher;v4
|
||||
emulator Revision 30.7.3
|
||||
|
||||
system-images;android-33;google_apis_playstore;x86_64
|
||||
Description: Google Play Intel x86 Atom_64 System Image
|
||||
Version: 7
|
||||
Dependencies:
|
||||
patcher;v4
|
||||
emulator Revision 30.7.3
|
||||
|
||||
system-images;android-TiramisuPrivacySandbox;google_apis_playstore;arm64-v8a
|
||||
Description: Google Play ARM 64 v8a System Image
|
||||
Version: 8
|
||||
Dependencies:
|
||||
patcher;v4
|
||||
emulator Revision 30.7.3
|
||||
|
||||
system-images;android-TiramisuPrivacySandbox;google_apis_playstore;x86_64
|
||||
Description: Google Play Intel x86 Atom_64 System Image
|
||||
Version: 8
|
||||
Dependencies:
|
||||
patcher;v4
|
||||
emulator Revision 30.7.3
|
||||
|
||||
Available Updates:
|
||||
--------------------------------------
|
||||
cmdline-tools;latest
|
||||
Installed Version: 8.0
|
||||
Available Version: 9.)");
|
||||
|
||||
}
|
||||
|
||||
} // namespace Android::Internal
|
||||
|
||||
74
src/plugins/android/sdkmanageroutputparser_test.h
Normal file
74
src/plugins/android/sdkmanageroutputparser_test.h
Normal file
@@ -0,0 +1,74 @@
|
||||
// Copyright (C) 2022 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#include "androidsdkpackage.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QString;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
namespace Android {
|
||||
namespace Internal {
|
||||
|
||||
class SdkManagerOutputParser;
|
||||
|
||||
class SdkManagerOutputParserTest : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
SdkManagerOutputParserTest(QObject *parent = nullptr);
|
||||
~SdkManagerOutputParserTest();
|
||||
|
||||
private:
|
||||
AndroidSdkPackageList m_packages;
|
||||
std::unique_ptr<SdkManagerOutputParser> m_parser;
|
||||
|
||||
private slots:
|
||||
void testParsePackageListing_data();
|
||||
void testParsePackageListing();
|
||||
|
||||
void testParseMarkers_data();
|
||||
void testParseMarkers();
|
||||
|
||||
void testParseBuildToolsPackage_data();
|
||||
void testParseBuildToolsPackage();
|
||||
void testParseBuildToolsPackageEmpty();
|
||||
|
||||
void testParseSdkToolsPackage_data();
|
||||
void testParseSdkToolsPackage();
|
||||
void testParseSdkToolsPackageEmpty();
|
||||
|
||||
void testParsePlatformToolsPackage_data();
|
||||
void testParsePlatformToolsPackage();
|
||||
void testParsePlatformToolsPackageEmpty();
|
||||
|
||||
void testParseEmulatorToolsPackage_data();
|
||||
void testParseEmulatorToolsPackage();
|
||||
void testParseEmulatorToolsPackageEmpty();
|
||||
|
||||
void testParseNdkPackage_data();
|
||||
void testParseNdkPackage();
|
||||
void testParseNdkPackageEmpty();
|
||||
|
||||
void testParseExtraToolsPackage_data();
|
||||
void testParseExtraToolsPackage();
|
||||
void testParseExtraToolsPackageEmpty();
|
||||
|
||||
void testParseGenericToolsPackage_data();
|
||||
void testParseGenericToolsPackage();
|
||||
void testParseGenericToolsPackageEmpty();
|
||||
|
||||
void testParsePlatformPackage_data();
|
||||
void testParsePlatformPackage();
|
||||
void testParsePlatformPackageEmpty();
|
||||
|
||||
void testParseSystemImagePackage_data();
|
||||
void testParseSystemImagePackage();
|
||||
void testParseSystemImagePackageEmpty();
|
||||
};
|
||||
} // namespace Internal
|
||||
} // namespace Android
|
||||
@@ -104,7 +104,7 @@ void GTestOutputReader::processOutputLine(const QByteArray &outputLine)
|
||||
} else if (ExactMatch match = newTestSetStarts.match(line)) {
|
||||
m_testSetStarted = true;
|
||||
setCurrentTestCase(match.captured(1));
|
||||
GTestResult testResult("internal", {}, m_projectFile);
|
||||
GTestResult testResult({}, {}, m_projectFile);
|
||||
testResult.setResult(ResultType::MessageCurrentTest);
|
||||
testResult.setDescription(Tr::tr("Entering test case %1").arg(m_currentTestCase));
|
||||
reportResult(testResult);
|
||||
|
||||
@@ -464,7 +464,7 @@ void QtTestOutputReader::sendCompleteInformation()
|
||||
|
||||
void QtTestOutputReader::sendMessageCurrentTest()
|
||||
{
|
||||
QtTestResult result("internal", {}, m_projectFile, m_testType);
|
||||
QtTestResult result({}, {}, m_projectFile, m_testType);
|
||||
result.setResult(ResultType::MessageCurrentTest);
|
||||
result.setDescription(Tr::tr("Entering test function %1::%2").arg(m_className, m_testCase));
|
||||
reportResult(result);
|
||||
|
||||
@@ -19,7 +19,7 @@ TestResult::TestResult(const QString &id, const QString &name, const ResultHooks
|
||||
|
||||
bool TestResult::isValid() const
|
||||
{
|
||||
return !m_id.isEmpty();
|
||||
return m_id.has_value();
|
||||
}
|
||||
|
||||
const QString TestResult::outputString(bool selected) const
|
||||
@@ -28,7 +28,7 @@ const QString TestResult::outputString(bool selected) const
|
||||
return m_hooks.outputString(*this, selected);
|
||||
|
||||
if (m_result == ResultType::Application)
|
||||
return m_id;
|
||||
return id();
|
||||
return selected ? m_description : m_description.split('\n').first();
|
||||
}
|
||||
|
||||
@@ -166,7 +166,7 @@ QColor TestResult::colorForType(const ResultType type)
|
||||
bool TestResult::isDirectParentOf(const TestResult &other, bool *needsIntermediate) const
|
||||
{
|
||||
QTC_ASSERT(other.isValid(), return false);
|
||||
const bool ret = !m_id.isEmpty() && m_id == other.m_id && m_name == other.m_name;
|
||||
const bool ret = m_id && m_id == other.m_id && m_name == other.m_name;
|
||||
if (!ret)
|
||||
return false;
|
||||
if (m_hooks.directParent)
|
||||
@@ -179,14 +179,14 @@ bool TestResult::isIntermediateFor(const TestResult &other) const
|
||||
QTC_ASSERT(other.isValid(), return false);
|
||||
if (m_hooks.intermediate)
|
||||
return m_hooks.intermediate(*this, other);
|
||||
return !m_id.isEmpty() && m_id == other.m_id && m_name == other.m_name;
|
||||
return m_id && m_id == other.m_id && m_name == other.m_name;
|
||||
}
|
||||
|
||||
TestResult TestResult::intermediateResult() const
|
||||
{
|
||||
if (m_hooks.createResult)
|
||||
return m_hooks.createResult(*this);
|
||||
return {m_id, m_name};
|
||||
return {id(), m_name};
|
||||
}
|
||||
|
||||
} // namespace Autotest
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
|
||||
#include <QColor>
|
||||
|
||||
#include <optional>
|
||||
|
||||
namespace Autotest {
|
||||
|
||||
class ITestTreeItem;
|
||||
@@ -65,9 +67,9 @@ struct ResultHooks
|
||||
using IntermediateHook = std::function<bool(const TestResult &, const TestResult &)>;
|
||||
using CreateResultHook = std::function<TestResult(const TestResult &)>;
|
||||
QVariant extraData;
|
||||
OutputStringHook outputString;
|
||||
FindTestItemHook findTestItem;
|
||||
DirectParentHook directParent;
|
||||
OutputStringHook outputString = {};
|
||||
FindTestItemHook findTestItem = {};
|
||||
DirectParentHook directParent = {};
|
||||
IntermediateHook intermediate = {};
|
||||
CreateResultHook createResult = {};
|
||||
};
|
||||
@@ -83,7 +85,7 @@ public:
|
||||
const QString outputString(bool selected) const;
|
||||
const ITestTreeItem *findTestTreeItem() const;
|
||||
|
||||
QString id() const { return m_id; }
|
||||
QString id() const { return m_id.value_or(QString()); }
|
||||
QString name() const { return m_name; }
|
||||
ResultType result() const { return m_result; }
|
||||
QString description() const { return m_description; }
|
||||
@@ -106,13 +108,13 @@ public:
|
||||
TestResult intermediateResult() const;
|
||||
|
||||
private:
|
||||
QString m_id;
|
||||
std::optional<QString> m_id = {};
|
||||
QString m_name;
|
||||
ResultType m_result = ResultType::Invalid; // the real result..
|
||||
QString m_description;
|
||||
Utils::FilePath m_file;
|
||||
int m_line = 0;
|
||||
ResultHooks m_hooks;
|
||||
ResultHooks m_hooks = {};
|
||||
};
|
||||
|
||||
} // namespace Autotest
|
||||
|
||||
@@ -715,7 +715,7 @@ void TestRunner::onFinished()
|
||||
|
||||
void TestRunner::reportResult(ResultType type, const QString &description)
|
||||
{
|
||||
TestResult result("internal", {});
|
||||
TestResult result({}, {});
|
||||
result.setResult(type);
|
||||
result.setDescription(description);
|
||||
emit testResultReady(result);
|
||||
|
||||
@@ -47,12 +47,12 @@ void DebuggerOutputParser::skipSpaces()
|
||||
++from;
|
||||
}
|
||||
|
||||
QString DebuggerOutputParser::readString(const std::function<bool(char)> &isValidChar)
|
||||
QStringView DebuggerOutputParser::readString(const std::function<bool(char)> &isValidChar)
|
||||
{
|
||||
QString res;
|
||||
const QChar *oldFrom = from;
|
||||
while (from < to && isValidChar(from->unicode()))
|
||||
res += *from++;
|
||||
return res;
|
||||
++from;
|
||||
return {oldFrom, from};
|
||||
}
|
||||
|
||||
int DebuggerOutputParser::readInt()
|
||||
@@ -96,7 +96,7 @@ void GdbMi::parseResultOrValue(DebuggerOutputParser &parser)
|
||||
return;
|
||||
}
|
||||
|
||||
m_name = parser.readString(isNameChar);
|
||||
m_name = parser.readString(isNameChar).toString();
|
||||
|
||||
if (!parser.isAtEnd() && parser.isCurrent('=')) {
|
||||
parser.advance();
|
||||
@@ -105,12 +105,10 @@ void GdbMi::parseResultOrValue(DebuggerOutputParser &parser)
|
||||
}
|
||||
|
||||
// Reads one \ooo entity.
|
||||
static bool parseOctalEscapedHelper(DebuggerOutputParser &parser, QByteArray &buffer)
|
||||
static bool parseOctalEscapedHelper(DebuggerOutputParser &parser, DebuggerOutputParser::Buffer &buffer)
|
||||
{
|
||||
if (parser.remainingChars() < 4)
|
||||
return false;
|
||||
if (!parser.isCurrent('\\'))
|
||||
return false;
|
||||
|
||||
const char c1 = parser.lookAhead(1).unicode();
|
||||
const char c2 = parser.lookAhead(2).unicode();
|
||||
@@ -123,12 +121,10 @@ static bool parseOctalEscapedHelper(DebuggerOutputParser &parser, QByteArray &bu
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool parseHexEscapedHelper(DebuggerOutputParser &parser, QByteArray &buffer)
|
||||
static bool parseHexEscapedHelper(DebuggerOutputParser &parser, DebuggerOutputParser::Buffer &buffer)
|
||||
{
|
||||
if (parser.remainingChars() < 4)
|
||||
return false;
|
||||
if (!parser.isCurrent('\\'))
|
||||
return false;
|
||||
if (parser.lookAhead(1) != 'x')
|
||||
return false;
|
||||
|
||||
@@ -142,7 +138,7 @@ static bool parseHexEscapedHelper(DebuggerOutputParser &parser, QByteArray &buff
|
||||
return true;
|
||||
}
|
||||
|
||||
static void parseSimpleEscape(DebuggerOutputParser &parser, QString &result)
|
||||
static void parseSimpleEscape(DebuggerOutputParser &parser, DebuggerOutputParser::Buffer &buffer)
|
||||
{
|
||||
if (parser.isAtEnd()) {
|
||||
qDebug() << "MI Parse Error, unterminated backslash escape";
|
||||
@@ -152,65 +148,64 @@ static void parseSimpleEscape(DebuggerOutputParser &parser, QString &result)
|
||||
const QChar c = parser.current();
|
||||
parser.advance();
|
||||
switch (c.unicode()) {
|
||||
case 'a': result += '\a'; break;
|
||||
case 'b': result += '\b'; break;
|
||||
case 'f': result += '\f'; break;
|
||||
case 'n': result += '\n'; break;
|
||||
case 'r': result += '\r'; break;
|
||||
case 't': result += '\t'; break;
|
||||
case 'v': result += '\v'; break;
|
||||
case '"': result += '"'; break;
|
||||
case '\'': result += '\''; break;
|
||||
case '\\': result += '\\'; break;
|
||||
case 'a': buffer += '\a'; break;
|
||||
case 'b': buffer += '\b'; break;
|
||||
case 'f': buffer += '\f'; break;
|
||||
case 'n': buffer += '\n'; break;
|
||||
case 'r': buffer += '\r'; break;
|
||||
case 't': buffer += '\t'; break;
|
||||
case 'v': buffer += '\v'; break;
|
||||
case '"': buffer += '"'; break;
|
||||
case '\'': buffer += '\''; break;
|
||||
case '\\': buffer += '\\'; break;
|
||||
default:
|
||||
qDebug() << "MI Parse Error, unrecognized backslash escape";
|
||||
}
|
||||
}
|
||||
|
||||
// Reads subsequent \123 or \x12 entities and converts to Utf8,
|
||||
// *or* one escaped char, *or* one unescaped char.
|
||||
static void parseCharOrEscape(DebuggerOutputParser &parser, QString &result)
|
||||
// Reads one \123 or \x12 entity, *or* one escaped char, *or* one unescaped char.
|
||||
static void parseCharOrEscape(DebuggerOutputParser &parser, DebuggerOutputParser::Buffer &buffer)
|
||||
{
|
||||
QByteArray buffer;
|
||||
while (parseOctalEscapedHelper(parser, buffer))
|
||||
;
|
||||
while (parseHexEscapedHelper(parser, buffer))
|
||||
;
|
||||
|
||||
if (!buffer.isEmpty()) {
|
||||
result.append(QString::fromUtf8(buffer));
|
||||
} else if (parser.isCurrent('\\')) {
|
||||
if (parser.isCurrent('\\')) {
|
||||
if (parseOctalEscapedHelper(parser, buffer))
|
||||
return;
|
||||
if (parseHexEscapedHelper(parser, buffer))
|
||||
return;
|
||||
parser.advance();
|
||||
parseSimpleEscape(parser, result);
|
||||
parseSimpleEscape(parser, buffer);
|
||||
} else {
|
||||
result += parser.readChar();
|
||||
buffer += char(parser.readChar().unicode());
|
||||
}
|
||||
}
|
||||
|
||||
QString DebuggerOutputParser::readCString()
|
||||
void DebuggerOutputParser::readCStringData(Buffer &buffer)
|
||||
{
|
||||
if (isAtEnd())
|
||||
return QString();
|
||||
return;
|
||||
|
||||
if (*from != '"') {
|
||||
qDebug() << "MI Parse Error, double quote expected";
|
||||
++from; // So we don't hang
|
||||
return QString();
|
||||
return;
|
||||
}
|
||||
|
||||
++from; // Skip initial quote.
|
||||
QString result;
|
||||
result.reserve(to - from);
|
||||
while (from < to) {
|
||||
if (*from == '"') {
|
||||
++from;
|
||||
return result;
|
||||
return;
|
||||
}
|
||||
parseCharOrEscape(*this, result);
|
||||
parseCharOrEscape(*this, buffer);
|
||||
}
|
||||
|
||||
qDebug() << "MI Parse Error, unfinished string";
|
||||
return QString();
|
||||
}
|
||||
|
||||
QString DebuggerOutputParser::readCString()
|
||||
{
|
||||
Buffer buffer;
|
||||
readCStringData(buffer);
|
||||
return QString::fromUtf8(buffer);
|
||||
}
|
||||
|
||||
void GdbMi::parseValue(DebuggerOutputParser &parser)
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <QString>
|
||||
#include <QJsonValue>
|
||||
#include <QJsonObject>
|
||||
#include <QVarLengthArray>
|
||||
#include <QVector>
|
||||
|
||||
#include <utils/filepath.h>
|
||||
@@ -105,6 +106,8 @@ class DebuggerOutputParser
|
||||
public:
|
||||
explicit DebuggerOutputParser(const QString &output);
|
||||
|
||||
using Buffer = QVarLengthArray<char, 30>;
|
||||
|
||||
QChar current() const { return *from; }
|
||||
bool isCurrent(QChar c) const { return *from == c; }
|
||||
bool isAtEnd() const { return from >= to; }
|
||||
@@ -116,9 +119,11 @@ public:
|
||||
int readInt();
|
||||
QChar readChar();
|
||||
QString readCString();
|
||||
QString readString(const std::function<bool(char)> &isValidChar);
|
||||
void readCStringData(Buffer &buffer);
|
||||
|
||||
QString buffer() const { return QString(from, to - from); }
|
||||
QStringView readString(const std::function<bool(char)> &isValidChar);
|
||||
|
||||
QStringView buffer() const { return QStringView(from, to - from); }
|
||||
int remainingChars() const { return int(to - from); }
|
||||
|
||||
void skipCommas();
|
||||
|
||||
@@ -246,7 +246,7 @@ void GdbEngine::handleResponse(const QString &buff)
|
||||
case '*':
|
||||
case '+':
|
||||
case '=': {
|
||||
const QString asyncClass = parser.readString(isNameChar);
|
||||
const QStringView asyncClass = parser.readString(isNameChar);
|
||||
GdbMi result;
|
||||
while (!parser.isAtEnd()) {
|
||||
GdbMi data;
|
||||
@@ -365,17 +365,17 @@ void GdbEngine::handleResponse(const QString &buff)
|
||||
|
||||
response.token = token;
|
||||
|
||||
QString resultClass = parser.readString(isNameChar);
|
||||
const QStringView resultClass = parser.readString(isNameChar);
|
||||
|
||||
if (resultClass == "done")
|
||||
if (resultClass == u"done")
|
||||
response.resultClass = ResultDone;
|
||||
else if (resultClass == "running")
|
||||
else if (resultClass == u"running")
|
||||
response.resultClass = ResultRunning;
|
||||
else if (resultClass == "connected")
|
||||
else if (resultClass == u"connected")
|
||||
response.resultClass = ResultConnected;
|
||||
else if (resultClass == "error")
|
||||
else if (resultClass == u"error")
|
||||
response.resultClass = ResultError;
|
||||
else if (resultClass == "exit")
|
||||
else if (resultClass == u"exit")
|
||||
response.resultClass = ResultExit;
|
||||
else
|
||||
response.resultClass = ResultUnknown;
|
||||
@@ -410,11 +410,14 @@ void GdbEngine::handleResponse(const QString &buff)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (debuggerSettings()->logTimeStamps.value())
|
||||
showMessage(QString("Output handled"));
|
||||
}
|
||||
|
||||
void GdbEngine::handleAsyncOutput(const QString &asyncClass, const GdbMi &result)
|
||||
void GdbEngine::handleAsyncOutput(const QStringView asyncClass, const GdbMi &result)
|
||||
{
|
||||
if (asyncClass == "stopped") {
|
||||
if (asyncClass == u"stopped") {
|
||||
if (m_inUpdateLocals) {
|
||||
showMessage("UNEXPECTED *stopped NOTIFICATION IGNORED", LogWarning);
|
||||
} else {
|
||||
@@ -422,7 +425,7 @@ void GdbEngine::handleAsyncOutput(const QString &asyncClass, const GdbMi &result
|
||||
m_pendingLogStreamOutput.clear();
|
||||
m_pendingConsoleStreamOutput.clear();
|
||||
}
|
||||
} else if (asyncClass == "running") {
|
||||
} else if (asyncClass == u"running") {
|
||||
if (m_inUpdateLocals) {
|
||||
showMessage("UNEXPECTED *running NOTIFICATION IGNORED", LogWarning);
|
||||
} else {
|
||||
@@ -443,7 +446,7 @@ void GdbEngine::handleAsyncOutput(const QString &asyncClass, const GdbMi &result
|
||||
notifyInferiorRunOk();
|
||||
}
|
||||
}
|
||||
} else if (asyncClass == "library-loaded") {
|
||||
} else if (asyncClass == u"library-loaded") {
|
||||
// Archer has 'id="/usr/lib/libdrm.so.2",
|
||||
// target-name="/usr/lib/libdrm.so.2",
|
||||
// host-name="/usr/lib/libdrm.so.2",
|
||||
@@ -464,7 +467,7 @@ void GdbEngine::handleAsyncOutput(const QString &asyncClass, const GdbMi &result
|
||||
module.modulePath = result["target-name"].data();
|
||||
module.moduleName = QFileInfo(module.hostPath).baseName();
|
||||
modulesHandler()->updateModule(module);
|
||||
} else if (asyncClass == "library-unloaded") {
|
||||
} else if (asyncClass == u"library-unloaded") {
|
||||
// Archer has 'id="/usr/lib/libdrm.so.2",
|
||||
// target-name="/usr/lib/libdrm.so.2",
|
||||
// host-name="/usr/lib/libdrm.so.2"
|
||||
@@ -472,9 +475,9 @@ void GdbEngine::handleAsyncOutput(const QString &asyncClass, const GdbMi &result
|
||||
modulesHandler()->removeModule(result["target-name"].data());
|
||||
progressPing();
|
||||
showStatusMessage(Tr::tr("Library %1 unloaded.").arg(id), 1000);
|
||||
} else if (asyncClass == "thread-group-added") {
|
||||
} else if (asyncClass == u"thread-group-added") {
|
||||
// 7.1-symbianelf has "{id="i1"}"
|
||||
} else if (asyncClass == "thread-group-started") {
|
||||
} else if (asyncClass == u"thread-group-started") {
|
||||
// Archer had only "{id="28902"}" at some point of 6.8.x.
|
||||
// *-started seems to be standard in 7.1, but in early
|
||||
// 7.0.x, there was a *-created instead.
|
||||
@@ -484,7 +487,7 @@ void GdbEngine::handleAsyncOutput(const QString &asyncClass, const GdbMi &result
|
||||
showStatusMessage(Tr::tr("Thread group %1 created.").arg(id), 1000);
|
||||
notifyInferiorPid(result["pid"].toProcessHandle());
|
||||
handleThreadGroupCreated(result);
|
||||
} else if (asyncClass == "thread-created") {
|
||||
} else if (asyncClass == u"thread-created") {
|
||||
//"{id="1",group-id="28902"}"
|
||||
QString id = result["id"].data();
|
||||
showStatusMessage(Tr::tr("Thread %1 created.").arg(id), 1000);
|
||||
@@ -492,23 +495,23 @@ void GdbEngine::handleAsyncOutput(const QString &asyncClass, const GdbMi &result
|
||||
thread.id = id;
|
||||
thread.groupId = result["group-id"].data();
|
||||
threadsHandler()->updateThread(thread);
|
||||
} else if (asyncClass == "thread-group-exited") {
|
||||
} else if (asyncClass == u"thread-group-exited") {
|
||||
// Archer has "{id="28902"}"
|
||||
QString id = result["id"].data();
|
||||
showStatusMessage(Tr::tr("Thread group %1 exited.").arg(id), 1000);
|
||||
handleThreadGroupExited(result);
|
||||
} else if (asyncClass == "thread-exited") {
|
||||
} else if (asyncClass == u"thread-exited") {
|
||||
//"{id="1",group-id="28902"}"
|
||||
QString id = result["id"].data();
|
||||
QString groupid = result["group-id"].data();
|
||||
showStatusMessage(Tr::tr("Thread %1 in group %2 exited.")
|
||||
.arg(id).arg(groupid), 1000);
|
||||
threadsHandler()->removeThread(id);
|
||||
} else if (asyncClass == "thread-selected") {
|
||||
} else if (asyncClass == u"thread-selected") {
|
||||
QString id = result["id"].data();
|
||||
showStatusMessage(Tr::tr("Thread %1 selected.").arg(id), 1000);
|
||||
//"{id="2"}"
|
||||
} else if (asyncClass == "breakpoint-modified") {
|
||||
} else if (asyncClass == u"breakpoint-modified") {
|
||||
// New in FSF gdb since 2011-04-27.
|
||||
// "{bkpt={number="3",type="breakpoint",disp="keep",
|
||||
// enabled="y",addr="<MULTIPLE>",times="1",
|
||||
@@ -547,7 +550,7 @@ void GdbEngine::handleAsyncOutput(const QString &asyncClass, const GdbMi &result
|
||||
}
|
||||
if (bp)
|
||||
bp->adjustMarker();
|
||||
} else if (asyncClass == "breakpoint-created") {
|
||||
} else if (asyncClass == u"breakpoint-created") {
|
||||
// "{bkpt={number="1",type="breakpoint",disp="del",enabled="y",
|
||||
// addr="<PENDING>",pending="main",times="0",
|
||||
// original-location="main"}}" -- or --
|
||||
@@ -561,7 +564,7 @@ void GdbEngine::handleAsyncOutput(const QString &asyncClass, const GdbMi &result
|
||||
br.updateFromGdbOutput(bkpt);
|
||||
handler->handleAlienBreakpoint(nr, br);
|
||||
}
|
||||
} else if (asyncClass == "breakpoint-deleted") {
|
||||
} else if (asyncClass == u"breakpoint-deleted") {
|
||||
// "breakpoint-deleted" "{id="1"}"
|
||||
// New in FSF gdb since 2011-04-27.
|
||||
const QString nr = result["id"].data();
|
||||
@@ -571,15 +574,15 @@ void GdbEngine::handleAsyncOutput(const QString &asyncClass, const GdbMi &result
|
||||
// if (!bp.isOneShot()) ... is not sufficient.
|
||||
// It keeps temporary "Jump" breakpoints alive.
|
||||
breakHandler()->removeAlienBreakpoint(nr);
|
||||
} else if (asyncClass == "cmd-param-changed") {
|
||||
} else if (asyncClass == u"cmd-param-changed") {
|
||||
// New since 2012-08-09
|
||||
// "{param="debug remote",value="1"}"
|
||||
} else if (asyncClass == "memory-changed") {
|
||||
} else if (asyncClass == u"memory-changed") {
|
||||
// New since 2013
|
||||
// "{thread-group="i1",addr="0x0918a7a8",len="0x10"}"
|
||||
} else if (asyncClass == "tsv-created") {
|
||||
} else if (asyncClass == u"tsv-created") {
|
||||
// New since 2013-02-06
|
||||
} else if (asyncClass == "tsv-modified") {
|
||||
} else if (asyncClass == u"tsv-modified") {
|
||||
// New since 2013-02-06
|
||||
} else {
|
||||
qDebug() << "IGNORED ASYNC OUTPUT"
|
||||
|
||||
@@ -134,7 +134,7 @@ private: ////////// General Interface //////////
|
||||
////////// Gdb Output, State & Capability Handling //////////
|
||||
|
||||
Q_INVOKABLE void handleResponse(const QString &buff);
|
||||
void handleAsyncOutput(const QString &asyncClass, const GdbMi &result);
|
||||
void handleAsyncOutput(const QStringView asyncClass, const GdbMi &result);
|
||||
void handleStopResponse(const GdbMi &data);
|
||||
void handleResultRecord(DebuggerResponse *response);
|
||||
void handleStop1(const GdbMi &data);
|
||||
|
||||
@@ -15,6 +15,10 @@
|
||||
|
||||
namespace Debugger::Internal {
|
||||
|
||||
const QStringView inameLocal = u"local.";
|
||||
const QStringView inameWatch = u"watch.";
|
||||
const QStringView inameInspect = u"inspect.";
|
||||
|
||||
bool isPointerType(const QStringView type)
|
||||
{
|
||||
return type.endsWith('*') || type.endsWith(u"* const");
|
||||
@@ -316,7 +320,7 @@ void WatchItem::parseHelper(const GdbMi &input, bool maySort)
|
||||
if (mi.isValid()) {
|
||||
address = mi.toAddress();
|
||||
if (exp.isEmpty()) {
|
||||
if (iname.startsWith("local.") && iname.count('.') == 1)
|
||||
if (iname.startsWith(inameLocal) && iname.count('.') == 1)
|
||||
// Solve one common case of adding 'class' in
|
||||
// *(class X*)0xdeadbeef for gdb.
|
||||
exp = name;
|
||||
@@ -519,7 +523,7 @@ bool WatchItem::isLocal() const
|
||||
if (arrayIndex >= 0)
|
||||
if (const WatchItem *p = parent())
|
||||
return p->isLocal();
|
||||
return iname.startsWith("local.");
|
||||
return iname.startsWith(inameLocal);
|
||||
}
|
||||
|
||||
bool WatchItem::isWatcher() const
|
||||
@@ -527,7 +531,7 @@ bool WatchItem::isWatcher() const
|
||||
if (arrayIndex >= 0)
|
||||
if (const WatchItem *p = parent())
|
||||
return p->isWatcher();
|
||||
return iname.startsWith("watch.");
|
||||
return iname.startsWith(inameWatch);
|
||||
}
|
||||
|
||||
bool WatchItem::isInspect() const
|
||||
@@ -535,7 +539,7 @@ bool WatchItem::isInspect() const
|
||||
if (arrayIndex >= 0)
|
||||
if (const WatchItem *p = parent())
|
||||
return p->isInspect();
|
||||
return iname.startsWith("inspect.");
|
||||
return iname.startsWith(inameInspect);
|
||||
}
|
||||
|
||||
QString WatchItem::internalName() const
|
||||
|
||||
@@ -80,6 +80,9 @@ public:
|
||||
bool outdated = false; // \internal item is to be removed.
|
||||
double time = 0; // Time used on the dumper side to produce this item
|
||||
|
||||
mutable QString valueCache; // Pre-computed displayed value
|
||||
void updateValueCache() const; // implemented in watchhandler.cpp
|
||||
|
||||
private:
|
||||
void parseHelper(const GdbMi &input, bool maySort);
|
||||
};
|
||||
|
||||
@@ -472,6 +472,7 @@ public:
|
||||
QSet<QString> m_expandedINames;
|
||||
QHash<QString, int> m_maxArrayCount;
|
||||
QTimer m_requestUpdateTimer;
|
||||
QTimer m_localsWindowsTimer;
|
||||
|
||||
QHash<QString, TypeInfo> m_reportedTypeInfo;
|
||||
QHash<QString, DisplayFormats> m_reportedTypeFormats; // Type name -> Dumper Formats
|
||||
@@ -518,6 +519,14 @@ WatchModel::WatchModel(WatchHandler *handler, DebuggerEngine *engine)
|
||||
connect(&m_requestUpdateTimer, &QTimer::timeout,
|
||||
this, &WatchModel::updateStarted);
|
||||
|
||||
m_localsWindowsTimer.setSingleShot(true);
|
||||
m_localsWindowsTimer.setInterval(50);
|
||||
connect(&m_localsWindowsTimer, &QTimer::timeout, this, [this] {
|
||||
// Force show/hide of return view.
|
||||
const bool showReturn = m_returnRoot->childCount() != 0;
|
||||
m_engine->updateLocalsWindow(showReturn);
|
||||
});
|
||||
|
||||
DebuggerSettings &s = *debuggerSettings();
|
||||
connect(&s.sortStructMembers, &BaseAspect::changed,
|
||||
m_engine, &DebuggerEngine::updateLocals);
|
||||
@@ -932,15 +941,22 @@ static QString displayName(const WatchItem *item)
|
||||
return result;
|
||||
}
|
||||
|
||||
static QString displayValue(const WatchItem *item)
|
||||
|
||||
void WatchItem::updateValueCache() const
|
||||
{
|
||||
QString result = truncateValue(formattedValue(item));
|
||||
result = watchModel(item)->removeNamespaces(result);
|
||||
if (result.isEmpty() && item->address)
|
||||
result += QString::fromLatin1("@0x" + QByteArray::number(item->address, 16));
|
||||
valueCache = truncateValue(formattedValue(this));
|
||||
valueCache = watchModel(this)->removeNamespaces(valueCache);
|
||||
if (valueCache.isEmpty() && this->address)
|
||||
valueCache += QString::fromLatin1("@0x" + QByteArray::number(this->address, 16));
|
||||
// if (origaddr)
|
||||
// result += QString::fromLatin1(" (0x" + QByteArray::number(origaddr, 16) + ')');
|
||||
return result;
|
||||
}
|
||||
|
||||
static QString displayValue(const WatchItem *item)
|
||||
{
|
||||
if (item->valueCache.isEmpty())
|
||||
item->updateValueCache();
|
||||
return item->valueCache;
|
||||
}
|
||||
|
||||
static QString displayType(const WatchItem *item)
|
||||
@@ -2311,7 +2327,7 @@ void WatchHandler::notifyUpdateFinished()
|
||||
m_model->forAllItems([this](WatchItem *item) {
|
||||
if (item->wantsChildren && isExpandedIName(item->iname)
|
||||
&& item->name != WatchItem::loadMoreName) {
|
||||
m_model->m_engine->showMessage(QString("ADJUSTING CHILD EXPECTATION FOR " + item->iname));
|
||||
// m_model->m_engine->showMessage(QString("ADJUSTING CHILD EXPECTATION FOR " + item->iname));
|
||||
item->wantsChildren = false;
|
||||
}
|
||||
});
|
||||
@@ -2570,9 +2586,7 @@ void WatchModel::clearWatches()
|
||||
|
||||
void WatchHandler::updateLocalsWindow()
|
||||
{
|
||||
// Force show/hide of return view.
|
||||
bool showReturn = m_model->m_returnRoot->childCount() != 0;
|
||||
m_engine->updateLocalsWindow(showReturn);
|
||||
m_model->m_localsWindowsTimer.start();
|
||||
}
|
||||
|
||||
QStringList WatchHandler::watchedExpressions()
|
||||
|
||||
@@ -171,7 +171,7 @@ void DocumentLocatorFilter::prepareSearch(const QString &/*entry*/)
|
||||
QMutexLocker locker(&m_mutex);
|
||||
if (m_symbolCache && !m_currentSymbols.has_value()) {
|
||||
locker.unlock();
|
||||
m_symbolCache->requestSymbols(m_currentUri, Schedule::Delayed);
|
||||
m_symbolCache->requestSymbols(m_currentUri, Schedule::Now);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2726,7 +2726,8 @@ void ProjectExplorerPluginPrivate::buildQueueFinished(bool success)
|
||||
RecentProjectsEntries ProjectExplorerPluginPrivate::recentProjects() const
|
||||
{
|
||||
return Utils::filtered(dd->m_recentProjects, [](const RecentProjectsEntry &p) {
|
||||
return p.first.isFile();
|
||||
// check if project is available, but avoid querying devices
|
||||
return p.first.needsDevice() || p.first.isFile();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -27,13 +27,11 @@
|
||||
#include <debugger/debuggeritemmanager.h>
|
||||
#include <debugger/debuggerkitinformation.h>
|
||||
|
||||
#include <coreplugin/icore.h>
|
||||
#include <utils/algorithm.h>
|
||||
|
||||
#include <QDebug>
|
||||
#include <QDir>
|
||||
#include <QDomDocument>
|
||||
#include <QMessageBox>
|
||||
#include <QFileInfo>
|
||||
|
||||
using namespace ProjectExplorer;
|
||||
using namespace QtSupport;
|
||||
@@ -178,15 +176,6 @@ bool QnxConfiguration::isActive() const
|
||||
return hasToolChain && hasDebugger;
|
||||
}
|
||||
|
||||
bool QnxConfiguration::canCreateKits() const
|
||||
{
|
||||
if (!isValid())
|
||||
return false;
|
||||
|
||||
return Utils::anyOf(m_targets,
|
||||
[this](const Target &target) -> bool { return qnxQtVersion(target); });
|
||||
}
|
||||
|
||||
FilePath QnxConfiguration::sdpPath() const
|
||||
{
|
||||
return envFile().parentDir();
|
||||
@@ -194,7 +183,7 @@ FilePath QnxConfiguration::sdpPath() const
|
||||
|
||||
QnxQtVersion *QnxConfiguration::qnxQtVersion(const Target &target) const
|
||||
{
|
||||
const QtVersions versions = QtVersionManager::instance()->versions(
|
||||
const QtVersions versions = QtVersionManager::versions(
|
||||
Utils::equal(&QtVersion::type, QString::fromLatin1(Constants::QNX_QNX_QT)));
|
||||
for (QtVersion *version : versions) {
|
||||
auto qnxQt = dynamic_cast<QnxQtVersion *>(version);
|
||||
@@ -228,13 +217,12 @@ void QnxConfiguration::createTools(const Target &target)
|
||||
|
||||
QVariant QnxConfiguration::createDebugger(const Target &target)
|
||||
{
|
||||
Utils::Environment sysEnv = Utils::Environment::systemEnvironment();
|
||||
Environment sysEnv = m_qnxHost.deviceEnvironment();
|
||||
sysEnv.modify(qnxEnvironmentItems());
|
||||
|
||||
Debugger::DebuggerItem debugger;
|
||||
debugger.setCommand(target.m_debuggerPath);
|
||||
debugger.reinitializeFromFile(nullptr, &sysEnv);
|
||||
debugger.setAutoDetected(true);
|
||||
debugger.setUnexpandedDisplayName(Tr::tr("Debugger for %1 (%2)")
|
||||
.arg(displayName())
|
||||
.arg(target.shortDescription()));
|
||||
@@ -278,10 +266,7 @@ QList<ToolChain *> QnxConfiguration::findToolChain(const QList<ToolChain *> &alr
|
||||
void QnxConfiguration::createKit(const Target &target, const QnxToolChainMap &toolChainMap,
|
||||
const QVariant &debugger)
|
||||
{
|
||||
QnxQtVersion *qnxQt = qnxQtVersion(target);
|
||||
// Do not create incomplete kits if no qt qnx version found
|
||||
if (!qnxQt)
|
||||
return;
|
||||
QnxQtVersion *qnxQt = qnxQtVersion(target); // nullptr is ok.
|
||||
|
||||
const auto init = [&](Kit *k) {
|
||||
QtKitAspect::setQtVersion(k, qnxQt);
|
||||
@@ -336,19 +321,43 @@ void QnxConfiguration::setVersion(const QnxVersionNumber &version)
|
||||
|
||||
void QnxConfiguration::readInformation()
|
||||
{
|
||||
const QString qConfigPath = m_qnxConfiguration.pathAppended("qconfig").toString();
|
||||
const QList <ConfigInstallInformation> installInfoList = QnxUtils::installedConfigs(qConfigPath);
|
||||
if (installInfoList.isEmpty())
|
||||
const FilePath configPath = m_qnxConfiguration / "qconfig";
|
||||
if (!configPath.isDir())
|
||||
return;
|
||||
|
||||
for (const ConfigInstallInformation &info : installInfoList) {
|
||||
if (m_qnxHost == FilePath::fromString(info.host).canonicalPath()
|
||||
&& m_qnxTarget == FilePath::fromString(info.target).canonicalPath()) {
|
||||
m_configName = info.name;
|
||||
setVersion(QnxVersionNumber(info.version));
|
||||
break;
|
||||
}
|
||||
}
|
||||
configPath.iterateDirectory([this, configPath](const FilePath &sdpFile) {
|
||||
QFile xmlFile(sdpFile.toFSPathString());
|
||||
if (!xmlFile.open(QIODevice::ReadOnly))
|
||||
return IterationPolicy::Continue;
|
||||
|
||||
QDomDocument doc;
|
||||
if (!doc.setContent(&xmlFile)) // Skip error message
|
||||
return IterationPolicy::Continue;
|
||||
|
||||
QDomElement docElt = doc.documentElement();
|
||||
if (docElt.tagName() != QLatin1String("qnxSystemDefinition"))
|
||||
return IterationPolicy::Continue;
|
||||
|
||||
QDomElement childElt = docElt.firstChildElement(QLatin1String("installation"));
|
||||
// The file contains only one installation node
|
||||
if (childElt.isNull()) // The file contains only one base node
|
||||
return IterationPolicy::Continue;
|
||||
|
||||
FilePath host = configPath.withNewPath(
|
||||
childElt.firstChildElement(QLatin1String("host")).text()).canonicalPath();
|
||||
if (m_qnxHost != host)
|
||||
return IterationPolicy::Continue;
|
||||
|
||||
FilePath target = configPath.withNewPath(
|
||||
childElt.firstChildElement(QLatin1String("target")).text()).canonicalPath();
|
||||
if (m_qnxTarget != target)
|
||||
return IterationPolicy::Continue;
|
||||
|
||||
m_configName = childElt.firstChildElement(QLatin1String("name")).text();
|
||||
QString version = childElt.firstChildElement(QLatin1String("version")).text();
|
||||
setVersion(QnxVersionNumber(version));
|
||||
return IterationPolicy::Stop;
|
||||
}, {{"*.xml"}, QDir::Files});
|
||||
}
|
||||
|
||||
void QnxConfiguration::setDefaultConfiguration(const FilePath &envScript)
|
||||
@@ -369,6 +378,10 @@ void QnxConfiguration::setDefaultConfiguration(const FilePath &envScript)
|
||||
if (qccPath.exists())
|
||||
m_qccCompiler = qccPath;
|
||||
|
||||
// Some fall back in case the qconfig dir with .xml files is not found later
|
||||
if (m_configName.isEmpty())
|
||||
m_configName = QString("%1 - %2").arg(m_qnxHost.fileName(), m_qnxTarget.fileName());
|
||||
|
||||
updateTargets();
|
||||
assignDebuggersToTargets();
|
||||
|
||||
|
||||
@@ -47,7 +47,6 @@ public:
|
||||
bool activate();
|
||||
void deactivate();
|
||||
bool isActive() const;
|
||||
bool canCreateKits() const;
|
||||
Utils::FilePath sdpPath() const;
|
||||
|
||||
QList<ProjectExplorer::ToolChain *> autoDetect(
|
||||
|
||||
@@ -99,7 +99,6 @@ void QnxConfigurationManager::saveConfigs()
|
||||
++count;
|
||||
}
|
||||
|
||||
|
||||
data.insert(QLatin1String(QNXConfigCountKey), count);
|
||||
m_writer->save(data, Core::ICore::dialogParent());
|
||||
}
|
||||
|
||||
@@ -130,8 +130,7 @@ void QnxSettingsWidget::addConfiguration()
|
||||
return;
|
||||
|
||||
QnxConfiguration *config = new QnxConfiguration(envFile);
|
||||
if (m_qnxConfigManager->configurations().contains(config)
|
||||
|| !config->isValid()) {
|
||||
if (m_qnxConfigManager->configurations().contains(config) || !config->isValid()) {
|
||||
QMessageBox::warning(Core::ICore::dialogParent(),
|
||||
Tr::tr("Warning"),
|
||||
Tr::tr("Configuration already exists or is invalid."));
|
||||
@@ -184,7 +183,7 @@ void QnxSettingsWidget::updateInformation()
|
||||
m_configsCombo->itemData(currentIndex).value<void*>());
|
||||
|
||||
// update the checkbox
|
||||
m_generateKitsCheckBox->setEnabled(config ? config->canCreateKits() : false);
|
||||
m_generateKitsCheckBox->setEnabled(config ? config->isValid() : false);
|
||||
m_generateKitsCheckBox->setChecked(config ? config->isActive() : false);
|
||||
|
||||
// update information
|
||||
|
||||
@@ -4,16 +4,11 @@
|
||||
#include "qnxutils.h"
|
||||
|
||||
#include <utils/algorithm.h>
|
||||
#include <utils/fileutils.h>
|
||||
#include <utils/hostosinfo.h>
|
||||
#include <utils/qtcprocess.h>
|
||||
#include <utils/temporaryfile.h>
|
||||
|
||||
#include <QDebug>
|
||||
#include <QDir>
|
||||
#include <QDirIterator>
|
||||
#include <QDomDocument>
|
||||
#include <QStandardPaths>
|
||||
#include <QApplication>
|
||||
|
||||
using namespace ProjectExplorer;
|
||||
@@ -125,7 +120,7 @@ EnvironmentItems QnxUtils::qnxEnvironmentFromEnvFile(const FilePath &filePath)
|
||||
return items;
|
||||
}
|
||||
|
||||
FilePath QnxUtils::envFilePath(const FilePath &sdpPath)
|
||||
EnvironmentItems QnxUtils::qnxEnvironment(const FilePath &sdpPath)
|
||||
{
|
||||
FilePaths entries;
|
||||
if (sdpPath.osType() == OsTypeWindows)
|
||||
@@ -133,68 +128,10 @@ FilePath QnxUtils::envFilePath(const FilePath &sdpPath)
|
||||
else
|
||||
entries = sdpPath.dirEntries({{"*-env.sh"}});
|
||||
|
||||
if (!entries.isEmpty())
|
||||
return entries.first();
|
||||
|
||||
if (entries.isEmpty())
|
||||
return {};
|
||||
}
|
||||
|
||||
QString QnxUtils::defaultTargetVersion(const QString &sdpPath)
|
||||
{
|
||||
const QList<ConfigInstallInformation> configs = installedConfigs();
|
||||
for (const ConfigInstallInformation &sdpInfo : configs) {
|
||||
if (!sdpInfo.path.compare(sdpPath, HostOsInfo::fileNameCaseSensitivity()))
|
||||
return sdpInfo.version;
|
||||
}
|
||||
|
||||
return QString();
|
||||
}
|
||||
|
||||
QList<ConfigInstallInformation> QnxUtils::installedConfigs(const QString &configPath)
|
||||
{
|
||||
QList<ConfigInstallInformation> sdpList;
|
||||
QString sdpConfigPath = configPath;
|
||||
|
||||
if (!QDir(sdpConfigPath).exists())
|
||||
return sdpList;
|
||||
|
||||
const QFileInfoList sdpfileList
|
||||
= QDir(sdpConfigPath).entryInfoList(QStringList{"*.xml"}, QDir::Files, QDir::Time);
|
||||
for (const QFileInfo &sdpFile : sdpfileList) {
|
||||
QFile xmlFile(sdpFile.absoluteFilePath());
|
||||
if (!xmlFile.open(QIODevice::ReadOnly))
|
||||
continue;
|
||||
|
||||
QDomDocument doc;
|
||||
if (!doc.setContent(&xmlFile)) // Skip error message
|
||||
continue;
|
||||
|
||||
QDomElement docElt = doc.documentElement();
|
||||
if (docElt.tagName() != QLatin1String("qnxSystemDefinition"))
|
||||
continue;
|
||||
|
||||
QDomElement childElt = docElt.firstChildElement(QLatin1String("installation"));
|
||||
// The file contains only one installation node
|
||||
if (!childElt.isNull()) {
|
||||
// The file contains only one base node
|
||||
ConfigInstallInformation sdpInfo;
|
||||
sdpInfo.path = childElt.firstChildElement(QLatin1String("base")).text();
|
||||
sdpInfo.name = childElt.firstChildElement(QLatin1String("name")).text();
|
||||
sdpInfo.host = childElt.firstChildElement(QLatin1String("host")).text();
|
||||
sdpInfo.target = childElt.firstChildElement(QLatin1String("target")).text();
|
||||
sdpInfo.version = childElt.firstChildElement(QLatin1String("version")).text();
|
||||
sdpInfo.installationXmlFilePath = sdpFile.absoluteFilePath();
|
||||
|
||||
sdpList.append(sdpInfo);
|
||||
}
|
||||
}
|
||||
|
||||
return sdpList;
|
||||
}
|
||||
|
||||
EnvironmentItems QnxUtils::qnxEnvironment(const FilePath &sdpPath)
|
||||
{
|
||||
return qnxEnvironmentFromEnvFile(envFilePath(sdpPath));
|
||||
return qnxEnvironmentFromEnvFile(entries.first());
|
||||
}
|
||||
|
||||
QList<QnxTarget> QnxUtils::findTargets(const FilePath &basePath)
|
||||
|
||||
@@ -3,30 +3,14 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "qnxconstants.h"
|
||||
|
||||
#include <projectexplorer/abi.h>
|
||||
|
||||
#include <utils/environment.h>
|
||||
#include <utils/qtcassert.h>
|
||||
#include <utils/fileutils.h>
|
||||
#include <utils/filepath.h>
|
||||
|
||||
namespace Qnx::Internal {
|
||||
|
||||
class ConfigInstallInformation
|
||||
{
|
||||
public:
|
||||
QString path;
|
||||
QString name;
|
||||
QString host;
|
||||
QString target;
|
||||
QString version;
|
||||
QString installationXmlFilePath;
|
||||
|
||||
bool isValid() { return !path.isEmpty() && !name.isEmpty() && !host.isEmpty()
|
||||
&& !target.isEmpty() && !version.isEmpty() && !installationXmlFilePath.isEmpty(); }
|
||||
};
|
||||
|
||||
class QnxTarget
|
||||
{
|
||||
public:
|
||||
@@ -38,19 +22,14 @@ public:
|
||||
ProjectExplorer::Abi m_abi;
|
||||
};
|
||||
|
||||
class QnxUtils
|
||||
{
|
||||
public:
|
||||
static QString cpuDirFromAbi(const ProjectExplorer::Abi &abi);
|
||||
static QString cpuDirShortDescription(const QString &cpuDir);
|
||||
static Utils::EnvironmentItems qnxEnvironmentFromEnvFile(const Utils::FilePath &filePath);
|
||||
static Utils::FilePath envFilePath(const Utils::FilePath &sdpPath);
|
||||
static QString defaultTargetVersion(const QString &sdpPath);
|
||||
static QList<ConfigInstallInformation> installedConfigs(const QString &configPath = QString());
|
||||
static Utils::EnvironmentItems qnxEnvironment(const Utils::FilePath &sdpPath);
|
||||
static QList<QnxTarget> findTargets(const Utils::FilePath &basePath);
|
||||
static ProjectExplorer::Abi convertAbi(const ProjectExplorer::Abi &abi);
|
||||
static ProjectExplorer::Abis convertAbis(const ProjectExplorer::Abis &abis);
|
||||
};
|
||||
namespace QnxUtils {
|
||||
QString cpuDirFromAbi(const ProjectExplorer::Abi &abi);
|
||||
QString cpuDirShortDescription(const QString &cpuDir);
|
||||
Utils::EnvironmentItems qnxEnvironmentFromEnvFile(const Utils::FilePath &filePath);
|
||||
Utils::EnvironmentItems qnxEnvironment(const Utils::FilePath &sdpPath);
|
||||
QList<QnxTarget> findTargets(const Utils::FilePath &basePath);
|
||||
ProjectExplorer::Abi convertAbi(const ProjectExplorer::Abi &abi);
|
||||
ProjectExplorer::Abis convertAbis(const ProjectExplorer::Abis &abis);
|
||||
}
|
||||
|
||||
} // Qnx::Internal
|
||||
|
||||
@@ -286,7 +286,7 @@ void TextMark::addToToolTipLayout(QGridLayout *target) const
|
||||
const bool isHidden = TextDocument::marksAnnotationHidden(m_category.id);
|
||||
visibilityAction->setIcon(Utils::Icons::EYE_OPEN_TOOLBAR.icon());
|
||||
const QString tooltip = (isHidden ? Tr::tr("Show inline annotations for %1")
|
||||
: Tr::tr("Temporary hide inline annotations for %1"))
|
||||
: Tr::tr("Temporarily hide inline annotations for %1"))
|
||||
.arg(m_category.displayName);
|
||||
visibilityAction->setToolTip(tooltip);
|
||||
auto callback = [id = m_category.id, isHidden] {
|
||||
|
||||
@@ -3577,10 +3577,10 @@ void tst_Dumpers::dumper_data()
|
||||
+ Check("ptr50.data", "", "Foo")
|
||||
+ Check("ptr53", "", "@QWeakPointer<Foo>")
|
||||
|
||||
+ Check("ptr60.data", "", "MyClass")
|
||||
+ Check("ptr61.data", "", "MyClass")
|
||||
+ Check("ptr60.data.val", "44", "int")
|
||||
+ Check("ptr61.data.val", "44", "int");
|
||||
+ Check("ptr60.data", "", "MyClass") % NoLldbEngine
|
||||
+ Check("ptr61.data", "", "MyClass") % NoLldbEngine
|
||||
+ Check("ptr60.data.val", "44", "int") % NoLldbEngine
|
||||
+ Check("ptr61.data.val", "44", "int") % NoLldbEngine;
|
||||
|
||||
|
||||
QTest::newRow("QLazilyAllocated")
|
||||
@@ -7467,7 +7467,7 @@ void tst_Dumpers::dumper_data()
|
||||
+ Check("dr.@2.c", "3", "int")
|
||||
+ Check("dr.d", "4", "int")
|
||||
|
||||
+ Check("array.0.val", "44", "int");
|
||||
+ Check("array.0.val", "44", "int") % NoLldbEngine;
|
||||
|
||||
|
||||
QTest::newRow("Gdb13393")
|
||||
|
||||
@@ -77,6 +77,8 @@ private slots:
|
||||
void testJoinStrings();
|
||||
void testTrim_data();
|
||||
void testTrim();
|
||||
void testWildcardToRegularExpression_data();
|
||||
void testWildcardToRegularExpression();
|
||||
|
||||
private:
|
||||
TestMacroExpander mx;
|
||||
@@ -330,6 +332,78 @@ void tst_StringUtils::testTrim()
|
||||
QCOMPARE(Utils::trim(data.input, data.ch), data.bothSides);
|
||||
}
|
||||
|
||||
void tst_StringUtils::testWildcardToRegularExpression_data()
|
||||
{
|
||||
QTest::addColumn<QString>("pattern");
|
||||
QTest::addColumn<QString>("string");
|
||||
QTest::addColumn<bool>("matches");
|
||||
auto addRow = [](const char *pattern, const char *string, bool matchesNonPathGlob) {
|
||||
QTest::addRow("%s@%s", pattern, string) << pattern << string << matchesNonPathGlob;
|
||||
};
|
||||
addRow("*.html", "test.html", true);
|
||||
addRow("*.html", "test.htm", false);
|
||||
addRow("*bar*", "foobarbaz", true);
|
||||
addRow("*", "Qt Rocks!", true);
|
||||
addRow("*.h", "test.cpp", false);
|
||||
addRow("*.???l", "test.html", true);
|
||||
addRow("*?", "test.html", true);
|
||||
addRow("*?ml", "test.html", true);
|
||||
addRow("*[*]", "test.html", false);
|
||||
addRow("*[?]", "test.html", false);
|
||||
addRow("*[?]ml", "test.h?ml", true);
|
||||
addRow("*[[]ml", "test.h[ml", true);
|
||||
addRow("*[]]ml", "test.h]ml", true);
|
||||
addRow("*.h[a-z]ml", "test.html", true);
|
||||
addRow("*.h[A-Z]ml", "test.html", false);
|
||||
addRow("*.h[A-Z]ml", "test.hTml", true);
|
||||
addRow("*.h[!A-Z]ml", "test.hTml", false);
|
||||
addRow("*.h[!A-Z]ml", "test.html", true);
|
||||
addRow("*.h[!T]ml", "test.hTml", false);
|
||||
addRow("*.h[!T]ml", "test.html", true);
|
||||
addRow("*.h[!T]m[!L]", "test.htmL", false);
|
||||
addRow("*.h[!T]m[!L]", "test.html", true);
|
||||
addRow("*.h[][!]ml", "test.h]ml", true);
|
||||
addRow("*.h[][!]ml", "test.h[ml", true);
|
||||
addRow("*.h[][!]ml", "test.h!ml", true);
|
||||
addRow("foo/*/bar", "foo/baz/bar", true);
|
||||
addRow("foo/*/bar", "foo/fie/baz/bar", true);
|
||||
addRow("foo?bar", "foo/bar", true);
|
||||
addRow("foo/(*)/bar", "foo/baz/bar", false);
|
||||
addRow("foo/(*)/bar", "foo/(baz)/bar", true);
|
||||
addRow("foo/?/bar", "foo/Q/bar", true);
|
||||
addRow("foo/?/bar", "foo/Qt/bar", false);
|
||||
addRow("foo/(?)/bar", "foo/Q/bar", false);
|
||||
addRow("foo/(?)/bar", "foo/(Q)/bar", true);
|
||||
addRow("foo\\*\\bar", "foo\\baz\\bar", true);
|
||||
addRow("foo\\*\\bar", "foo/baz/bar", false);
|
||||
addRow("foo\\*\\bar", "foo/baz\\bar", false);
|
||||
addRow("foo\\*\\bar", "foo\\fie\\baz\\bar", true);
|
||||
addRow("foo\\*\\bar", "foo/fie/baz/bar", false);
|
||||
addRow("foo/*/bar", "foo\\baz\\bar", false);
|
||||
addRow("foo/*/bar", "foo/baz/bar", true);
|
||||
addRow("foo/*/bar", "foo\\fie\\baz\\bar", false);
|
||||
addRow("foo/*/bar", "foo/fie/baz/bar", true);
|
||||
addRow("foo\\(*)\\bar", "foo\\baz\\bar", false);
|
||||
addRow("foo\\(*)\\bar", "foo\\(baz)\\bar", true);
|
||||
addRow("foo\\?\\bar", "foo\\Q\\bar", true);
|
||||
addRow("foo\\?\\bar", "foo\\Qt\\bar", false);
|
||||
addRow("foo\\(?)\\bar", "foo\\Q\\bar", false);
|
||||
addRow("foo\\(?)\\bar", "foo\\(Q)\\bar", true);
|
||||
|
||||
addRow("foo*bar", "foo/fie/baz/bar", true);
|
||||
addRow("fie*bar", "foo/fie/baz/bar", false);
|
||||
}
|
||||
|
||||
void tst_StringUtils::testWildcardToRegularExpression()
|
||||
{
|
||||
QFETCH(QString, pattern);
|
||||
QFETCH(QString, string);
|
||||
QFETCH(bool, matches);
|
||||
|
||||
const QRegularExpression re(Utils::wildcardToRegularExpression(pattern));
|
||||
QCOMPARE(string.contains(re), matches);
|
||||
}
|
||||
|
||||
QTEST_GUILESS_MAIN(tst_StringUtils)
|
||||
|
||||
#include "tst_stringutils.moc"
|
||||
|
||||
@@ -1138,26 +1138,40 @@ void tst_TaskTree::storageOperators()
|
||||
}
|
||||
|
||||
// This test checks whether a running task tree may be safely destructed.
|
||||
// It also checks whether destructor of task tree deletes properly the storage created
|
||||
// while starting the task tree.
|
||||
// It also checks whether the destructor of a task tree deletes properly the storage created
|
||||
// while starting the task tree. When running task tree is destructed, the storage done
|
||||
// handler shouldn't be invoked.
|
||||
void tst_TaskTree::storageDestructor()
|
||||
{
|
||||
bool setupCalled = false;
|
||||
const auto setupHandler = [&setupCalled](CustomStorage *) {
|
||||
setupCalled = true;
|
||||
};
|
||||
bool doneCalled = false;
|
||||
const auto doneHandler = [&doneCalled](CustomStorage *) {
|
||||
doneCalled = true;
|
||||
};
|
||||
QCOMPARE(CustomStorage::instanceCount(), 0);
|
||||
{
|
||||
TreeStorage<CustomStorage> storage;
|
||||
const auto setupProcess = [testAppPath = m_testAppPath](QtcProcess &process) {
|
||||
process.setCommand(CommandLine(testAppPath, {"-sleep", "1000"}));
|
||||
};
|
||||
const Group root {
|
||||
Storage(TreeStorage<CustomStorage>()),
|
||||
Storage(storage),
|
||||
Process(setupProcess)
|
||||
};
|
||||
|
||||
TaskTree processTree(root);
|
||||
TaskTree taskTree(root);
|
||||
QCOMPARE(CustomStorage::instanceCount(), 0);
|
||||
processTree.start();
|
||||
taskTree.onStorageSetup(storage, setupHandler);
|
||||
taskTree.onStorageDone(storage, doneHandler);
|
||||
taskTree.start();
|
||||
QCOMPARE(CustomStorage::instanceCount(), 1);
|
||||
}
|
||||
QCOMPARE(CustomStorage::instanceCount(), 0);
|
||||
QVERIFY(setupCalled);
|
||||
QVERIFY(!doneCalled);
|
||||
}
|
||||
|
||||
QTEST_GUILESS_MAIN(tst_TaskTree)
|
||||
|
||||
@@ -241,7 +241,7 @@ void tst_CodeSize::codesize()
|
||||
#endif
|
||||
const int index = suite.cmd.indexOf(' ');
|
||||
QString command = suite.cmd.left(index);
|
||||
arguments = QString::fromLatin1(suite.cmd.mid(index + 1)) + arguments;
|
||||
arguments = QString::fromLatin1(suite.cmd.mid(index + 1)) + ' ' + arguments;
|
||||
QProcess final;
|
||||
final.setWorkingDirectory(t->buildPath);
|
||||
final.setProcessEnvironment(m_env);
|
||||
|
||||
@@ -21,6 +21,10 @@ class Targets:
|
||||
"Desktop 5.14.1 default",
|
||||
"Desktop 6.2.4"]))
|
||||
|
||||
@staticmethod
|
||||
def isOnlineInstaller(target):
|
||||
return target == Targets.DESKTOP_6_2_4
|
||||
|
||||
@staticmethod
|
||||
def availableTargetClasses(ignoreValidity=False):
|
||||
availableTargets = set(Targets.ALL_TARGETS)
|
||||
@@ -75,19 +79,20 @@ class LibType:
|
||||
return "Qt Plugin"
|
||||
return None
|
||||
|
||||
class Qt5Path:
|
||||
class QtPath:
|
||||
DOCS = 0
|
||||
EXAMPLES = 1
|
||||
|
||||
@staticmethod
|
||||
def getPaths(pathSpec):
|
||||
qt5targets = [Targets.DESKTOP_5_10_1_DEFAULT, Targets.DESKTOP_5_14_1_DEFAULT]
|
||||
qtTargets = [Targets.DESKTOP_5_10_1_DEFAULT, Targets.DESKTOP_5_14_1_DEFAULT,
|
||||
Targets.DESKTOP_6_2_4]
|
||||
if platform.system() != 'Darwin':
|
||||
qt5targets.append(Targets.DESKTOP_5_4_1_GCC)
|
||||
if pathSpec == Qt5Path.DOCS:
|
||||
return map(lambda target: Qt5Path.docsPath(target), qt5targets)
|
||||
elif pathSpec == Qt5Path.EXAMPLES:
|
||||
return map(lambda target: Qt5Path.examplesPath(target), qt5targets)
|
||||
qtTargets.append(Targets.DESKTOP_5_4_1_GCC)
|
||||
if pathSpec == QtPath.DOCS:
|
||||
return map(lambda target: QtPath.docsPath(target), qtTargets)
|
||||
elif pathSpec == QtPath.EXAMPLES:
|
||||
return map(lambda target: QtPath.examplesPath(target), qtTargets)
|
||||
else:
|
||||
test.fatal("Unknown pathSpec given: %s" % str(pathSpec))
|
||||
return []
|
||||
@@ -97,9 +102,9 @@ class Qt5Path:
|
||||
if target not in Targets.ALL_TARGETS:
|
||||
raise Exception("Unexpected target '%s'" % str(target))
|
||||
|
||||
matcher = re.match("^Desktop (5\.\\d{1,2}\.\\d{1,2}).*$", Targets.getStringForTarget(target))
|
||||
matcher = re.match("^Desktop ([56]\.\\d{1,2}\.\\d{1,2}).*$", Targets.getStringForTarget(target))
|
||||
if matcher is None:
|
||||
raise Exception("Currently this is supported for Desktop Qt5 only, got target '%s'"
|
||||
raise Exception("Currently this is supported for Desktop Qt5/Qt6 only, got target '%s'"
|
||||
% str(Targets.getStringForTarget(target)))
|
||||
return matcher.group(1)
|
||||
|
||||
@@ -110,35 +115,50 @@ class Qt5Path:
|
||||
else:
|
||||
return os.path.expanduser("~/Qt5.%d.1" % qt5Minor)
|
||||
|
||||
@staticmethod
|
||||
def __createQtOnlineInstallerPath__():
|
||||
qtBasePath = os.getenv('SYSTEST_QTOI_BASEPATH', None)
|
||||
if qtBasePath is None:
|
||||
qtBasePath = 'C:/Qt' if platform.system() in ('Microsoft', 'Windows') else '~/Qt'
|
||||
qtBasePath = os.path.expanduser(qtBasePath)
|
||||
if not os.path.exists(qtBasePath):
|
||||
test.fatal("Unexpected Qt install path '%s'" % qtBasePath)
|
||||
return ""
|
||||
return qtBasePath
|
||||
|
||||
@staticmethod
|
||||
def toVersionTuple(versionString):
|
||||
return tuple(map(__builtin__.int, versionString.split(".")))
|
||||
|
||||
@staticmethod
|
||||
def getQtMinorAndPatchVersion(target):
|
||||
qtVersionStr = Qt5Path.__preCheckAndExtractQtVersionStr__(target)
|
||||
versionTuple = Qt5Path.toVersionTuple(qtVersionStr)
|
||||
return versionTuple[1], versionTuple[2]
|
||||
def getQtVersion(target):
|
||||
qtVersionStr = QtPath.__preCheckAndExtractQtVersionStr__(target)
|
||||
versionTuple = QtPath.toVersionTuple(qtVersionStr)
|
||||
return versionTuple
|
||||
|
||||
@staticmethod
|
||||
def examplesPath(target):
|
||||
qtMinorVersion, qtPatchVersion = Qt5Path.getQtMinorAndPatchVersion(target)
|
||||
if qtMinorVersion < 10:
|
||||
path = "Examples/Qt-5.%d" % qtMinorVersion
|
||||
qtMajorVersion, qtMinorVersion, qtPatchVersion = QtPath.getQtVersion(target)
|
||||
if qtMajorVersion == 5 and qtMinorVersion < 10:
|
||||
path = "Examples/Qt-%d.%d" % (qtMajorVersion, qtMinorVersion)
|
||||
else:
|
||||
path = "Examples/Qt-5.%d.%d" % (qtMinorVersion, qtPatchVersion)
|
||||
path = "Examples/Qt-%d.%d.%d" % (qtMajorVersion, qtMinorVersion, qtPatchVersion)
|
||||
|
||||
return os.path.join(Qt5Path.__createPlatformQtPath__(qtMinorVersion), path)
|
||||
if Targets.isOnlineInstaller(target):
|
||||
return os.path.join(QtPath.__createQtOnlineInstallerPath__(), path)
|
||||
return os.path.join(QtPath.__createPlatformQtPath__(qtMinorVersion), path)
|
||||
|
||||
@staticmethod
|
||||
def docsPath(target):
|
||||
qtMinorVersion, qtPatchVersion = Qt5Path.getQtMinorAndPatchVersion(target)
|
||||
if qtMinorVersion < 10:
|
||||
path = "Docs/Qt-5.%d" % qtMinorVersion
|
||||
qtMajorVersion, qtMinorVersion, qtPatchVersion = QtPath.getQtVersion(target)
|
||||
if qtMajorVersion == 5 and qtMinorVersion < 10:
|
||||
path = "Docs/Qt-%d.%d" % (qtMajorVersion, qtMinorVersion)
|
||||
else:
|
||||
path = "Docs/Qt-5.%d.%d" % (qtMinorVersion, qtPatchVersion)
|
||||
path = "Docs/Qt-%d.%d.%d" % (qtMajorVersion, qtMinorVersion, qtPatchVersion)
|
||||
|
||||
return os.path.join(Qt5Path.__createPlatformQtPath__(qtMinorVersion), path)
|
||||
if Targets.isOnlineInstaller(target):
|
||||
return os.path.join(QtPath.__createQtOnlineInstallerPath__(), path)
|
||||
return os.path.join(QtPath.__createPlatformQtPath__(qtMinorVersion), path)
|
||||
|
||||
class TestSection:
|
||||
def __init__(self, description):
|
||||
|
||||
@@ -188,7 +188,7 @@ def __modifyAvailableTargets__(available, requiredQt, asStrings=False):
|
||||
item = Targets.getStringForTarget(currentItem)
|
||||
found = versionFinder.search(item)
|
||||
if found:
|
||||
if Qt5Path.toVersionTuple(found.group(1)) < Qt5Path.toVersionTuple(requiredQt):
|
||||
if QtPath.toVersionTuple(found.group(1)) < QtPath.toVersionTuple(requiredQt):
|
||||
available.discard(currentItem)
|
||||
elif currentItem.endswith(" (invalid)"):
|
||||
available.discard(currentItem)
|
||||
|
||||
@@ -6,7 +6,7 @@ source("../../shared/qtcreator.py")
|
||||
# entry of test
|
||||
def main():
|
||||
# prepare example project
|
||||
sourceExample = os.path.join(Qt5Path.examplesPath(Targets.DESKTOP_5_14_1_DEFAULT),
|
||||
sourceExample = os.path.join(QtPath.examplesPath(Targets.DESKTOP_5_14_1_DEFAULT),
|
||||
"quick", "animation")
|
||||
proFile = "animation.pro"
|
||||
if not neededFilePresent(os.path.join(sourceExample, proFile)):
|
||||
|
||||
@@ -7,7 +7,7 @@ source("../../shared/qtcreator.py")
|
||||
# entry of test
|
||||
def main():
|
||||
# prepare example project
|
||||
sourceExample = os.path.join(Qt5Path.examplesPath(Targets.DESKTOP_5_14_1_DEFAULT),
|
||||
sourceExample = os.path.join(QtPath.examplesPath(Targets.DESKTOP_5_14_1_DEFAULT),
|
||||
"quick", "animation")
|
||||
proFile = "animation.pro"
|
||||
if not neededFilePresent(os.path.join(sourceExample, proFile)):
|
||||
|
||||
@@ -6,7 +6,7 @@ source("../../shared/qtcreator.py")
|
||||
# entry of test
|
||||
def main():
|
||||
# prepare example project
|
||||
sourceExample = os.path.join(Qt5Path.examplesPath(Targets.DESKTOP_5_14_1_DEFAULT),
|
||||
sourceExample = os.path.join(QtPath.examplesPath(Targets.DESKTOP_5_14_1_DEFAULT),
|
||||
"gui", "openglwindow")
|
||||
proFile = "openglwindow.pro"
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ source("../../shared/qtcreator.py")
|
||||
# entry of test
|
||||
def main():
|
||||
# prepare example project
|
||||
sourceExample = os.path.join(Qt5Path.examplesPath(Targets.DESKTOP_5_14_1_DEFAULT),
|
||||
sourceExample = os.path.join(QtPath.examplesPath(Targets.DESKTOP_5_14_1_DEFAULT),
|
||||
"gui", "openglwindow")
|
||||
proFile = "openglwindow.pro"
|
||||
if not neededFilePresent(os.path.join(sourceExample, proFile)):
|
||||
|
||||
@@ -48,7 +48,7 @@ def main():
|
||||
if not startedWithoutPluginError():
|
||||
return
|
||||
docFiles = ["qtdoc.qch", "qtsql.qch"]
|
||||
docFiles = [os.path.join(Qt5Path.docsPath(Targets.DESKTOP_5_14_1_DEFAULT), file) for file in docFiles]
|
||||
docFiles = [os.path.join(QtPath.docsPath(Targets.DESKTOP_5_14_1_DEFAULT), file) for file in docFiles]
|
||||
addHelpDocumentation(docFiles)
|
||||
# switch to help mode
|
||||
switchViewTo(ViewConstants.HELP)
|
||||
|
||||
@@ -25,7 +25,7 @@ def main():
|
||||
if not startedWithoutPluginError():
|
||||
return
|
||||
qchs = []
|
||||
for p in Qt5Path.getPaths(Qt5Path.DOCS):
|
||||
for p in QtPath.getPaths(QtPath.DOCS):
|
||||
qchs.append(os.path.join(p, "qtquick.qch"))
|
||||
addHelpDocumentation(qchs)
|
||||
setFixedHelpViewer(HelpViewer.SIDEBYSIDE)
|
||||
|
||||
@@ -45,7 +45,7 @@ def checkUsages(resultsView, expectedResults, directory):
|
||||
|
||||
def main():
|
||||
# prepare example project
|
||||
sourceExample = os.path.join(Qt5Path.examplesPath(Targets.DESKTOP_5_14_1_DEFAULT),
|
||||
sourceExample = os.path.join(QtPath.examplesPath(Targets.DESKTOP_5_14_1_DEFAULT),
|
||||
"quick", "animation")
|
||||
proFile = "animation.pro"
|
||||
if not neededFilePresent(os.path.join(sourceExample, proFile)):
|
||||
|
||||
@@ -12,7 +12,7 @@ def main():
|
||||
# create qt quick application
|
||||
createNewQtQuickApplication(tempDir(), "SampleApp")
|
||||
# create syntax error in qml file
|
||||
openDocument("SampleApp.Resources.qml\.qrc./.main\\.qml")
|
||||
openDocument("SampleApp.appSampleApp.Main\\.qml")
|
||||
if not appendToLine(waitForObject(":Qt Creator_QmlJSEditor::QmlJSTextEditorWidget"), "Window {", "SyntaxError"):
|
||||
invokeMenuItem("File", "Exit")
|
||||
return
|
||||
|
||||
@@ -43,7 +43,7 @@ def checkTypeAndProperties(typePropertiesDetails):
|
||||
|
||||
def main():
|
||||
# prepare example project
|
||||
sourceExample = os.path.join(Qt5Path.examplesPath(Targets.DESKTOP_5_14_1_DEFAULT),
|
||||
sourceExample = os.path.join(QtPath.examplesPath(Targets.DESKTOP_5_14_1_DEFAULT),
|
||||
"quick", "animation")
|
||||
if not neededFilePresent(sourceExample):
|
||||
return
|
||||
|
||||
@@ -41,7 +41,7 @@ def main():
|
||||
if not startedWithoutPluginError():
|
||||
return
|
||||
qchs = []
|
||||
for p in Qt5Path.getPaths(Qt5Path.DOCS):
|
||||
for p in QtPath.getPaths(QtPath.DOCS):
|
||||
qchs.extend([os.path.join(p, "qtopengl.qch"), os.path.join(p, "qtwidgets.qch")])
|
||||
addHelpDocumentation(qchs)
|
||||
setFixedHelpViewer(HelpViewer.HELPMODE)
|
||||
@@ -72,7 +72,7 @@ def main():
|
||||
test.verify(example is None, "Verifying: No example is shown.")
|
||||
|
||||
proFiles = [os.path.join(p, "opengl", "2dpainting", "2dpainting.pro")
|
||||
for p in Qt5Path.getPaths(Qt5Path.EXAMPLES)]
|
||||
for p in QtPath.getPaths(QtPath.EXAMPLES)]
|
||||
cleanUpUserFiles(proFiles)
|
||||
for p in proFiles:
|
||||
removePackagingDirectory(os.path.dirname(p))
|
||||
@@ -94,7 +94,7 @@ def main():
|
||||
# go to "Welcome" page and choose another example
|
||||
switchViewTo(ViewConstants.WELCOME)
|
||||
proFiles = [os.path.join(p, "widgets", "itemviews", "addressbook", "addressbook.pro")
|
||||
for p in Qt5Path.getPaths(Qt5Path.EXAMPLES)]
|
||||
for p in QtPath.getPaths(QtPath.EXAMPLES)]
|
||||
cleanUpUserFiles(proFiles)
|
||||
for p in proFiles:
|
||||
removePackagingDirectory(os.path.dirname(p))
|
||||
|
||||
@@ -7,7 +7,7 @@ focusDocumentPath = "keyinteraction.Resources.keyinteraction\.qrc./keyinteractio
|
||||
|
||||
def main():
|
||||
target = Targets.DESKTOP_5_14_1_DEFAULT
|
||||
sourceExample = os.path.join(Qt5Path.examplesPath(target), "quick/keyinteraction")
|
||||
sourceExample = os.path.join(QtPath.examplesPath(target), "quick/keyinteraction")
|
||||
proFile = "keyinteraction.pro"
|
||||
if not neededFilePresent(os.path.join(sourceExample, proFile)):
|
||||
return
|
||||
@@ -15,7 +15,7 @@ def main():
|
||||
if not startedWithoutPluginError():
|
||||
return
|
||||
# add docs to have the correct tool tips
|
||||
addHelpDocumentation([os.path.join(Qt5Path.docsPath(target), "qtquick.qch")])
|
||||
addHelpDocumentation([os.path.join(QtPath.docsPath(target), "qtquick.qch")])
|
||||
templateDir = prepareTemplate(sourceExample)
|
||||
openQmakeProject(os.path.join(templateDir, proFile), [target])
|
||||
openDocument(focusDocumentPath % "focus\\.qml")
|
||||
|
||||
@@ -15,8 +15,8 @@ def main():
|
||||
invokeMenuItem("File", "Exit")
|
||||
|
||||
def prepareQmlFile():
|
||||
if not openDocument("untitled.untitled.qml\\.qrc./.main\\.qml"):
|
||||
test.fatal("Could not open main.qml")
|
||||
if not openDocument("untitled.appuntitled.Main\\.qml"):
|
||||
test.fatal("Could not open Main.qml")
|
||||
return None
|
||||
editor = waitForObject(":Qt Creator_QmlJSEditor::QmlJSTextEditorWidget")
|
||||
isDarwin = platform.system() == 'Darwin'
|
||||
|
||||
@@ -6,7 +6,7 @@ source("../../shared/qtcreator.py")
|
||||
def main():
|
||||
# prepare example project
|
||||
projectName = "adding"
|
||||
sourceExample = os.path.join(Qt5Path.examplesPath(Targets.DESKTOP_5_14_1_DEFAULT),
|
||||
sourceExample = os.path.join(QtPath.examplesPath(Targets.DESKTOP_5_14_1_DEFAULT),
|
||||
"qml", "referenceexamples", "adding")
|
||||
proFile = projectName + ".pro"
|
||||
if not neededFilePresent(os.path.join(sourceExample, proFile)):
|
||||
|
||||
@@ -45,9 +45,9 @@ def main():
|
||||
invokeMenuItem("File", "Exit")
|
||||
|
||||
def prepareTestExamples():
|
||||
examples = [os.path.join(Qt5Path.examplesPath(Targets.DESKTOP_5_14_1_DEFAULT),
|
||||
examples = [os.path.join(QtPath.examplesPath(Targets.DESKTOP_5_14_1_DEFAULT),
|
||||
"quick", "animation", "animation.pro"),
|
||||
os.path.join(Qt5Path.examplesPath(Targets.DESKTOP_5_14_1_DEFAULT),
|
||||
os.path.join(QtPath.examplesPath(Targets.DESKTOP_5_14_1_DEFAULT),
|
||||
"quick", "keyinteraction", "keyinteraction.pro")
|
||||
]
|
||||
projects = []
|
||||
|
||||
@@ -8,7 +8,7 @@ outline = ":Qt Creator_QmlJSEditor::Internal::QmlJSOutlineTreeView"
|
||||
treebase = "keyinteraction.Resources.keyinteraction\\.qrc./keyinteraction.focus."
|
||||
|
||||
def main():
|
||||
sourceExample = os.path.join(Qt5Path.examplesPath(Targets.DESKTOP_5_14_1_DEFAULT),
|
||||
sourceExample = os.path.join(QtPath.examplesPath(Targets.DESKTOP_5_14_1_DEFAULT),
|
||||
"quick", "keyinteraction")
|
||||
proFile = "keyinteraction.pro"
|
||||
if not neededFilePresent(os.path.join(sourceExample, proFile)):
|
||||
|
||||
@@ -33,7 +33,7 @@ def main():
|
||||
checkCompile()
|
||||
else:
|
||||
appOutput = logApplicationOutput()
|
||||
test.verify(not ("main.qml" in appOutput or "MainForm.ui.qml" in appOutput),
|
||||
test.verify(not ("Main.qml" in appOutput or "MainForm.ui.qml" in appOutput),
|
||||
"Does the Application Output indicate QML errors?")
|
||||
invokeMenuItem("File", "Close All Projects and Editors")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user