diff --git a/cmake/QtCreatorAPI.cmake b/cmake/QtCreatorAPI.cmake index 7a390b1ad97..0493fb95bc0 100644 --- a/cmake/QtCreatorAPI.cmake +++ b/cmake/QtCreatorAPI.cmake @@ -399,6 +399,7 @@ function(add_qtc_plugin target_name) ### Configure plugin.json file: if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${name}.json.in") + list(APPEND _arg_SOURCES ${name}.json.in) file(READ "${name}.json.in" plugin_json_in) string(REPLACE "\\\"" "\"" plugin_json_in ${plugin_json_in}) string(REPLACE "\\'" "'" plugin_json_in ${plugin_json_in}) diff --git a/coin/instructions/make_instructions.yaml b/coin/instructions/build.yaml similarity index 89% rename from coin/instructions/make_instructions.yaml rename to coin/instructions/build.yaml index bee20f2527d..6c276b1b27e 100644 --- a/coin/instructions/make_instructions.yaml +++ b/coin/instructions/build.yaml @@ -13,7 +13,7 @@ instructions: maxTimeBetweenOutput: 360 userMessageOnFailure: "Failed to extract elfutils package, check logs." - type: ExecuteCommand - command: "curl --fail -L --retry 5 --retry-delay 5 -o {{.AgentWorkingDir}}/build/qt_temp/libclang.7z {{.Env.LLVM_BASE_URL}}-linux-Ubuntu18.04-gcc9.3-x86_64.7z" + command: "curl --fail -L --retry 5 --retry-delay 5 -o {{.AgentWorkingDir}}/build/qt_temp/libclang.7z {{.Env.LLVM_BASE_URL}}-linux-Rhel8.2-gcc9.2-x86_64.7z" maxTimeInSeconds: 3600 maxTimeBetweenOutput: 360 userMessageOnFailure: "Failed to download LLVM package, check logs." @@ -23,7 +23,7 @@ instructions: maxTimeBetweenOutput: 360 userMessageOnFailure: "Failed to extract LLVM package, check logs." - type: ExecuteCommand - command: "python -u {{.AgentWorkingDir}}/qt-creator/qt-creator/scripts/build.py --build-type {{.Env.QTC_BUILD_TYPE}} --src {{.AgentWorkingDir}}/qt-creator/qt-creator --build {{.AgentWorkingDir}}/qt-creator/qt-creator_build --qt-path {{.AgentWorkingDir}}/build/qt5_install_dir --elfutils-path {{.AgentWorkingDir}}/build/qt_temp/elfutils --llvm-path {{.AgentWorkingDir}}/build/qt_temp/libclang --with-tests --no-zip --add-config=-DCMAKE_C_COMPILER_LAUNCHER=sccache --add-config=-DCMAKE_CXX_COMPILER_LAUNCHER=sccache" + command: "python -u {{.AgentWorkingDir}}/qt-creator/qt-creator/scripts/build.py --build-type {{.Env.QTC_BUILD_TYPE}} --src {{.AgentWorkingDir}}/qt-creator/qt-creator --build {{.AgentWorkingDir}}/qt-creator/qt-creator_build --qt-path {{.AgentWorkingDir}}/build/qt_install_dir --elfutils-path {{.AgentWorkingDir}}/build/qt_temp/elfutils --llvm-path {{.AgentWorkingDir}}/build/qt_temp/libclang --with-tests --no-zip --add-config=-DCMAKE_C_COMPILER_LAUNCHER=sccache --add-config=-DCMAKE_CXX_COMPILER_LAUNCHER=sccache" maxTimeInSeconds: 36000 maxTimeBetweenOutput: 3600 userMessageOnFailure: "Failed to run build.py, check logs." @@ -40,7 +40,7 @@ instructions: - type: Group instructions: - type: ExecuteCommand - command: "curl --fail -L --retry 5 --retry-delay 5 -o {{.AgentWorkingDir}}/build/qt_temp/libclang.7z {{.Env.LLVM_BASE_URL}}-mac.7z" + command: "curl --fail -L --retry 5 --retry-delay 5 -o {{.AgentWorkingDir}}/build/qt_temp/libclang.7z {{.Env.LLVM_BASE_URL}}-macos-universal.7z" maxTimeInSeconds: 3600 maxTimeBetweenOutput: 360 userMessageOnFailure: "Failed to download LLVM package, check logs." @@ -50,7 +50,7 @@ instructions: maxTimeBetweenOutput: 360 userMessageOnFailure: "Failed to extract LLVM package, check logs." - type: ExecuteCommand - command: "python -u {{.AgentWorkingDir}}/qt-creator/qt-creator/scripts/build.py --build-type {{.Env.QTC_BUILD_TYPE}} --src {{.AgentWorkingDir}}/qt-creator/qt-creator --build {{.AgentWorkingDir}}/qt-creator/qt-creator_build --qt-path {{.AgentWorkingDir}}/build/qt5_install_dir --llvm-path {{.AgentWorkingDir}}/build/qt_temp/libclang --keychain-unlock-script /Users/qt/unlock-keychain.sh --with-tests --no-zip --add-config=-DCMAKE_C_COMPILER_LAUNCHER=sccache --add-config=-DCMAKE_CXX_COMPILER_LAUNCHER=sccache" + command: "python -u {{.AgentWorkingDir}}/qt-creator/qt-creator/scripts/build.py --build-type {{.Env.QTC_BUILD_TYPE}} --src {{.AgentWorkingDir}}/qt-creator/qt-creator --build {{.AgentWorkingDir}}/qt-creator/qt-creator_build --qt-path {{.AgentWorkingDir}}/build/qt_install_dir --llvm-path {{.AgentWorkingDir}}/build/qt_temp/libclang --keychain-unlock-script /Users/qt/unlock-keychain.sh --with-tests --no-zip --add-config=-DCMAKE_C_COMPILER_LAUNCHER=sccache --add-config=-DCMAKE_CXX_COMPILER_LAUNCHER=sccache" maxTimeInSeconds: 36000 maxTimeBetweenOutput: 3600 userMessageOnFailure: "Failed to run build.py, check logs." @@ -92,7 +92,7 @@ instructions: maxTimeBetweenOutput: 360 userMessageOnFailure: "Failed to extract LLVM package, check logs." - type: ExecuteCommand - command: "python -u {{.AgentWorkingDir}}\\qt-creator\\qt-creator\\scripts\\build.py --build-type {{.Env.QTC_BUILD_TYPE}} --src {{.AgentWorkingDir}}\\qt-creator\\qt-creator --build {{.AgentWorkingDir}}\\qt-creator\\qt-creator_build --qt-path {{.AgentWorkingDir}}/build/qt5_install_dir --python-path {{.AgentWorkingDir}}\\build\\qt_temp\\python --elfutils-path {{.AgentWorkingDir}}\\buid\\qt_temp\\elfutils --llvm-path {{.AgentWorkingDir}}\\build\\qt_temp\\libclang --with-tests --no-zip --add-config=-DCMAKE_C_COMPILER_LAUNCHER=sccache --add-config=-DCMAKE_CXX_COMPILER_LAUNCHER=sccache --add-config=-DWITH_SCCACHE_SUPPORT=ON" + command: "python -u {{.AgentWorkingDir}}\\qt-creator\\qt-creator\\scripts\\build.py --build-type {{.Env.QTC_BUILD_TYPE}} --src {{.AgentWorkingDir}}\\qt-creator\\qt-creator --build {{.AgentWorkingDir}}\\qt-creator\\qt-creator_build --qt-path {{.AgentWorkingDir}}/build/qt_install_dir --python-path {{.AgentWorkingDir}}\\build\\qt_temp\\python --elfutils-path {{.AgentWorkingDir}}\\buid\\qt_temp\\elfutils --llvm-path {{.AgentWorkingDir}}\\build\\qt_temp\\libclang --with-tests --no-zip --add-config=-DCMAKE_C_COMPILER_LAUNCHER=sccache --add-config=-DCMAKE_CXX_COMPILER_LAUNCHER=sccache --add-config=-DWITH_SCCACHE_SUPPORT=ON" maxTimeInSeconds: 36000 maxTimeBetweenOutput: 3600 userMessageOnFailure: "Failed to run build.py, check logs." diff --git a/coin/instructions/common_environment.yaml b/coin/instructions/common_environment.yaml index f70a662c3b8..3279aa6d93c 100644 --- a/coin/instructions/common_environment.yaml +++ b/coin/instructions/common_environment.yaml @@ -7,13 +7,13 @@ instructions: variableValue: "RelWithDebInfo" - type: EnvironmentVariable variableName: QTC_QT_BASE_URL - variableValue: "http://ci-files02-hki.intra.qt.io/packages/jenkins/archive/qt/6.2/6.2.3-final-released/Qt6.2.3" + variableValue: "http://ci-files02-hki.intra.qt.io/packages/jenkins/archive/qt/6.2/6.2.4-final-released/Qt6.2.4" - type: EnvironmentVariable variableName: QTC_QT_MODULES variableValue: "qt5compat qtbase qtdeclarative qtimageformats qtquick3d qtquickcontrols2 qtquicktimeline qtserialport qtshadertools qtsvg qttools qttranslations" - type: EnvironmentVariable variableName: LLVM_BASE_URL - variableValue: http://master.qt.io/development_releases/prebuilt/libclang/libclang-release_120-based + variableValue: http://master.qt.io/development_releases/prebuilt/libclang/libclang-release_140-based - type: EnvironmentVariable variableName: MACOSX_DEPLOYMENT_TARGET variableValue: 10.14 diff --git a/coin/instructions/qmake_module_build.yaml b/coin/instructions/provision.yaml similarity index 66% rename from coin/instructions/qmake_module_build.yaml rename to coin/instructions/provision.yaml index ad3d966b4a8..86c7ca32f63 100644 --- a/coin/instructions/qmake_module_build.yaml +++ b/coin/instructions/provision.yaml @@ -32,7 +32,7 @@ instructions: property: host.os in_values: [MacOS, Linux, Windows] - type: ExecuteCommand - command: "python -u {{.AgentWorkingDir}}/build/qtsdk/packaging-tools/install_qt.py --qt-path {{.AgentWorkingDir}}/build/qt5_install_dir --temp-path {{.AgentWorkingDir}}/build/qt_temp --base-url {{.Env.QTC_QT_BASE_URL}} --base-url-postfix=-Linux-RHEL_8_4-GCC-Linux-RHEL_8_4-X86_64.7z --icu7z http://master.qt.io/development_releases/prebuilt/icu/prebuilt/56.1/icu-linux-g++-Rhel7.2-x64.7z {{.Env.QTC_QT_MODULES}}" + command: "python -u {{.AgentWorkingDir}}/build/qtsdk/packaging-tools/install_qt.py --qt-path {{.AgentWorkingDir}}/build/qt_install_dir --temp-path {{.AgentWorkingDir}}/build/qt_temp --base-url {{.Env.QTC_QT_BASE_URL}} --base-url-postfix=-Linux-RHEL_8_4-GCC-Linux-RHEL_8_4-X86_64.7z --icu7z http://master.qt.io/development_releases/prebuilt/icu/prebuilt/56.1/icu-linux-g++-Rhel7.2-x64.7z {{.Env.QTC_QT_MODULES}}" executeCommandArgumentSplitingBehavior: SplitAfterVariableSubstitution maxTimeInSeconds: 3600 maxTimeBetweenOutput: 360 @@ -42,7 +42,7 @@ instructions: property: host.os equals_value: Linux - type: ExecuteCommand - command: "python -u {{.AgentWorkingDir}}/build/qtsdk/packaging-tools/install_qt.py --qt-path {{.AgentWorkingDir}}/build/qt5_install_dir --temp-path {{.AgentWorkingDir}}/build/qt_temp --base-url {{.Env.QTC_QT_BASE_URL}} --base-url-postfix=-MacOS-MacOS_12-Clang-MacOS-MacOS_12-X86_64-ARM64.7z {{.Env.QTC_QT_MODULES}}" + command: "python -u {{.AgentWorkingDir}}/build/qtsdk/packaging-tools/install_qt.py --qt-path {{.AgentWorkingDir}}/build/qt_install_dir --temp-path {{.AgentWorkingDir}}/build/qt_temp --base-url {{.Env.QTC_QT_BASE_URL}} --base-url-postfix=-MacOS-MacOS_12-Clang-MacOS-MacOS_12-X86_64-ARM64.7z {{.Env.QTC_QT_MODULES}}" executeCommandArgumentSplitingBehavior: SplitAfterVariableSubstitution maxTimeInSeconds: 3600 maxTimeBetweenOutput: 360 @@ -61,7 +61,7 @@ instructions: property: host.os equals_value: Windows - type: ExecuteCommand - command: "python -u {{.AgentWorkingDir}}/build/qtsdk/packaging-tools/install_qt.py --qt-path {{.AgentWorkingDir}}/build/qt5_install_dir --temp-path {{.AgentWorkingDir}}/build/qt_temp --base-url {{.Env.QTC_QT_BASE_URL}} --base-url-postfix=-Windows-Windows_10-MSVC2019-Windows-Windows_10-X86_64.7z --opengl32sw7z http://master.qt.io/development_releases/prebuilt/llvmpipe/windows/opengl32sw-64.7z --d3dcompiler7z http://master.qt.io/development_releases/prebuilt/d3dcompiler/msvc2013/d3dcompiler_47-x64.7z --openssl7z http://ci-files02-hki.intra.qt.io/packages/jenkins/openssl/openssl_1.1.1d_prebuild_x64.7z {{.Env.QTC_QT_MODULES}}" + command: "python -u {{.AgentWorkingDir}}/build/qtsdk/packaging-tools/install_qt.py --qt-path {{.AgentWorkingDir}}/build/qt_install_dir --temp-path {{.AgentWorkingDir}}/build/qt_temp --base-url {{.Env.QTC_QT_BASE_URL}} --base-url-postfix=-Windows-Windows_10_21H2-MSVC2019-Windows-Windows_10_21H2-X86_64.7z --opengl32sw7z http://master.qt.io/development_releases/prebuilt/llvmpipe/windows/opengl32sw-64.7z --d3dcompiler7z http://master.qt.io/development_releases/prebuilt/d3dcompiler/msvc2013/d3dcompiler_47-x64.7z --openssl7z http://ci-files02-hki.intra.qt.io/packages/jenkins/openssl/openssl_1.1.1d_prebuild_x64.7z {{.Env.QTC_QT_MODULES}}" executeCommandArgumentSplitingBehavior: SplitAfterVariableSubstitution maxTimeInSeconds: 3600 maxTimeBetweenOutput: 360 @@ -76,5 +76,3 @@ instructions: property: target.arch equals_value: X86_64 - - !include "{{qt-creator/qt-creator}}/make_instructions.yaml" - diff --git a/coin/module_config.yaml b/coin/module_config.yaml index 05175f38cd1..163721ea254 100644 --- a/coin/module_config.yaml +++ b/coin/module_config.yaml @@ -60,7 +60,8 @@ common_environment: &common_environment make_instructions: &make_instructions type: Group instructions: - - !include "{{qt-creator/qt-creator}}/qmake_module_build.yaml" + - !include "{{qt-creator/qt-creator}}/provision.yaml" + - !include "{{qt-creator/qt-creator}}/build.yaml" instructions: diff --git a/src/plugins/autotest/testrunner.cpp b/src/plugins/autotest/testrunner.cpp index fea438dc35a..8dac62a4ed8 100644 --- a/src/plugins/autotest/testrunner.cpp +++ b/src/plugins/autotest/testrunner.cpp @@ -287,6 +287,7 @@ void TestRunner::scheduleNext() reportResult(ResultType::MessageFatal, tr("Failed to start test for project \"%1\".").arg(m_currentConfig->displayName()) + processInformation(m_currentProcess) + rcInfo(m_currentConfig)); + onProcessFinished(); } } diff --git a/src/plugins/clangcodemodel/clangdclient.cpp b/src/plugins/clangcodemodel/clangdclient.cpp index 84e2bed10af..9429b6269bd 100644 --- a/src/plugins/clangcodemodel/clangdclient.cpp +++ b/src/plugins/clangcodemodel/clangdclient.cpp @@ -2093,7 +2093,10 @@ void ClangdClient::findLocalUsages(TextDocument *document, const QTextCursor &cu const QList astPath = getAstPath(ast, linkPos); bool isVar = false; for (auto it = astPath.rbegin(); it != astPath.rend(); ++it) { - if (it->role() == "declaration" && it->kind() == "Function") { + if (it->role() == "declaration" + && (it->kind() == "Function" || it->kind() == "CXXMethod" + || it->kind() == "CXXConstructor" || it->kind() == "CXXDestructor" + || it->kind() == "Lambda")) { if (!isVar) break; diff --git a/src/plugins/clangcodemodel/test/clangdtests.cpp b/src/plugins/clangcodemodel/test/clangdtests.cpp index b672dec291d..0381bd25772 100644 --- a/src/plugins/clangcodemodel/test/clangdtests.cpp +++ b/src/plugins/clangcodemodel/test/clangdtests.cpp @@ -434,8 +434,8 @@ void ClangdTestLocalReferences::test_data() /* QList{{40, 7, 3}, {43, 9, 3}} */; QTest::newRow("instantiated template object") << 52 << 19 << QList{{52, 19, 3}, {53, 5, 3}}; - QTest::newRow("variable in template") << 62 << 13 << QList() - /* QList{{62, 13, 3}, {63, 11, 3}} */; + QTest::newRow("variable in template") << 62 << 13 + << QList{{62, 13, 3}, {63, 11, 3}}; QTest::newRow("member in template") << 67 << 7 << QList() /* QList{{64, 16, 3}, {67, 7, 3}} */; QTest::newRow("template type") << 58 << 19 << QList() diff --git a/src/plugins/clangformat/clangformat.qbs b/src/plugins/clangformat/clangformat.qbs index cbb93d7c77d..f7d60ad73d1 100644 --- a/src/plugins/clangformat/clangformat.qbs +++ b/src/plugins/clangformat/clangformat.qbs @@ -20,6 +20,12 @@ QtcPlugin { && (!qbs.targetOS.contains("windows") || libclang.llvmBuildModeMatches) cpp.cxxFlags: base.concat(libclang.llvmToolingCxxFlags) + cpp.linkerFlags: { + var flags = base; + if (qbs.targetOS.contains("unix") && !qbs.targetOS.contains("macos")) + flags.push("--exclude-libs", "ALL"); + return flags; + } cpp.includePaths: base.concat(libclang.llvmIncludeDir) cpp.libraryPaths: base.concat(libclang.llvmLibDir) cpp.dynamicLibraries: base.concat(libclang.llvmFormattingLibs) diff --git a/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp b/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp index 817098b8f65..13a0be44199 100644 --- a/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp +++ b/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp @@ -620,7 +620,7 @@ void CMakeBuildSettingsWidget::updateInitialCMakeArguments() *it = ci; if (ci.isUnset) initialList.erase(it); - } else { + } else if (!ci.key.isEmpty()) { initialList.push_back(ci); } } @@ -1105,7 +1105,7 @@ static CommandLine defaultInitialCMakeCommand(const Kit *k, const QString buildT if (ToolChain *tc = ToolChainKitAspect::cxxToolChain(k)) { const QString targetTriple = tc->originalTargetTriple(); cmd.addArg("-DCMAKE_C_COMPILER_TARGET:STRING=" + targetTriple); - cmd.addArg("-DCMAKE_CXX_COMPILER_TARGET:STRING=%1" + targetTriple); + cmd.addArg("-DCMAKE_CXX_COMPILER_TARGET:STRING=" + targetTriple); } } } diff --git a/src/plugins/cmakeprojectmanager/cmakekitinformation.cpp b/src/plugins/cmakeprojectmanager/cmakekitinformation.cpp index f627db0d393..22c0847b74c 100644 --- a/src/plugins/cmakeprojectmanager/cmakekitinformation.cpp +++ b/src/plugins/cmakeprojectmanager/cmakekitinformation.cpp @@ -1122,8 +1122,12 @@ void CMakeConfigurationKitAspect::fromStringList(Kit *k, const QStringList &in) QStringList CMakeConfigurationKitAspect::toArgumentsList(const Kit *k) { - return Utils::transform(CMakeConfigurationKitAspect::configuration(k).toList(), - [](const CMakeConfigItem &i) { return i.toArgument(nullptr); }); + QStringList current = Utils::transform(CMakeConfigurationKitAspect::configuration(k).toList(), + [](const CMakeConfigItem &i) { + return i.toArgument(nullptr); + }); + current = Utils::filtered(current, [](const QString &s) { return s != "-D" || s != "-U"; }); + return current; } CMakeConfig CMakeConfigurationKitAspect::defaultConfiguration(const Kit *k) diff --git a/src/plugins/coreplugin/progressmanager/progressmanager.cpp b/src/plugins/coreplugin/progressmanager/progressmanager.cpp index f0b42da7d62..598d1ac02b7 100644 --- a/src/plugins/coreplugin/progressmanager/progressmanager.cpp +++ b/src/plugins/coreplugin/progressmanager/progressmanager.cpp @@ -269,16 +269,23 @@ void ProgressManagerPrivate::init() m_summaryProgressWidget = new QWidget(m_statusBarWidget); m_summaryProgressWidget->setVisible(!m_progressViewPinned); m_summaryProgressWidget->setGraphicsEffect(m_opacityEffect); - m_summaryProgressLayout = new QHBoxLayout(m_summaryProgressWidget); - m_summaryProgressLayout->setContentsMargins(0, 0, 0, 2); - m_summaryProgressLayout->setSpacing(0); - m_summaryProgressWidget->setLayout(m_summaryProgressLayout); + auto summaryProgressLayout = new QHBoxLayout(m_summaryProgressWidget); + summaryProgressLayout->setContentsMargins(0, 0, 0, 2); + summaryProgressLayout->setSpacing(0); + m_summaryProgressWidget->setLayout(summaryProgressLayout); + m_statusDetailsWidgetContainer = new QWidget(m_summaryProgressWidget); + m_statusDetailsWidgetLayout = new QHBoxLayout(m_summaryProgressWidget); + m_statusDetailsWidgetLayout->setContentsMargins(0, 0, 0, 0); + m_statusDetailsWidgetLayout->setSpacing(0); + m_statusDetailsWidgetLayout->addStretch(1); + m_statusDetailsWidgetContainer->setLayout(m_statusDetailsWidgetLayout); + summaryProgressLayout->addWidget(m_statusDetailsWidgetContainer); m_summaryProgressBar = new ProgressBar(m_summaryProgressWidget); m_summaryProgressBar->setMinimumWidth(70); m_summaryProgressBar->setTitleVisible(false); m_summaryProgressBar->setSeparatorVisible(false); m_summaryProgressBar->setCancelEnabled(false); - m_summaryProgressLayout->addWidget(m_summaryProgressBar); + summaryProgressLayout->addWidget(m_summaryProgressBar); layout->addWidget(m_summaryProgressWidget); auto toggleButton = new QToolButton(m_statusBarWidget); layout->addWidget(toggleButton); @@ -609,6 +616,8 @@ void ProgressManagerPrivate::updateVisibilityWithDelay() QTimer::singleShot(150, this, &ProgressManagerPrivate::updateVisibility); } +const int RASTER = 20; + void ProgressManagerPrivate::updateStatusDetailsWidget() { QWidget *candidateWidget = nullptr; @@ -636,16 +645,25 @@ void ProgressManagerPrivate::updateStatusDetailsWidget() } } + // make size fit on raster, to avoid flickering in status bar + // because the output pane buttons resize, if the widget changes a lot (like it is the case for + // the language server indexing) + if (candidateWidget) { + const int preferredWidth = candidateWidget->sizeHint().width(); + const int width = preferredWidth + (RASTER - preferredWidth % RASTER); + m_statusDetailsWidgetContainer->setFixedWidth(width); + } + if (candidateWidget == m_currentStatusDetailsWidget) return; if (m_currentStatusDetailsWidget) { m_currentStatusDetailsWidget->hide(); - m_summaryProgressLayout->removeWidget(m_currentStatusDetailsWidget); + m_statusDetailsWidgetLayout->removeWidget(m_currentStatusDetailsWidget); } if (candidateWidget) { - m_summaryProgressLayout->insertWidget(0, candidateWidget); + m_statusDetailsWidgetLayout->addWidget(candidateWidget); candidateWidget->show(); } diff --git a/src/plugins/coreplugin/progressmanager/progressmanager_p.h b/src/plugins/coreplugin/progressmanager/progressmanager_p.h index fe1416cb3af..edd933fa2cb 100644 --- a/src/plugins/coreplugin/progressmanager/progressmanager_p.h +++ b/src/plugins/coreplugin/progressmanager/progressmanager_p.h @@ -101,7 +101,8 @@ private: StatusBarWidget *m_statusBarWidgetContainer; QWidget *m_statusBarWidget; QWidget *m_summaryProgressWidget; - QHBoxLayout *m_summaryProgressLayout; + QWidget *m_statusDetailsWidgetContainer = nullptr; + QHBoxLayout *m_statusDetailsWidgetLayout = nullptr; QWidget *m_currentStatusDetailsWidget = nullptr; QPointer m_currentStatusDetailsProgress; QLabel *m_statusDetailsLabel = nullptr; diff --git a/src/plugins/cppeditor/cppcodeformatter.cpp b/src/plugins/cppeditor/cppcodeformatter.cpp index e806dab1a8a..6df0a44659b 100644 --- a/src/plugins/cppeditor/cppcodeformatter.cpp +++ b/src/plugins/cppeditor/cppcodeformatter.cpp @@ -172,6 +172,7 @@ void CodeFormatter::recalculateStateAfter(const QTextBlock &block) case T_COLON: enter(member_init_open); enter(member_init_expected); break; case T_OPERATOR: enter(operator_declaration); break; case T_GREATER_GREATER: break; + case T_LBRACKET: break; default: tryExpression(true); break; } break; @@ -825,8 +826,11 @@ bool CodeFormatter::tryExpression(bool alsoExpression) break; } - if (m_currentToken.isStringLiteral()) - newState = m_currentToken.kind() == T_RAW_STRING_LITERAL ? raw_string_open : string_open; + if (m_currentToken.isStringLiteral()) { + newState = m_currentToken.kind() >= T_FIRST_RAW_STRING_LITERAL + && m_currentToken.kind() <= T_LAST_RAW_STRING_LITERAL ? raw_string_open + : string_open; + } if (newState != -1) { if (alsoExpression) diff --git a/src/plugins/cppeditor/cppeditorplugin.cpp b/src/plugins/cppeditor/cppeditorplugin.cpp index a6baee1fefb..042344c52c3 100644 --- a/src/plugins/cppeditor/cppeditorplugin.cpp +++ b/src/plugins/cppeditor/cppeditorplugin.cpp @@ -294,14 +294,6 @@ bool CppEditorPlugin::initialize(const QStringList & /*arguments*/, QString *err tr("Insert \"#pragma once\" instead of \"#ifndef\" include guards into header file"), [] { return usePragmaOnce() ? QString("true") : QString(); }); - const auto clangdPanelFactory = new ProjectPanelFactory; - clangdPanelFactory->setPriority(100); - clangdPanelFactory->setDisplayName(tr("Clangd")); - clangdPanelFactory->setCreateWidgetFunction([](Project *project) { - return new ClangdProjectSettingsWidget(project); - }); - ProjectPanelFactory::registerFactory(clangdPanelFactory); - const auto quickFixSettingsPanelFactory = new ProjectPanelFactory; quickFixSettingsPanelFactory->setPriority(100); quickFixSettingsPanelFactory->setId(Constants::QUICK_FIX_PROJECT_PANEL_ID); @@ -441,8 +433,17 @@ void CppEditorPlugin::extensionsInitialized() d->m_fileSettings.fromSettings(ICore::settings()); if (!d->m_fileSettings.applySuffixesToMimeDB()) qWarning("Unable to apply cpp suffixes to mime database (cpp mime types not found).\n"); - if (CppModelManager::instance()->isClangCodeModelActive()) + + if (CppModelManager::instance()->isClangCodeModelActive()) { d->m_clangdSettingsPage = new ClangdSettingsPage; + const auto clangdPanelFactory = new ProjectPanelFactory; + clangdPanelFactory->setPriority(100); + clangdPanelFactory->setDisplayName(tr("Clangd")); + clangdPanelFactory->setCreateWidgetFunction([](Project *project) { + return new ClangdProjectSettingsWidget(project); + }); + ProjectPanelFactory::registerFactory(clangdPanelFactory); + } // Add the hover handler factories here instead of in initialize() // so that the Clang Code Model has a chance to hook in. diff --git a/src/plugins/help/litehtmlhelpviewer.cpp b/src/plugins/help/litehtmlhelpviewer.cpp index 8d54e01b69c..3079c868fb7 100644 --- a/src/plugins/help/litehtmlhelpviewer.cpp +++ b/src/plugins/help/litehtmlhelpviewer.cpp @@ -68,7 +68,13 @@ LiteHtmlHelpViewer::LiteHtmlHelpViewer(QWidget *parent) m_viewer->setResourceHandler([](const QUrl &url) { return getData(url); }); m_viewer->setFrameStyle(QFrame::NoFrame); m_viewer->viewport()->installEventFilter(this); - connect(m_viewer, &QLiteHtmlWidget::linkClicked, this, &LiteHtmlHelpViewer::setSource); + connect(m_viewer, &QLiteHtmlWidget::linkClicked, this, [this](const QUrl &url) { + const Qt::KeyboardModifiers modifiers = QGuiApplication::keyboardModifiers(); + if (modifiers == Qt::ControlModifier) + emit newPageRequested(url); + else + setSource(url); + }); connect(m_viewer, &QLiteHtmlWidget::contextMenuRequested, this, diff --git a/src/plugins/help/localhelpmanager.cpp b/src/plugins/help/localhelpmanager.cpp index 49d09d28855..99c73c200d4 100644 --- a/src/plugins/help/localhelpmanager.cpp +++ b/src/plugins/help/localhelpmanager.cpp @@ -589,10 +589,22 @@ bool LocalHelpManager::openOnlineHelp(const QUrl &url) if (canOpenOnlineHelp(url)) { QString urlPrefix = "http://doc.qt.io/"; - if (url.authority().startsWith(unversionedLocalDomainName)) + if (url.authority().startsWith(unversionedLocalDomainName)) { urlPrefix.append(Core::Constants::IDE_ID); - else - urlPrefix.append("qt-5"); + } else { + const auto host = url.host(); + const auto dot = host.lastIndexOf('.'); + if (dot < 0) { + urlPrefix.append("qt-5"); + } else { + const auto version = host.mid(dot + 1); + if (version.startsWith('6')) { + urlPrefix.append("qt-6"); + } else { + urlPrefix.append("qt-5"); + } + } + } const QString address = url.toString(); QDesktopServices::openUrl(QUrl(urlPrefix + address.mid(address.lastIndexOf(QLatin1Char('/'))))); return true; diff --git a/src/plugins/projectexplorer/kitinformation.cpp b/src/plugins/projectexplorer/kitinformation.cpp index 5860d798407..8a3e6758cdd 100644 --- a/src/plugins/projectexplorer/kitinformation.cpp +++ b/src/plugins/projectexplorer/kitinformation.cpp @@ -1240,11 +1240,20 @@ BuildDeviceKitAspect::BuildDeviceKitAspect() this, &BuildDeviceKitAspect::kitsWereLoaded); } -QVariant BuildDeviceKitAspect::defaultValue(const Kit *k) const +void BuildDeviceKitAspect::setup(Kit *k) { - Q_UNUSED(k); - IDevice::ConstPtr defaultDevice = DeviceManager::defaultDesktopDevice(); - return defaultDevice->id().toString(); + QTC_ASSERT(DeviceManager::instance()->isLoaded(), return ); + IDevice::ConstPtr dev = BuildDeviceKitAspect::device(k); + if (!dev.isNull() && dev->isCompatibleWith(k)) + return; + + dev = defaultDevice(); + setDeviceId(k, dev ? dev->id() : Id()); +} + +IDevice::ConstPtr BuildDeviceKitAspect::defaultDevice() +{ + return DeviceManager::defaultDesktopDevice(); } Tasks BuildDeviceKitAspect::validate(const Kit *k) const @@ -1314,10 +1323,8 @@ IDevice::ConstPtr BuildDeviceKitAspect::device(const Kit *k) { QTC_ASSERT(DeviceManager::instance()->isLoaded(), return IDevice::ConstPtr()); IDevice::ConstPtr dev = DeviceManager::instance()->find(deviceId(k)); - // Use the "run" device as fallback if no build device is present. - // FIXME: Think about whether this shouldn't be the other way round. if (!dev) - dev = DeviceKitAspect::device(k); + dev = defaultDevice(); return dev; } diff --git a/src/plugins/projectexplorer/kitinformation.h b/src/plugins/projectexplorer/kitinformation.h index 6118bec9aed..5675b02c062 100644 --- a/src/plugins/projectexplorer/kitinformation.h +++ b/src/plugins/projectexplorer/kitinformation.h @@ -182,6 +182,7 @@ class PROJECTEXPLORER_EXPORT BuildDeviceKitAspect : public KitAspect public: BuildDeviceKitAspect(); + void setup(Kit *k) override; Tasks validate(const Kit *k) const override; KitAspectWidget *createConfigWidget(Kit *k) const override; @@ -199,7 +200,7 @@ public: static void setDeviceId(Kit *k, Utils::Id dataId); private: - QVariant defaultValue(const Kit *k) const; + static IDevice::ConstPtr defaultDevice(); void kitsWereLoaded(); void deviceUpdated(Utils::Id dataId); diff --git a/src/plugins/qmldesigner/cmakegeneratordialog.cpp b/src/plugins/qmldesigner/cmakegeneratordialog.cpp index e8cf8e872f4..19edd3e30a6 100644 --- a/src/plugins/qmldesigner/cmakegeneratordialog.cpp +++ b/src/plugins/qmldesigner/cmakegeneratordialog.cpp @@ -34,7 +34,8 @@ #include #include #include -#include + +#include using namespace Utils; @@ -49,36 +50,62 @@ CmakeGeneratorDialog::CmakeGeneratorDialog(const FilePath &rootDir, const FilePa setWindowTitle(QCoreApplication::translate("QmlDesigner::GenerateCmake", "Select Files to Generate")); - m_model = new CMakeGeneratorDialogTreeModel(rootDir, files, this); + QLabel *mainLabel = new QLabel(QCoreApplication::translate("QmlDesigner::GenerateCmake", + "Start CMakeFiles.txt generation"), + this); + mainLabel->setMargin(30); QVBoxLayout *dialogLayout = new QVBoxLayout(this); - dialogLayout->setSizeConstraint(QLayout::SetFixedSize); + dialogLayout->addWidget(mainLabel); + dialogLayout->addWidget(createDetailsWidget()); + dialogLayout->addWidget(createButtons()); setLayout(dialogLayout); - QWidget *advancedInnerWidget = new QWidget(this); - QVBoxLayout *advancedInnerLayout = new QVBoxLayout(advancedInnerWidget); - advancedInnerWidget->setLayout(advancedInnerLayout); - advancedInnerWidget->setMinimumHeight(640); + setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + setMaximumHeight(layout()->totalSizeHint().height()); + + refreshNotificationText(); +} + +QTreeView* CmakeGeneratorDialog::createFileTree() +{ + m_model = new CMakeGeneratorDialogTreeModel(m_rootDir, m_files, this); QTreeView *tree = new QTreeView(this); tree->setModel(m_model); tree->expandAll(); tree->setHeaderHidden(true); + return tree; +} + +QWidget* CmakeGeneratorDialog::createDetailsWidget() +{ + QTreeView* tree = createFileTree(); + m_notifications = new QTextEdit(this); m_warningIcon = Utils::Icons::WARNING.pixmap(); - refreshNotificationText(); - - advancedInnerLayout->addWidget(tree, 2); - advancedInnerLayout->addWidget(m_notifications, 1); + QSplitter *advancedInnerWidget = new QSplitter(this); + advancedInnerWidget->addWidget(tree); + advancedInnerWidget->addWidget(m_notifications); + advancedInnerWidget->setStretchFactor(0, 2); + advancedInnerWidget->setStretchFactor(1, 1); + advancedInnerWidget->setOrientation(Qt::Vertical); + advancedInnerWidget->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::MinimumExpanding); DetailsWidget *advancedWidget = new DetailsWidget(this); advancedWidget->setMinimumWidth(600); advancedWidget->setWidget(advancedInnerWidget); advancedWidget->setSummaryText(QCoreApplication::translate("QmlDesigner::GenerateCmake", "Advanced Options")); + connect(advancedWidget, &DetailsWidget::expanded, this, &CmakeGeneratorDialog::advancedVisibilityChanged); + return advancedWidget; +} + +QWidget* CmakeGeneratorDialog::createButtons() +{ QDialogButtonBox *buttons = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel); auto *okButton = buttons->button(QDialogButtonBox::Ok); okButton->setDefault(true); @@ -87,14 +114,7 @@ CmakeGeneratorDialog::CmakeGeneratorDialog(const FilePath &rootDir, const FilePa connect(buttons, &QDialogButtonBox::rejected, this, &QDialog::reject); connect(m_model, &CMakeGeneratorDialogTreeModel::checkedStateChanged, this, &CmakeGeneratorDialog::refreshNotificationText); - QLabel *mainLabel = new QLabel(QCoreApplication::translate("QmlDesigner::GenerateCmake", - "Start CMakeFiles.txt generation"), - this); - mainLabel->setMargin(50); - - dialogLayout->addWidget(mainLabel); - dialogLayout->addWidget(advancedWidget); - dialogLayout->addWidget(buttons); + return buttons; } FilePaths CmakeGeneratorDialog::getFilePaths() @@ -151,5 +171,19 @@ void CmakeGeneratorDialog::refreshNotificationText() } } +void CmakeGeneratorDialog::advancedVisibilityChanged(bool visible) +{ + if (visible) { + setMaximumHeight(QWIDGETSIZE_MAX); + setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + } + else { + setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + int height = layout()->totalSizeHint().height(); + setMaximumHeight(height); + resize(width(), height); + } +} + } //GenerateCmake } //QmlDesigner diff --git a/src/plugins/qmldesigner/cmakegeneratordialog.h b/src/plugins/qmldesigner/cmakegeneratordialog.h index cb04eec18d4..f7c9984bcbf 100644 --- a/src/plugins/qmldesigner/cmakegeneratordialog.h +++ b/src/plugins/qmldesigner/cmakegeneratordialog.h @@ -33,7 +33,8 @@ #include #include - +#include +#include namespace QmlDesigner { namespace GenerateCmake { @@ -48,6 +49,12 @@ public: public slots: void refreshNotificationText(); + void advancedVisibilityChanged(bool visible); + +private: + QTreeView* createFileTree(); + QWidget* createDetailsWidget(); + QWidget* createButtons(); private: CMakeGeneratorDialogTreeModel *m_model; @@ -57,7 +64,7 @@ private: Utils::FilePaths m_files; }; -} -} +} //GenerateCmake +} //QmlDesigner #endif // CMAKEGENERATORDIALOG_H diff --git a/src/plugins/qmldesigner/designercore/include/nodeinstanceview.h b/src/plugins/qmldesigner/designercore/include/nodeinstanceview.h index bc3ca88d810..d4ff9358f52 100644 --- a/src/plugins/qmldesigner/designercore/include/nodeinstanceview.h +++ b/src/plugins/qmldesigner/designercore/include/nodeinstanceview.h @@ -34,6 +34,8 @@ #include #include +#include + #include #include #include @@ -51,6 +53,10 @@ namespace ProjectExplorer { class Target; } +namespace Utils { +class QtcProcess; +} + namespace QmlDesigner { class NodeInstanceServerProxy; @@ -229,7 +235,8 @@ private: // functions void updatePreviewImageForNode(const ModelNode &modelNode, const QImage &image); void updateWatcher(const QString &path); - + void handleShaderChanges(); + void handleQsbProcessExit(Utils::QtcProcess *qsbProcess, const QString &shader); void updateRotationBlocks(); void maybeResetOnPropertyChange(const PropertyName &name, const ModelNode &node, PropertyChangeFlags flags); @@ -278,7 +285,11 @@ private: QFileSystemWatcher *m_fileSystemWatcher; QTimer m_resetTimer; QTimer m_updateWatcherTimer; + QTimer m_generateQsbFilesTimer; + Utils::FilePath m_qsbPath; QSet m_pendingUpdateDirs; + QSet m_pendingQsbTargets; + int m_remainingQsbTargets; QTimer m_rotBlockTimer; }; diff --git a/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp b/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp index 670a6a5c4ac..818b6093b3b 100644 --- a/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp +++ b/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp @@ -92,12 +92,18 @@ #include #endif +#include + +#include #include #include #include #include +#include + +#include #include #include @@ -161,6 +167,18 @@ NodeInstanceView::NodeInstanceView(ConnectionManagerInterface &connectionManager m_pendingUpdateDirs.clear(); }); + // Since generating qsb files is asynchronous and can trigger directory changes, which in turn + // can trigger qsb generation, compressing qsb generation is necessary to avoid a lot of + // unnecessary generation when project with multiple shaders is opened. + m_generateQsbFilesTimer.setSingleShot(true); + m_generateQsbFilesTimer.setInterval(100); + QObject::connect(&m_generateQsbFilesTimer, &QTimer::timeout, [this] { + handleShaderChanges(); + + if (m_qsbPath.isEmpty() || m_remainingQsbTargets <= 0) + m_resetTimer.start(); + }); + connect(m_fileSystemWatcher, &QFileSystemWatcher::directoryChanged, [this](const QString &path) { const QSet pendingDirs = m_pendingUpdateDirs; @@ -177,8 +195,9 @@ NodeInstanceView::NodeInstanceView(ConnectionManagerInterface &connectionManager m_updateWatcherTimer.start(); }); - connect(m_fileSystemWatcher, &QFileSystemWatcher::fileChanged, [this] { - m_resetTimer.start(); + connect(m_fileSystemWatcher, &QFileSystemWatcher::fileChanged, [this](const QString &path) { + m_pendingQsbTargets.insert(path); + m_generateQsbFilesTimer.start(); }); m_rotBlockTimer.setSingleShot(true); @@ -1461,6 +1480,17 @@ void NodeInstanceView::setTarget(ProjectExplorer::Target *newTarget) { if (m_currentTarget != newTarget) { m_currentTarget = newTarget; + if (m_currentTarget && m_currentTarget->kit()) { + if (QtSupport::QtVersion *qtVer = QtSupport::QtKitAspect::qtVersion(m_currentTarget->kit())) { + m_qsbPath = qtVer->binPath().pathAppended("qsb").withExecutableSuffix(); + if (!m_qsbPath.exists()) + m_qsbPath.clear(); + } + } + + m_generateQsbFilesTimer.stop(); + m_pendingQsbTargets.clear(); + m_remainingQsbTargets = 0; restartProcess(); } } @@ -1904,9 +1934,88 @@ void NodeInstanceView::updateWatcher(const QString &path) m_fileSystemWatcher->removePaths(oldFiles); if (!newFiles.isEmpty()) m_fileSystemWatcher->addPaths(newFiles); + + for (const auto &newFile : qAsConst(newFiles)) { + if (!oldFiles.contains(newFile)) + m_pendingQsbTargets.insert(newFile); + } + + if (!m_pendingQsbTargets.isEmpty()) + m_generateQsbFilesTimer.start(); } } +void NodeInstanceView::handleQsbProcessExit(Utils::QtcProcess *qsbProcess, const QString &shader) +{ + --m_remainingQsbTargets; + + QString errStr = qsbProcess->errorString(); + QByteArray stdErrStr = qsbProcess->readAllStandardError(); + + if (!errStr.isEmpty() || !stdErrStr.isEmpty()) { + Core::MessageManager::writeSilently( + QCoreApplication::translate("QmlDesigner::NodeInstanceView", + "Failed to generate QSB file for: %1") + .arg(shader)); + if (!errStr.isEmpty()) + Core::MessageManager::writeSilently(errStr); + if (!stdErrStr.isEmpty()) + Core::MessageManager::writeSilently(QString::fromUtf8(stdErrStr)); + } + + if (m_remainingQsbTargets <= 0) + m_resetTimer.start(); + + qsbProcess->deleteLater(); +} + +void NodeInstanceView::handleShaderChanges() +{ + m_remainingQsbTargets += m_pendingQsbTargets.size(); + + for (const auto &shader : qAsConst(m_pendingQsbTargets)) { + // Run qsb for changed shader file + if (!m_qsbPath.isEmpty() && !shader.isEmpty()) { + const Utils::FilePath sourceFile = Utils::FilePath::fromString(shader); + const Utils::FilePath srcPath = sourceFile.absolutePath(); + const Utils::FilePath outPath = Utils::FilePath::fromString(shader + ".qsb"); + + if (!sourceFile.exists() || (outPath.exists() && outPath.lastModified() > sourceFile.lastModified())) { + --m_remainingQsbTargets; + continue; + } + + // Run QSB with same parameters as Qt build does + // TODO: Parameters should be configurable (QDS-6590) + const QStringList args = {"-s", "--glsl", "100 es,120,150", "--hlsl", "50", "--msl", "12", + "-o", outPath.toString(), shader}; + auto qsbProcess = new Utils::QtcProcess; + qsbProcess->setWorkingDirectory(srcPath); + qsbProcess->setCommand({m_qsbPath, args}); + qsbProcess->start(); + + if (!qsbProcess->waitForStarted()) { + handleQsbProcessExit(qsbProcess, shader); + continue; + } + + if (qsbProcess->state() == QProcess::Running) { + connect(qsbProcess, &Utils::QtcProcess::finished, + [thisView = QPointer(this), qsbProcess, shader]() { + if (thisView) + thisView->handleQsbProcessExit(qsbProcess, shader); + else + qsbProcess->deleteLater(); + }); + } else { + handleQsbProcessExit(qsbProcess, shader); + } + } + } + + m_pendingQsbTargets.clear(); +} + void NodeInstanceView::updateRotationBlocks() { if (!model()) diff --git a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp index ad3c1693304..6eb2faa02e6 100644 --- a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp +++ b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp @@ -924,6 +924,10 @@ static QList generatePossibleFileImports(const QString &pat std::function checkDir; checkDir = [&](const QString &checkPath) { + + if (QFileInfo(checkPath).isRoot()) + return; + const QStringList entries = QDir(checkPath).entryList(QDir::Dirs | QDir::NoDot | QDir::NoDotDot); const QString checkPathDelim = checkPath + delimeter; for (const QString &entry : entries) { @@ -1007,7 +1011,8 @@ void TextToModelMerger::setupPossibleImports(const QmlJS::Snapshot &snapshot, co QList possibleImports = generatePossibleLibraryImports(filteredPossibleImportKeys); - possibleImports.append(generatePossibleFileImports(document()->path(), imports->all())); + if (document()->fileName() != "") + possibleImports.append(generatePossibleFileImports(document()->path(), imports->all())); if (m_rewriterView->isAttached()) m_rewriterView->model()->setPossibleImports(possibleImports); diff --git a/src/plugins/qmldesigner/generateresource.cpp b/src/plugins/qmldesigner/generateresource.cpp index f06abddf225..7876639c9b2 100644 --- a/src/plugins/qmldesigner/generateresource.cpp +++ b/src/plugins/qmldesigner/generateresource.cpp @@ -148,8 +148,7 @@ QStringList GenerateResource::getFileList(const QList &fileNames) bool skipSuffix(const QString &fileName) { - const QStringList suffixes = {".qmlproject", - ".pri", + const QStringList suffixes = {".pri", ".pro", ".user", ".qrc", @@ -158,7 +157,10 @@ bool skipSuffix(const QString &fileName) ".db", ".tmp", ".TMP", - ".metainfo"}; + ".metainfo", + ".qtds", + ".db-shm", + ".db-wal"}; for (const auto &suffix : suffixes) if (fileName.endsWith(suffix)) diff --git a/tests/auto/cplusplus/codeformatter/tst_codeformatter.cpp b/tests/auto/cplusplus/codeformatter/tst_codeformatter.cpp index db0c7aeb1c1..d98dc3e21e2 100644 --- a/tests/auto/cplusplus/codeformatter/tst_codeformatter.cpp +++ b/tests/auto/cplusplus/codeformatter/tst_codeformatter.cpp @@ -128,6 +128,7 @@ private Q_SLOTS: void initializerWithinFunctionArg(); void shiftWithinInitializer(); void lambdaWithReturnType(); + void structuredBinding(); }; struct Line { @@ -2209,6 +2210,17 @@ void tst_CodeFormatter::lambdaWithReturnType() checkIndent(data); } +void tst_CodeFormatter::structuredBinding() +{ + QList data; + data << Line("int main() {") + << Line(" auto [v1, v2] = tuple_func();") + << Line(" return 0;") + << Line("}") + ; + checkIndent(data); +} + QTEST_MAIN(tst_CodeFormatter) #include "tst_codeformatter.moc"