diff --git a/qbs/modules/libclang/functions.js b/qbs/modules/libclang/functions.js index 85334992600..bdffcc9c23a 100644 --- a/qbs/modules/libclang/functions.js +++ b/qbs/modules/libclang/functions.js @@ -101,17 +101,33 @@ function extraLibraries(llvmConfig, targetOS) })); } -function formattingLibs(llvmConfig, targetOS) +function formattingLibs(llvmConfig, qtcFunctions, targetOS) { - var fixedList = [ - "clangFormat", - "clangToolingCore", - "clangRewrite", - "clangLex", - "clangBasic", - ]; + var clangVersion = version(llvmConfig) + var libs = [] + if (qtcFunctions.versionIsAtLeast(clangVersion, MinimumLLVMVersion)) { + if (qtcFunctions.versionIsAtLeast(clangVersion, "7.0.0")) { + libs.concat([ + "clangFormat", + "clangToolingInclusions", + "clangToolingCore", + "clangRewrite", + "clangLex", + "clangBasic", + ]); + } else { + libs.concat([ + "clangFormat", + "clangToolingCore", + "clangRewrite", + "clangLex", + "clangBasic", + ]); + } + libs.concat(extraLibraries(llvmConfig, targetOS)); + } - return fixedList.concat(extraLibraries(llvmConfig, targetOS)); + return libs; } function toolingLibs(llvmConfig, targetOS) diff --git a/qbs/modules/libclang/libclang.qbs b/qbs/modules/libclang/libclang.qbs index 1d695a2c8d5..e95250ddba3 100644 --- a/qbs/modules/libclang/libclang.qbs +++ b/qbs/modules/libclang/libclang.qbs @@ -38,7 +38,7 @@ Module { llvmToolingDefines = toolingParams.defines; llvmToolingIncludes = toolingParams.includes; llvmToolingCxxFlags = toolingParams.cxxFlags; - llvmFormattingLibs = ClangFunctions.formattingLibs(llvmConfig, targetOS); + llvmFormattingLibs = ClangFunctions.formattingLibs(llvmConfig, QtcFunctions, targetOS); found = llvmConfig && File.exists(llvmIncludeDir.concat("/clang-c/Index.h")); } } diff --git a/share/qtcreator/themes/design.creatortheme b/share/qtcreator/themes/design.creatortheme index b3ca4e3a02a..60f074f328a 100644 --- a/share/qtcreator/themes/design.creatortheme +++ b/share/qtcreator/themes/design.creatortheme @@ -419,6 +419,7 @@ FlatProjectsMode=true FlatMenuBar=true ToolBarIconShadow=true WindowColorAsBase=false +DarkUserInterface=true [Gradients] DetailsWidgetHeaderGradient\1\color=00000000 diff --git a/src/libs/utils/synchronousprocess.cpp b/src/libs/utils/synchronousprocess.cpp index 0f8d4ea8258..f9ab96eb478 100644 --- a/src/libs/utils/synchronousprocess.cpp +++ b/src/libs/utils/synchronousprocess.cpp @@ -443,7 +443,8 @@ static bool isGuiThread() } SynchronousProcessResponse SynchronousProcess::run(const QString &binary, - const QStringList &args) + const QStringList &args, + const QByteArray &writeData) { if (debug) qDebug() << '>' << Q_FUNC_INFO << binary << args; @@ -454,8 +455,20 @@ SynchronousProcessResponse SynchronousProcess::run(const QString &binary, // executable cannot be found in the path. Do not start the // event loop in that case. d->m_binary = binary; - d->m_process.start(binary, args, QIODevice::ReadOnly); - d->m_process.closeWriteChannel(); + d->m_process.start(binary, args, writeData.isEmpty() ? QIODevice::ReadOnly : QIODevice::ReadWrite); + connect(&d->m_process, &QProcess::started, this, [this, writeData] { + if (!writeData.isEmpty()) { + int pos = 0; + int sz = writeData.size(); + do { + d->m_process.waitForBytesWritten(); + auto res = d->m_process.write(writeData.constData() + pos, sz - pos); + if (res > 0) pos += res; + } while (pos < sz); + d->m_process.waitForBytesWritten(); + } + d->m_process.closeWriteChannel(); + }); if (!d->m_startFailure) { d->m_timer.start(); if (isGuiThread()) diff --git a/src/libs/utils/synchronousprocess.h b/src/libs/utils/synchronousprocess.h index b1901207d8e..d8e3275030b 100644 --- a/src/libs/utils/synchronousprocess.h +++ b/src/libs/utils/synchronousprocess.h @@ -127,7 +127,7 @@ public: ExitCodeInterpreter exitCodeInterpreter() const; // Starts an nested event loop and runs the binary with the arguments - SynchronousProcessResponse run(const QString &binary, const QStringList &args); + SynchronousProcessResponse run(const QString &binary, const QStringList &args, const QByteArray &writeData = {}); // Starts the binary with the arguments blocking the UI fully SynchronousProcessResponse runBlocking(const QString &binary, const QStringList &args); diff --git a/src/plugins/android/androidconfigurations.cpp b/src/plugins/android/androidconfigurations.cpp index 0ceb88240f9..de738bee302 100644 --- a/src/plugins/android/androidconfigurations.cpp +++ b/src/plugins/android/androidconfigurations.cpp @@ -768,6 +768,27 @@ FileName AndroidConfig::ndkLocation() const return m_ndkLocation; } +static inline QString gdbServerArch(const Abi &abi) +{ + switch (abi.architecture()) { + case Abi::X86Architecture: + return abi.wordWidth() == 64 ? QString{"x86_64"} : QString{"x86"}; + case Abi::ArmArchitecture: + return abi.wordWidth() == 64 ? QString{"arm64"} : QString{"arm"}; + default: return {}; + }; +} + +FileName AndroidConfig::gdbServer(const ProjectExplorer::Abi &abi) const +{ + FileName path = AndroidConfigurations::currentConfig().ndkLocation(); + path.appendPath(QString::fromLatin1("prebuilt/android-%1/gdbserver/gdbserver") + .arg(gdbServerArch(abi))); + if (path.exists()) + return path; + return {}; +} + QVersionNumber AndroidConfig::ndkVersion() const { QVersionNumber version; @@ -1081,7 +1102,7 @@ void AndroidConfigurations::updateAutomaticKitList() QVariant id = Debugger::DebuggerItemManager::registerDebugger(debugger); Debugger::DebuggerKitInformation::setDebugger(toSetup, id); - AndroidGdbServerKitInformation::setGdbSever(toSetup, tc->suggestedGdbServer()); + AndroidGdbServerKitInformation::setGdbSever(toSetup, currentConfig().gdbServer(tc->targetAbi())); toSetup->makeSticky(); toSetup->setUnexpandedDisplayName(tr("Android for %1 (GCC %2, %3)") .arg(static_cast(qt)->targetArch()) diff --git a/src/plugins/android/androidconfigurations.h b/src/plugins/android/androidconfigurations.h index 941fab7fbd5..99544da511e 100644 --- a/src/plugins/android/androidconfigurations.h +++ b/src/plugins/android/androidconfigurations.h @@ -106,6 +106,7 @@ public: void setSdkManagerToolArgs(const QStringList &args); Utils::FileName ndkLocation() const; + Utils::FileName gdbServer(const ProjectExplorer::Abi &abi) const; QVersionNumber ndkVersion() const; void setNdkLocation(const Utils::FileName &ndkLocation); diff --git a/src/plugins/android/androidrunnerworker.cpp b/src/plugins/android/androidrunnerworker.cpp index f117d70c82e..648a0d363d4 100644 --- a/src/plugins/android/androidrunnerworker.cpp +++ b/src/plugins/android/androidrunnerworker.cpp @@ -29,6 +29,7 @@ #include "androidconstants.h" #include "androidmanager.h" #include "androidrunconfiguration.h" +#include "androidgdbserverkitinformation.h" #include #include @@ -42,6 +43,7 @@ #include #include #include +#include #include #include @@ -222,6 +224,7 @@ AndroidRunnerWorker::AndroidRunnerWorker(RunWorker *runner, const QString &packa << "Extra Start Args:" << m_amStartExtraArgs << "Before Start ADB cmds:" << m_beforeStartAdbCommands << "After finish ADB cmds:" << m_afterFinishAdbCommands; + m_gdbserverPath = AndroidGdbServerKitInformation::gdbServer(target->kit()).toString(); } AndroidRunnerWorker::~AndroidRunnerWorker() @@ -255,13 +258,13 @@ bool AndroidRunnerWorker::adbShellAmNeedsQuotes() return !oldSdk; } -bool AndroidRunnerWorker::runAdb(const QStringList &args, int timeoutS) +bool AndroidRunnerWorker::runAdb(const QStringList &args, int timeoutS, const QByteArray &writeData) { QStringList adbArgs = selector() + args; qCDebug(androidRunWorkerLog) << "ADB command: " << m_adb << adbArgs.join(' '); Utils::SynchronousProcess adb; adb.setTimeoutS(timeoutS); - Utils::SynchronousProcessResponse response = adb.run(m_adb, adbArgs); + Utils::SynchronousProcessResponse response = adb.run(m_adb, adbArgs, writeData); m_lastRunAdbError = response.exitMessage(m_adb, timeoutS); m_lastRunAdbRawOutput = response.allRawOutput(); bool success = response.result == Utils::SynchronousProcessResponse::Finished; @@ -269,6 +272,18 @@ bool AndroidRunnerWorker::runAdb(const QStringList &args, int timeoutS) return success; } +bool AndroidRunnerWorker::uploadFile(const QString &from, const QString &to, const QString &flags) +{ + QFile f(from); + if (!f.open(QIODevice::ReadOnly)) + return false; + runAdb({"shell", "run-as", m_packageName, "rm", to}); + auto res = runAdb({"shell", "run-as", m_packageName, "sh", "-c", QString("'cat > %1'").arg(to)}, 60, f.readAll()); + if (!res) + return false; + return runAdb({"shell", "run-as", m_packageName, "chmod", flags, to}); +} + void AndroidRunnerWorker::adbKill(qint64 pid) { runAdb({"shell", "kill", "-9", QString::number(pid)}); @@ -410,30 +425,17 @@ void AndroidRunnerWorker::asyncStartHelper() // e.g. on Android 8 with NDK 10e runAdb({"shell", "run-as", m_packageName, "chmod", "a+x", packageDir}); - QString gdbServerExecutable; - if (!runAdb({"shell", "run-as", m_packageName, "ls", "lib/"})) { - emit remoteProcessFinished(tr("Failed to get process path. Reason: %1.").arg(m_lastRunAdbError)); - return; - } - - for (const auto &line: m_lastRunAdbRawOutput.split('\n')) { - if (line.indexOf("gdbserver") != -1/* || line.indexOf("lldb-server") != -1*/) { - gdbServerExecutable = QString::fromUtf8(line.trimmed()); - break; - } - } - - if (gdbServerExecutable.isEmpty()) { - emit remoteProcessFinished(tr("Cannot find C++ debugger.")); + if (m_gdbserverPath.isEmpty() || !uploadFile(m_gdbserverPath, "gdbserver")) { + emit remoteProcessFinished(tr("Can not find/copy C++ debug server.")); return; } QString gdbServerSocket = packageDir + "/debug-socket"; - runAdb({"shell", "run-as", m_packageName, "killall", gdbServerExecutable}); + runAdb({"shell", "run-as", m_packageName, "killall", "gdbserver"}); runAdb({"shell", "run-as", m_packageName, "rm", gdbServerSocket}); std::unique_ptr gdbServerProcess(new QProcess, deleter); gdbServerProcess->start(m_adb, selector() << "shell" << "run-as" - << m_packageName << "lib/" + gdbServerExecutable + << m_packageName << "./gdbserver" << "--multi" << "+" + gdbServerSocket); if (!gdbServerProcess->waitForStarted()) { emit remoteProcessFinished(tr("Failed to start C++ debugger.")); diff --git a/src/plugins/android/androidrunnerworker.h b/src/plugins/android/androidrunnerworker.h index c9714724ccf..ee5ec87287a 100644 --- a/src/plugins/android/androidrunnerworker.h +++ b/src/plugins/android/androidrunnerworker.h @@ -47,7 +47,8 @@ public: AndroidRunnerWorker(ProjectExplorer::RunWorker *runner, const QString &packageName); ~AndroidRunnerWorker() override; bool adbShellAmNeedsQuotes(); - bool runAdb(const QStringList &args, int timeoutS = 10); + bool runAdb(const QStringList &args, int timeoutS = 10, const QByteArray &writeData = {}); + bool uploadFile(const QString &from, const QString &to, const QString &flags = QString("+x")); void adbKill(qint64 pid); QStringList selector() const; void forceStop(); @@ -110,6 +111,7 @@ protected: int m_apiLevel = -1; QString m_extraAppParams; Utils::Environment m_extraEnvVars; + QString m_gdbserverPath; }; } // namespace Internal diff --git a/src/plugins/android/androidtoolchain.cpp b/src/plugins/android/androidtoolchain.cpp index 9540b162408..7b32e5be69c 100644 --- a/src/plugins/android/androidtoolchain.cpp +++ b/src/plugins/android/androidtoolchain.cpp @@ -193,19 +193,7 @@ FileName AndroidToolChain::suggestedDebugger() const FileName AndroidToolChain::suggestedGdbServer() const { - FileName path = AndroidConfigurations::currentConfig().ndkLocation(); - path.appendPath(QString::fromLatin1("prebuilt/android-%1/gdbserver/gdbserver") - .arg(Abi::toString(targetAbi().architecture()))); - if (path.exists()) - return path; - path = AndroidConfigurations::currentConfig().ndkLocation(); - path.appendPath(QString::fromLatin1("toolchains/%1-%2/prebuilt/gdbserver") - .arg(AndroidConfig::toolchainPrefix(targetAbi())) - .arg(m_ndkToolChainVersion)); - if (path.exists()) - return path; - - return FileName(); + return AndroidConfigurations::currentConfig().gdbServer(targetAbi()); } QVariantMap AndroidToolChain::toMap() const diff --git a/src/plugins/clangformat/clangformat.pro b/src/plugins/clangformat/clangformat.pro index 8657acb21b3..c2e2edd49f5 100644 --- a/src/plugins/clangformat/clangformat.pro +++ b/src/plugins/clangformat/clangformat.pro @@ -3,7 +3,7 @@ include(../../shared/clang/clang_installation.pri) include(../../shared/clang/clang_defines.pri) -requires(!isEmpty(LLVM_VERSION)) +requires(!isEmpty(CLANGFORMAT_LIBS)) win32 { LLVM_BUILDMODE = $$system($$llvm_config --build-mode, lines) diff --git a/src/plugins/clangformat/clangformatindenter.cpp b/src/plugins/clangformat/clangformatindenter.cpp index f83cefb8aed..3164f4ad003 100644 --- a/src/plugins/clangformat/clangformatindenter.cpp +++ b/src/plugins/clangformat/clangformatindenter.cpp @@ -36,6 +36,8 @@ #include +#include + #include #include #include @@ -60,7 +62,12 @@ void adjustFormatStyleForLineBreak(format::FormatStyle &style, if (length > 0) style.ColumnLimit = prevBlockSize; style.AlwaysBreakBeforeMultilineStrings = true; +#if LLVM_VERSION_MAJOR >= 7 + style.AlwaysBreakTemplateDeclarations = FormatStyle::BTDS_Yes; +#else style.AlwaysBreakTemplateDeclarations = true; +#endif + style.AllowAllParametersOfDeclarationOnNextLine = true; style.AllowShortBlocksOnASingleLine = true; style.AllowShortCaseLabelsOnASingleLine = true; diff --git a/src/plugins/cpptools/compileroptionsbuilder.cpp b/src/plugins/cpptools/compileroptionsbuilder.cpp index 8ec63484f97..e722722e252 100644 --- a/src/plugins/cpptools/compileroptionsbuilder.cpp +++ b/src/plugins/cpptools/compileroptionsbuilder.cpp @@ -170,11 +170,6 @@ void CompilerOptionsBuilder::add(const QString &option) m_options.append(option); } -void CompilerOptionsBuilder::addDefine(const ProjectExplorer::Macro ¯o) -{ - m_options.append(defineDirectiveToDefineOption(macro)); -} - void CompilerOptionsBuilder::addWordWidth() { const QString argument = m_projectPart.toolChainWordWidth == ProjectPart::WordWidth64Bit @@ -211,7 +206,7 @@ static QString creatorResourcePath() #ifndef UNIT_TESTS return Core::ICore::resourcePath(); #else - return QString(); + return QDir::toNativeSeparators(QString::fromUtf8(QTC_RESOURCE_DIR "")); #endif } @@ -221,7 +216,7 @@ static QString clangIncludeDirectory(const QString &clangVersion, #ifndef UNIT_TESTS return Core::ICore::clangIncludeDirectory(clangVersion, clangResourceDirectory); #else - return QString(); + return QDir::toNativeSeparators(QString::fromUtf8(CLANG_RESOURCE_DIR "")); #endif } @@ -238,12 +233,20 @@ static int lastIncludeIndex(const QStringList &options, const QRegularExpression return index; } -static int includeIndexForResourceDirectory(const QStringList &options) +static int includeIndexForResourceDirectory(const QStringList &options, bool isMacOs = false) { // include/c++/{version}, include/c++/v1 and include/g++ - const int cppIncludeIndex = lastIncludeIndex( - options, - QRegularExpression("\\A.*[\\/\\\\]include[\\/\\\\].*(g\\+\\+.*\\z|c\\+\\+[\\/\\\\](v1\\z|\\d+.*\\z))")); + static const QRegularExpression includeRegExp( + R"(\A.*[\/\\]include[\/\\].*(g\+\+.*\z|c\+\+[\/\\](v1\z|\d+.*\z)))"); + + // The same as includeRegExp but also matches /usr/local/include + static const QRegularExpression includeRegExpMac( + R"(\A(.*[\/\\]include[\/\\].*(g\+\+.*\z|c\+\+[\/\\](v1\z|\d+.*\z))))" + R"(|([\/\\]usr[\/\\]local[\/\\]include\z))"); + + const int cppIncludeIndex = lastIncludeIndex(options, isMacOs + ? includeRegExpMac + : includeRegExp); if (cppIncludeIndex > 0) return cppIncludeIndex + 1; @@ -317,7 +320,8 @@ void CompilerOptionsBuilder::addHeaderPathOptions() const QString clangIncludePath = clangIncludeDirectory(m_clangVersion, m_clangResourceDirectory); - int includeIndexForResourceDir = includeIndexForResourceDirectory(builtInIncludes); + int includeIndexForResourceDir = includeIndexForResourceDirectory( + builtInIncludes, m_projectPart.toolChainTargetTriple.contains("darwin")); if (includeIndexForResourceDir >= 0) { builtInIncludes.insert(includeIndexForResourceDir, clangIncludePath); diff --git a/src/plugins/cpptools/compileroptionsbuilder.h b/src/plugins/cpptools/compileroptionsbuilder.h index ba29d6e4301..1274c1b860c 100644 --- a/src/plugins/cpptools/compileroptionsbuilder.h +++ b/src/plugins/cpptools/compileroptionsbuilder.h @@ -56,33 +56,27 @@ public: SkipBuiltIn skipBuiltInHeaderPathsAndDefines = SkipBuiltIn::No, QString clangVersion = QString(), QString clangResourceDirectory = QString()); - virtual ~CompilerOptionsBuilder() {} - - virtual void addTargetTriple(); - virtual void addExtraCodeModelFlags(); - virtual void enableExceptions(); - virtual void insertWrappedQtHeaders(); - virtual void addOptionsForLanguage(bool checkForBorlandExtensions = true); - virtual void updateLanguageOption(ProjectFile::Kind fileKind); - - virtual void addExtraOptions() {} QStringList build(ProjectFile::Kind fileKind, PchUsage pchUsage); QStringList options() const; - // Add custom options - void add(const QString &option); - void addDefine(const ProjectExplorer::Macro &marco); - + virtual void addExtraOptions() {} // Add options based on project part + virtual void addToolchainAndProjectMacros(); void addWordWidth(); void addToolchainFlags(); void addHeaderPathOptions(); void addPrecompiledHeaderOptions(PchUsage pchUsage); - virtual void addToolchainAndProjectMacros(); void addMacros(const ProjectExplorer::Macros ¯os); + void addTargetTriple(); + void addExtraCodeModelFlags(); + void enableExceptions(); + void insertWrappedQtHeaders(); + void addOptionsForLanguage(bool checkForBorlandExtensions = true); + void updateLanguageOption(ProjectFile::Kind fileKind); + void addMsvcCompatibilityVersion(); void undefineCppLanguageFeatureMacrosForMsvc2015(); void addDefineFunctionMacrosMsvc(); @@ -97,8 +91,13 @@ protected: virtual QString defineOption() const; virtual QString undefineOption() const; virtual QString includeOption() const; + + // Add custom options + void add(const QString &option); + QString includeDirOptionForPath(const QString &path) const; - const ProjectPart m_projectPart; + + const ProjectPart &m_projectPart; private: QByteArray macroOption(const ProjectExplorer::Macro ¯o) const; diff --git a/src/plugins/debugger/debugger.qrc b/src/plugins/debugger/debugger.qrc index 4dbc903b591..2e457b74e13 100644 --- a/src/plugins/debugger/debugger.qrc +++ b/src/plugins/debugger/debugger.qrc @@ -14,6 +14,8 @@ images/debugger_interrupt@2x.png images/debugger_interrupt_mask.png images/debugger_interrupt_mask@2x.png + images/debugger_stop_mask.png + images/debugger_stop_mask@2x.png images/debugger_reversemode.png images/debugger_reversemode@2x.png images/debugger_reversemode_background.png diff --git a/src/plugins/debugger/debuggerengine.cpp b/src/plugins/debugger/debuggerengine.cpp index d18cfd3f54c..67a01d026c1 100644 --- a/src/plugins/debugger/debuggerengine.cpp +++ b/src/plugins/debugger/debuggerengine.cpp @@ -770,7 +770,7 @@ void DebuggerEnginePrivate::setupViews() m_perspective->addWindow(m_sourceFilesWindow, Perspective::AddToTab, m_modulesWindow, false); m_perspective->addWindow(m_localsAndInspectorWindow, Perspective::AddToTab, nullptr, true, Qt::RightDockWidgetArea); m_perspective->addWindow(m_watchersWindow, Perspective::AddToTab, m_localsAndInspectorWindow, true, Qt::RightDockWidgetArea); - m_perspective->addWindow(m_registerWindow, Perspective::AddToTab, m_watchersWindow, true, Qt::RightDockWidgetArea); + m_perspective->addWindow(m_registerWindow, Perspective::AddToTab, m_watchersWindow, false, Qt::RightDockWidgetArea); m_perspective->addWindow(m_logWindow, Perspective::AddToTab, nullptr, false, Qt::TopDockWidgetArea); m_perspective->select(); @@ -2529,7 +2529,7 @@ Context CppDebuggerEngine::languageContext() const void CppDebuggerEngine::validateExecutable() { DebuggerRunParameters &rp = mutableRunParameters(); - const bool warnOnRelease = boolSetting(WarnOnReleaseBuilds); + const bool warnOnRelease = boolSetting(WarnOnReleaseBuilds) && rp.toolChainAbi.osFlavor() != Abi::AndroidLinuxFlavor; bool warnOnInappropriateDebugger = false; QString detailedWarning; switch (rp.toolChainAbi.binaryFormat()) { diff --git a/src/plugins/debugger/debuggericons.cpp b/src/plugins/debugger/debuggericons.cpp index 776e54afe12..96107377df7 100644 --- a/src/plugins/debugger/debuggericons.cpp +++ b/src/plugins/debugger/debuggericons.cpp @@ -66,6 +66,9 @@ const Icon INTERRUPT( const Icon INTERRUPT_FLAT({ {":/debugger/images/debugger_interrupt_mask.png", Theme::IconsInterruptToolBarColor}, {":/projectexplorer/images/debugger_beetle_mask.png", Theme::IconsDebugColor}}); +const Icon STOP_FLAT({ + {":/debugger/images/debugger_stop_mask.png", Theme::IconsStopColor}, + {":/projectexplorer/images/debugger_beetle_mask.png", Theme::IconsDebugColor}}); const Icon DEBUG_INTERRUPT_SMALL({ {":/utils/images/interrupt_small.png", Theme::IconsInterruptColor}, {":/projectexplorer/images/debugger_overlay_small.png", Theme::PanelTextColorMid}}, Icon::MenuTintedStyle); diff --git a/src/plugins/debugger/debuggericons.h b/src/plugins/debugger/debuggericons.h index 0030597dbfa..3785a2191e5 100644 --- a/src/plugins/debugger/debuggericons.h +++ b/src/plugins/debugger/debuggericons.h @@ -50,6 +50,7 @@ extern const Utils::Icon DEBUG_CONTINUE_SMALL; extern const Utils::Icon DEBUG_CONTINUE_SMALL_TOOLBAR; extern const Utils::Icon INTERRUPT; extern const Utils::Icon INTERRUPT_FLAT; +extern const Utils::Icon STOP_FLAT; extern const Utils::Icon DEBUG_INTERRUPT_SMALL; extern const Utils::Icon DEBUG_INTERRUPT_SMALL_TOOLBAR; extern const Utils::Icon DEBUG_EXIT_SMALL; diff --git a/src/plugins/debugger/debuggermainwindow.cpp b/src/plugins/debugger/debuggermainwindow.cpp index 7c7e632388d..c1586e6edd4 100644 --- a/src/plugins/debugger/debuggermainwindow.cpp +++ b/src/plugins/debugger/debuggermainwindow.cpp @@ -568,6 +568,7 @@ void Perspective::setEnabled(bool enabled) QToolButton *PerspectivePrivate::setupToolButton(QAction *action) { + QTC_ASSERT(action, return nullptr); auto toolButton = new QToolButton(m_innerToolBar); toolButton->setProperty("panelwidget", true); toolButton->setDefaultAction(action); @@ -577,16 +578,19 @@ QToolButton *PerspectivePrivate::setupToolButton(QAction *action) void Perspective::addToolBarAction(QAction *action) { + QTC_ASSERT(action, return); d->setupToolButton(action); } void Perspective::addToolBarAction(OptionalAction *action) { + QTC_ASSERT(action, return); action->m_toolButton = d->setupToolButton(action); } void Perspective::addToolBarWidget(QWidget *widget) { + QTC_ASSERT(widget, return); // QStyle::polish is called before it is added to the toolbar, explicitly make it a panel widget widget->setProperty("panelwidget", true); widget->setParent(d->m_innerToolBar); @@ -644,6 +648,7 @@ void Perspective::addWindow(QWidget *widget, bool visibleByDefault, Qt::DockWidgetArea area) { + QTC_ASSERT(widget, return); DockOperation op; op.widget = widget; if (anchorWidget) diff --git a/src/plugins/debugger/debuggerplugin.cpp b/src/plugins/debugger/debuggerplugin.cpp index 68f224f5eb2..81c657345bc 100644 --- a/src/plugins/debugger/debuggerplugin.cpp +++ b/src/plugins/debugger/debuggerplugin.cpp @@ -1143,11 +1143,14 @@ bool DebuggerPluginPrivate::initialize(const QStringList &arguments, m_visibleStartAction.initialize(&m_startAction); m_visibleStartAction.setAttribute(ProxyAction::UpdateText); + m_visibleStartAction.setAttribute(ProxyAction::UpdateIcon); m_visibleStartAction.setAction(&m_startAction); - m_visibleStartAction.setIcon(startIcon(true)); ModeManager::addAction(&m_visibleStartAction, Constants::P_ACTION_DEBUG); + m_undisturbableAction.setIcon(interruptIcon(false)); + m_undisturbableAction.setEnabled(false); + cmd = ActionManager::registerAction(&m_debugWithoutDeployAction, "Debugger.DebugWithoutDeploy"); cmd->setAttribute(Command::CA_Hide); @@ -1446,28 +1449,31 @@ void DebuggerPluginPrivate::updatePresetState() DebuggerEngine *currentEngine = EngineManager::currentEngine(); QString whyNot; - const bool canRun = startupProject - && ProjectExplorerPlugin::canRunStartupProject(ProjectExplorer::Constants::DEBUG_RUN_MODE, &whyNot); + const bool canRun = + ProjectExplorerPlugin::canRunStartupProject(ProjectExplorer::Constants::DEBUG_RUN_MODE, &whyNot); + + QString startupRunConfigName; + if (startupRunConfig) + startupRunConfigName = startupRunConfig->displayName(); + if (startupRunConfigName.isEmpty() && startupProject) + startupRunConfigName = startupProject->displayName(); + + const QString startToolTip = + canRun ? tr("Start debugging of \"%1\"").arg(startupRunConfigName) : whyNot; + + m_startAction.setToolTip(startToolTip); + m_startAction.setText(canRun ? startToolTip : tr("Start Debugging")); if (!currentEngine || !currentEngine->isStartupRunConfiguration()) { // No engine running -- or -- we have a running engine but it does not // correspond to the current start up project. - QString startupRunConfigName; - if (startupRunConfig) - startupRunConfigName = startupRunConfig->displayName(); - if (startupRunConfigName.isEmpty() && startupProject) - startupRunConfigName = startupProject->displayName(); - - QString startToolTip = canRun ? tr("Start debugging of \"%1\"").arg(startupRunConfigName) : whyNot; - QString stepToolTip = canRun ? tr("Start \"%1\" and break at function \"main\"").arg(startupRunConfigName) : whyNot; // Step into/next: Start and break at 'main' unless a debugger is running. - m_stepAction.setEnabled(canRun); + QString stepToolTip = canRun ? tr("Start \"%1\" and break at function \"main\"").arg(startupRunConfigName) : whyNot; m_stepAction.setToolTip(stepToolTip); - m_nextAction.setEnabled(canRun); m_nextAction.setToolTip(stepToolTip); + m_stepAction.setEnabled(canRun); + m_nextAction.setEnabled(canRun); m_startAction.setEnabled(canRun); - m_startAction.setToolTip(startToolTip); - m_startAction.setText(startToolTip); m_startAction.setIcon(startIcon(false)); m_startAction.setToolButtonStyle(Qt::ToolButtonTextBesideIcon); m_startAction.setVisible(true); @@ -1475,7 +1481,7 @@ void DebuggerPluginPrivate::updatePresetState() m_continueAction.setEnabled(false); m_exitAction.setEnabled(false); m_debugWithoutDeployAction.setEnabled(canRun); - m_visibleStartAction.setIcon(startIcon(true)); + m_visibleStartAction.setAction(&m_startAction); m_hiddenStopAction.setAction(&m_undisturbableAction); m_detachAction.setEnabled(false); m_jumpToLineAction.setEnabled(false); @@ -1490,15 +1496,13 @@ void DebuggerPluginPrivate::updatePresetState() m_nextAction.setToolTip(QString()); // The 'state' bits only affect the fat debug button, not the preset start button. - m_startAction.setText(QString()); - m_startAction.setToolTip(whyNot); m_startAction.setIcon(startIcon(false)); m_startAction.setEnabled(false); m_startAction.setVisible(false); QString currentDisplayName = currentEngine->displayName(); - m_interruptAction.setToolTip(tr("Interrupt \"%1\"").arg(currentDisplayName)); - m_continueAction.setToolTip(tr("Continue \"%1\"").arg(currentDisplayName)); + m_interruptAction.setToolTip(tr("Interrupt %1").arg(currentDisplayName)); + m_continueAction.setToolTip(tr("Continue %1").arg(currentDisplayName)); m_debugWithoutDeployAction.setEnabled(canRun); @@ -1517,7 +1521,6 @@ void DebuggerPluginPrivate::updatePresetState() m_exitAction.setEnabled(true); m_debugWithoutDeployAction.setEnabled(false); m_visibleStartAction.setAction(&m_continueAction); - m_visibleStartAction.setIcon(continueIcon(true)); m_hiddenStopAction.setAction(&m_exitAction); m_stepAction.setEnabled(!companionPreventsAction); m_nextAction.setEnabled(!companionPreventsAction); @@ -1537,7 +1540,6 @@ void DebuggerPluginPrivate::updatePresetState() m_exitAction.setEnabled(true); m_debugWithoutDeployAction.setEnabled(false); m_visibleStartAction.setAction(&m_interruptAction); - m_visibleStartAction.setIcon(interruptIcon(true)); m_hiddenStopAction.setAction(&m_interruptAction); m_stepAction.setEnabled(false); m_nextAction.setEnabled(false); @@ -1557,7 +1559,6 @@ void DebuggerPluginPrivate::updatePresetState() m_exitAction.setEnabled(false); m_debugWithoutDeployAction.setEnabled(canRun); m_visibleStartAction.setAction(&m_startAction); - m_visibleStartAction.setIcon(startIcon(true)); m_hiddenStopAction.setAction(&m_undisturbableAction); m_stepAction.setEnabled(false); m_nextAction.setEnabled(false); @@ -1576,8 +1577,7 @@ void DebuggerPluginPrivate::updatePresetState() m_continueAction.setEnabled(false); m_exitAction.setEnabled(true); m_debugWithoutDeployAction.setEnabled(false); - m_visibleStartAction.setAction(&m_undisturbableAction); - m_visibleStartAction.setIcon(startIcon(true)); + m_visibleStartAction.setAction(&m_exitAction); m_hiddenStopAction.setAction(&m_exitAction); m_stepAction.setEnabled(false); m_nextAction.setEnabled(false); @@ -1589,10 +1589,10 @@ void DebuggerPluginPrivate::updatePresetState() m_stepOutAction.setEnabled(false); m_runToLineAction.setEnabled(false); m_runToSelectedFunctionAction.setEnabled(false); - } else if (state == DebuggerNotReady) { - // The startup phase should be over once we are here - QTC_CHECK(false); } else { + // The startup phase should be over once we are here. + // But treat it as 'undisturbable if we are here by accident. + QTC_CHECK(state != DebuggerNotReady); // Everything else is "undisturbable". m_startAction.setEnabled(false); m_interruptAction.setEnabled(false); @@ -1600,7 +1600,6 @@ void DebuggerPluginPrivate::updatePresetState() m_exitAction.setEnabled(false); m_debugWithoutDeployAction.setEnabled(false); m_visibleStartAction.setAction(&m_undisturbableAction); - m_visibleStartAction.setIcon(startIcon(true)); m_hiddenStopAction.setAction(&m_undisturbableAction); m_stepAction.setEnabled(false); m_nextAction.setEnabled(false); diff --git a/src/plugins/debugger/images/debugger_stop_mask.png b/src/plugins/debugger/images/debugger_stop_mask.png new file mode 100644 index 00000000000..d56a35f4857 Binary files /dev/null and b/src/plugins/debugger/images/debugger_stop_mask.png differ diff --git a/src/plugins/debugger/images/debugger_stop_mask@2x.png b/src/plugins/debugger/images/debugger_stop_mask@2x.png new file mode 100644 index 00000000000..e69d67dfaf8 Binary files /dev/null and b/src/plugins/debugger/images/debugger_stop_mask@2x.png differ diff --git a/src/plugins/languageclient/images/settingscategory_languageclient.png b/src/plugins/languageclient/images/settingscategory_languageclient.png new file mode 100644 index 00000000000..78978b45ca1 Binary files /dev/null and b/src/plugins/languageclient/images/settingscategory_languageclient.png differ diff --git a/src/plugins/languageclient/images/settingscategory_languageclient@2x.png b/src/plugins/languageclient/images/settingscategory_languageclient@2x.png new file mode 100644 index 00000000000..ea201e68232 Binary files /dev/null and b/src/plugins/languageclient/images/settingscategory_languageclient@2x.png differ diff --git a/src/plugins/languageclient/languageclient.pro b/src/plugins/languageclient/languageclient.pro index e34f11ddd6a..e17e0e0b6a3 100644 --- a/src/plugins/languageclient/languageclient.pro +++ b/src/plugins/languageclient/languageclient.pro @@ -18,3 +18,6 @@ SOURCES += \ languageclientmanager.cpp \ languageclientplugin.cpp \ languageclientsettings.cpp + +RESOURCES += \ + languageclient.qrc diff --git a/src/plugins/languageclient/languageclient.qrc b/src/plugins/languageclient/languageclient.qrc new file mode 100644 index 00000000000..eb73a75300a --- /dev/null +++ b/src/plugins/languageclient/languageclient.qrc @@ -0,0 +1,6 @@ + + + images/settingscategory_languageclient.png + images/settingscategory_languageclient@2x.png + + diff --git a/src/plugins/languageclient/languageclientsettings.cpp b/src/plugins/languageclient/languageclientsettings.cpp index 4348e95e521..6b23f38e7c6 100644 --- a/src/plugins/languageclient/languageclientsettings.cpp +++ b/src/plugins/languageclient/languageclientsettings.cpp @@ -201,7 +201,8 @@ LanguageClientSettingsPage::LanguageClientSettingsPage() setCategory(Constants::LANGUAGECLIENT_SETTINGS_CATEGORY); setDisplayCategory(QCoreApplication::translate("LanguageClient", Constants::LANGUAGECLIENT_SETTINGS_TR)); - //setCategoryIcon( /* TODO */ ); + setCategoryIcon(Utils::Icon({{":/languageclient/images/settingscategory_languageclient.png", + Utils::Theme::PanelTextColorDark}}, Utils::Icon::Tint)); } LanguageClientSettingsPage::~LanguageClientSettingsPage() diff --git a/src/plugins/projectexplorer/projectconfigurationaspects.cpp b/src/plugins/projectexplorer/projectconfigurationaspects.cpp index 92dd68f60a1..fc295bbec0e 100644 --- a/src/plugins/projectexplorer/projectconfigurationaspects.cpp +++ b/src/plugins/projectexplorer/projectconfigurationaspects.cpp @@ -41,6 +41,7 @@ #include #include #include +#include #include using namespace Utils; @@ -77,6 +78,19 @@ public: QPixmap m_labelPixmap; }; +class BaseIntegerAspectPrivate +{ +public: + QVariant m_value; + QVariant m_minimumValue; + QVariant m_maximumValue; + int m_displayIntegerBase = 10; + QString m_label; + QString m_prefix; + QString m_suffix; + QPointer m_spinBox; // Owned by configuration widget +}; + } // Internal /*! @@ -337,4 +351,82 @@ void BaseBoolAspect::setLabel(const QString &label) d->m_label = label; } +/*! + \class ProjectExplorer::BaseIntegerAspect +*/ + +// BaseIntegerAspect + +BaseIntegerAspect::BaseIntegerAspect() + : d(new Internal::BaseIntegerAspectPrivate) +{} + +BaseIntegerAspect::~BaseIntegerAspect() = default; + +void BaseIntegerAspect::addToConfigurationLayout(QFormLayout *layout) +{ + QTC_CHECK(!d->m_spinBox); + d->m_spinBox = new QSpinBox(layout->parentWidget()); + d->m_spinBox->setValue(d->m_value.toInt()); + d->m_spinBox->setDisplayIntegerBase(d->m_displayIntegerBase); + d->m_spinBox->setPrefix(d->m_prefix); + d->m_spinBox->setSuffix(d->m_suffix); + if (d->m_maximumValue.isValid() && d->m_maximumValue.isValid()) + d->m_spinBox->setRange(d->m_minimumValue.toInt(), d->m_maximumValue.toInt()); + layout->addRow(d->m_label, d->m_spinBox); + connect(d->m_spinBox.data(), static_cast(&QSpinBox::valueChanged), + this, [this](int value) { + d->m_value = value; + emit changed(); + }); +} + +void BaseIntegerAspect::fromMap(const QVariantMap &map) +{ + d->m_value = map.value(settingsKey()); +} + +void BaseIntegerAspect::toMap(QVariantMap &data) const +{ + data.insert(settingsKey(), d->m_value); +} + +int BaseIntegerAspect::value() const +{ + return d->m_value.toInt(); +} + +void BaseIntegerAspect::setValue(int value) +{ + d->m_value = value; + if (d->m_spinBox) + d->m_spinBox->setValue(d->m_value.toInt()); +} + +void BaseIntegerAspect::setRange(int min, int max) +{ + d->m_minimumValue = min; + d->m_maximumValue = max; +} + +void BaseIntegerAspect::setLabel(const QString &label) +{ + d->m_label = label; +} + +void BaseIntegerAspect::setPrefix(const QString &prefix) +{ + d->m_prefix = prefix; +} + +void BaseIntegerAspect::setSuffix(const QString &suffix) +{ + d->m_suffix = suffix; +} + +void BaseIntegerAspect::setDisplayIntegerBase(int base) +{ + d->m_displayIntegerBase = base; +} + } // namespace ProjectExplorer diff --git a/src/plugins/projectexplorer/projectconfigurationaspects.h b/src/plugins/projectexplorer/projectconfigurationaspects.h index a058c20ec0f..e47d232f2ee 100644 --- a/src/plugins/projectexplorer/projectconfigurationaspects.h +++ b/src/plugins/projectexplorer/projectconfigurationaspects.h @@ -38,6 +38,7 @@ namespace ProjectExplorer { namespace Internal { class BaseBoolAspectPrivate; class BaseStringAspectPrivate; +class BaseIntegerAspectPrivate; } // Internal class PROJECTEXPLORER_EXPORT BaseBoolAspect : public ProjectConfigurationAspect @@ -106,4 +107,30 @@ private: std::unique_ptr d; }; +class PROJECTEXPLORER_EXPORT BaseIntegerAspect : public ProjectConfigurationAspect +{ + Q_OBJECT + +public: + BaseIntegerAspect(); + ~BaseIntegerAspect() override; + + void addToConfigurationLayout(QFormLayout *layout) override; + + int value() const; + void setValue(int val); + + void setRange(int min, int max); + void setLabel(const QString &label); + void setPrefix(const QString &prefix); + void setSuffix(const QString &suffix); + void setDisplayIntegerBase(int base); + + void fromMap(const QVariantMap &map) override; + void toMap(QVariantMap &map) const override; + +private: + std::unique_ptr d; +}; + } // namespace ProjectExplorer diff --git a/src/plugins/qmlprofiler/tests/qmlprofilertool_test.cpp b/src/plugins/qmlprofiler/tests/qmlprofilertool_test.cpp index 6a766b6aa86..a519f6a775a 100644 --- a/src/plugins/qmlprofiler/tests/qmlprofilertool_test.cpp +++ b/src/plugins/qmlprofiler/tests/qmlprofilertool_test.cpp @@ -69,11 +69,20 @@ void QmlProfilerToolTest::testAttachToWaitingApplication() QTimer timer; timer.setInterval(100); + + bool modalSeen = false; connect(&timer, &QTimer::timeout, this, [&]() { - if (auto activeModal - = qobject_cast(QApplication::activeModalWidget())) { - activeModal->setPort(serverUrl.port()); - activeModal->accept(); + if (QWidget *activeModal = QApplication::activeModalWidget()) { + modalSeen = true; + auto dialog = qobject_cast(activeModal); + if (dialog) { + dialog->setPort(serverUrl.port()); + dialog->accept(); + timer.stop(); + } else { + qWarning() << "Some other modal widget popped up:" << activeModal; + activeModal->close(); + } } }); @@ -83,6 +92,8 @@ void QmlProfilerToolTest::testAttachToWaitingApplication() QTRY_VERIFY(connection); QTRY_VERIFY(runControl->isRunning()); + QTRY_VERIFY(modalSeen); + QTRY_VERIFY(!timer.isActive()); QTRY_VERIFY(profilerTool.clientManager()->isConnected()); connection.reset(); diff --git a/src/shared/clang/clang_installation.pri b/src/shared/clang/clang_installation.pri index 863d29cf481..728cbb3ba4e 100644 --- a/src/shared/clang/clang_installation.pri +++ b/src/shared/clang/clang_installation.pri @@ -116,9 +116,6 @@ CLANGTOOLING_LIBS=-lclangTooling -lclangIndex -lclangFrontend -lclangParse -lcla -lclangASTMatchers -lclangToolingCore -lclangAST -lclangLex -lclangBasic win32:CLANGTOOLING_LIBS += -lversion -CLANGFORMAT_LIBS=-lclangFormat -lclangToolingCore -lclangRewrite -lclangLex -lclangBasic -win32:CLANGFORMAT_LIBS += -lversion - BIN_EXTENSION = win32: BIN_EXTENSION = .exe @@ -141,6 +138,17 @@ isEmpty(LLVM_INSTALL_DIR) { output = $$system($$llvm_config --version, lines) LLVM_VERSION = $$extractVersion($$output) + +!isEmpty(LLVM_VERSION) { + versionIsAtLeast($$LLVM_VERSION, 7, 0, 0): { + CLANGFORMAT_LIBS=-lclangFormat -lclangToolingInclusions -lclangToolingCore -lclangRewrite -lclangLex -lclangBasic + win32:CLANGFORMAT_LIBS += -lversion + } else:versionIsAtLeast($$LLVM_VERSION, 6, 0, 0): { + CLANGFORMAT_LIBS=-lclangFormat -lclangToolingCore -lclangRewrite -lclangLex -lclangBasic + win32:CLANGFORMAT_LIBS += -lversion + } +} + isEmpty(LLVM_VERSION) { $$llvmWarningOrError(\ "Cannot determine clang version. Set LLVM_INSTALL_DIR to build the Clang Code Model",\ diff --git a/src/tools/icons/export.py b/src/tools/icons/export.py index d7bb9a1bcc2..e28b7e6e4e9 100644 --- a/src/tools/icons/export.py +++ b/src/tools/icons/export.py @@ -68,6 +68,12 @@ for svgElement in svgTreeRoot.iter(): except: pass +for id in svgIDs: + pngFile = qtcSourceRoot + id + ".png" + pngAt2XFile = qtcSourceRoot + id + "@2x.png" + if not (os.path.isfile(pngFile) or os.path.isfile(pngAt2XFile)): + sys.stderr.write(id + " has not yet been exported as .png.\n") + # The shell mode of Inkscape is used to execute several export commands # with one launch of Inkscape. inkscapeShellCommands = "" diff --git a/src/tools/icons/qtcreatoricons.svg b/src/tools/icons/qtcreatoricons.svg index f3dca3a6c00..67f88eda497 100644 --- a/src/tools/icons/qtcreatoricons.svg +++ b/src/tools/icons/qtcreatoricons.svg @@ -1300,7 +1300,7 @@ sodipodi:nodetypes="cc" /> + id="share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/images/down-arrow"> @@ -2528,52 +2528,6 @@ width="100%" height="100%" /> - - - - - - - - - @@ -2770,7 +2724,7 @@ x="0" /> + id="g2818" /> - - - - - @@ -3190,6 +3119,75 @@ width="100%" height="100%" /> + + + + + + + + + + + + id="src/libs/tracing/qml/ico_rangeselection"> + id="src/libs/tracing/qml/ico_rangeselected"> + id="src/libs/tracing/qml/ico_edit"> - - - - - - - + id="../boot2qt/common/images/boot2qtdevice"> + id="../boot2qt/common/images/boot2qtemulator"> + id="../boot2qt/common/images/boot2qtstartvm"> + id="../vxworks/plugins/vxworks/images/vxworksqtdevice"> + + + + diff --git a/tests/unit/mockup/projectexplorer/project.h b/tests/unit/mockup/projectexplorer/project.h index 78b4211dca4..9e8f2e1ac39 100644 --- a/tests/unit/mockup/projectexplorer/project.h +++ b/tests/unit/mockup/projectexplorer/project.h @@ -33,6 +33,8 @@ namespace ProjectExplorer { class Project : public QObject { public: + Project() = default; + Utils::FileName projectDirectory() const { return Utils::FileName(); } diff --git a/tests/unit/unittest/clang_dependency.pri b/tests/unit/unittest/clang_dependency.pri index e0c3b1a9483..744c9ff4283 100644 --- a/tests/unit/unittest/clang_dependency.pri +++ b/tests/unit/unittest/clang_dependency.pri @@ -1,4 +1,6 @@ include(../../../src/shared/clang/clang_installation.pri) +include(../../../src/shared/clang/clang_defines.pri) + !isEmpty(LLVM_VERSION) { requires(!isEmpty(LIBCLANG_LIBS)) equals(LLVM_IS_COMPILED_WITH_RTTI, "NO") : message("LLVM needs to be compiled with RTTI!") diff --git a/tests/unit/unittest/compileroptionsbuilder-test.cpp b/tests/unit/unittest/compileroptionsbuilder-test.cpp new file mode 100644 index 00000000000..ae81f7d0cae --- /dev/null +++ b/tests/unit/unittest/compileroptionsbuilder-test.cpp @@ -0,0 +1,343 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "googletest.h" + +#include +#include +#include + +#include +#include + +using CppTools::CompilerOptionsBuilder; +using CppTools::ProjectFile; +using CppTools::ProjectPart; +using ProjectExplorer::HeaderPath; +using ProjectExplorer::HeaderPathType; +using ProjectExplorer::Project; + +MATCHER_P(IsPartOfHeader, headerPart, std::string(negation ? "isn't " : "is ") + headerPart) +{ + return arg.contains(QString::fromUtf8(headerPart)); +} + +class CompilerOptionsBuilderTest : public ::testing::Test +{ +protected: + void SetUp() final + { + projectPart.project = project.get(); + projectPart.toolchainType = ProjectExplorer::Constants::CLANG_TOOLCHAIN_TYPEID; + projectPart.languageVersion = CppTools::ProjectPart::CXX17; + projectPart.toolChainWordWidth = CppTools::ProjectPart::WordWidth64Bit; + projectPart.toolChainTargetTriple = "x86_64-apple-darwin10"; + projectPart.extraCodeModelFlags = QStringList{"-arch", "x86_64"}; + + projectPart.precompiledHeaders = QStringList{TESTDATA_DIR "/compileroptionsbuilder.pch"}; + projectPart.toolChainMacros = {ProjectExplorer::Macro{"foo", "bar"}}; + projectPart.projectMacros = {ProjectExplorer::Macro{"projectFoo", "projectBar"}}; + projectPart.qtVersion = ProjectPart::Qt5; + + projectPart.headerPaths = {HeaderPath{"/tmp/builtin_path", HeaderPathType::BuiltIn}, + HeaderPath{"/tmp/system_path", HeaderPathType::System}, + HeaderPath{"/tmp/path", HeaderPathType::User}}; + } + + std::unique_ptr project{std::make_unique()}; + ProjectPart projectPart; + CompilerOptionsBuilder compilerOptionsBuilder{projectPart}; +}; + +TEST_F(CompilerOptionsBuilderTest, AddToolchainAndProjectMacros) +{ + compilerOptionsBuilder.addToolchainAndProjectMacros(); + + ASSERT_THAT(compilerOptionsBuilder.options(), ElementsAre("-Dfoo=bar", "-DprojectFoo=projectBar")); +} + +TEST_F(CompilerOptionsBuilderTest, AddWordWidth) +{ + compilerOptionsBuilder.addWordWidth(); + + ASSERT_THAT(compilerOptionsBuilder.options(), ElementsAre("-m64")); +} + +TEST_F(CompilerOptionsBuilderTest, AddToolchainFlags) +{ + compilerOptionsBuilder.addToolchainFlags(); + + ASSERT_THAT(compilerOptionsBuilder.options(), ElementsAre("-undef")); +} + +TEST_F(CompilerOptionsBuilderTest, HeaderPathOptionsOrder) +{ + compilerOptionsBuilder.addHeaderPathOptions(); + + ASSERT_THAT(compilerOptionsBuilder.options(), + ElementsAre("-nostdlibinc", + "-I", QDir::toNativeSeparators("/tmp/path"), + "-I", QDir::toNativeSeparators("/tmp/system_path"), + "-isystem", QDir::toNativeSeparators("/tmp/builtin_path"))); +} + +TEST_F(CompilerOptionsBuilderTest, UseSystemHeader) +{ + CompilerOptionsBuilder compilerOptionsBuilder(projectPart, CppTools::UseSystemHeader::Yes); + + compilerOptionsBuilder.addHeaderPathOptions(); + + ASSERT_THAT(compilerOptionsBuilder.options(), + ElementsAre("-nostdlibinc", + "-I", QDir::toNativeSeparators("/tmp/path"), + "-isystem", QDir::toNativeSeparators("/tmp/system_path"), + "-isystem", QDir::toNativeSeparators("/tmp/builtin_path"))); +} + +TEST_F(CompilerOptionsBuilderTest, ClangHeadersPath) +{ + CompilerOptionsBuilder compilerOptionsBuilder(projectPart, + CppTools::UseSystemHeader::No, + CppTools::SkipBuiltIn::No, + "7.0.0", + ""); + + compilerOptionsBuilder.addHeaderPathOptions(); + + ASSERT_THAT(compilerOptionsBuilder.options(), + ElementsAre("-nostdinc", + "-nostdlibinc", + "-I", QDir::toNativeSeparators("/tmp/path"), + "-I", QDir::toNativeSeparators("/tmp/system_path"), + "-isystem", QDir::toNativeSeparators(CLANG_RESOURCE_DIR ""), + "-isystem", QDir::toNativeSeparators("/tmp/builtin_path"))); +} + +TEST_F(CompilerOptionsBuilderTest, ClangHeadersAndCppIncludesPathsOrderMacOs) +{ + auto defaultPaths = projectPart.headerPaths; + projectPart.headerPaths = {HeaderPath{"/usr/include/c++/4.2.1", HeaderPathType::BuiltIn}, + HeaderPath{"/usr/include/c++/4.2.1/backward", HeaderPathType::BuiltIn}, + HeaderPath{"/usr/local/include", HeaderPathType::BuiltIn}, + HeaderPath{"/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/clang/6.0/include", HeaderPathType::BuiltIn}, + HeaderPath{"/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include", HeaderPathType::BuiltIn}, + HeaderPath{"/usr/include", HeaderPathType::BuiltIn} + }; + projectPart.headerPaths.append(defaultPaths); + CompilerOptionsBuilder compilerOptionsBuilder(projectPart, + CppTools::UseSystemHeader::No, + CppTools::SkipBuiltIn::No, + "7.0.0", + ""); + + compilerOptionsBuilder.addHeaderPathOptions(); + + ASSERT_THAT(compilerOptionsBuilder.options(), + ElementsAre("-nostdinc", + "-nostdlibinc", + "-I", QDir::toNativeSeparators("/tmp/path"), + "-I", QDir::toNativeSeparators("/tmp/system_path"), + "-isystem", QDir::toNativeSeparators("/usr/include/c++/4.2.1"), + "-isystem", QDir::toNativeSeparators("/usr/include/c++/4.2.1/backward"), + "-isystem", QDir::toNativeSeparators("/usr/local/include"), + "-isystem", QDir::toNativeSeparators(CLANG_RESOURCE_DIR ""), + "-isystem", QDir::toNativeSeparators("/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include"), + "-isystem", QDir::toNativeSeparators("/usr/include"), + "-isystem", QDir::toNativeSeparators("/tmp/builtin_path"))); +} + +TEST_F(CompilerOptionsBuilderTest, ClangHeadersAndCppIncludesPathsOrderLinux) +{ + projectPart.headerPaths = {HeaderPath{"/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8", HeaderPathType::BuiltIn}, + HeaderPath{"/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/backward", HeaderPathType::BuiltIn}, + HeaderPath{"/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/x86_64-linux-gnu/c++/4.8", HeaderPathType::BuiltIn}, + HeaderPath{"/usr/local/include", HeaderPathType::BuiltIn}, + HeaderPath{"/usr/lib/gcc/x86_64-linux-gnu/4.8/include", HeaderPathType::BuiltIn}, + HeaderPath{"/usr/include/x86_64-linux-gnu", HeaderPathType::BuiltIn}, + HeaderPath{"/usr/include", HeaderPathType::BuiltIn} + }; + projectPart.toolChainTargetTriple = "x86_64-linux-gnu"; + CompilerOptionsBuilder compilerOptionsBuilder(projectPart, + CppTools::UseSystemHeader::No, + CppTools::SkipBuiltIn::No, + "7.0.0", + ""); + + compilerOptionsBuilder.addHeaderPathOptions(); + + ASSERT_THAT(compilerOptionsBuilder.options(), + ElementsAre("-nostdinc", + "-nostdlibinc", + "-isystem", QDir::toNativeSeparators("/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8"), + "-isystem", QDir::toNativeSeparators("/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/backward"), + "-isystem", QDir::toNativeSeparators("/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/x86_64-linux-gnu/c++/4.8"), + "-isystem", QDir::toNativeSeparators(CLANG_RESOURCE_DIR ""), + "-isystem", QDir::toNativeSeparators("/usr/local/include"), + "-isystem", QDir::toNativeSeparators("/usr/lib/gcc/x86_64-linux-gnu/4.8/include"), + "-isystem", QDir::toNativeSeparators("/usr/include/x86_64-linux-gnu"), + "-isystem", QDir::toNativeSeparators("/usr/include"))); +} + +TEST_F(CompilerOptionsBuilderTest, NoPrecompiledHeader) +{ + compilerOptionsBuilder.addPrecompiledHeaderOptions(CompilerOptionsBuilder::PchUsage::None); + + ASSERT_THAT(compilerOptionsBuilder.options().empty(), true); +} + +TEST_F(CompilerOptionsBuilderTest, UsePrecompiledHeader) +{ + compilerOptionsBuilder.addPrecompiledHeaderOptions(CompilerOptionsBuilder::PchUsage::Use); + + ASSERT_THAT(compilerOptionsBuilder.options(), + ElementsAre("-include", QDir::toNativeSeparators(TESTDATA_DIR "/compileroptionsbuilder.pch"))); +} + +TEST_F(CompilerOptionsBuilderTest, AddMacros) +{ + compilerOptionsBuilder.addMacros(ProjectExplorer::Macros{ProjectExplorer::Macro{"key", "value"}}); + + ASSERT_THAT(compilerOptionsBuilder.options(), ElementsAre("-Dkey=value")); +} + +TEST_F(CompilerOptionsBuilderTest, AddTargetTriple) +{ + compilerOptionsBuilder.addTargetTriple(); + + ASSERT_THAT(compilerOptionsBuilder.options(), ElementsAre("-target", "x86_64-apple-darwin10")); +} + +TEST_F(CompilerOptionsBuilderTest, EnableCExceptions) +{ + projectPart.languageVersion = CppTools::ProjectPart::C99; + + compilerOptionsBuilder.enableExceptions(); + + ASSERT_THAT(compilerOptionsBuilder.options(), ElementsAre("-fexceptions")); +} + +TEST_F(CompilerOptionsBuilderTest, EnableCXXExceptions) +{ + compilerOptionsBuilder.enableExceptions(); + + ASSERT_THAT(compilerOptionsBuilder.options(), ElementsAre("-fcxx-exceptions", "-fexceptions")); +} + +TEST_F(CompilerOptionsBuilderTest, InsertWrappedQtHeaders) +{ + compilerOptionsBuilder.insertWrappedQtHeaders(); + + ASSERT_THAT(compilerOptionsBuilder.options(), Contains(IsPartOfHeader("wrappedQtHeaders"))); +} + +TEST_F(CompilerOptionsBuilderTest, SetLanguageVersion) +{ + compilerOptionsBuilder.updateLanguageOption(ProjectFile::CXXSource); + + ASSERT_THAT(compilerOptionsBuilder.options(), ElementsAre("-x", "c++")); +} + +TEST_F(CompilerOptionsBuilderTest, HandleLanguageExtension) +{ + projectPart.languageExtensions = ProjectPart::ObjectiveCExtensions; + + compilerOptionsBuilder.updateLanguageOption(ProjectFile::CXXSource); + + ASSERT_THAT(compilerOptionsBuilder.options(), ElementsAre("-x", "objective-c++")); +} + +TEST_F(CompilerOptionsBuilderTest, UpdateLanguageVersion) +{ + compilerOptionsBuilder.updateLanguageOption(ProjectFile::CXXSource); + + compilerOptionsBuilder.updateLanguageOption(ProjectFile::CXXHeader); + + ASSERT_THAT(compilerOptionsBuilder.options(), ElementsAre("-x", "c++-header")); +} + +TEST_F(CompilerOptionsBuilderTest, AddMsvcCompatibilityVersion) +{ + projectPart.toolchainType = ProjectExplorer::Constants::MSVC_TOOLCHAIN_TYPEID; + projectPart.toolChainMacros.append(ProjectExplorer::Macro{"_MSC_FULL_VER", "190000000"}); + + compilerOptionsBuilder.addMsvcCompatibilityVersion(); + + ASSERT_THAT(compilerOptionsBuilder.options(), ElementsAre("-fms-compatibility-version=19.00")); +} + +TEST_F(CompilerOptionsBuilderTest, UndefineCppLanguageFeatureMacrosForMsvc2015) +{ + projectPart.toolchainType = ProjectExplorer::Constants::MSVC_TOOLCHAIN_TYPEID; + projectPart.isMsvc2015Toolchain = true; + + compilerOptionsBuilder.undefineCppLanguageFeatureMacrosForMsvc2015(); + + ASSERT_THAT(compilerOptionsBuilder.options(), Contains(QString{"-U__cpp_aggregate_bases"})); +} + +TEST_F(CompilerOptionsBuilderTest, AddDefineFunctionMacrosMsvc) +{ + projectPart.toolchainType = ProjectExplorer::Constants::MSVC_TOOLCHAIN_TYPEID; + + compilerOptionsBuilder.addDefineFunctionMacrosMsvc(); + + ASSERT_THAT(compilerOptionsBuilder.options(), Contains(QString{"-D__FUNCTION__=\"\""})); +} + +TEST_F(CompilerOptionsBuilderTest, AddProjectConfigFileInclude) +{ + projectPart.projectConfigFile = "dummy_file.h"; + + compilerOptionsBuilder.addProjectConfigFileInclude(); + + ASSERT_THAT(compilerOptionsBuilder.options(), ElementsAre("-include", "dummy_file.h")); +} + +TEST_F(CompilerOptionsBuilderTest, UndefineClangVersionMacrosForMsvc) +{ + projectPart.toolchainType = ProjectExplorer::Constants::MSVC_TOOLCHAIN_TYPEID; + + compilerOptionsBuilder.undefineClangVersionMacrosForMsvc(); + + ASSERT_THAT(compilerOptionsBuilder.options(), Contains(QString{"-U__clang__"})); +} + +TEST_F(CompilerOptionsBuilderTest, BuildAllOptions) +{ + compilerOptionsBuilder.build(ProjectFile::CXXSource, CompilerOptionsBuilder::PchUsage::None); + + ASSERT_THAT(compilerOptionsBuilder.options(), + ElementsAre( + "-nostdlibinc", "-c", "-m64", "-target", "x86_64-apple-darwin10", + "-arch", "x86_64", "-x", "c++", "-std=c++17", "-fcxx-exceptions", + "-fexceptions", "-Dfoo=bar", "-DprojectFoo=projectBar", "-undef", + "-I", QDir::toNativeSeparators("D:/code/qt-creator/tests/unit/unittest/../../../share/qtcreator/cplusplus/wrappedQtHeaders"), + "-I", QDir::toNativeSeparators("D:/code/qt-creator/tests/unit/unittest/../../../share/qtcreator/cplusplus/wrappedQtHeaders/QtCore"), + "-I", QDir::toNativeSeparators("/tmp/path"), + "-I", QDir::toNativeSeparators("/tmp/system_path"), + "-isystem", QDir::toNativeSeparators("/tmp/builtin_path") + )); +} + diff --git a/tests/unit/unittest/data/compileroptionsbuilder.pch b/tests/unit/unittest/data/compileroptionsbuilder.pch new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/unit/unittest/unittest.pro b/tests/unit/unittest/unittest.pro index c0807a541d2..bbd4c0f3aff 100644 --- a/tests/unit/unittest/unittest.pro +++ b/tests/unit/unittest/unittest.pro @@ -20,6 +20,7 @@ DEFINES += \ QT_USE_FAST_CONCATENATION \ UNIT_TESTS \ DONT_CHECK_MESSAGE_COUNTER \ + QTC_RESOURCE_DIR=\"R\\\"xxx($$PWD/../../../share/qtcreator)xxx\\\"\" \ TESTDATA_DIR=\"R\\\"xxx($$PWD/data)xxx\\\"\" msvc: QMAKE_CXXFLAGS_WARN_ON -= -w34100 # 'unreferenced formal parameter' in MATCHER_* functions win32:DEFINES += ECHOSERVER=\"R\\\"xxx($$OUT_PWD/../echo)xxx\\\"\" @@ -102,6 +103,7 @@ SOURCES += \ projectpartqueue-test.cpp \ processormanager-test.cpp \ taskscheduler-test.cpp \ + compileroptionsbuilder-test.cpp !isEmpty(LIBCLANG_LIBS) { SOURCES += \