diff --git a/dist/changelog/changes-11.0.2.md b/dist/changelog/changes-11.0.2.md new file mode 100644 index 00000000000..91994e79b9f --- /dev/null +++ b/dist/changelog/changes-11.0.2.md @@ -0,0 +1,73 @@ +Qt Creator 11.0.2 +================= + +Qt Creator version 11.0.2 contains bug fixes. + +The most important changes are listed in this document. For a complete list of +changes, see the Git log for the Qt Creator sources that you can check out from +the public Git repository. For example: + + git clone git://code.qt.io/qt-creator/qt-creator.git + git log --cherry-pick --pretty=oneline origin/v11.0.1..v11.0.2 + +General +------- + +* Allow fractional high DPI scaling without modifying the environment + ([QTCREATORBUG-29461](https://bugreports.qt.io/browse/QTCREATORBUG-29461)) + +Editing +------- + +### General + +* Fixed a potential crash when reloading a document + ([QTCREATORBUG-29432](https://bugreports.qt.io/browse/QTCREATORBUG-29432)) + +### Copilot + +* Fixed a crash when configuring an unusable copilot agent in the settings + +Debug +----- + +* Fixed a problem where debugging with "Run In Terminal" would fail on Linux + ([QTCREATORBUG-29463](https://bugreports.qt.io/browse/QTCREATORBUG-29463)) + +Projects +-------- + +### CMake + +* Fixed code completion for ui file components for CMake based projects + ([QTCREATORBUG-28787](https://bugreports.qt.io/browse/QTCREATORBUG-28787)) +* Fix reading ninjaPath from QtCreator.ini + ([QTBUG-115754](https://bugreports.qt.io/browse/QTBUG-115754)) +* Fixed incorrect device checks when using Boot2Qt + ([QTCREATORBUG-29474](https://bugreports.qt.io/browse/QTCREATORBUG-29474)) + +### QMake + +* Avoid cleaning the build directory after switching kits + ([QTCREATORBUG-29451](https://bugreports.qt.io/browse/QTCREATORBUG-29451)) + ([QTCREATORBUG-29481](https://bugreports.qt.io/browse/QTCREATORBUG-29481)) + +Version Control Systems +----------------------- + +### Fossil + +* Show the correct dialog when reverting the current file + +Credits for these changes go to: +-------------------------------- +Aaron Barany +André Pönitz +Björn Schäpers +Christian Kandeler +Cristian Adam +David Schulz +Jaroslaw Kobus +Leena Miettinen +Marcus Tillmanns +Orgad Shaneh diff --git a/src/libs/3rdparty/cplusplus/Parser.cpp b/src/libs/3rdparty/cplusplus/Parser.cpp index 6bf19f59829..395556777dd 100644 --- a/src/libs/3rdparty/cplusplus/Parser.cpp +++ b/src/libs/3rdparty/cplusplus/Parser.cpp @@ -3020,6 +3020,11 @@ bool Parser::parseInitDeclarator(DeclaratorAST *&node, SpecifierListAST *decl_sp if (!_languageFeatures.cxx11Enabled || LA(2) == T_NUMERIC_LITERAL) { parseInitializer(node->initializer, &node->equal_token); } else { + if (LA(2) != T_NUMERIC_LITERAL && LA(2) != T_DEFAULT && LA(2) != T_DELETE) { + error(cursor(), "expected 'default', 'delete' or '0', got '%s'", tok(2).spell()); + return false; + } + node->equal_token = consumeToken(); IdExpressionAST *id_expr = new (_pool) IdExpressionAST; diff --git a/src/libs/3rdparty/libptyqt/unixptyprocess.cpp b/src/libs/3rdparty/libptyqt/unixptyprocess.cpp index b40c8933ac7..91dbf36d7ec 100644 --- a/src/libs/3rdparty/libptyqt/unixptyprocess.cpp +++ b/src/libs/3rdparty/libptyqt/unixptyprocess.cpp @@ -184,29 +184,10 @@ bool UnixPtyProcess::startProcess(const QString &shellPath, m_readMasterNotify->disconnect(); }); - const QStringList defaultVars = { - "TERM=xterm-256color", - "ITERM_PROFILE=Default", - "XPC_FLAGS=0x0", - "XPC_SERVICE_NAME=0", - "LANG=en_US.UTF-8", - "LC_ALL=en_US.UTF-8", - "LC_CTYPE=UTF-8", - "INIT_CWD=" + QCoreApplication::applicationDirPath(), - "COMMAND_MODE=unix2003", - "COLORTERM=truecolor" - }; - QStringList varNames; for (const QString &line : std::as_const(environment)) varNames.append(line.split("=").first()); - //append default env vars only if they don't exists in current env - for (const QString &defVar : defaultVars) { - if (!varNames.contains(defVar.split("=").first())) - environment.append(defVar); - } - QProcessEnvironment envFormat; for (const QString &line : std::as_const(environment)) envFormat.insert(line.split("=").first(), line.split("=").last()); diff --git a/src/libs/utils/filepath.cpp b/src/libs/utils/filepath.cpp index 8349fb68180..42c1a19957f 100644 --- a/src/libs/utils/filepath.cpp +++ b/src/libs/utils/filepath.cpp @@ -204,7 +204,27 @@ FilePath FilePath::currentWorkingPath() bool FilePath::isRootPath() const { - // FIXME: Make host-independent + if (needsDevice()) { + QStringView path = pathView(); + if (osType() != OsTypeWindows) + return path == QLatin1String("/"); + + // Remote windows paths look like this: "/c:/", so we remove the leading '/' + if (path.startsWith('/')) + path = path.mid(1); + + if (path.length() > 3) + return false; + + if (!startsWithDriveLetter()) + return false; + + if (path.length() == 3 && path[2] != QLatin1Char('/')) + return false; + + return true; + } + return *this == FilePath::fromString(QDir::rootPath()); } @@ -1383,15 +1403,15 @@ bool FilePath::contains(const QString &s) const /*! \brief Checks whether the FilePath starts with a drive letter. - - Defaults to \c false if it is a non-Windows host or represents a path on device - Returns whether FilePath starts with a drive letter */ bool FilePath::startsWithDriveLetter() const { - const QStringView p = pathView(); - return !needsDevice() && p.size() >= 2 && isWindowsDriveLetter(p[0]) && p.at(1) == ':'; + QStringView p = pathView(); + if (needsDevice() && !p.isEmpty()) + p = p.mid(1); + + return p.size() >= 2 && isWindowsDriveLetter(p[0]) && p.at(1) == ':'; } /*! diff --git a/src/plugins/autotest/ctest/ctesttreeitem.cpp b/src/plugins/autotest/ctest/ctesttreeitem.cpp index 89c06411522..60f1081e77a 100644 --- a/src/plugins/autotest/ctest/ctesttreeitem.cpp +++ b/src/plugins/autotest/ctest/ctesttreeitem.cpp @@ -82,7 +82,7 @@ QList CTestTreeItem::testConfigurationsFor(const QStringLi if (!project) return {}; - const ProjectExplorer::Target *target = project->targets().value(0); + const ProjectExplorer::Target *target = ProjectExplorer::ProjectManager::startupTarget(); if (!target) return {}; diff --git a/src/plugins/cmakeprojectmanager/cmakebuildstep.cpp b/src/plugins/cmakeprojectmanager/cmakebuildstep.cpp index 294fb055c53..bff01796157 100644 --- a/src/plugins/cmakeprojectmanager/cmakebuildstep.cpp +++ b/src/plugins/cmakeprojectmanager/cmakebuildstep.cpp @@ -14,6 +14,8 @@ #include +#include + #include #include @@ -202,6 +204,8 @@ static bool supportsStageForInstallation(const Kit *kit) return runDevice->id() != buildDevice->id() && runDevice->type() != Android::Constants::ANDROID_DEVICE_TYPE && runDevice->type() != Ios::Constants::IOS_DEVICE_TYPE + && runDevice->type() != Ios::Constants::IOS_SIMULATOR_TYPE + && runDevice->type() != BareMetal::Constants::BareMetalOsType && runDevice->type() != WebAssembly::Constants::WEBASSEMBLY_DEVICE_TYPE; } diff --git a/src/plugins/coreplugin/idocument.cpp b/src/plugins/coreplugin/idocument.cpp index c6fdac85736..06218411b15 100644 --- a/src/plugins/coreplugin/idocument.cpp +++ b/src/plugins/coreplugin/idocument.cpp @@ -343,10 +343,10 @@ IDocument::OpenResult IDocument::open(QString *errorString, const Utils::FilePat */ bool IDocument::save(QString *errorString, const Utils::FilePath &filePath, bool autoSave) { - emit aboutToSave(filePath, autoSave); + emit aboutToSave(filePath.isEmpty() ? this->filePath() : filePath, autoSave); const bool success = saveImpl(errorString, filePath, autoSave); if (success) - emit saved(filePath, autoSave); + emit saved(filePath.isEmpty() ? this->filePath() : filePath, autoSave); return success; } diff --git a/src/plugins/cppeditor/cpprefactoringchanges.cpp b/src/plugins/cppeditor/cpprefactoringchanges.cpp index 32b6b9d88c9..f4bcc471ad8 100644 --- a/src/plugins/cppeditor/cpprefactoringchanges.cpp +++ b/src/plugins/cppeditor/cpprefactoringchanges.cpp @@ -131,6 +131,9 @@ bool CppRefactoringFile::isCursorOn(unsigned tokenIndex) const bool CppRefactoringFile::isCursorOn(const AST *ast) const { + if (!ast) + return false; + QTextCursor tc = cursor(); int cursorBegin = tc.selectionStart(); diff --git a/src/plugins/languageclient/languageclientcompletionassist.cpp b/src/plugins/languageclient/languageclientcompletionassist.cpp index 5d68cb92e91..96aebde7850 100644 --- a/src/plugins/languageclient/languageclientcompletionassist.cpp +++ b/src/plugins/languageclient/languageclientcompletionassist.cpp @@ -273,8 +273,13 @@ public: void setProposal(IAssistProposal *proposal, const QString &prefix) { - if (!proposal) + if (!proposal) { + // Close the proposal if we have no running processor otherwise ignore the empty + // proposal and wait for the processor to finish + if (!m_processor || !m_processor->running()) + closeProposal(); return; + } if (proposal->id() != TextEditor::Constants::GENERIC_PROPOSAL_ID) { // We received something else than a generic proposal so we cannot update the model closeProposal(); @@ -291,13 +296,14 @@ public: GenericProposalWidget::updateProposal(std::move(interface)); return; } - auto processor = m_provider->createProcessor(interface.get()); - QTC_ASSERT(processor, return); + m_processor = m_provider->createProcessor(interface.get()); + QTC_ASSERT(m_processor, return); const QString prefix = interface->textAt(m_basePosition, interface->position() - m_basePosition); - processor->setAsyncCompletionAvailableHandler([this, processor, prefix](IAssistProposal *proposal) { + m_processor->setAsyncCompletionAvailableHandler([this, processor = m_processor, prefix]( + IAssistProposal *proposal) { QTC_ASSERT(processor == m_processor, return); if (!processor->running()) { // do not delete this processor directly since this function is called from within the processor @@ -310,11 +316,11 @@ public: setProposal(proposal, prefix); }); - setProposal(processor->start(std::move(interface)), prefix); - if (processor->running()) - m_processor = processor; - else - delete processor; + setProposal(m_processor->start(std::move(interface)), prefix); + if (!m_processor->running()) { + delete m_processor; + m_processor = nullptr; + } } private: diff --git a/src/plugins/languageclient/languageclientsettings.cpp b/src/plugins/languageclient/languageclientsettings.cpp index 650b450a5d3..349a84f7b88 100644 --- a/src/plugins/languageclient/languageclientsettings.cpp +++ b/src/plugins/languageclient/languageclientsettings.cpp @@ -120,16 +120,15 @@ public: applyCurrentSettings(); LanguageClientManager::applySettings(); - for (BaseSettings *setting : m_model.removed()) { + for (BaseSettings *setting : m_settings.removed()) { for (Client *client : LanguageClientManager::clientsForSetting(setting)) LanguageClientManager::shutdownClient(client); } int row = currentRow(); - m_model.reset(LanguageClientManager::currentSettings()); + m_settings.reset(LanguageClientManager::currentSettings()); resetCurrentSettings(row); } - void finish() { m_settings.reset(LanguageClientManager::currentSettings()); @@ -148,7 +147,6 @@ private: LanguageClientSettingsModel &m_settings; QSet &m_changedSettings; - LanguageClientSettingsModel m_model; }; QMap &clientTypes() @@ -302,8 +300,6 @@ LanguageClientSettingsPage::LanguageClientSettingsPage() void LanguageClientSettingsPage::init() { m_model.reset(LanguageClientSettings::fromSettings(Core::ICore::settings())); - apply(); - finish(); } QList LanguageClientSettingsPage::settings() const @@ -603,6 +599,7 @@ static LanguageClientSettingsPage &settingsPage() void LanguageClientSettings::init() { settingsPage().init(); + LanguageClientManager::applySettings(); } QList LanguageClientSettings::fromSettings(QSettings *settingsIn) diff --git a/src/plugins/projectexplorer/devicesupport/sshsettings.cpp b/src/plugins/projectexplorer/devicesupport/sshsettings.cpp index d428c4640a3..adbf458d264 100644 --- a/src/plugins/projectexplorer/devicesupport/sshsettings.cpp +++ b/src/plugins/projectexplorer/devicesupport/sshsettings.cpp @@ -107,10 +107,10 @@ static FilePath filePathValue(const FilePath &value, const QStringList &candidat { if (!value.isEmpty()) return value; - const FilePaths additionalSearchPaths = sshSettings->searchPathRetriever(); + Environment env = Environment::systemEnvironment(); + env.prependToPath(sshSettings->searchPathRetriever()); for (const QString &candidate : candidateFileNames) { - const FilePath filePath = Environment::systemEnvironment() - .searchInPath(candidate, additionalSearchPaths); + const FilePath filePath = env.searchInPath(candidate); if (!filePath.isEmpty()) return filePath; } diff --git a/src/plugins/terminal/terminalwidget.cpp b/src/plugins/terminal/terminalwidget.cpp index 326ed523915..c648406e39c 100644 --- a/src/plugins/terminal/terminalwidget.cpp +++ b/src/plugins/terminal/terminalwidget.cpp @@ -113,6 +113,13 @@ void TerminalWidget::setupPty() Environment env = m_openParameters.environment.value_or(Environment{}) .appliedToEnvironment(shellCommand.executable().deviceEnvironment()); + // Set some useful defaults + env.setFallback("TERM", "xterm-256color"); + env.setFallback("TERM_PROGRAM", QCoreApplication::applicationName()); + env.setFallback("COLORTERM", "truecolor"); + env.setFallback("COMMAND_MODE", "unix2003"); + env.setFallback("INIT_CWD", QCoreApplication::applicationDirPath()); + // For git bash on Windows env.prependOrSetPath(shellCommand.executable().parentDir()); if (env.hasKey("CLINK_NOAUTORUN")) diff --git a/src/tools/process_stub/main.cpp b/src/tools/process_stub/main.cpp index 00312b833f6..702450f8b7f 100644 --- a/src/tools/process_stub/main.cpp +++ b/src/tools/process_stub/main.cpp @@ -24,6 +24,7 @@ #ifdef Q_OS_LINUX #include +#include #endif #include @@ -221,7 +222,25 @@ void onInferiorStarted() if (!debugMode) sendPid(inferiorId); #else - ptrace(PTRACE_DETACH, inferiorId, 0, SIGSTOP); + if (debugMode) { + qCInfo(log) << "Detaching ..."; + ptrace(PTRACE_DETACH, inferiorId, 0, SIGSTOP); + + // Wait until the process actually finished detaching + int status = 0; + waitpid(inferiorId, &status, WUNTRACED); + if (log().isInfoEnabled()) { + if (WIFEXITED(status)) + qCInfo(log) << "inferior exited, status=" << WEXITSTATUS(status); + else if (WIFSIGNALED(status)) + qCInfo(log) << "inferior killed by signal" << WTERMSIG(status); + else if (WIFSTOPPED(status)) + qCInfo(log) << "inferior stopped by signal" << WSTOPSIG(status); + else if (WIFCONTINUED(status)) + qCInfo(log) << "inferior continued"; + } + } + sendPid(inferiorId); #endif } diff --git a/tests/auto/cplusplus/ast/tst_ast.cpp b/tests/auto/cplusplus/ast/tst_ast.cpp index fc1ab3538e8..5790cb090ac 100644 --- a/tests/auto/cplusplus/ast/tst_ast.cpp +++ b/tests/auto/cplusplus/ast/tst_ast.cpp @@ -190,6 +190,7 @@ private slots: void enumDeclaration(); void invalidEnumClassDeclaration(); void invalidEnumWithDestructorId(); + void invalidFunctionInitializer(); }; void tst_AST::gcc_attributes_1() @@ -2052,6 +2053,14 @@ void tst_AST::invalidEnumWithDestructorId() QVERIFY(diag.errorCount != 0); } +void tst_AST::invalidFunctionInitializer() +{ + QSharedPointer unit(parse( + "int main() { a t=b; c d(e)=\"\"; }", TranslationUnit::ParseTranlationUnit, false, false, true)); + + QVERIFY(diag.errorCount != 0); +} + void tst_AST::initTestCase() { control.setDiagnosticClient(&diag); diff --git a/tests/auto/utils/filepath/tst_filepath.cpp b/tests/auto/utils/filepath/tst_filepath.cpp index f09665abc90..0cd0629609e 100644 --- a/tests/auto/utils/filepath/tst_filepath.cpp +++ b/tests/auto/utils/filepath/tst_filepath.cpp @@ -115,6 +115,8 @@ private slots: void sort(); void sort_data(); + void isRootPath(); + private: QTemporaryDir tempDir; QString rootPath; @@ -1308,6 +1310,14 @@ void tst_filepath::startsWithDriveLetter_data() QTest::newRow("simple-win") << FilePath::fromString("c:/a") << true; QTest::newRow("simple-linux") << FilePath::fromString("/c:/a") << false; QTest::newRow("relative") << FilePath("a/b") << false; + + QTest::newRow("remote-slash") << FilePath::fromString("docker://1234/") << false; + QTest::newRow("remote-single-letter") << FilePath::fromString("docker://1234/c") << false; + QTest::newRow("remote-drive") << FilePath::fromString("docker://1234/c:") << true; + QTest::newRow("remote-invalid-drive") << FilePath::fromString("docker://1234/c:a") << true; + QTest::newRow("remote-with-path") << FilePath::fromString("docker://1234/c:/a") << true; + QTest::newRow("remote-z") << FilePath::fromString("docker://1234/z:") << true; + QTest::newRow("remote-1") << FilePath::fromString("docker://1234/1:") << false; } void tst_filepath::startsWithDriveLetter() @@ -1656,6 +1666,31 @@ void tst_filepath::sort() QCOMPARE(sortedPaths, sorted); } +void tst_filepath::isRootPath() +{ + FilePath localRoot = FilePath::fromString(QDir::rootPath()); + QVERIFY(localRoot.isRootPath()); + + FilePath localNonRoot = FilePath::fromString(QDir::rootPath() + "x"); + QVERIFY(!localNonRoot.isRootPath()); + + if (HostOsInfo::isWindowsHost()) { + FilePath remoteWindowsRoot = FilePath::fromString("device://test/c:/"); + QVERIFY(remoteWindowsRoot.isRootPath()); + + FilePath remoteWindowsRoot1 = FilePath::fromString("device://test/c:"); + QVERIFY(remoteWindowsRoot1.isRootPath()); + + FilePath remoteWindowsNotRoot = FilePath::fromString("device://test/c:/x"); + QVERIFY(!remoteWindowsNotRoot.isRootPath()); + } else { + FilePath remoteRoot = FilePath::fromString("device://test/"); + QVERIFY(remoteRoot.isRootPath()); + + FilePath remotePath = FilePath::fromString("device://test/x"); + QVERIFY(!remotePath.isRootPath()); + } +} void tst_filepath::sort_data() { QTest::addColumn("input");