From 5f5e2543a5f6971fa1d07c9e84eba9742ba329f8 Mon Sep 17 00:00:00 2001 From: Thomas Hartmann Date: Mon, 11 Feb 2019 13:01:35 +0100 Subject: [PATCH 01/59] QmlDesigner: Do not generate auxiliaryDataAsQML for offset -1 If a node does not have a proper offset, then the data is inconsistent. Change-Id: I1fbff3e169b225bc4ca00b1deb21982f30281f9a Reviewed-by: Tim Jenssen --- .../qmldesigner/designercore/model/rewriterview.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/plugins/qmldesigner/designercore/model/rewriterview.cpp b/src/plugins/qmldesigner/designercore/model/rewriterview.cpp index f4cd9c7e796..2b22844bb9c 100644 --- a/src/plugins/qmldesigner/designercore/model/rewriterview.cpp +++ b/src/plugins/qmldesigner/designercore/model/rewriterview.cpp @@ -486,6 +486,8 @@ QString RewriterView::auxiliaryDataAsQML() const QString str = "Designer {\n "; + QTC_ASSERT(!m_canonicalIntModelNode.isEmpty(), return {}); + int columnCount = 0; for (const auto &node : allModelNodes()) { QHash data = node.auxiliaryData(); @@ -727,8 +729,11 @@ void RewriterView::setupCanonicalHashes() const using myPair = std::pair; std::vector data; - for (const ModelNode &node : allModelNodes()) - data.emplace_back(std::make_pair(node, nodeOffset(node))); + for (const ModelNode &node : allModelNodes()) { + int offset = nodeOffset(node); + QTC_ASSERT(offset > 0, qDebug() << Q_FUNC_INFO << "no offset" << node; return); + data.emplace_back(std::make_pair(node, offset)); + } std::sort(data.begin(), data.end(), [](myPair a, myPair b) { return a.second < b.second; @@ -1066,6 +1071,8 @@ void RewriterView::restoreAuxiliaryData() setupCanonicalHashes(); + QTC_ASSERT(!m_canonicalIntModelNode.isEmpty(), return); + const QString text = m_textModifier->text(); int startIndex = text.indexOf(annotationsStart()); From e8a511f313422602626edc86d7669603fc52ea51 Mon Sep 17 00:00:00 2001 From: hjk Date: Thu, 24 Jan 2019 15:04:47 +0100 Subject: [PATCH 02/59] Debugger: Change workaround for scrambled dock widget layouts The workaround from 3d92a79a introduces a bug by itself: When a user moves all docks off the bottom area, the workaround will trigger as the condition "nothing below the tool bar" is met. This here changes the condition to toolbar.width() != mainwindow.width(), which will trigger in the known scrambled situations (there was always something to the right of the toolbar), but not in the situation described above. Task-number: QTCREATORBUG-21669 Task-number: QTCREATORBUG-21455 Change-Id: Ic2eabbe2ed07352680add4fc5e3b5f6673600479 Reviewed-by: Eike Ziller --- src/plugins/debugger/debuggermainwindow.cpp | 22 +++++++-------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/src/plugins/debugger/debuggermainwindow.cpp b/src/plugins/debugger/debuggermainwindow.cpp index 2607c1fbd0b..233f9d9a6df 100644 --- a/src/plugins/debugger/debuggermainwindow.cpp +++ b/src/plugins/debugger/debuggermainwindow.cpp @@ -372,24 +372,16 @@ void DebuggerMainWindowPrivate::fixupLayoutIfNeeded() { // Evil workaround for QTCREATORBUG-21455: In some so far unknown situation // the saveLayout/restoreLayout process leads to a situation where some docks - // does not end up below the perspective toolbar even though they were there + // do not end up below the perspective toolbar even though they were there // initially, leading to an awkward dock layout. - // This here tries to detect the situation (no other dock directly below the - // toolbar) and "corrects" that by restoring the default layout. - const QRect toolbarRect = m_toolBarDock->geometry(); - const int targetX = toolbarRect.left(); - const int targetY = toolbarRect.bottom(); + // This here tries to detect the situation (sonmething else in the bottom + // area is at the right of the toolbar) "corrects" that by restoring the + // default layout. - const QList docks = q->dockWidgets(); - for (QDockWidget *dock : docks) { - const QRect dockRect = dock->geometry(); - // 10 for some decoration wiggle room. Found something below? Good. - if (targetX == dockRect.left() && qAbs(targetY - dockRect.top()) < 10) - return; + if (m_toolBarDock->width() != q->width()) { + qDebug() << "Scrambled dock layout found. Resetting it."; + resetCurrentPerspective(); } - - qDebug() << "Scrambled dock layout found. Resetting it."; - resetCurrentPerspective(); } void DebuggerMainWindowPrivate::selectPerspective(Perspective *perspective) From 25487daffd54bb73e59fc4aa1414beac5b7ed93b Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar Date: Thu, 14 Feb 2019 09:27:29 +0100 Subject: [PATCH 03/59] C++: Fix nullptr references in preprocessor Fixes: QTCREATORBUG-21981 Change-Id: Iaded998eb793fb4284a9f8b22b2fa7a7443a1585 Reviewed-by: Eike Ziller --- src/libs/cplusplus/pp-engine.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/libs/cplusplus/pp-engine.cpp b/src/libs/cplusplus/pp-engine.cpp index 0050a2fd847..50dbb7c140d 100644 --- a/src/libs/cplusplus/pp-engine.cpp +++ b/src/libs/cplusplus/pp-engine.cpp @@ -764,7 +764,7 @@ QByteArray Preprocessor::run(const QString &fileName, preprocessed.reserve(source.size() * 2); // multiply by 2 because we insert #gen lines. preprocess(fileName, source, &preprocessed, &includeGuardMacroName, noLines, markGeneratedTokens, false); - if (!includeGuardMacroName.isEmpty()) + if (m_client && !includeGuardMacroName.isEmpty()) m_client->markAsIncludeGuard(includeGuardMacroName); return preprocessed; } @@ -986,10 +986,12 @@ bool Preprocessor::handleIdentifier(PPToken *tk) if (!expandFunctionlikeMacros() // Still expand if this originally started with an object-like macro. && m_state.m_expansionStatus != Expanding) { - m_client->notifyMacroReference(m_state.m_bytesOffsetRef + idTk.byteOffset, - m_state.m_utf16charsOffsetRef + idTk.utf16charOffset, - idTk.lineno, - *macro); + if (m_client) { + m_client->notifyMacroReference(m_state.m_bytesOffsetRef + idTk.byteOffset, + m_state.m_utf16charsOffsetRef + idTk.utf16charOffset, + idTk.lineno, + *macro); + } return false; } @@ -1793,7 +1795,7 @@ void Preprocessor::handleDefineDirective(PPToken *tk) } } } else if (macroReference) { - if (tk->is(T_LPAREN)) { + if (m_client && tk->is(T_LPAREN)) { m_client->notifyMacroReference(previousBytesOffset, previousUtf16charsOffset, previousLine, *macroReference); } From 0f6e5a56cb29a2c774823266ce45e2e250dcf247 Mon Sep 17 00:00:00 2001 From: Thomas Hartmann Date: Thu, 14 Feb 2019 17:52:28 +0100 Subject: [PATCH 04/59] QmlDesigner: Avoid puppet crash If the property is invalid the propertyTypeName is a nullptr. Calling strcmp on nullptr is undefined and can result in a nullptr access. Change-Id: I270091fa1d2635019ad2e41c4a5eab9985227dcf Reviewed-by: Alessandro Portale --- .../qml/qmlpuppet/qml2puppet/instances/objectnodeinstance.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/objectnodeinstance.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/objectnodeinstance.cpp index 3720bdc90a2..5247f1f3836 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/objectnodeinstance.cpp +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/objectnodeinstance.cpp @@ -267,13 +267,13 @@ static bool isList(const QQmlProperty &property) static bool isQJSValue(const QQmlProperty &property) { - return !strcmp(property.propertyTypeName(), "QJSValue"); + return property.isValid() && !strcmp(property.propertyTypeName(), "QJSValue"); } static bool isObject(const QQmlProperty &property) { /* QVariant and QJSValue can also store QObjects. Lets trust our model. */ - return (property.propertyTypeCategory() == QQmlProperty::Object + return property.isValid() && (property.propertyTypeCategory() == QQmlProperty::Object || !strcmp(property.propertyTypeName(), "QVariant") || isQJSValue(property)); } From 99d20280ca27e73cd1601e248469216c3582130e Mon Sep 17 00:00:00 2001 From: Kirill Burtsev Date: Tue, 19 Feb 2019 14:05:43 +0100 Subject: [PATCH 05/59] Clang: Fix stack-use-after-scope sanitizer error in diagnostic filter Change-Id: I97d69caf9c7b642bef277fdfa0df80820fcdbe2f Reviewed-by: Nikolai Kosjar --- src/plugins/clangcodemodel/clangdiagnosticfilter.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/clangcodemodel/clangdiagnosticfilter.h b/src/plugins/clangcodemodel/clangdiagnosticfilter.h index 0fe164ecf07..a61734718ea 100644 --- a/src/plugins/clangcodemodel/clangdiagnosticfilter.h +++ b/src/plugins/clangcodemodel/clangdiagnosticfilter.h @@ -49,7 +49,7 @@ private: void filterFixits(); private: - const QString &m_filePath; + const QString m_filePath; QVector m_warningDiagnostics; QVector m_errorDiagnostics; From c219b00ca39c59d3d23ae8ef49692eb8946bef98 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Wed, 20 Feb 2019 09:33:46 +0100 Subject: [PATCH 06/59] Tests: Fix test expectation And disable the check for Qt < 5.11 as we fail to get the respective information there. Change-Id: Ie21115f4de81c046028ab1df6f5cd8397d0f75dd Reviewed-by: hjk --- tests/auto/debugger/tst_dumpers.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/auto/debugger/tst_dumpers.cpp b/tests/auto/debugger/tst_dumpers.cpp index 63f0f25bf40..91d1918de6f 100644 --- a/tests/auto/debugger/tst_dumpers.cpp +++ b/tests/auto/debugger/tst_dumpers.cpp @@ -2828,8 +2828,8 @@ void tst_Dumpers::dumper_data() + Check("ob", "\"An Object\"", "@QWidget") + Check("ob1", "\"Another Object\"", "@QObject") + Check("ob2", "\"A Subobject\"", "@QObject") - + Check("ob.[extra].[connections].0.0.receiver", "\"Another Object\"", - "@QObject") % NoCdbEngine; + + Check("ob.[extra].[connections].@1.0.0.receiver", "\"Another Object\"", + "@QObject") % NoCdbEngine % QtVersion(0x50b00); QString senderData = From 00ee1ca7e030d59630925decdfd14d3ed57beb69 Mon Sep 17 00:00:00 2001 From: Thomas Hartmann Date: Tue, 19 Feb 2019 17:58:58 +0100 Subject: [PATCH 07/59] QmlDesigner: Fix crash The version number of 'GradientStop' was hardcoded, but does change with QtQuick 5.12. The issue is not consistently triggered. This is a backport from master. Task-number: QDS-472 Change-Id: I939659aa14ae1570fc5d833726f28894c043da02 Reviewed-by: Alessandro Portale Reviewed-by: Tim Jenssen --- .../propertyeditor/gradientmodel.cpp | 242 ++++++++++++++---- .../components/propertyeditor/gradientmodel.h | 17 +- 2 files changed, 213 insertions(+), 46 deletions(-) diff --git a/src/plugins/qmldesigner/components/propertyeditor/gradientmodel.cpp b/src/plugins/qmldesigner/components/propertyeditor/gradientmodel.cpp index aa7cfe1bb08..b2e25fa6d66 100644 --- a/src/plugins/qmldesigner/components/propertyeditor/gradientmodel.cpp +++ b/src/plugins/qmldesigner/components/propertyeditor/gradientmodel.cpp @@ -28,6 +28,7 @@ #include "qmlanchorbindingproxy.h" #include "propertyeditorview.h" +#include #include #include #include @@ -35,8 +36,11 @@ #include #include +#include + GradientModel::GradientModel(QObject *parent) : QAbstractListModel(parent), m_locked(false) + ,m_gradientTypeName("Gradient") { } @@ -101,28 +105,29 @@ int GradientModel::addStop(qreal position, const QColor &color) return -1; if (m_itemNode.modelNode().hasNodeProperty(gradientPropertyName().toUtf8())) { - //QmlDesigner::RewriterTransaction transaction = m_itemNode.modelNode().view()->beginRewriterTransaction(); - //### TODO does not work - - QmlDesigner::ModelNode gradientNode = m_itemNode.modelNode().nodeProperty(gradientPropertyName().toUtf8()).modelNode(); - - QmlDesigner::ModelNode gradientStopNode = - m_itemNode.modelNode().view()->createModelNode("QtQuick.GradientStop", - m_itemNode.modelNode().view()->majorQtQuickVersion(), 0); - gradientStopNode.variantProperty("position").setValue(position); - gradientStopNode.variantProperty("color").setValue(color); - gradientNode.nodeListProperty("stops").reparentHere(gradientStopNode); - - const QList stopNodes = gradientNode.nodeListProperty("stops").toModelNodeList(); - int properPos = 0; - for (int i = 0; i < stopNodes.count(); i++) { - if (QmlDesigner::QmlObjectNode(stopNodes.at(i)).modelValue("position").toReal() < position) - properPos = i + 1; - } - gradientNode.nodeListProperty("stops").slide(stopNodes.count() - 1, properPos); + try { - setupModel(); + QmlDesigner::ModelNode gradientNode = m_itemNode.modelNode().nodeProperty(gradientPropertyName().toUtf8()).modelNode(); + + QmlDesigner::ModelNode gradientStopNode = createGradientStopNode(); + + gradientStopNode.variantProperty("position").setValue(position); + gradientStopNode.variantProperty("color").setValue(color); + gradientNode.nodeListProperty("stops").reparentHere(gradientStopNode); + + const QList stopNodes = gradientNode.nodeListProperty("stops").toModelNodeList(); + + for (int i = 0; i < stopNodes.count(); i++) { + if (QmlDesigner::QmlObjectNode(stopNodes.at(i)).modelValue("position").toReal() < position) + properPos = i + 1; + } + gradientNode.nodeListProperty("stops").slide(stopNodes.count() - 1, properPos); + + setupModel(); + } catch (const QmlDesigner::Exception &e) { + e.showException(); + } return properPos; } @@ -139,38 +144,38 @@ void GradientModel::addGradient() return; if (!m_itemNode.modelNode().hasNodeProperty(gradientPropertyName().toUtf8())) { + try { - QColor color = m_itemNode.instanceValue("color").value(); + QColor color = m_itemNode.instanceValue("color").value(); - if (!color.isValid()) - color = QColor(Qt::white); + if (!color.isValid()) + color = QColor(Qt::white); - QmlDesigner::RewriterTransaction transaction = m_itemNode.modelNode().view()->beginRewriterTransaction(QByteArrayLiteral("GradientModel::addGradient")); + QmlDesigner::RewriterTransaction transaction = view()->beginRewriterTransaction(QByteArrayLiteral("GradientModel::addGradient")); - QmlDesigner::ModelNode gradientNode = - m_itemNode.modelNode().view()->createModelNode("QtQuick.Gradient", - m_itemNode.modelNode().view()->majorQtQuickVersion(), 0); - m_itemNode.modelNode().nodeProperty(gradientPropertyName().toUtf8()).reparentHere(gradientNode); + QmlDesigner::ModelNode gradientNode = createGradientNode(); + m_itemNode.modelNode().nodeProperty(gradientPropertyName().toUtf8()).reparentHere(gradientNode); - QmlDesigner::ModelNode gradientStopNode = - m_itemNode.modelNode().view()->createModelNode("QtQuick.GradientStop", - m_itemNode.modelNode().view()->majorQtQuickVersion(), 0); - gradientStopNode.variantProperty("position").setValue(0.0); - gradientStopNode.variantProperty("color").setValue(color); - gradientNode.nodeListProperty("stops").reparentHere(gradientStopNode); + QmlDesigner::ModelNode gradientStopNode = createGradientStopNode(); + gradientStopNode.variantProperty("position").setValue(0.0); + gradientStopNode.variantProperty("color").setValue(color); + gradientNode.nodeListProperty("stops").reparentHere(gradientStopNode); - gradientStopNode = m_itemNode.modelNode().view()->createModelNode( - "QtQuick.GradientStop", - m_itemNode.modelNode().view()->majorQtQuickVersion(), 0); - gradientStopNode.variantProperty("position").setValue(1.0); - gradientStopNode.variantProperty("color").setValue(QColor(Qt::black)); - gradientNode.nodeListProperty("stops").reparentHere(gradientStopNode); + gradientStopNode = createGradientStopNode(); + gradientStopNode.variantProperty("position").setValue(1.0); + gradientStopNode.variantProperty("color").setValue(QColor(Qt::black)); + gradientNode.nodeListProperty("stops").reparentHere(gradientStopNode); + + } catch (const QmlDesigner::Exception &e) { + e.showException(); + } } setupModel(); emit hasGradientChanged(); + emit gradientTypeChanged(); } void GradientModel::setColor(int index, const QColor &color) @@ -231,7 +236,7 @@ qreal GradientModel::getPosition(int index) const void GradientModel::removeStop(int index) { if (index < rowCount() - 1 && index != 0) { - QmlDesigner::RewriterTransaction transaction = m_itemNode.modelNode().view()->beginRewriterTransaction(QByteArrayLiteral("GradientModel::removeStop")); + QmlDesigner::RewriterTransaction transaction = view()->beginRewriterTransaction(QByteArrayLiteral("GradientModel::removeStop")); QmlDesigner::ModelNode gradientNode = m_itemNode.modelNode().nodeProperty(gradientPropertyName().toUtf8()).modelNode(); QmlDesigner::QmlObjectNode stop = gradientNode.nodeListProperty("stops").at(index); if (stop.isValid()) { @@ -255,7 +260,7 @@ void GradientModel::deleteGradient() if (m_itemNode.isInBaseState()) { if (modelNode.hasProperty(gradientPropertyName().toUtf8())) { - QmlDesigner::RewriterTransaction transaction = m_itemNode.modelNode().view()->beginRewriterTransaction(QByteArrayLiteral("GradientModel::deleteGradient")); + QmlDesigner::RewriterTransaction transaction = view()->beginRewriterTransaction(QByteArrayLiteral("GradientModel::deleteGradient")); QmlDesigner::ModelNode gradientNode = modelNode.nodeProperty(gradientPropertyName().toUtf8()).modelNode(); if (QmlDesigner::QmlObjectNode(gradientNode).isValid()) QmlDesigner::QmlObjectNode(gradientNode).destroy(); @@ -263,6 +268,7 @@ void GradientModel::deleteGradient() } emit hasGradientChanged(); + emit gradientTypeChanged(); } void GradientModel::lock() @@ -280,6 +286,22 @@ void GradientModel::registerDeclarativeType() qmlRegisterType("HelperWidgets",2,0,"GradientModel"); } +qreal GradientModel::readGradientProperty(const QString &propertyName) const +{ + if (!m_itemNode.isValid()) + return 0; + + QmlDesigner::QmlObjectNode gradient; + + if (m_itemNode.modelNode().hasProperty(gradientPropertyName().toUtf8())) + gradient = m_itemNode.modelNode().nodeProperty(gradientPropertyName().toUtf8()).modelNode(); + + if (!gradient.isValid()) + return 0; + + return gradient.modelValue(propertyName.toUtf8()).toReal(); +} + void GradientModel::setupModel() { m_locked = true; @@ -299,12 +321,17 @@ void GradientModel::setAnchorBackend(const QVariant &anchorBackend) if (backendCasted) m_itemNode = backendCasted->getItemNode(); + if (m_itemNode.isValid() + && m_itemNode.modelNode().hasProperty(gradientPropertyName().toUtf8())) + m_gradientTypeName = m_itemNode.modelNode().nodeProperty(gradientPropertyName().toUtf8()).modelNode().simplifiedTypeName(); + setupModel(); m_locked = true; emit anchorBackendChanged(); emit hasGradientChanged(); + emit gradientTypeChanged(); m_locked = false; } @@ -319,6 +346,16 @@ void GradientModel::setGradientPropertyName(const QString &name) m_gradientPropertyName = name; } +QString GradientModel::gradientTypeName() const +{ + return m_gradientTypeName; +} + +void GradientModel::setGradientTypeName(const QString &name) +{ + m_gradientTypeName = name; +} + bool GradientModel::hasGradient() const { return m_itemNode.isValid() @@ -330,10 +367,125 @@ bool GradientModel::locked() const if (m_locked) return true; - auto view = qobject_cast(m_itemNode.view()); + auto editorView = qobject_cast(view()); - if (view && view->locked()) - return true; + return editorView && editorView->locked(); +} + +bool GradientModel::hasShapesImport() const +{ + if (m_itemNode.isValid()) { + QmlDesigner::Import import = QmlDesigner::Import::createLibraryImport("QtQuick.Shapes", "1.0"); + return model()->hasImport(import, true, true); + } return false; } + +void GradientModel::ensureShapesImport() +{ + if (!hasShapesImport()) { + QmlDesigner::Import timelineImport = QmlDesigner::Import::createLibraryImport("QtQuick.Shapes", "1.0"); + model()->changeImports({timelineImport}, {}); + } +} + +void GradientModel::setupGradientProperties(const QmlDesigner::ModelNode &gradient) +{ + QTC_ASSERT(m_itemNode.isValid(), return); + + QTC_ASSERT(gradient.isValid(), return); + + if (m_gradientTypeName == "Gradient") { + } else if (m_gradientTypeName == "LinearGradient") { + gradient.variantProperty("x1").setValue(0); + gradient.variantProperty("x2").setValue(m_itemNode.instanceValue("width")); + gradient.variantProperty("y1").setValue(0); + gradient.variantProperty("y2").setValue(m_itemNode.instanceValue("height")); + } else if (m_gradientTypeName == "RadialGradient") { + qreal width = m_itemNode.instanceValue("width").toReal(); + qreal height = m_itemNode.instanceValue("height").toReal(); + gradient.variantProperty("centerX").setValue(width / 2.0); + gradient.variantProperty("centerY").setValue(height / 2.0); + + gradient.variantProperty("focalX").setValue(width / 2.0); + gradient.variantProperty("focalY").setValue(height / 2.0); + + qreal radius = qMin(width, height) / 2; + + gradient.variantProperty("centerRadius").setValue(radius); + gradient.variantProperty("focalRadius").setValue(0); + + } else if (m_gradientTypeName == "ConicalGradient") { + qreal width = m_itemNode.instanceValue("width").toReal(); + qreal height = m_itemNode.instanceValue("height").toReal(); + gradient.variantProperty("centerX").setValue(width / 2.0); + gradient.variantProperty("centerY").setValue(height / 2.0); + + gradient.variantProperty("angle").setValue(0); + } +} + +QmlDesigner::Model *GradientModel::model() const +{ + QTC_ASSERT(m_itemNode.isValid(), return nullptr); + return m_itemNode.view()->model(); +} + +QmlDesigner::AbstractView *GradientModel::view() const +{ + QTC_ASSERT(m_itemNode.isValid(), return nullptr); + return m_itemNode.view(); +} + +QmlDesigner::ModelNode GradientModel::createGradientNode() +{ + QByteArray fullTypeName = m_gradientTypeName.toUtf8(); + + if (m_gradientTypeName == "Gradient") { + fullTypeName.prepend("QtQuick."); + } else { + fullTypeName.prepend("QtQuick.Shapes."); + ensureShapesImport(); + } + + auto metaInfo = model()->metaInfo(fullTypeName); + + int minorVersion = metaInfo.minorVersion(); + int majorVersion = metaInfo.majorVersion(); + + auto gradientNode = view()->createModelNode(fullTypeName, majorVersion, minorVersion); + + setupGradientProperties(gradientNode); + + return gradientNode; +} + +QmlDesigner::ModelNode GradientModel::createGradientStopNode() +{ + QByteArray fullTypeName = "QtQuick.GradientStop"; + auto metaInfo = model()->metaInfo(fullTypeName); + + int minorVersion = metaInfo.minorVersion(); + int majorVersion = metaInfo.majorVersion(); + + return view()->createModelNode(fullTypeName, majorVersion, minorVersion); +} + +void GradientModel::setGradientProperty(const QString &propertyName, qreal value) +{ + QTC_ASSERT(m_itemNode.isValid(), return); + + QmlDesigner::QmlObjectNode gradient; + + if (m_itemNode.modelNode().hasProperty(gradientPropertyName().toUtf8())) + gradient = m_itemNode.modelNode().nodeProperty(gradientPropertyName().toUtf8()).modelNode(); + + QTC_ASSERT(gradient.isValid(), return); + + try { + gradient.setVariantProperty(propertyName.toUtf8(), value); + } catch (const QmlDesigner::Exception &e) { + e.showException(); + } +} diff --git a/src/plugins/qmldesigner/components/propertyeditor/gradientmodel.h b/src/plugins/qmldesigner/components/propertyeditor/gradientmodel.h index 2ca8b93c429..48514ae6885 100644 --- a/src/plugins/qmldesigner/components/propertyeditor/gradientmodel.h +++ b/src/plugins/qmldesigner/components/propertyeditor/gradientmodel.h @@ -37,6 +37,7 @@ class GradientModel : public QAbstractListModel Q_PROPERTY(QVariant anchorBackendProperty READ anchorBackend WRITE setAnchorBackend NOTIFY anchorBackendChanged) Q_PROPERTY(QString gradientPropertyName READ gradientPropertyName WRITE setGradientPropertyName) + Q_PROPERTY(QString gradientTypeName READ gradientTypeName WRITE setGradientTypeName NOTIFY gradientTypeChanged) Q_PROPERTY(int count READ rowCount) Q_PROPERTY(bool hasGradient READ hasGradient NOTIFY hasGradientChanged) @@ -65,9 +66,14 @@ public: static void registerDeclarativeType(); + Q_INVOKABLE qreal readGradientProperty(const QString &property) const; + + Q_INVOKABLE void setGradientProperty(const QString &propertyName, qreal value); + signals: void anchorBackendChanged(); void hasGradientChanged(); + void gradientTypeChanged(); private: void setupModel(); @@ -75,14 +81,23 @@ private: QVariant anchorBackend() const {return QVariant(); } QString gradientPropertyName() const; void setGradientPropertyName(const QString &name); + QString gradientTypeName() const; + void setGradientTypeName(const QString &name); bool hasGradient() const; bool locked() const; + QmlDesigner::ModelNode createGradientNode(); + QmlDesigner::ModelNode createGradientStopNode(); private: QmlDesigner::QmlItemNode m_itemNode; QString m_gradientPropertyName; + QString m_gradientTypeName; bool m_locked; - + bool hasShapesImport() const; + void ensureShapesImport(); + void setupGradientProperties(const QmlDesigner::ModelNode &gradient); + QmlDesigner::Model *model() const; + QmlDesigner::AbstractView *view() const; }; QML_DECLARE_TYPE(GradientModel) From 2c6bda5950424021f3601b77fc21222786b451f9 Mon Sep 17 00:00:00 2001 From: Ivan Donchevskii Date: Fri, 15 Feb 2019 16:13:20 +0100 Subject: [PATCH 08/59] ClangRefactoring: Map unsaved files with non-native paths in ClangTool Otherwise the ClangTool complains that it does not see them. Change-Id: Ib616058584f8f95229213224cec98fa6b6f7522b Reviewed-by: Marco Bubke --- .../source/clangtool.cpp | 19 ++---------------- .../source/clangtool.h | 4 ++-- .../unit/unittest/commandlinebuilder-test.cpp | 14 +++++++++---- tests/unit/unittest/symbolindexer-test.cpp | 20 +++++++++---------- 4 files changed, 24 insertions(+), 33 deletions(-) diff --git a/src/tools/clangrefactoringbackend/source/clangtool.cpp b/src/tools/clangrefactoringbackend/source/clangtool.cpp index 1798504a692..b96f479a81e 100644 --- a/src/tools/clangrefactoringbackend/source/clangtool.cpp +++ b/src/tools/clangrefactoringbackend/source/clangtool.cpp @@ -31,21 +31,6 @@ namespace ClangBackEnd { -namespace { - -// use std::filesystem::path if it is supported by all compilers - -template -String toNativePath(String &&path) -{ -#ifdef _WIN32 - std::replace(path.begin(), path.end(), '/', '\\'); -#endif - - return std::move(path); -} -} - void ClangTool::addFile(FilePath &&filePath, Utils::SmallString &&content, Utils::SmallStringVector &&commandLine) @@ -72,7 +57,7 @@ void ClangTool::addUnsavedFiles(const V2::FileContainers &unsavedFiles) m_unsavedFileContents.reserve(m_unsavedFileContents.size() + unsavedFiles.size()); auto convertToUnsavedFileContent = [](const V2::FileContainer &unsavedFile) { - return UnsavedFileContent{NativeFilePath{unsavedFile.filePath}, + return UnsavedFileContent{unsavedFile.filePath.clone(), unsavedFile.unsavedFileContent.clone()}; }; @@ -83,7 +68,7 @@ void ClangTool::addUnsavedFiles(const V2::FileContainers &unsavedFiles) } namespace { -template +template llvm::StringRef toStringRef(const String &string) { return llvm::StringRef(string.data(), string.size()); diff --git a/src/tools/clangrefactoringbackend/source/clangtool.h b/src/tools/clangrefactoringbackend/source/clangtool.h index 2abad0f49b5..1f266e86ebf 100644 --- a/src/tools/clangrefactoringbackend/source/clangtool.h +++ b/src/tools/clangrefactoringbackend/source/clangtool.h @@ -55,12 +55,12 @@ struct FileContent struct UnsavedFileContent { - UnsavedFileContent(NativeFilePath &&filePath, Utils::SmallString &&content) + UnsavedFileContent(FilePath &&filePath, Utils::SmallString &&content) : filePath(std::move(filePath)) , content(std::move(content)) {} - NativeFilePath filePath; + FilePath filePath; Utils::SmallString content; }; diff --git a/tests/unit/unittest/commandlinebuilder-test.cpp b/tests/unit/unittest/commandlinebuilder-test.cpp index 8eb7fafa3c3..a75c8d8a35c 100644 --- a/tests/unit/unittest/commandlinebuilder-test.cpp +++ b/tests/unit/unittest/commandlinebuilder-test.cpp @@ -155,7 +155,13 @@ TYPED_TEST(CommandLineBuilder, CSource) Builder builder{this->emptyProjectInfo, {}, InputFileType::Source, "/source/file.c"}; ASSERT_THAT(builder.commandLine, - ElementsAre("clang", "-DNOMINMAX", "-x", "c", "-std=c11", "-nostdinc", "/source/file.c")); + ElementsAre("clang", + "-DNOMINMAX", + "-x", + "c", + "-std=c11", + "-nostdinc", + toNativePath("/source/file.c").path())); } TYPED_TEST(CommandLineBuilder, ObjectiveCHeader) @@ -191,7 +197,7 @@ TYPED_TEST(CommandLineBuilder, ObjectiveCSource) "objective-c", "-std=c11", "-nostdinc", - "/source/file.c")); + toNativePath("/source/file.c").path())); } TYPED_TEST(CommandLineBuilder, CppHeader) @@ -227,7 +233,7 @@ TYPED_TEST(CommandLineBuilder, CppSource) "-std=c++98", "-nostdinc", "-nostdinc++", - "/source/file.cpp")); + toNativePath("/source/file.cpp").path())); } TYPED_TEST(CommandLineBuilder, ObjectiveCppHeader) @@ -265,7 +271,7 @@ TYPED_TEST(CommandLineBuilder, ObjectiveCppSource) "-std=c++98", "-nostdinc", "-nostdinc++", - "/source/file.cpp")); + toNativePath("/source/file.cpp").path())); } TYPED_TEST(CommandLineBuilder, Cpp98) diff --git a/tests/unit/unittest/symbolindexer-test.cpp b/tests/unit/unittest/symbolindexer-test.cpp index 9283eea8b6c..0a7b6acba19 100644 --- a/tests/unit/unittest/symbolindexer-test.cpp +++ b/tests/unit/unittest/symbolindexer-test.cpp @@ -630,15 +630,15 @@ TEST_F(SymbolIndexer, UpdateProjectPartsCallsInOrderButGetsAnErrorForCollectingS "-DBAR=1", "-DFOO=1", "-I", - "/project/includes", + toNativePath("/project/includes").path(), "-I", - "/other/project/includes", + toNativePath("/other/project/includes").path(), "-isystem", - TESTDATA_DIR, + toNativePath(TESTDATA_DIR).path(), "-isystem", - "/other/includes", + toNativePath("/other/includes").path(), "-isystem", - "/includes"))); + toNativePath("/includes").path()))); EXPECT_CALL(mockCollector, collectSymbols()).WillOnce(Return(false)); EXPECT_CALL(mockSqliteTransactionBackend, immediateBegin()).Times(0); EXPECT_CALL(mockSymbolStorage, addSymbolsAndSourceLocations(symbolEntries, sourceLocations)).Times(0); @@ -752,15 +752,15 @@ TEST_F(SymbolIndexer, UpdateChangedPathCallsInOrderButGetsAnErrorForCollectingSy "-DBAR=1", "-DFOO=1", "-I", - "/project/includes", + toNativePath("/project/includes").path(), "-I", - "/other/project/includes", + toNativePath("/other/project/includes").path(), "-isystem", - TESTDATA_DIR, + toNativePath(TESTDATA_DIR).path(), "-isystem", - "/other/includes", + toNativePath("/other/includes").path(), "-isystem", - "/includes"))); + toNativePath("/includes").path()))); EXPECT_CALL(mockCollector, collectSymbols()).WillOnce(Return(false)); EXPECT_CALL(mockSqliteTransactionBackend, immediateBegin()).Times(0); EXPECT_CALL(mockSymbolStorage, addSymbolsAndSourceLocations(symbolEntries, sourceLocations)).Times(0); From 56584b1ddebce554e382e759ead42f761929f87f Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar Date: Thu, 14 Feb 2019 15:33:00 +0100 Subject: [PATCH 09/59] Clang: Fix unit test build without QTC_ENABLE_CLANG_LIBTOOLING Change-Id: Ifa6588d1427489e8ae98ea8093d5d94049c270ee Reviewed-by: Marco Bubke --- .../source/clangpchmanagerbackend-source.pri | 1 + .../source/pchcreator.h | 9 +--- .../source/pchcreatorincludes.h | 40 ++++++++++++++++++ tests/unit/unittest/googletest.h | 1 + .../unit/unittest/gtest-creator-printing.cpp | 17 +------- tests/unit/unittest/gtest-llvm-printing.cpp | 42 +++++++++++++++++++ tests/unit/unittest/gtest-llvm-printing.h | 39 +++++++++++++++++ tests/unit/unittest/unittest.pro | 2 + 8 files changed, 128 insertions(+), 23 deletions(-) create mode 100644 src/tools/clangpchmanagerbackend/source/pchcreatorincludes.h create mode 100644 tests/unit/unittest/gtest-llvm-printing.cpp create mode 100644 tests/unit/unittest/gtest-llvm-printing.h diff --git a/src/tools/clangpchmanagerbackend/source/clangpchmanagerbackend-source.pri b/src/tools/clangpchmanagerbackend/source/clangpchmanagerbackend-source.pri index fa8d6e527a6..94d9540beae 100644 --- a/src/tools/clangpchmanagerbackend/source/clangpchmanagerbackend-source.pri +++ b/src/tools/clangpchmanagerbackend/source/clangpchmanagerbackend-source.pri @@ -9,6 +9,7 @@ SOURCES += \ $$PWD/pchtaskqueue.cpp HEADERS += \ + $$PWD/pchcreatorincludes.h \ $$PWD/pchmanagerserver.h \ $$PWD/clangpchmanagerbackend_global.h \ $$PWD/pchnotcreatederror.h \ diff --git a/src/tools/clangpchmanagerbackend/source/pchcreator.h b/src/tools/clangpchmanagerbackend/source/pchcreator.h index 7c736dd2342..73f185176d7 100644 --- a/src/tools/clangpchmanagerbackend/source/pchcreator.h +++ b/src/tools/clangpchmanagerbackend/source/pchcreator.h @@ -27,6 +27,7 @@ #include "pchcreatorinterface.h" +#include "pchcreatorincludes.h" #include "idpaths.h" #include "sourceentry.h" #include "clangtool.h" @@ -49,14 +50,6 @@ class GeneratedFiles; class PchManagerClientInterface; class ClangPathWatcherInterface; -class PchCreatorIncludes -{ -public: - FilePathIds includeIds; - FilePathIds topIncludeIds; - FilePathIds topSystemIncludeIds; -}; - class PchCreator final : public PchCreatorInterface { public: diff --git a/src/tools/clangpchmanagerbackend/source/pchcreatorincludes.h b/src/tools/clangpchmanagerbackend/source/pchcreatorincludes.h new file mode 100644 index 00000000000..6854c599070 --- /dev/null +++ b/src/tools/clangpchmanagerbackend/source/pchcreatorincludes.h @@ -0,0 +1,40 @@ +/**************************************************************************** +** +** Copyright (C) 2019 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. +** +****************************************************************************/ + +#pragma once + +#include + +namespace ClangBackEnd { + +class PchCreatorIncludes +{ +public: + FilePathIds includeIds; + FilePathIds topIncludeIds; + FilePathIds topSystemIncludeIds; +}; + +} // namespace ClangBackEnd diff --git a/tests/unit/unittest/googletest.h b/tests/unit/unittest/googletest.h index b685b83c78f..0b9bf2d2fa1 100644 --- a/tests/unit/unittest/googletest.h +++ b/tests/unit/unittest/googletest.h @@ -40,6 +40,7 @@ #include "conditionally-disabled-tests.h" #include "gtest-qt-printing.h" #include "gtest-creator-printing.h" +#include "gtest-llvm-printing.h" #ifdef CLANG_UNIT_TESTS # include "gtest-clang-printing.h" #endif diff --git a/tests/unit/unittest/gtest-creator-printing.cpp b/tests/unit/unittest/gtest-creator-printing.cpp index 30660376e1f..8427e79af8a 100644 --- a/tests/unit/unittest/gtest-creator-printing.cpp +++ b/tests/unit/unittest/gtest-creator-printing.cpp @@ -41,10 +41,11 @@ #include #include #include +#include #include #include #include -#include +#include #include #include #include @@ -69,24 +70,10 @@ #include #include -#include - namespace { ClangBackEnd::FilePathCaching *filePathCache = nullptr; } -namespace clang { -namespace tooling { -struct CompileCommand; - -std::ostream &operator<<(std::ostream &out, const CompileCommand &command) -{ - return out << "(" << command.Directory << ", " << command.Filename << ", " - << command.CommandLine << ", " << command.Output << ")"; -} -} // namespace tooling -} // namespace clang - void PrintTo(const Utf8String &text, ::std::ostream *os) { *os << text; diff --git a/tests/unit/unittest/gtest-llvm-printing.cpp b/tests/unit/unittest/gtest-llvm-printing.cpp new file mode 100644 index 00000000000..c78b4f9eea5 --- /dev/null +++ b/tests/unit/unittest/gtest-llvm-printing.cpp @@ -0,0 +1,42 @@ +/**************************************************************************** +** +** Copyright (C) 2019 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 + +#include + +#include + +namespace clang { +namespace tooling { +struct CompileCommand; + +std::ostream &operator<<(std::ostream &out, const CompileCommand &command) +{ + return out << "(" << command.Directory << ", " << command.Filename << ", " + << command.CommandLine << ", " << command.Output << ")"; +} +} // namespace tooling +} // namespace clang diff --git a/tests/unit/unittest/gtest-llvm-printing.h b/tests/unit/unittest/gtest-llvm-printing.h new file mode 100644 index 00000000000..167f9341d0e --- /dev/null +++ b/tests/unit/unittest/gtest-llvm-printing.h @@ -0,0 +1,39 @@ +/**************************************************************************** +** +** Copyright (C) 2019 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. +** +****************************************************************************/ + +#pragma once + +#include + +#include + +namespace clang { +namespace tooling { +struct CompileCommand; + +std::ostream &operator<<(std::ostream &out, const CompileCommand &command); + +} // namespace tooling +} // namespace clang diff --git a/tests/unit/unittest/unittest.pro b/tests/unit/unittest/unittest.pro index e3c9430acf0..6fccdebcc7c 100644 --- a/tests/unit/unittest/unittest.pro +++ b/tests/unit/unittest/unittest.pro @@ -176,6 +176,7 @@ SOURCES += \ !isEmpty(LIBTOOLING_LIBS) { SOURCES += \ + gtest-llvm-printing.cpp \ clangquerygatherer-test.cpp \ clangqueryprojectfindfilter-test.cpp \ clangquery-test.cpp \ @@ -214,6 +215,7 @@ HEADERS += \ filesystem-utilities.h \ googletest.h \ gtest-creator-printing.h \ + gtest-llvm-printing.h \ gtest-qt-printing.h \ mimedatabase-utilities.h \ mockclangcodemodelclient.h \ From 27f12bd2ce7407fe352b16cd65ce9b494a3546f7 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Fri, 15 Feb 2019 10:24:18 +0100 Subject: [PATCH 10/59] Doc: Update AutoTest plugin related docs Grouping of test results by their application had been added. More blacklisted result types had been added to Qt5.12. Change-Id: I860c301fd5b9586809679d7def275a908d6fcf10 Reviewed-by: Leena Miettinen --- .../howto/creator-only/creator-autotest.qdoc | 46 +++++++++++++------ 1 file changed, 33 insertions(+), 13 deletions(-) diff --git a/doc/src/howto/creator-only/creator-autotest.qdoc b/doc/src/howto/creator-only/creator-autotest.qdoc index d5d51edb641..b9971d2ac0e 100644 --- a/doc/src/howto/creator-only/creator-autotest.qdoc +++ b/doc/src/howto/creator-only/creator-autotest.qdoc @@ -333,22 +333,9 @@ \row \li BENCH \li Benchmark test. - \row - \li BFAIL - \li Blacklisted test case failed. Since Qt 5.4, you can - provide a BLACKLIST file for tests. It is mainly used internally - by the Qt CI system. - \row - \li BPASS - \li Blacklisted test case passed. \row \li DEBUG \li Debug message. - \row - \li XFAIL - \li Test case is expected to fail, so it is marked by using the - QEXPECT_FAIL macro. If the test case passes instead, an - unexpected pass (XPASS) is written to the test log. \row \li FAIL \li Test case failed. Double-click the line for more information. @@ -371,12 +358,40 @@ \row \li SYSTEM \li An error message received from or influenced by the OS. + \row + \li XFAIL + \li Test case is expected to fail, so it is marked by using the + QEXPECT_FAIL macro. If the test case passes instead, an + unexpected pass (XPASS) is written to the test log. \row \li XPASS \li Test case passed even though it was expected to fail. \row \li WARN \li Warning message. + + \endtable + + Since Qt 5.4, you can provide a BLACKLIST file for tests. It is mainly used + internally by the Qt CI system. + + \table + \header + \li Result + \li Description + \row + \li BFAIL + \li Blacklisted test case failed. + \row + \li BPASS + \li Blacklisted test case passed. + \row + \li BXFAIL + \li Blacklisted test case failed but was marked to be expected to fail. + \row + \li BXPASS + \li Blacklisted test case passed even though it was expected to fail. + \endtable To view only messages of a particular type, select @@ -391,6 +406,11 @@ \uicontrol {Limit result output} check box. To disable automatic scrolling, deselect the \uicontrol {Automatically scroll results} check box. + Test results can be grouped by the executable path that was used to run the + tests. This is useful if you have multiple test executables and run them all + at once. To enable this functionality you need to select the + \uicontrol {Group results by application} check box. + Internal messages and run configuration warnings for deduced configurations are omitted by default. To view them, deselect the \uicontrol {Omit internal messages} and \uicontrol {Omit run configuration warnings} check boxes. From da01512676b0ea89882fd70430b593358292d076 Mon Sep 17 00:00:00 2001 From: Leena Miettinen Date: Wed, 20 Feb 2019 15:45:44 +0100 Subject: [PATCH 11/59] Doc: Replace "Nut menu" with "Settings menu" Change-Id: Ie53abecac566fbd69023572390fabf5db40fbec3 Reviewed-by: Mitch Curtis --- doc/src/qtquick/qtquick-components.qdoc | 2 +- doc/src/qtquick/qtquick-properties.qdoc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/src/qtquick/qtquick-components.qdoc b/doc/src/qtquick/qtquick-components.qdoc index 77e0a8c58a3..aecac17aed4 100644 --- a/doc/src/qtquick/qtquick-components.qdoc +++ b/doc/src/qtquick/qtquick-components.qdoc @@ -163,7 +163,7 @@ Property bindings are created implicitly in QML whenever a property is assigned a JavaScript expression. To set JavaScript expressions as values - of properties in the Design mode, select the \uicontrol Nut menu next to + of properties in the Design mode, select the \uicontrol Settings menu next to a property, and then select \uicontrol {Set Binding}. \image qmldesigner-set-expression.png "Type properties context menu" diff --git a/doc/src/qtquick/qtquick-properties.qdoc b/doc/src/qtquick/qtquick-properties.qdoc index c9d134d15c7..41e1086f8ad 100644 --- a/doc/src/qtquick/qtquick-properties.qdoc +++ b/doc/src/qtquick/qtquick-properties.qdoc @@ -50,7 +50,7 @@ \uicontrol Properties pane, and enter the name of another QML type in the field. If you have specified properties for the item that are not supported for the new type, the type cannot be changed and an error message is - displayed. Select the \uicontrol Nut menu next to the property name, and + displayed. Select the \uicontrol Settings menu next to the property name, and then select \uicontrol Reset to remove the property values before trying again. From 434c9602430b0b8eef2793d1b5c927bad443bf48 Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Wed, 20 Feb 2019 17:44:14 +0100 Subject: [PATCH 12/59] ProjectExplorer: Fix "Remove subproject" functionality This was completely broken: Both The qmake-specific logic for enabling the menu item and the generic code executing the action operated on the wrong nodes. Change-Id: Ic6af6f87999dfd3b939f185312be944750b21fa9 Reviewed-by: hjk --- src/plugins/projectexplorer/projectexplorer.cpp | 9 +++------ src/plugins/qmakeprojectmanager/qmakenodes.cpp | 9 ++++++++- src/plugins/qmakeprojectmanager/qmakenodes.h | 1 + 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/plugins/projectexplorer/projectexplorer.cpp b/src/plugins/projectexplorer/projectexplorer.cpp index b514b3f2fbb..4b700e89a21 100644 --- a/src/plugins/projectexplorer/projectexplorer.cpp +++ b/src/plugins/projectexplorer/projectexplorer.cpp @@ -3406,15 +3406,12 @@ void ProjectExplorerPluginPrivate::removeProject() Node *node = ProjectTree::findCurrentNode(); if (!node) return; - ProjectNode *subProjectNode = node->managingProject(); - if (!subProjectNode) - return; - ProjectNode *projectNode = subProjectNode->managingProject(); + ProjectNode *projectNode = node->managingProject(); if (projectNode) { - Utils::RemoveFileDialog removeFileDialog(subProjectNode->filePath().toString(), ICore::mainWindow()); + Utils::RemoveFileDialog removeFileDialog(node->filePath().toString(), ICore::mainWindow()); removeFileDialog.setDeleteFileVisible(false); if (removeFileDialog.exec() == QDialog::Accepted) - projectNode->removeSubProject(subProjectNode->filePath().toString()); + projectNode->removeSubProject(node->filePath().toString()); } } diff --git a/src/plugins/qmakeprojectmanager/qmakenodes.cpp b/src/plugins/qmakeprojectmanager/qmakenodes.cpp index 7ae34f31b62..1fc048e3ced 100644 --- a/src/plugins/qmakeprojectmanager/qmakenodes.cpp +++ b/src/plugins/qmakeprojectmanager/qmakenodes.cpp @@ -132,7 +132,7 @@ bool QmakePriFileNode::supportsAction(ProjectAction action, const Node *node) co break; } case ProjectType::SubDirsTemplate: - if (action == AddSubProject || action == RemoveSubProject) + if (action == AddSubProject) return true; break; default: @@ -347,6 +347,13 @@ bool QmakeProFileNode::includedInExactParse() const return pro && pro->includedInExactParse(); } +bool QmakeProFileNode::supportsAction(ProjectAction action, const Node *node) const +{ + if (action == RemoveSubProject) + return parentProjectNode() && !parentProjectNode()->asContainerNode(); + return QmakePriFileNode::supportsAction(action, node); +} + FolderNode::AddNewInformation QmakeProFileNode::addNewInformation(const QStringList &files, Node *context) const { Q_UNUSED(files) diff --git a/src/plugins/qmakeprojectmanager/qmakenodes.h b/src/plugins/qmakeprojectmanager/qmakenodes.h index 0a70b7a8ea5..2f29eac5e40 100644 --- a/src/plugins/qmakeprojectmanager/qmakenodes.h +++ b/src/plugins/qmakeprojectmanager/qmakenodes.h @@ -90,6 +90,7 @@ public: bool isQtcRunnable() const; bool includedInExactParse() const; + bool supportsAction(ProjectExplorer::ProjectAction action, const Node *node) const override; bool showInSimpleTree() const override; QString buildKey() const override; From 296f7709bd2f829fdb17ca3e848b1725416a8986 Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar Date: Wed, 20 Feb 2019 12:28:52 +0100 Subject: [PATCH 13/59] LicenseTemplate: Fix %USER% on Windows Fixes: QTCREATORBUG-21871 Change-Id: Ibec147b32cc3bd1053e5df07b27838094dc02e88 Reviewed-by: Friedemann Kleint Reviewed-by: Orgad Shaneh --- src/plugins/cpptools/cppfilesettingspage.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/plugins/cpptools/cppfilesettingspage.cpp b/src/plugins/cpptools/cppfilesettingspage.cpp index 5ff64b165da..187f5d5913e 100644 --- a/src/plugins/cpptools/cppfilesettingspage.cpp +++ b/src/plugins/cpptools/cppfilesettingspage.cpp @@ -37,6 +37,7 @@ #include #include +#include #include #include @@ -173,7 +174,8 @@ static bool keyWordReplacement(const QString &keyWord, return true; } if (keyWord == QLatin1String("%USER%")) { - *value = QLatin1String("%{Env:USER}"); + *value = Utils::HostOsInfo::isWindowsHost() ? QLatin1String("%{Env:USERNAME}") + : QLatin1String("%{Env:USER}"); return true; } // Environment variables (for example '%$EMAIL%'). From 4401749e85afb3da0443439f4db1be5a4a3fab80 Mon Sep 17 00:00:00 2001 From: Leena Miettinen Date: Wed, 20 Feb 2019 15:20:23 +0100 Subject: [PATCH 14/59] Doc: Fix menu paths to the positioners and layouts Change-Id: I5a03596ef5cb07dc09144f19eb68b79445169081 Reviewed-by: Thomas Hartmann --- doc/src/qtquick/qtquick-components.qdoc | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/doc/src/qtquick/qtquick-components.qdoc b/doc/src/qtquick/qtquick-components.qdoc index aecac17aed4..3b2185e95e6 100644 --- a/doc/src/qtquick/qtquick-components.qdoc +++ b/doc/src/qtquick/qtquick-components.qdoc @@ -269,9 +269,9 @@ arranges its child items side by side, wrapping as necessary. \endlist - To lay out several items in a \uicontrol Column, \uicontrol Row, + To position several items in a \uicontrol Column, \uicontrol Row, \uicontrol Grid, or \uicontrol Flow, select the items on the canvas, and - then select \uicontrol Layout in the context menu. + then select \uicontrol Position in the context menu. \section2 Using Layouts @@ -284,8 +284,7 @@ \list \li \l{Layout} provides attached properties for items pushed onto a - \uicontrol {Column Layout}, \uicontrol {Row Layout}, or - \uicontrol {Grid Layout}. + column, row, or grid layout. \li \l{ColumnLayout}{Column Layout} provides a grid layout with only one column. \li \l{RowLayout}{Row Layout} provides a grid layout with only one row. @@ -295,8 +294,7 @@ one item is visible at a time. \endlist - To lay out several items in a \uicontrol {Column Layout}, - \uicontrol {Row Layout}, \uicontrol {Grid Layout}, or + To lay out several items in a column, row, grid, or \uicontrol {Stack Layout}, select the items in the \uicontrol {Form Editor}, and then select \uicontrol Layout in the context menu. From cb8367d1ba1261e5539028aeb71ae72d72b9fa29 Mon Sep 17 00:00:00 2001 From: Leena Miettinen Date: Wed, 20 Feb 2019 15:48:50 +0100 Subject: [PATCH 15/59] Doc: Fix the name of the "States" pane in the docs Change-Id: Icd6a2c9643392bdfff3a5ef0b22ba563b76bbac2 Reviewed-by: Thomas Hartmann --- doc/src/qtquick/qtquick-states.qdoc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/src/qtquick/qtquick-states.qdoc b/doc/src/qtquick/qtquick-states.qdoc index f476026d55b..c316df4575c 100644 --- a/doc/src/qtquick/qtquick-states.qdoc +++ b/doc/src/qtquick/qtquick-states.qdoc @@ -63,12 +63,12 @@ \li Show a different view or screen. \endlist - The \uicontrol State pane displays the different \l{State}{states} - of the component in the Design mode. The \uicontrol State pane is + The \uicontrol States pane displays the different \l{State}{states} + of the component in the Design mode. The \uicontrol States pane is collapsed by default to save space. Select \uicontrol Expand in the context menu to view the whole pane. - \image qmldesigner-transitions.png "State pane" + \image qmldesigner-transitions.png "States pane" To add states, click the \inlineimage plus.png button. Then modify the new state in the editor. For example, to change the @@ -81,7 +81,7 @@ \uicontrol {Set when Condition} in the menu and specify a \l [QtQuick]{State::when}{when} property for the state. - You can preview the states in the \uicontrol State pane and click them to + You can preview the states in the \uicontrol States pane and click them to switch between states on the canvas. \section1 Using States From e7a3628e564c44b3205e486707b07039c19edfd9 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Wed, 20 Feb 2019 15:17:37 +0100 Subject: [PATCH 16/59] PerfProfiler: Enable by default There is no reason to disable this anymore. Change-Id: I0b440a3e4df5780635361859bd82b14bca6f9c7a Reviewed-by: Eike Ziller --- src/plugins/perfprofiler/PerfProfiler.json.in | 1 - 1 file changed, 1 deletion(-) diff --git a/src/plugins/perfprofiler/PerfProfiler.json.in b/src/plugins/perfprofiler/PerfProfiler.json.in index 7a0d175bc12..af54edf5499 100644 --- a/src/plugins/perfprofiler/PerfProfiler.json.in +++ b/src/plugins/perfprofiler/PerfProfiler.json.in @@ -3,7 +3,6 @@ \"Version\" : \"$$QTCREATOR_VERSION\", \"CompatVersion\" : \"$$QTCREATOR_COMPAT_VERSION\", \"Revision\" : \"$$QTC_PLUGIN_REVISION\", - \"DisabledByDefault\" : true, \"Vendor\" : \"The Qt Company Ltd\", \"Copyright\" : \"(C) $$QTCREATOR_COPYRIGHT_YEAR The Qt Company Ltd\", \"License\" : [ \"Commercial Usage\", From d288aec3d932e2bec4f796a1517d05f4e86e8e68 Mon Sep 17 00:00:00 2001 From: Leena Miettinen Date: Wed, 20 Feb 2019 15:09:16 +0100 Subject: [PATCH 17/59] Doc: Describe caching autotest settings and clearing the cache Change-Id: Ie9e885e9c73a30575cbed9fe620da3ee2a2eb840 Reviewed-by: Christian Stenger --- doc/images/qtcreator-autotests-options.png | Bin 28078 -> 7194 bytes .../howto/creator-only/creator-autotest.qdoc | 9 ++++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/doc/images/qtcreator-autotests-options.png b/doc/images/qtcreator-autotests-options.png index 9e1879bb55eaae064026e0a635b0584bb2ac39a3..e880c8d61665db2a12d5f37f1bf305043793e237 100644 GIT binary patch literal 7194 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 literal 28078 zcmeAS@N?(olHy`uVBq!ia0y~yV0_HLz-Yn2#K6Gt{0&bt14C}9r;B4q#jQ7cODkj| z%l_}ZX>-ur|6AoG^`EKC+&6XJr)}EIY%O=b=jOB&PcdU-`5(eS7ZFd+-rQiJAP76 zj}r?j(~qA`JQ!}h>%orx4JlU5e#)_5mV#ZM6x99T)Gcl9ExXebUOs!4wm5z2-TkM2 zOXa=TnY4d)Uu%5tl?tZTuG?Cj+YC%iOFLKIS!(1Ft<2gfx;cVrria4i55{YM>MctX zn|96Y+O)J~%OZ7)H%w7-6F(sM!K>|tH5Y6D%(XQE2AfqP~lLW zYA1g`9yBM{=d5l{&Klh_XKj)`i}BAidF9!?DAeP_tYZnu?5Dd|$@xEeX=0;fDkP-z zwK72di(1Ah>2JaQ0p1IPPg*N0^6g@as#+QA@+PBg_w0?^*7O8Am`yvqe4R;^gv5(X z>CiO>;jfiqeYbwC4RUL%Vv^-8F)exI?WQKZC^fcwAJfW03meJ$8RARUX1t9Hob*0x zRjTCmEq1dM|7K5JvToyCW|^5y@w4BoJaKy0`r^m?^Jk>mXuX(sPc4Z*&Ar`S?Rj5E ziBMW{R!K@tUUKceh~L}Iolm)!ed{mqzrDSF+LeZCp)|cSKCWjku3xmpKuyU+ar4w8 zi}TO+@b;gTf531s<fFm_X;v+Y}|96rPcpdtc0A* z%$VB;g+DBcmC@TiZJJnH^xs$i*WGkq7Pj@vy9b%o-H)4dT1_PuS`d z1EZtPYNS;Jm)x*$$x=~qc@-S+*-ABdK=o8O-rsc~$$<@ViKSami#=ezg+_Ro(G+q_=lX3`|i3M1c& zGw;rSn($F0m8{_Y-~x07ym9AB4K{W5N+T50U{mC18U zEM_NHJic}}yZ+bOiTSBzQ+l&5sFc~?Kks!r;_s?cf8X7#-E?A|`i1`1Lsz9#W4|9O z-4t-ZJ|g48rVD0aldo}UNW5NG96TC#ZT)?fr?!AMI_e%cp-U6SbP{Cdwr_JMY`OjZ>Gd zE3aSwT1rYvEHJ=2ZuW}TA04i|DOuUSaogtUd#}kV|2{P3#d?n{uFnfJfBpS_M*7yTmZCTa0qN7-j7&d%{EZkoSyX>we6`kH&O z&)0Z^#!mW4i&)!Xm1Kje#=_;qXG^nV41 z?|A-S{Qt+y=zA+8OExBdU-Rrw7ktM`ZK z&a}6=F<-mLpqzKb(Ep;A5RT*56`84Fab!#1l;0;$ zN~f!_d0Rd=-apINHnQe@?aL>MJZrXHl3H7QePiv8V^4N@i_bf@NXX@I&U24m`)6-? zp0A3pdtP_z@v~*q{=J(w@#8&r!|zK?a*J+z)x4V#x;9{EiPE!07k8fDzVf=&q<3{` zR~;8TP`_RCB{jdwm2Gvl>$SIB{IjQi)nPtl<0Hzvt@Y3}iRhmVD-ulK9!cY=-WG81 zr`?2Gf!3Q8&OVg2+`Q=2v1e_w4j!ExJ4g8|V|(?C7608MyFaWtcJ0}(bDgc7^L`2W zC)-}$a3zJE`}~Ept`9SQ+{w^TG8MWs+du2%ndy(aSx$347M-@MOG`_O>()G5YnyZT zHmu(`XH(avV2{f;Ji?qjS2ygMJZr|KJ)Y{iS8r?I4-UNeLHC8++WwPkq#kjxTv_Sm zovUk`d%9sxPv5Rj3-0Kd1^i_F{maJQlrvmtO|iSH{^P)fTbFIgP2$eme)Yv)X|sF7l+N!}TA>f4Ov_e6D%@3=GP&>M;VjwL&0D17gKuW@Yqwsw!& ztQWHlcWm%g5!|sVJI$Hf`I|s5{fH`swQR_ja7u@8bL5&2?pW-Cf(w7w-Fn9aCDI`mDpl zp$=T$eHQw2v!m~Pr0b#k&&B2HJ%hRvToi&itNV>>L+t;4w2n%&Hqq*Wt z#r;(oQ(YA6Zrei%FyE%RIx^=lWC||z$sCQ?G(mT%yX7kP@UGiLHVPAN|!d)c( zYY_{VV&D`&^)kz=zw~-Nv80t=S`F-igjz+;Ld; z-J0`${^#}9$T#l%pX=xAzQoPRX-Qq>5;ITHn+5VQR7nj5+@qu{i$?AgwC^aU9;JLwPcP>7m_iM zF%#zGeAz1;bBmXkcYW7)XQOW#E>2EPPE}D3FT*>oc!0q9>NdfZ6DLfV0BVfEDHP6x zIM$%~Q$k(#_O*Oj>+#{IW<8&O%qGowovx;kr`H}xnZN3t)1!avro8h zlpK3_?boGKYV%rR=Sj_<6M3kx#oINE&2eRlOV*O<*?#M|&nxjrXag-c{2)az38xV=LYI zZpV`CeEj_V`fG$w-Z;E>>(QsOGHLl`Sv6I8laC31vfw%N?%SV3hwK{NZp6=Ec{CaB)X^4emw<=VtBuRQq|KKy%r9yDFOU`pf6cNOZ{%&oU? zEqt4-+NXA~+ z6DA6z2ui)oUXv$z_QB^@hws=Vy=s3YbjD{*X#R>N-`2~{-yHqA=Bcyx^rK~3D^1Tt z-@X+TcXd(WmiG^9Ek2g6(K&2HDW=R`SYsm>=kkmiCyrTRpWPE(IboZ#SeeDelUMFI zc)zX-3S727D#ki@-K%+BPhVWjn$#Oza<`zo_4?k~tFBM+S#_O1{qvh8>+TuwbAK}} z>GWN{zVmz8C*Re&9HG;LukBen-EhMx=Xmt7ny&Wrf!*e>Uk=_PX~UINYTRCx%z-*&(R#dEuOun;Xx(w=e9`;NEg=)44 zPy9ocJxOPu$N&9#+)eM>C;7iow@-S%z4V?byX;4RNv>A-JF_sON57f5&+D z`}gnX-!=#pTe|91v`&=YT>p=Smv?>Ly}GZHIkeEKXkYh{%694Lay^CLU)j7ndYwmo zc5RvSwR0ig&8I&(e0kEHxtm_gPiKu>addh(%a7kn?AMh{yqcxTVeb9r{SVP?%O&n_ z_HPc0t||HV;dT7&_R@n(!&AP#OFzc>+v1Yo)Dy1rUYp-ub}!R^%H(fxjqDq*GV0rk zu068FA<}a8k5?O4zMT2<=PL#M=LgEP%CFq_*e2fp$T#btTl5Y2`cK}Pl~?`m{au=v6J2>B_IZz> zq07(8g;mdw+f^Ew>_fB{JD7Vb>XZd%bXg0NU^<&ff7tA$&Gk@Z& zJAxm7OIt0yn|yh*aIm+vcJO0W!*9Ey?Czeu`AP4g^_}1#dA?az5mVRA*^}KJy6Nm2 z_PXWLCwCq(4R?`RQGK**>hhhE%kzxP7oC0jYI_T}>N}}S*V6C3PqsEyA5%Z3Hm%%T z-PlLe(Cj)-6JNRTO(_%5teyt9MNEH%X81)V6;5 zG_@r~Z2FE{vv*$=p7~erR8Z;d8%F7(u7@Y=*|Xxwq-jFo>dDikDn700-!|FsOE0g{ zuA;-%j~6bT=g%Y+=u%a=;F+KF`SYhsdzFJ$%m1i8>N4xzuE*9kVXHOti|v^OhgM7K`|PJVd& zctUhlp{|pn;qidT`_`5o?{CTe{_t&41^3h!sjnu@zqMTT^r4$Jr==CIzLq^%{(gn( zvuD4Krs?O%T(gS*w>IX2;^YUPj?3RITK}BmyS$Z_r1jCrm)bu}dU(|`X8aI4*z7cO z>caYz;K)gN{*9BwB}D`TLT=gbH?+HDy@hkb^Q7nUN7>j@ zMZcQ(>FRzd?LE6OaEja|Zza@%1q=n>xgghHmITCf{}->R{;N-OEiK9?IvZF379kR6cpuJMtYz z>t|b&ZRu4@RqZV_EZ$svVaF5kO;nZD-FD95&Sd)+?Xq{@es)T9rZ#TMq-OTsVgk!f}U-Mu(6SWV@eySDxsNnO`0>T=-)ran^oT?rX{DX6BgpZ)IjGbM0*Zn%ZjmR5Gyf;KQ9~ z+kF&wJ-Js9ByTUhrNnV*(ZP?G6Ia%+GqAKuoe;M!wzlfh-B}G9b?d1gG?uozdZ?J2HD2SB^vkoLu^u6zORN2|7=$vpd5@j}L}D)vjL2k#6!8=E^fZ(3Se9a2!-d&|ng z;>Nvu%K|jg+d4CRCZ4`~|Ni~EcU}KBf9c{*;8r)7=uvZT)4x9&wu})P4VhMR`IcL= zbH1D^&ezVo`q7&dG1YqsMh|7$_OB?O5Ld{U=BXkiAr?RD$_CXr-!HJ(*cVNl5SM#U zSwZ4Th0Q;kl?UH5UgLTtvm`veA(E}R@o3V1u9XjU*spWGa#?cyk<0R+l^s_+*1zZE z;p1`1QUMRhfI2A3&Ot^`uDYNxKy;b*orZV&bHgl$>rKO$E%*)G5 zOl16bsEFfU-M_w%bK_4eGD)ssF>!e%9MoK@ywUQ9M|||6OSQj$PvTs(!radNg1vwV z@AG@!N~Uizv$MIMy?-~KEAB9l;g6MOW@c*Y>hq0OSNaPX?#tjh`*CMW@1Et`g+I(= z)suNMeQ(!J8Md@?X7|*^o;Dpc3r9&Z-&zb*DQc8@Z{Kf`3pQ$L;^w)@2Sv~tg7=Lg<=ZhNf0Z<(onyDNTv zbj_zvIe#Z_7tg89GhGrs`HIqe_V+bf8T(R#-f!2wXjdU5{Ur6xyQPz76=zk0a(`-OAA_{uI?ym)J`iIV*Jj&lKW z?S4xQb~4$`c3WnYpn9ez|Lub+|5eKtWuLKYJ^Z*k!|%3aen$4q@Zsw}ylAqg z3)j?>%~Sgi-btUduvW~y#9K(lc%_O_E2I3u@+SrwDne6R{Vs-2y0RfAC%E`$OipUc z+CGn}pMR?h>Yo%%JAz?z2XqG!ysY(qFJ#LXX^idumAtq{=czKJMY0zT}4xc zZsXrCuBm=q#VmN%{B_gRtCPygZ~6B0d=<&_m|f}0KI86ARq<%sjYa`-BJ+h)zJBbl z`&)l(p5^UDMW>h^g}9~^<)l0JuHCb2*T1*cY$q>&UaKbm=ZAUy4%raHt(GB4YuB$` zloonxw{h5G^|c&Nmk4jZY%`^V=WAZ=GTEC>k2mfLcK*t{WohZ0tYgdNZ+Up;WMxR2 zM?FZW41d_RsIN76Mtk!Y-kCGnbYHAEBvH&NH=kMRIO$^DBtgf~5|18}Y2+v=E=|3l?S{1nl&Zq?y`oh*Ir~UTD^41%qtch$=;B!I#lQC$-6!7R8q&Tnu5aU`uy*g?7r?ya{JJAI_dMd&;Y?Xv+fHN z9u>1OlyQCSusdn`T!&ABGhX=H)GsQtP=C*IWR64Z{atS_FN^zqW1Dc$W6prmNmpW1 z7CoJG@y5;Tw<9Nt#Thu-eLwT*$eza=BZY2D@3RfRlev7~*~z8%Pc-bG?)z%#Qq>Q> zr%#>I($+rAcj(Ze0}IN^%G$~v?EKVo<--4J-p1)6chWN#&1c#lkywAddc*!7zkClb z>$GdXEg$)$&+qz=+t$CPr5@Azb^W_o|!_4(Jr ze|i17QPemyG2xoZY^%2`bQWj7UsC_MHg)onFA1NepGmriEx+Xbv+L{Py)XAzPtRF+ zOeT4&uHB87zw+&jI?nZ%273rkjtVi}rTpib?bl@o?Ka&lVLF6rFr;tDD#czUQ;pqop?;TD1B)|MgXqoE8^Z z@wxhE9qRqpb)uu=%q}|~QTuNdJjWkDzRvdQ*tH)u-+n##!8h0Uo{SeaH)pTU>$^+1 ze{Q+jx$D-aOOq}gmz=n5qpiz1xAHWHB zJL0zR;o7gPojvJDBdGxwv=S_g2J6Qo}S!z(v|03M&XXt8*S80 zY_=6L^84@iQG3lR{6IwJsDA&I?(Xgn7vJ9A&UishP0jxAOaJ;GhvnbBed}m#u&L55 z>jrbJ#?w#Bm*uit^xt;>Ye2YSTH-dJgF0oicZw~4IK{MN$5r8HZ{CE@o4i8sno&Sf zs$A#^Ve8Eg`M2rcymWV)j`iUvdtvP(%V&9~`>wY!GVWe)D_1C9X zsM%lh(@&N#)9g3BdUl>rQk3ozX0|Z)nzf~O4k@om4Vkm3Na_5xB`yP)Skx6TYYE3rJeE<=gyA5VYJQgYUm8n*H028uWwNJ zxI}qx){-_4O{wOi%kPtc$ox|VPJ^xhnuJ-Ktycae)?_*d{#{Rvi8ZktykyG5)hAG?;y{t+RZN6UsF1_YQ-6=^0oa} znfWZeADTI)>ZUrD&H5I%G4NfOTb$zM=ypT5{kzt^kN&qqRr{Fb!Y!6(ZXPmRmNNNJ zqVdc1TNl_XPGN9Q+a#{#`-iFeTVLyrnGxo>y0N?8$woD=|D~Gw^~a{RdY;B1f zH(q-tC0JUk{4?r=hv)9+tZy0url$d0V^O+5H++5SW(o2Gt_ zH7(Ph|84L+u!+sB-d{(;V9FiG^OL2H{b{*#S3=v>_4Z^Po@u*#+QrgYCl2Z!DLMM$rj+P1n+w4`w?*ZS zWz@~F*%zC*c;)+P*0%SbFIk*1^^(>7`!b-)+ch1o9xKevy?W2hc2{}*a+8o??d%omfq}PH z6s6VeSh6Z-!!CvG>-28D`PJTbvRAZ!b$0BO_1ee9m(5-H_*v}&=g{puxquLeH59@VLPe9><{rkATdvb5%Us-JO{ zTG1}L{mZu=S;1?@e`Wq`KIYQ=!27P zq<`?Rsoj3tqwen>8t5d1vETW#e7+}Z*tt%*|B?j{wp@?;pt5)0zB-o$^6yQgBdhJ= zSRPB+Ti+0RzGj-mp8GOMZ)aZRPm4ZQyMGej#PiQ9_MSPUxXVJ-NX156S>)W*BW*6v z&z>o*l)6#UIY)K3V4c~%($`Lmv%jTrM(`|u;jLTj=>UBmZ^tD^I<$ zD~Fx#n{6m?k4f#^b7x+7l)R~Zv{2ic?p~HBBhQ;U`{ir*5dBHvv*(;G{rct0 zWUcmJR$iB^rzu`ZTB2#awfOH0gUPay8%up&p6A(YaH0IW&&u3)*&4ntVwTBwJ3DiH z=AF4zRN_ovWoFoIEkXNxQ)XWD73cW9d5){DlxvyKSKES%#%88xU&Y7do!@@R*rfEU ztd-TWb0HDZQI?i>>Mz{rI-Imh`0W~>ssBFM&lg!Q$9*z6@!GMfs$KhL_CEH#xr@zB z?O9=R#IMX0j!W9^SzNu22YuXUM_$J$tj(*elPyZ@z5-n1{>GUknuj3NC{7S2P=VMc4KS!8wwf>6o zc6!yUe8=#+!u5N1ES5AWEj#!`dHRxrZ;vS~pD{^s-Gmtr)5N2-b_qUW7w)+$XZEbk z`qz;I{ASZ0B|e{QZhrq&TFOQ4=u2v~GQ5ke`&w++zMd62Ahl>_yxdB~Bq^z>N4E3w z@-}wA(s?A?_iX0QNzWfIaJlw$BV zI+hW0$!E>lNn4ucZJV?xH0I#FgMMw(YraW1d)z+Py{-O+QLubUp}l!eUUnb z@aWYmEsLX#Clc%q?=7jUto#+SLB=L5zlOoaU*u`~Z26b3U(4THRv<7j-aSaTQ-y2h z2IgZ5^Hg?qX|(KpyLN7^%+zBFZ`bpdZ7cugv*ulXLcxx=Pjz)>IvshVlmB+I=9R^B zr>?ElnS9tTX4b2W?A*5!F*lVjtlY8n?bleHUdIDDx$9+wGD_6AZ@tXU&wVR(>wwYC zl1JyBeUj^QQWgHb{ra{-9=X)?ij0cK9ZriU#b+}nHE;@~Di}#e#=JThlwKX39UcAu zi&(Fx?VVdUEDuc32oamU&(xAd_L}8JzK>gZ#7fHxH!WUUTaff`g2N4&Y#x)%XWz@c zc`JA0(B>Ng0^W6(S(Z!AnV^4u8Cz}LiF3CPwi*AHJA1n7uLp0Xy@EgM2T8X|g{b*1 zZ5~x!C;B~_9V&!$M4x9iEVP@rlbbL1qL$KevtFHFQ#9jxd340qA6w*n!1l-`;~9&V zX@q>_&T!k(x`%!`Y?R}};lRs>`ifbwch`g{?sZ_&X=Le zrb|qkGgMcIRCRpW%39NSJiDNw=IKA1LkZiaFSnAuE%trm4D;{ijsF@Ce4ajKAt&d{ zQgzcCg|)S{bLY;T@IN6TA>qT(rmIyG{>`bXu3l)od-v{#reAJ6|Dyio+fm<=^6%gH z`+9o6eeZ~_EWUd2qM?n=pGlkMDJkx~wq)9qOOv0NHE*nth`d=7W#FM#$(YME;oqEd zmlO_jzc75U_xWxS7H(CQs@c|D=R7^-+(E+>uk>BAPHHe)@Fu1)@N}%5!!_@b;(Y;| zrA|G*f<( z-Q5S5ayUB}$bSEsotwI6_u92HotoN+Qqx(m+oJ_c5UYlcd)P}uW$u1*lQc3` zuC{!>&8Xqd@5jlXy+i)IVHOvDyIcP6^=k88-<(gouIuj$`nh9bW2VgK-mTgP3)-S( zmA+~_X8p^Id&b?msZ)9HJ~Pu8E&G2T`~N?U|HnFmiGS7k8&{&=TJGAEx0n5qX26xm z{NmaybEZN1v!gD`t z;uNaWH$ULw8GBTF?K0E*f5q*8-z~L$zEIgE%jH%6qCHNEuI-q#nrj8~I`;PpO5RPQZ-2rccyD{?739XLXHwC3 z`_Y+6xA|L--+n21G`V_?LCus_`{K{86RKs#xB*|_>y(%*1OELE>g*9 z3pQ8(%P3!Lz1_h2p#6%Hl4ymKm-U^*leefHzJJ|(Z%vbS%C{vgzgboK@;{D6p{+d`b?_wQJ3Jh%Lf+177s z-@oJUy}nFMZTgk3e5TLX*w|E`l*q{HR-gL+Wzw9`!jq4?)-~$3P1tHZ=f!*RsrQ)0 zWz)88Tx6ns$9~0{`l;Fi^7h?U*CMUYn)4ugq5N_TBg#9sQGB+#IW9?zPX?xDDV zOz7?XC!gksA7}Z=s`72!1OKkyNaC!AGr>)plU7h`0&W&w5cmCA>_eg(T%uXh8 zHi17iXT@uxkIY{(=h%^}J2y-|I<4s7Ji+j;K z%k-3Xts0&6b0bYV#0}##BG&EtyWBqOx9HULiWd>l>*R$d#q{bHyG09|)ED11x)}Yt zR`Y(QmA}S6t=-I;Qst>Oi{!$#>VKP7k(GU;)k;FU+V#t}<(hxar{3O>FjYHfeBoD^LHbd;i9#t9{el^f@2*de6GaZTxbT)Wpz3d;M5_kH0!tCw|p?eg?bQ z_p|!n!dib<$Nc}IJpa=)mc{m7(yZp(ch=-*~br@5rq`i)a6O$Nai|Z>r(Gb*tq6d*&yU9(s65 z{%Ovm=+p8sJF5=gx$XS;+T9O#=B;8$zxv|dGnSR#pPW&SG1bfbnJ<%<#(rC3*RNfx zPG;SDHZAQ%{QmT*4}^owHXX3?73%i*E9#-U@soqW4yI!d&he#Oi=J;Sx`x^KwcYbo zvom$hoyfMTSbg&InuI2$FSqZwGUeIG3wL__)twY&)c-o&{`XD(x)01Z{=B=pJ0ZZ_ z%*@Gp!{*PWBK@0Vv zZhtg$((@}p>CwA4n0?F++O#Vw!}N!S+E?E-hc7F=4P{o?vh~jIw)o3l`8{bKU)u^+ z2VT9p`AJ~c;#K$e1>E>_;n0$VI=$-`Y*q$#NSbW;kSp<~bo>(F&b<^sYX*WdH z%v-Fj!b4;24 zhQ;{~o`tLSCnnWAqQ=+4{=LkAL6)|IhyKWqZbDqN1Xz z+fRMIy7RzS?Hlhy{=e~ac;0v7OP|Ta%{q!}M7*Wl)&);r6q0-SSNV18CfPYPr#C+e zZJzy0Zl+}W)1q@8djk~n6R(#lr0}bsoEf?9O|r7?lR4bSW^c;b66C&M%A${^)BT!S zu56L=R}Q_Lv+?K5Z%WiO+cAb-Z z`gG+qu5Fur5`#DG^gMVdWY@Bw5ZUszVSYDP29kbHG5{o)9}<8uU3~NwhFK8OK83R{8i-A5{~ayQ%dJ%hpBv>!P=hOpL_r3 z*2KKxdjDVQ_B*HDv$-?>>FQ;ZH~PzNnmAcYR_5E@?C?E4?S~F z(OG`)kA2rnOlPlAd|0-4l4n71dh5=K#~#PN3#wbv>U-_WFGlA3`Tv*yH|>0pu&{_V zzW>Sw&KZrjpKno~_QW*CrejaM*M;Qtz2AFWLJN=D3n+a({W;j%=~Yi}FXQF<&*t@) z@87RCk}2!E@lKnI)=UURVET;>7ZMeBmyCA1{?MjecIXLfu)a{K5{k>fhgZGp{yu&Aeu#ez-^Q zVc_hgThjR_NXlW_zgcP}n*RUf(pHmlRY}q2+4WWK_UVm#CKUgE?B5fbU$@}NO1`0X2u>w0xosWRVhG<&|H?)KWE=FPu zWv*A_751}I$Lg3(YO)PNUaZwR&0*v#_u|B*;xn>B?@U(DWZ_BteyT|)RpiQ3z4|2& z!{X+>U9)g$mHW9Z84ANo8Ha{TajlXBOj zJ@Tv1bN-TSi}26VRSeocN5l5yH-i(eA3ju+^swm;s?hTCH@T*MV6F3?uRo03p0GSL zJi#uZ)O}b*F3~gK$_%#y4?l<)eH8E){V-#8_h#en+a`s-vh_l`4?J4o)1hFwOfKiF zpKsn9Va^b?-X2?}iwmD|J!5cxTu`|@Q0&U$-jg3UwwCssu-|88ZMfB`HAzQ?>l?%Q zCq*ZJFf;XfD$6`N$rE_mf@%8M8LzeaI6nqX_^Go^_)&U4|Frby;?v3vCj62)H8-)t zgpb89c*E^r;mgtiDt)Ic(7Q;s=;!Rp~Meo9oDe4V1C02t9IVG zjtT)9DmHB%%P012NU`c?l^2}B^zB+kaMF_fZEM!Jp0jA*W^Qa}xOp4@+l8KP_e0(s zpSfV-pFcGxy8k!rk$=s5TRf03Qr)V z|Bl#mvFUnj6Wvg7_U1o<*`gD!dWxPsZMnOK{q{5K^S-X{R{}l5MCa|${PFw|-%;tgN7i+GQ?s%uiKTsQ4)ZVpfRsODX;jJ&KXyF{!ZQaQ1aPpv8C-Ee>ZvZ23n-QvpHG(sIpP@ z(=3Uq^??zec21UVt*YTR`zpC+p~3O`f6wa=nYea@Hcb96IlF4Hski&RWC3Nv2JyeT zJgdYzwV!?yySH$+NL2ck=?iQ7jtF|s*577SJXftVf7_yCtTq)+*5%$7&jL0|@Ju`v zw|?*Yxl_CaZ5Im8e01LWPg2q8Fcmc`x#oit{cE08y%s@Arj9kAG}c zGVNL}w(k#*@BGQS(y19vRlOd(DU4RHU%Y5(Z9TZHuC6X2pxNKQ;@}zaveHT2ncpTi zyzbP=-aSJm@LvD_-xqWZPG0+6ckakd4i(+Y&ZdPas}32i%av5Ck$oC*l=snhtH(i~ zw8dv0IUAA9d$am`j8U8TtUrrBWrr=F-78{J#>z_!w=e!kO8%zx^niXcv zRTX@;`E2Nv5Rtd5-PJDT=KpyX{(rSZr0-+pAmyONYnFTDGp=s}2luS3jXxbycIokK&Kg~*?KYiW($>*-zyyEOuIw`p1enQ{0 z{I@zi2Jh9iewQU|llr4CXtLb?+sw-!mio0&4y~5{mSgFtSh|kt@e>&Q6Mz2pvFj6uFt>EAO^zVulD}Jor z|4ZBR9{+=_PZm|#y+5AeIAdGv!%Qj0yx5MvhwJXdc?Tp^3GO*xR{rJOOpD&IXwQPe zT&o!0>tAxBm@kXZU-9sMcP0mS)Y8H(|f`=k5RR+?OW>|DF-{SZ-FZ z@y-jA*VP`?S-oY?s%>c*h5Z#fZU#+yu_QUvrgDdUh?v|I$Ev%3u5?_1tSvGBcKGN~ z)@ST{e!ttDZn*#a^S=+?^Hsk-X?5(`)vH%kcdv>w?PC$1bx%GsB{k4;SLe%<7sA8) zHCy(-UOE7*DL zsIA5a$BG4=&zm_pl0}V9=j;*syu2Wr*RRS=vQ&W4dYkW)OMK6F&DO3hS<0kcZKgIW zmWRivEqo`FOBM(&+1_v^z0&@HRbx-pbK%;UIp3QtX1~bKW!-e;;??cEeN|gr@6oYo<0&xf`b+Atdm@;MYgR_DxrASsL)!@kGULl3pVg zXI8u6(j~)v3Qq#PlK*Vpy)A*CyZ`ntcm4-QqoVh1USZh(>EhzveIe}G(d{4pm=;uh z-ng{T@0zFYm+*X#kDnKR3Ao1(9*bIU^x1V%57R%UB!wc*WjP*3Aq@$#9QJ?btj=4w zS8M-{w=a@DO}Ncfl)dX&M80IFf)-B~$N4xFPy5Atp&;P`_3^WF!Y zbW#vh`g(fyPbOPCOH0dAzXx?q>25!`Pe0W8@0XyvFLLpjUmaKC5B+9b?Rby>1TW`K zyK8=|!MWd$G=2WL=;jlT`ZO28U%bBx-dZ|>T%|wt$_8}~i=(!>J3Jm7V(^zg@atqw z(aC4+el?wbQ)4M|FMN;R&KbQouil-!ut$GWZ_4uH@zt_R%$2`A_9-w*PfPPk zyB+88>g~sKSpm7PFTJ~XDImKv*SXreIM%oH`wyw#Yt>Cp{r<>RY5!mzXZ?K3oxZ-l zuV24@D8=yj*O6syS57|JdhF0OQzPMN1|Pi7in?|$Vqs58pQ>@Wjpf|&9Y-5ib$z^h zcjBdUg<|m)QBu>(Yjh$f9=G;9r6}MVY+uV;Y5X9-|56&q&(M2Da+$uHYnfvYM>7?! z>leP|^{q(9^GKDBl}VwS;HPsT-j(`scP@4Q_EGrfQ=sE_MKP*o-jC8 zDSQ6y`D|il7B=ZSv){kxpXvBv`W_Q}T5c)Z4T%$fp76`BmX30NUK$%y z^m@h>dn1efT5XQjMPK4{gARZCyqlk&zkTxUt5-$+{u&24mnr>wmpu3T+1KTYs~a0U z@4U#Z+vC^bQ&#fk;WxX9Cl@~6UdHz#hp{qy*XrD|EqC6^%J#4HwTYf&-g0=6qu=hs zdzC%f4=i*LTOrF6IOSu<`8)S--myF2tY&A`%cYtT$-~xtdL4HN-ziORL*wgP&)-xt z?DIF!eX?28IyzcHiof9Wf*?ts6UFCR9?xIR9s29Smdxn~T6*eK9{sy_O|g@C=erCM zsmZ*n4HTySDG6QhNcHr!S|#@@Q#;!86;`SSR;Bkp`LN-~`=rL)A2s*-?{17rzq+9A zjAwyNtJ*wkzxP+U&)yK4t(SA@;=6Zty_)L+4=j~=^G@!8rq7!NoxQFJSB2(Q_jvSr z{0;KtO*fk&-QL2vLDxq85KGLAer~poC&w$CUi}s8mi9aQdy&)jD{t3n@K2vNlT*Hu z*Z1x0_ot=Vf9<}rxA3&(%DlQAW_L^t@5O)p|M!oq>G2PiiyU$;_*u-(jGcJBM?*Sm zeXrTYi+h)61)FX%o%g!TH|%fUuJGLI#E#WxFHGE^eERCXk`3y9*KM^9K0Ic<|Hs|b z&sX?P%ws=h(!THGiQ5mlru6hUKeBte;lee$wJ!yXr#+Q=BL05ir|$ayTc^b4++D0P zSNhYbs!Qcxl*>&r6`=%d!blCzwjY zf`hqvcv^Dz?%jLv*@urG1?}uVyB^5$_+FwX^wiHP=FRF=`Ezdzo)^B8dEtZS9OZ(7 z_F&JrzGcg9@fmKduDFw2ukET^+I(Wt!c`yQ|9-pv{@#YXn+Xa*%0c^Wg1oiPIX*lx z+dSXtbwSkOle{Z)Tl~X?D%!40*;?}{o>H`$HJce<==Ye@S1gdlO?YCt0b7U z8_Rq#*~Q<|+qrDl&DgtvQHnpe9*wKZdzc$D(Un=fC1I;!Q0%GNna8}!r3!SLFStJCu?-H?raUKiTC>TPiX42torAP!QK=0_&#K++jr>XJ^O|0_udJ# zEC_6ACb{p=R zmzNhqhN!4$MaZ9*{`Fd&`zxnisXjZ+{QdX9qt2bbb>F$&Ds`@1XJi+!Y3Y??M$1x| z?Sm8EriIR$oS8n!`huwH+nEQ2b}x2aa_pPrObgNVToIEqi?-YGo?Mriks}isGgD4( zUCo2^WpAP)roYQsW$z`pO=XtUv$Af_*x(269!uIQ*eIITKMU-bmd0jt)67Ns^|PtW zDC0-rs5dO`l@x^gG))6JqXTIMrXU)3x7=ebwcwNFcM zcYMhNp_iqyfh~-O_Wygmf7+A39sT{&V?xBA{H+jKm>TRbagX&1zZ3d*r%td^c$-je zddK&=g2L`)+x9KZ{nFraGvbXeciF|llM5e;)hIi2iBFg>HSyQd>otO1>dJqgneU%C z=Z>eRr#iEq|Kwjk76d;29+bE8=hLT8znW@Zdvz+bHg=l)?QaET#a~SRZW1$0mi%?? z*H2B)wk*xZlQrj`%zAp|TjI>5^@_`aLyu~t&QUtRck8sLrOleGbNZ_@w7a}du0H#9 z|JQkCX{9SCUo+i(f+u+A_s~nbZ#Adb8okbTvJstfXZ5k|KOPmjy~)|Qb&Hon)wYe( zyzbqInfp1`wY$T^`=-C?ovK}{&)QGz&6kp_5m{AmSZ%S5&&#%~(^s4pZR=_D-?IGL z@1io#$<6(}`lns5_dk$WvE_}l+;7I2eu|!#+2v~r#C8=p-s3-%G-q;WXa?7u^R0>J z7Pg*U^fx#B^o}Ds!kugRZFuHBntl6rwOV+F%&nsQ>da~D+k75e`jk^Lp|>*OrBr7( zs7RANQs*GLX#W2{&jV)vd9%GS`vK=l#Y;{5;zZtN=cjW!KfU-E?Mw z9+R(%&J~t;b+4k-`RkPz9;GiiTDJ#FJa{5BXOoYRJWJ`~J!{HRX7jvDyA!f>{^GT3 z*Ot59&q?>(F?VnBiN$&+&e+|al9XR=Z>77sD6M?&>%h}b`11DJ-?@43^+knteJy_G zw7*{I`{u6A4Y;ZzBbU4N>h+sE6i!nyalYo;;_XK9eJLYT%#a($FxI~?ud{!}+XJjhw* zt>ZgR=i842T|X6h-af$S{pH3C@#nnr@AzxnRe2M}cCWmo?Ckp}(Vd&ByJ}^atIO{H z+4)rC{c&xVtd1FN0l_~wqS`zEu(Pvon4l{5$0MO|{_4dQ2YW-mJU0oNS)OMwr#`D- zj>`?tSGk?{V=P#|zMLPksq4WS+jqt82W;b?y8fB!e{St17VFza?_OFx|6VF4)UfEw zJ&&Mf72|E^KGikc{-xv3x`vs*&uNLi@(bq|+r^*$ZMf%FX&?7Z#`WY+UC$$SwX5D2 z^gRj}>-JN1Dvfs8y}jqkq-=*z-<%FUOW$6+L|?;m`~DT)fm&0i&;8!~J!x-QrM-)v z5M$Td3UAL|(4iGloSYL8c%sxqDNZPXO@i~~S5?y^4>{v>LgsRVG`_S}Gu^@=Eb={G zhpY8awQ7;2ci*GgmQyA#+vk>SGvz+mykAQvO8KPC(B~@_OiX%l)8^vOpOv29JS;e7 z82>8KO8?mNv3pr^_obqm))Xn5iLUy3UyJ@&&hB3C^zqEq_4dLsG5=kQV(U%sc&VN3 zezuIePjG|a%83Fi&U~7l6%DmQUW|# zv>u<1n=B(X*Qcq;FvjX*#`BJni5Gb^p8HH$woKLZT9|t4RUhwt=fan4ad3!#-}6c9 z?c4MHUY@rXaqUydsoZezT0-R-|AS()J(mScd@K(No?odGq#}4S?DqdYckbN&pR@ND zmX)=AJ-E+K*;KwK?O5ENTh-TNH}(4o8#vB%I@#SPV?O!LN8{qqoU$T)jToH@t*t_} zn=Nk~%xY6s@w;ZXLMnCs?mOp});-+bW@!EGls&CC5?-nE2>{C;)IQcpnDbMd?-`WEGTKhIyiuO#SM`AWS*PvVZ;$XMBTUHRDM z-HsDnm$*4CsgqpNrW){vbyJA*rMQJV{(O*J`S9(wOy zZP%<<)w`QY?0&s`T3sm0%yOzsO~v%&>{Py} z{j9KfnwC-_#iAl=x+U-Of{rsjVX1Gm`jmgR1#g|`$5-~xGIv5}(OzwSqs_mLP5t(@ z+>VR?Yp3R&B|_H5O*y%DwV!Joe;u0EwbAseVp^V@w@P9D#+j4Xo-};e_>ncX;?K3k z0ykDye>U>=h&snnylMN_wX8zKDN)`yW%C@p@%er)z=kKIHXX^gk_Sb#vef^pH zq8gdEGK;IObxc~c*8|+Gxo@!YptJAdi%CgILc+p{w^yywIi>Klm}eUtwl_@AQjj@>g=RSIcMJ*(WsTW~5|x?cvpB z)heIo?MbUij6DBEtT5k9+3L=RZ~yQ1p3Cy(_)vE4w8!U79-jRM8}#Se#pG8cyc64e zPN25{UgWz@apYnU$@Bj!prAcoDOpT-x?gfzp^sDU8<($ z_TGf#9S1JmEaUao=PWNfG5dvP;Z?uc0$kH=?JloqusQJhXwb8VPg&!xwMMPK4?S!+m*aqP3NU>hI{{+a`=>%@|3%m*i_E7&%Ea1 zZ7G}k^1I!a${Rw@pTC_necGFpe;H-lubtOaQM5c|zp=>mQ)(r9t)JU6J^oM9?9YA~ zJAL_Te8lo$>)VB8+um*cu;|38L$<7|8sAu3O0n7ae7xdY)pf-uX3^!Z3({n!qwUysxiVq&V zKl?>W)}#05doT~Nv znXDyyxWB%<@ypwJQ=fKfEn`#G-aTosEG zq0$*op6se{%F1cFJhh?Cc7=%Kf}iuUUrOmH>+tvL=|9}2b~k1HY4;_^UTGdR%kh13 zLnDf1OW0D&EVu7lm)4scYg6W17U>k_D=P*mD+bkPU)?DqE6aG< z{>MT7W5DnY|qm5gp zWYz!u75jXL2mj$8eo}eI+&{n4tz^Bw=GV8J_u4_PtWIt6@^qc6`7p6gweqH2S>VH{GnJ=dM>NAbJC(!d#02+$K`?vgQX;^T;N+Z+jZuaMk z6ZTdHnDnf%2W_6zb6yBA0x6$z6({&(LWXbZj_rGU zm5pEMoHOk2y?_7a;Ykl8JgTE_v#V4bOud|GVm15l!pj;PG-rD*zYsCug?#mf-P`+B z4Hazq&o6mYzU>=_z$dr#Cd0E!A8j)?=PwXhai6JI{-KA+4!4&kR=jyK7sTdoz5O~R z<@$!hB2#syf8n0)d*lASJNH^O94}sf9#FpBy!=~X$PcfQ8?7tc#G6aD?A`0$dcIOe ztMy#UrIjX9zn7Ttv^zGt<`fEaG&J38wX$eev6}66tGSG?P{2X=fgxXcIllpm)a-*v zMj0V&HHlJb`PK5?YLB*U-}a4DCSqqBy!cdCBk-{MH}xlr`hSI!j(1`89%uEXL%IrGP|&H zd1BS0{v(1Vi{2}9=02Nma&mf&f{1^n_|@B@@A>Z;o3$0aZtJ-7SugQl=0n$cPb~ar z3A~+CU-jmZ>^zy46)Qg%N;Wb+N~TJtm!hBiosg1Ywa-JtS@_cb`}b-q zTxY(ol)Jw_rL64xoST-$<=^iVr{~|dzI*xMwr!G2dnKZx14NGAXftC@I?$mqaZYgn z<4Mcoi!`{p=B#cwWf}fCEWjm_0k4cotk?*jD-_xlC{G z≪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 I&MBb@06V^A#{d8T diff --git a/doc/src/howto/creator-only/creator-autotest.qdoc b/doc/src/howto/creator-only/creator-autotest.qdoc index b9971d2ac0e..80a8f91f6b5 100644 --- a/doc/src/howto/creator-only/creator-autotest.qdoc +++ b/doc/src/howto/creator-only/creator-autotest.qdoc @@ -242,9 +242,16 @@ You can add filters to specify the directories within the current project to scan for tests. Select the \uicontrol {Global Filters} check box, and - the select \uicontrol Add to specify paths to the directories to scan for + then select \uicontrol Add to specify paths to the directories to scan for tests. Wildcards are not supported in the filter expressions. + In some special setups, \QC cannot deduce which executable or run + configuration it should use. If \QC repeatedly asks you to select the + tests to run when trying to execute tests, you can enable it to cache + your choices and use them were appropriate. The cached information is + cleared when you switch to another project, close the current one, or + select \uicontrol {Reset Cached Choices}. + To show or hide init and cleanup or data functions in the \uicontrol Tests view, select \inlineimage filtericon.png (\uicontrol {Filter Test Tree}), and then select \uicontrol {Show Init and From 61775a844efc86a37aa8c11ffdefa23b1771cf10 Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar Date: Thu, 14 Feb 2019 15:56:35 +0100 Subject: [PATCH 18/59] Clang: Build clangformat only if clang/Format/Format.h exists ...in the LLVM_INSTALL_DIR. Change-Id: I974f32759bca7fb467524bf61ff7967098748f0e Reviewed-by: Ivan Donchevskii --- qbs/modules/libclang/functions.js | 4 +++ src/plugins/clangformat/clangformat.qbs | 1 + src/shared/clang/clang_installation.pri | 42 +++++++++++----------- tests/unit/unittest/creator_dependency.pri | 2 +- 4 files changed, 28 insertions(+), 21 deletions(-) diff --git a/qbs/modules/libclang/functions.js b/qbs/modules/libclang/functions.js index 4d384d773e4..3a75fe1ead9 100644 --- a/qbs/modules/libclang/functions.js +++ b/qbs/modules/libclang/functions.js @@ -103,6 +103,10 @@ function extraLibraries(llvmConfig, targetOS) function formattingLibs(llvmConfig, qtcFunctions, targetOS) { + var llvmIncludeDir = includeDir(llvmConfig); + if (!File.exists(llvmIncludeDir.concat("/clang/Format/Format.h"))) + return []; + var clangVersion = version(llvmConfig) var libs = [] if (qtcFunctions.versionIsAtLeast(clangVersion, MinimumLLVMVersion)) { diff --git a/src/plugins/clangformat/clangformat.qbs b/src/plugins/clangformat/clangformat.qbs index c7b9182373a..3e40832c577 100644 --- a/src/plugins/clangformat/clangformat.qbs +++ b/src/plugins/clangformat/clangformat.qbs @@ -15,6 +15,7 @@ QtcPlugin { Depends { name: "Qt.widgets" } condition: libclang.present + && libclang.llvmFormattingLibs.length && (!qbs.targetOS.contains("windows") || libclang.llvmBuildModeMatches) cpp.cxxFlags: { diff --git a/src/shared/clang/clang_installation.pri b/src/shared/clang/clang_installation.pri index 4629aedaab4..6c820dc36d9 100644 --- a/src/shared/clang/clang_installation.pri +++ b/src/shared/clang/clang_installation.pri @@ -150,25 +150,6 @@ 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 - ALL_CLANG_LIBS=-lclangFormat -lclangToolingInclusions -lclangTooling -lclangToolingCore \ - -lclangRewrite -lclangIndex -lclangFrontend -lclangParse -lclangSerialization \ - -lclangSema -lclangEdit -lclangAnalysis -lclangDriver -lclangDynamicASTMatchers \ - -lclangASTMatchers -lclangAST -lclangLex -lclangBasic - } else:versionIsAtLeast($$LLVM_VERSION, 6, 0, 0): { - CLANGFORMAT_LIBS=-lclangFormat -lclangToolingCore -lclangRewrite -lclangLex -lclangBasic - ALL_CLANG_LIBS=-lclangFormat -lclangTooling -lclangToolingCore \ - -lclangRewrite -lclangIndex -lclangFrontend -lclangParse -lclangSerialization \ - -lclangSema -lclangEdit -lclangAnalysis -lclangDriver -lclangDynamicASTMatchers \ - -lclangASTMatchers -lclangAST -lclangLex -lclangBasic - } - - win32:CLANGFORMAT_LIBS += -lversion - win32:ALL_CLANG_LIBS += -lversion -} - isEmpty(LLVM_VERSION) { $$llvmWarningOrError(\ "Cannot determine clang version. Set LLVM_INSTALL_DIR to build the Clang Code Model",\ @@ -204,6 +185,25 @@ isEmpty(LLVM_VERSION) { LLVM_STATIC_LIBS = $$split(LLVM_STATIC_LIBS_STRING, " ") + CLANGFORMAT_MAIN_HEADER = $$LLVM_INCLUDEPATH/clang/Format/Format.h + exists($$CLANGFORMAT_MAIN_HEADER) { + versionIsAtLeast($$LLVM_VERSION, 7, 0, 0): { + CLANGFORMAT_LIBS=-lclangFormat -lclangToolingInclusions -lclangToolingCore -lclangRewrite -lclangLex -lclangBasic + ALL_CLANG_LIBS=-lclangFormat -lclangToolingInclusions -lclangTooling -lclangToolingCore \ + -lclangRewrite -lclangIndex -lclangFrontend -lclangParse -lclangSerialization \ + -lclangSema -lclangEdit -lclangAnalysis -lclangDriver -lclangDynamicASTMatchers \ + -lclangASTMatchers -lclangAST -lclangLex -lclangBasic + } else:versionIsAtLeast($$LLVM_VERSION, 6, 0, 0): { + CLANGFORMAT_LIBS=-lclangFormat -lclangToolingCore -lclangRewrite -lclangLex -lclangBasic + ALL_CLANG_LIBS=-lclangFormat -lclangTooling -lclangToolingCore \ + -lclangRewrite -lclangIndex -lclangFrontend -lclangParse -lclangSerialization \ + -lclangSema -lclangEdit -lclangAnalysis -lclangDriver -lclangDynamicASTMatchers \ + -lclangASTMatchers -lclangAST -lclangLex -lclangBasic + } + win32:CLANGFORMAT_LIBS += -lversion + } + win32:ALL_CLANG_LIBS += -lversion + LIBCLANG_MAIN_HEADER = $$LLVM_INCLUDEPATH/clang-c/Index.h !exists($$LIBCLANG_MAIN_HEADER) { $$llvmWarningOrError(\ @@ -231,7 +231,9 @@ isEmpty(LLVM_VERSION) { warning("Clang LibTooling is disabled. Set QTC_ENABLE_CLANG_LIBTOOLING to enable it.") } - CLANGFORMAT_LIBS = -L$${LLVM_LIBDIR} $$CLANGFORMAT_LIBS $$LLVM_STATIC_LIBS + !isEmpty(CLANGFORMAT_LIBS) { + CLANGFORMAT_LIBS = -L$${LLVM_LIBDIR} $$CLANGFORMAT_LIBS $$LLVM_STATIC_LIBS + } ALL_CLANG_LIBS = -L$${LLVM_LIBDIR} $$ALL_CLANG_LIBS $$CLANG_LIB $$LLVM_STATIC_LIBS contains(QMAKE_DEFAULT_INCDIRS, $$LLVM_INCLUDEPATH): LLVM_INCLUDEPATH = diff --git a/tests/unit/unittest/creator_dependency.pri b/tests/unit/unittest/creator_dependency.pri index 41ddd5bae1d..46d936d9c3e 100644 --- a/tests/unit/unittest/creator_dependency.pri +++ b/tests/unit/unittest/creator_dependency.pri @@ -19,7 +19,7 @@ include(cplusplus.pri) include($$PWD/../../../src/shared/clang/clang_defines.pri) include($$PWD/../../../src/tools/clangbackend/source/clangbackendclangipc-source.pri) include($$PWD/../../../src/plugins/clangcodemodel/clangcodemodelunittestfiles.pri) -include($$PWD/../../../src/plugins/clangformat/clangformat-source.pri) +!isEmpty(CLANGFORMAT_LIBS): include($$PWD/../../../src/plugins/clangformat/clangformat-source.pri) } else { DEFINES += CLANG_VERSION=\\\"6.0.0\\\" DEFINES += "\"CLANG_RESOURCE_DIR=\\\"/usr/include\\\"\"" From c00c9d19fa7a8dd141d610b1c771a5acd2f1d952 Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar Date: Thu, 21 Feb 2019 09:00:47 +0100 Subject: [PATCH 19/59] Clang: Fix infinite loop when resolving pointer type Fixes: QTCREATORBUG-22010 Change-Id: I5a2932089e9f7fb1e283635e228192fdb7e59cab Reviewed-by: Ivan Donchevskii --- src/tools/clangbackend/source/clangtooltipinfocollector.cpp | 5 +++-- src/tools/clangbackend/source/clangtype.cpp | 5 +++++ src/tools/clangbackend/source/clangtype.h | 1 + 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/tools/clangbackend/source/clangtooltipinfocollector.cpp b/src/tools/clangbackend/source/clangtooltipinfocollector.cpp index 8eb15eb89e0..beecf63bb66 100644 --- a/src/tools/clangbackend/source/clangtooltipinfocollector.cpp +++ b/src/tools/clangbackend/source/clangtooltipinfocollector.cpp @@ -36,6 +36,7 @@ #include #include #include +#include #include @@ -392,7 +393,7 @@ static bool isBuiltinOrPointerToBuiltin(const Type &type) // TODO: Simplify // TODO: Test with ** - while (theType.pointeeType().isValid()) { + while (theType.pointeeType().isValid() && theType != theType.pointeeType()) { theType = theType.pointeeType(); if (theType.isBuiltinType()) return true; @@ -436,7 +437,7 @@ ToolTipInfo ToolTipInfoCollector::qDocInfo(const Cursor &cursor) const } Type type = cursor.type(); - while (type.pointeeType().isValid()) + while (type.pointeeType().isValid() && type != type.pointeeType()) type = type.pointeeType(); const Cursor typeCursor = type.declaration(); diff --git a/src/tools/clangbackend/source/clangtype.cpp b/src/tools/clangbackend/source/clangtype.cpp index 46ed23d54c0..af58f715959 100644 --- a/src/tools/clangbackend/source/clangtype.cpp +++ b/src/tools/clangbackend/source/clangtype.cpp @@ -245,6 +245,11 @@ bool operator==(Type first, Type second) return clang_equalTypes(first.m_cxType, second.m_cxType); } +bool operator!=(Type first, Type second) +{ + return !operator==(first, second); +} + std::ostream &operator<<(std::ostream &os, CXTypeKind typeKind) { ClangString typeKindSpelling(clang_getTypeKindSpelling(typeKind)); diff --git a/src/tools/clangbackend/source/clangtype.h b/src/tools/clangbackend/source/clangtype.h index ed6977ee73e..53953392e36 100644 --- a/src/tools/clangbackend/source/clangtype.h +++ b/src/tools/clangbackend/source/clangtype.h @@ -81,6 +81,7 @@ private: }; bool operator==(Type first, Type second); +bool operator!=(Type first, Type second); std::ostream &operator<<(std::ostream &os, CXTypeKind typeKind); std::ostream &operator<<(std::ostream &os, const Type &type); From 5c96ec191bdc8f0469171ee3ee7cf7d1474ecf3f Mon Sep 17 00:00:00 2001 From: Robert Loehning Date: Wed, 20 Feb 2019 17:30:09 +0100 Subject: [PATCH 20/59] Fix crash in AndroidBuildApkStep::init Change-Id: Ia0b985eb63389edb58c7d32a1fe89c1bad57a1f8 Done-by: Aleksandr Konovalov Fixes: QTCREATORBUG-22007 Reviewed-by: hjk Reviewed-by: Vikas Pachdha --- src/plugins/android/androidbuildapkstep.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/plugins/android/androidbuildapkstep.cpp b/src/plugins/android/androidbuildapkstep.cpp index 20b8e73876a..c9cc74872a5 100644 --- a/src/plugins/android/androidbuildapkstep.cpp +++ b/src/plugins/android/androidbuildapkstep.cpp @@ -180,6 +180,7 @@ bool AndroidBuildApkStep::init(QList &earlierSteps) &Utils::FileName::toString)); AndroidQtSupport *qtSupport = AndroidManager::androidQtSupport(target()); + QTC_ASSERT(qtSupport, return false); QFileInfo sourceDirInfo(qtSupport->targetData(Constants::AndroidPackageSourceDir, target()).toString()); parser->setSourceDirectory(Utils::FileName::fromString(sourceDirInfo.canonicalFilePath())); parser->setBuildDirectory(Utils::FileName::fromString(bc->buildDirectory().appendPath(Constants::ANDROID_BUILDDIRECTORY).toString())); From 41d19e99e04de6115887e68cb9109461774e17ba Mon Sep 17 00:00:00 2001 From: Alessandro Portale Date: Thu, 21 Feb 2019 13:45:27 +0100 Subject: [PATCH 21/59] QmlDesigner: Add environment variable for enabling timeline editor This change adds the possibility to enable the QtQuick.Timeline editor in the QtQuick Designer via an environment variable QTC_ENABLE_QTQUICKTIMELINE_EDITOR So, far this was only possible via a settings key. Change-Id: I71ef8a17944abf5ee030383430a804282a4e9bec Reviewed-by: Thomas Hartmann --- src/plugins/qmldesigner/designersettings.h | 1 + src/plugins/qmldesigner/qmldesignerplugin.cpp | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/plugins/qmldesigner/designersettings.h b/src/plugins/qmldesigner/designersettings.h index bdaa22bb4b2..9b73dc1faf8 100644 --- a/src/plugins/qmldesigner/designersettings.h +++ b/src/plugins/qmldesigner/designersettings.h @@ -65,6 +65,7 @@ const char REFORMAT_UI_QML_FILES[] = "ReformatUiQmlFiles"; /* These setti const char IGNORE_DEVICE_PIXEL_RATIO[] = "IgnoreDevicePixelRaio"; /* The settings can be used to turn off the feature, if there are serious issues */ const char STANDALONE_MODE[] = "StandAloneMode"; const char ENABLE_TIMELINEVIEW[] = "EnableTimelineView"; +const char ENABLE_TIMELINEVIEW_ENVVAR[] = "QTC_ENABLE_QTQUICKTIMELINE_EDITOR"; } class DesignerSettings : public QHash diff --git a/src/plugins/qmldesigner/qmldesignerplugin.cpp b/src/plugins/qmldesigner/qmldesignerplugin.cpp index 84b95cccc3b..09e10c3b0c1 100644 --- a/src/plugins/qmldesigner/qmldesignerplugin.cpp +++ b/src/plugins/qmldesigner/qmldesignerplugin.cpp @@ -194,7 +194,8 @@ bool QmlDesignerPlugin::delayedInitialize() d->settings.fromSettings(Core::ICore::settings()); d->viewManager.registerViewTakingOwnership(new QmlDesigner::Internal::ConnectionView); - if (DesignerSettings::getValue(DesignerSettingsKey::ENABLE_TIMELINEVIEW).toBool()) + if (DesignerSettings::getValue(DesignerSettingsKey::ENABLE_TIMELINEVIEW).toBool() + || qEnvironmentVariableIsSet(DesignerSettingsKey::ENABLE_TIMELINEVIEW_ENVVAR)) d->viewManager.registerViewTakingOwnership(new QmlDesigner::TimelineView); d->viewManager.registerFormEditorToolTakingOwnership(new QmlDesigner::SourceTool); d->viewManager.registerFormEditorToolTakingOwnership(new QmlDesigner::ColorTool); From ad606bfe1b8dfdef2ee562e12b4ed0ebeb058776 Mon Sep 17 00:00:00 2001 From: hjk Date: Thu, 21 Feb 2019 15:25:18 +0100 Subject: [PATCH 22/59] Debugger: Show Global Log in top area by default It's off by default anyway, and in case when one wants to see it the previous position was not providing enough space. Change-Id: Ie5c6f56f482a8ca59fd47a534bbae70721313e0b Reviewed-by: Christian Stenger --- src/plugins/debugger/debuggerplugin.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/debugger/debuggerplugin.cpp b/src/plugins/debugger/debuggerplugin.cpp index cdb1e87ad24..8c9f0e96ffd 100644 --- a/src/plugins/debugger/debuggerplugin.cpp +++ b/src/plugins/debugger/debuggerplugin.cpp @@ -1405,7 +1405,7 @@ bool DebuggerPluginPrivate::initialize(const QStringList &arguments, m_perspective.addWindow(m_engineManagerWindow, Perspective::SplitVertical, nullptr); m_perspective.addWindow(m_breakpointManagerWindow, Perspective::SplitHorizontal, m_engineManagerWindow); - m_perspective.addWindow(m_globalLogWindow, Perspective::AddToTab, m_breakpointManagerWindow, false); + m_perspective.addWindow(m_globalLogWindow, Perspective::AddToTab, nullptr, false, Qt::TopDockWidgetArea); setInitialState(); From 97e1bc28d21862593fe317794904c5854c92fcda Mon Sep 17 00:00:00 2001 From: Ivan Donchevskii Date: Thu, 21 Feb 2019 11:07:03 +0100 Subject: [PATCH 23/59] Clang: Do not assume that one of the overloads always has parameters Fixes: QTCREATORBUG-21841 Change-Id: I5d4fc5d10cdf38d124e84952862b9aaf66888c88 Reviewed-by: Nikolai Kosjar --- src/plugins/clangcodemodel/clangcompletionassistprocessor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/clangcodemodel/clangcompletionassistprocessor.cpp b/src/plugins/clangcodemodel/clangcompletionassistprocessor.cpp index d53edaea190..8eb71210830 100644 --- a/src/plugins/clangcodemodel/clangcompletionassistprocessor.cpp +++ b/src/plugins/clangcodemodel/clangcompletionassistprocessor.cpp @@ -86,7 +86,7 @@ static void addFunctionOverloadAssistProposalItem(QList(sameItem); - item->setHasOverloadsWithParameters(true); + item->setHasOverloadsWithParameters(codeCompletion.hasParameters); if (codeCompletion.completionKind == CodeCompletion::ConstructorCompletionKind) { // It's the constructor, currently constructor definitions do not lead here. // CLANG-UPGRADE-CHECK: Can we get here with constructor definition? From 8782414984294bc6a4a9b3dc1f6fe2a0b9deb4a1 Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar Date: Tue, 19 Feb 2019 15:17:17 +0100 Subject: [PATCH 24/59] ClangTools: Remove unused variable Change-Id: Idc361f1aa969fa14f0268f14ad405abbfcd6d92c Reviewed-by: Ivan Donchevskii --- src/plugins/clangtools/clangfixitsrefactoringchanges.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/plugins/clangtools/clangfixitsrefactoringchanges.cpp b/src/plugins/clangtools/clangfixitsrefactoringchanges.cpp index 4be95a2744c..c3b6f4ac3ef 100644 --- a/src/plugins/clangtools/clangfixitsrefactoringchanges.cpp +++ b/src/plugins/clangtools/clangfixitsrefactoringchanges.cpp @@ -85,9 +85,6 @@ bool FixitsRefactoringFile::apply() ICodeStylePreferencesFactory *factory = TextEditorSettings::codeStyleFactory( CppTools::Constants::CPP_SETTINGS_ID); - const TextEditor::TabSettings tabSettings - = CppTools::CppCodeStyleSettings::currentProjectTabSettings(); - // Apply changes std::unique_ptr indenter; QString lastFilename; From 256d140933216b64123d1c50dd5e047898037ec2 Mon Sep 17 00:00:00 2001 From: Denis Shienkov Date: Thu, 21 Feb 2019 00:45:26 +0300 Subject: [PATCH 25/59] Fix missed item for 16-bit word width ABI GCC compiler for 8-bit AVR architecture returns the define '__SIZEOF_SIZE_T__' with the value of 2. It means that the ABI's word width is 16-bit. But the ABI's combobox shows the 32-bit word width instead. The issue was in the missed 16-bit word width item in that combobox. Change-Id: Icf6accf6f233170c21254c43983167dbd1b59ded Reviewed-by: Christian Kandeler --- src/plugins/projectexplorer/abiwidget.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/plugins/projectexplorer/abiwidget.cpp b/src/plugins/projectexplorer/abiwidget.cpp index d4a3070d695..80b88ac03e4 100644 --- a/src/plugins/projectexplorer/abiwidget.cpp +++ b/src/plugins/projectexplorer/abiwidget.cpp @@ -140,10 +140,12 @@ AbiWidget::AbiWidget(QWidget *parent) : QWidget(parent), d->m_wordWidthComboBox = new QComboBox(this); layout->addWidget(d->m_wordWidthComboBox); + d->m_wordWidthComboBox->addItem(Abi::toString(16), 16); d->m_wordWidthComboBox->addItem(Abi::toString(32), 32); d->m_wordWidthComboBox->addItem(Abi::toString(64), 64); d->m_wordWidthComboBox->addItem(Abi::toString(0), 0); - d->m_wordWidthComboBox->setCurrentIndex(2); + // Setup current word width of 0 by default. + d->m_wordWidthComboBox->setCurrentIndex(d->m_wordWidthComboBox->count() - 1); connect(d->m_wordWidthComboBox, static_cast(&QComboBox::currentIndexChanged), this, &AbiWidget::customComboBoxesChanged); From 8c781f7e6aa763a4caa21c5f5c5504b79634ea46 Mon Sep 17 00:00:00 2001 From: Marco Bubke Date: Tue, 19 Feb 2019 19:20:57 +0100 Subject: [PATCH 26/59] Clang: Fix progress bar Sometimes the messages are not send immediately, so we force it. Task-number: QTCREATORBUG-21957 Change-Id: I9526cb4b4e3dd8b7a02e15f77bffdc51917d47c8 Reviewed-by: Ivan Donchevskii --- src/libs/clangsupport/baseserverproxy.cpp | 29 +++++++++---- src/libs/clangsupport/baseserverproxy.h | 3 +- .../clangcodemodelclientproxy.cpp | 33 +++++++++++---- .../clangsupport/clangcodemodelclientproxy.h | 3 ++ .../clangcodemodelconnectionclient.cpp | 12 +++--- .../clangcodemodelconnectionclient.h | 2 +- .../clangcodemodelserverproxy.cpp | 5 +++ .../clangsupport/clangcodemodelserverproxy.h | 1 + src/libs/clangsupport/connectionclient.h | 2 +- .../clangsupport/pchmanagerclientproxy.cpp | 42 ++++++++----------- src/libs/clangsupport/pchmanagerclientproxy.h | 8 ++-- .../clangsupport/pchmanagerserverproxy.cpp | 5 +++ src/libs/clangsupport/pchmanagerserverproxy.h | 1 + src/libs/clangsupport/progresscounter.h | 2 +- .../clangsupport/refactoringclientproxy.cpp | 42 ++++++++----------- .../clangsupport/refactoringclientproxy.h | 6 +-- .../clangsupport/refactoringserverproxy.cpp | 8 +++- .../clangsupport/refactoringserverproxy.h | 2 + src/libs/clangsupport/writemessageblock.cpp | 24 ++++++++--- src/libs/clangsupport/writemessageblock.h | 8 +++- .../pchmanagerconnectionclient.cpp | 4 +- .../pchmanagerconnectionclient.h | 2 +- src/plugins/clangpchmanager/progressmanager.h | 2 + .../refactoringconnectionclient.cpp | 9 ++-- .../refactoringconnectionclient.h | 2 +- .../readandwritemessageblock-test.cpp | 2 +- 26 files changed, 157 insertions(+), 102 deletions(-) diff --git a/src/libs/clangsupport/baseserverproxy.cpp b/src/libs/clangsupport/baseserverproxy.cpp index 6f563ffd9de..0c565de269b 100644 --- a/src/libs/clangsupport/baseserverproxy.cpp +++ b/src/libs/clangsupport/baseserverproxy.cpp @@ -26,14 +26,25 @@ #include "baseserverproxy.h" #include "messageenvelop.h" -#include +#include namespace ClangBackEnd { +BaseServerProxy::BaseServerProxy(IpcClientInterface *client, QLocalSocket *localSocket) + : m_writeMessageBlock(localSocket) + , m_readMessageBlock(localSocket) + , m_client(client) +{ + if (localSocket) + QObject::connect(localSocket, &QIODevice::readyRead, [this]() { + BaseServerProxy::readMessages(); + }); +} + BaseServerProxy::BaseServerProxy(IpcClientInterface *client, QIODevice *ioDevice) - : m_writeMessageBlock(ioDevice), - m_readMessageBlock(ioDevice), - m_client(client) + : m_writeMessageBlock(ioDevice) + , m_readMessageBlock(ioDevice) + , m_client(client) { if (ioDevice) QObject::connect(ioDevice, &QIODevice::readyRead, [this] () { BaseServerProxy::readMessages(); }); @@ -51,11 +62,13 @@ void BaseServerProxy::resetState() m_readMessageBlock.resetState(); } -void BaseServerProxy::setIoDevice(QIODevice *ioDevice) +void BaseServerProxy::setLocalSocket(QLocalSocket *localSocket) { - QObject::connect(ioDevice, &QIODevice::readyRead, [this] () { BaseServerProxy::readMessages(); }); - m_writeMessageBlock.setIoDevice(ioDevice); - m_readMessageBlock.setIoDevice(ioDevice); + QObject::connect(localSocket, &QIODevice::readyRead, [this]() { + BaseServerProxy::readMessages(); + }); + m_writeMessageBlock.setLocalSocket(localSocket); + m_readMessageBlock.setIoDevice(localSocket); } } // namespace ClangBackEnd diff --git a/src/libs/clangsupport/baseserverproxy.h b/src/libs/clangsupport/baseserverproxy.h index 246f0604ecf..797f02999dc 100644 --- a/src/libs/clangsupport/baseserverproxy.h +++ b/src/libs/clangsupport/baseserverproxy.h @@ -37,13 +37,14 @@ class CLANGSUPPORT_EXPORT BaseServerProxy BaseServerProxy &operator=(const BaseServerProxy&) = delete; public: + BaseServerProxy(IpcClientInterface *client, QLocalSocket *localSocket); BaseServerProxy(IpcClientInterface *client, QIODevice *ioDevice); void readMessages(); void resetState(); - void setIoDevice(QIODevice *ioDevice); + void setLocalSocket(QLocalSocket *localSocket); protected: ~BaseServerProxy() = default; diff --git a/src/libs/clangsupport/clangcodemodelclientproxy.cpp b/src/libs/clangsupport/clangcodemodelclientproxy.cpp index 538677e6c1c..cf3e699e217 100644 --- a/src/libs/clangsupport/clangcodemodelclientproxy.cpp +++ b/src/libs/clangsupport/clangcodemodelclientproxy.cpp @@ -31,19 +31,34 @@ #include "messageenvelop.h" #include -#include +#include #include #include namespace ClangBackEnd { -ClangCodeModelClientProxy::ClangCodeModelClientProxy(ClangCodeModelServerInterface *server, QIODevice *ioDevice) - : m_writeMessageBlock(ioDevice), - m_readMessageBlock(ioDevice), - m_server(server), - m_ioDevice(ioDevice) +ClangCodeModelClientProxy::ClangCodeModelClientProxy(ClangCodeModelServerInterface *server, + QLocalSocket *localSocket) + : m_writeMessageBlock(localSocket) + , m_readMessageBlock(localSocket) + , m_server(server) + , m_ioDevice(localSocket) { - QObject::connect(m_ioDevice, &QIODevice::readyRead, [this] () {ClangCodeModelClientProxy::readMessages();}); + QObject::connect(m_ioDevice, &QIODevice::readyRead, [this]() { + ClangCodeModelClientProxy::readMessages(); + }); +} + +ClangCodeModelClientProxy::ClangCodeModelClientProxy(ClangCodeModelServerInterface *server, + QIODevice *ioDevice) + : m_writeMessageBlock(ioDevice) + , m_readMessageBlock(ioDevice) + , m_server(server) + , m_ioDevice(ioDevice) +{ + QObject::connect(m_ioDevice, &QIODevice::readyRead, [this]() { + ClangCodeModelClientProxy::readMessages(); + }); } ClangCodeModelClientProxy::ClangCodeModelClientProxy(ClangCodeModelClientProxy &&other) @@ -106,9 +121,9 @@ void ClangCodeModelClientProxy::readMessages() m_server->dispatch(message); } -bool ClangCodeModelClientProxy::isUsingThatIoDevice(QIODevice *m_ioDevice) const +bool ClangCodeModelClientProxy::isUsingThatIoDevice(QIODevice *ioDevice) const { - return this->m_ioDevice == m_ioDevice; + return m_ioDevice == ioDevice; } } // namespace ClangBackEnd diff --git a/src/libs/clangsupport/clangcodemodelclientproxy.h b/src/libs/clangsupport/clangcodemodelclientproxy.h index 480cbe646e1..4b0e1f9d2a5 100644 --- a/src/libs/clangsupport/clangcodemodelclientproxy.h +++ b/src/libs/clangsupport/clangcodemodelclientproxy.h @@ -36,6 +36,7 @@ QT_BEGIN_NAMESPACE class QLocalServer; +class QLocalSocket; class QIODevice; QT_END_NAMESPACE @@ -44,6 +45,8 @@ namespace ClangBackEnd { class CLANGSUPPORT_EXPORT ClangCodeModelClientProxy : public ClangCodeModelClientInterface { public: + explicit ClangCodeModelClientProxy(ClangCodeModelServerInterface *server, + QLocalSocket *localSocket); explicit ClangCodeModelClientProxy(ClangCodeModelServerInterface *server, QIODevice *ioDevice); ClangCodeModelClientProxy(const ClangCodeModelClientProxy&) = delete; const ClangCodeModelClientProxy &operator=(const ClangCodeModelClientProxy&) = delete; diff --git a/src/libs/clangsupport/clangcodemodelconnectionclient.cpp b/src/libs/clangsupport/clangcodemodelconnectionclient.cpp index 56186e24dc6..618782d1d82 100644 --- a/src/libs/clangsupport/clangcodemodelconnectionclient.cpp +++ b/src/libs/clangsupport/clangcodemodelconnectionclient.cpp @@ -41,12 +41,10 @@ QString currentProcessId() } -ClangCodeModelConnectionClient::ClangCodeModelConnectionClient( - ClangCodeModelClientInterface *client) +ClangCodeModelConnectionClient::ClangCodeModelConnectionClient(ClangCodeModelClientInterface *client) : ConnectionClient(Utils::TemporaryDirectory::masterDirectoryPath() - + QStringLiteral("/ClangBackEnd-") - + currentProcessId()), - m_serverProxy(client, nullptr) + + QStringLiteral("/ClangBackEnd-") + currentProcessId()) + , m_serverProxy(client) { m_processCreator.setTemporaryDirectoryPattern("clangbackend-XXXXXX"); m_processCreator.setArguments({connectionName()}); @@ -85,9 +83,9 @@ QString ClangCodeModelConnectionClient::outputName() const return QStringLiteral("ClangCodeModelConnectionClient"); } -void ClangCodeModelConnectionClient::newConnectedServer(QIODevice *ioDevice) +void ClangCodeModelConnectionClient::newConnectedServer(QLocalSocket *localSocket) { - m_serverProxy.setIoDevice(ioDevice); + m_serverProxy.setLocalSocket(localSocket); } } // namespace ClangBackEnd diff --git a/src/libs/clangsupport/clangcodemodelconnectionclient.h b/src/libs/clangsupport/clangcodemodelconnectionclient.h index c1618b06d95..9b0e49ae5b3 100644 --- a/src/libs/clangsupport/clangcodemodelconnectionclient.h +++ b/src/libs/clangsupport/clangcodemodelconnectionclient.h @@ -41,7 +41,7 @@ protected: void sendEndCommand() override; void resetState() override; QString outputName() const override; - void newConnectedServer(QIODevice *ioDevice) override; + void newConnectedServer(QLocalSocket *localSocket) override; private: ClangCodeModelServerProxy m_serverProxy; diff --git a/src/libs/clangsupport/clangcodemodelserverproxy.cpp b/src/libs/clangsupport/clangcodemodelserverproxy.cpp index 6d90f20016a..d77e27bffd0 100644 --- a/src/libs/clangsupport/clangcodemodelserverproxy.cpp +++ b/src/libs/clangsupport/clangcodemodelserverproxy.cpp @@ -31,6 +31,11 @@ namespace ClangBackEnd { +ClangCodeModelServerProxy::ClangCodeModelServerProxy(ClangCodeModelClientInterface *client, + QLocalSocket *localSocket) + : BaseServerProxy(client, localSocket) +{} + ClangCodeModelServerProxy::ClangCodeModelServerProxy(ClangCodeModelClientInterface *client, QIODevice *ioDevice) : BaseServerProxy(client, ioDevice) diff --git a/src/libs/clangsupport/clangcodemodelserverproxy.h b/src/libs/clangsupport/clangcodemodelserverproxy.h index e18fd37402d..0ea4b016729 100644 --- a/src/libs/clangsupport/clangcodemodelserverproxy.h +++ b/src/libs/clangsupport/clangcodemodelserverproxy.h @@ -46,6 +46,7 @@ class CLANGSUPPORT_EXPORT ClangCodeModelServerProxy : public BaseServerProxy, public ClangCodeModelServerInterface { public: + ClangCodeModelServerProxy(ClangCodeModelClientInterface *client, QLocalSocket *localSocket = {}); ClangCodeModelServerProxy(ClangCodeModelClientInterface *client, QIODevice *ioDevice); void end() override; diff --git a/src/libs/clangsupport/connectionclient.h b/src/libs/clangsupport/connectionclient.h index 8fbc73a06c9..c3ded380293 100644 --- a/src/libs/clangsupport/connectionclient.h +++ b/src/libs/clangsupport/connectionclient.h @@ -100,7 +100,7 @@ protected: QString connectionName() const; bool event(QEvent* event); - virtual void newConnectedServer(QIODevice *ioDevice) = 0; + virtual void newConnectedServer(QLocalSocket *localSocket) = 0; private: static bool isProcessRunning(QProcess *process); diff --git a/src/libs/clangsupport/pchmanagerclientproxy.cpp b/src/libs/clangsupport/pchmanagerclientproxy.cpp index 595187d155b..a18ac166d2f 100644 --- a/src/libs/clangsupport/pchmanagerclientproxy.cpp +++ b/src/libs/clangsupport/pchmanagerclientproxy.cpp @@ -32,35 +32,29 @@ #include "progressmessage.h" #include -#include +#include namespace ClangBackEnd { +PchManagerClientProxy::PchManagerClientProxy(PchManagerServerInterface *server, + QLocalSocket *localSocket) + : writeMessageBlock(localSocket) + , readMessageBlock(localSocket) + , server(server) +{ + QObject::connect(localSocket, &QIODevice::readyRead, [this]() { + PchManagerClientProxy::readMessages(); + }); +} + PchManagerClientProxy::PchManagerClientProxy(PchManagerServerInterface *server, QIODevice *ioDevice) - : writeMessageBlock(ioDevice), - readMessageBlock(ioDevice), - server(server), - ioDevice(ioDevice) + : writeMessageBlock(ioDevice) + , readMessageBlock(ioDevice) + , server(server) { - QObject::connect(ioDevice, &QIODevice::readyRead, [this] () {PchManagerClientProxy::readMessages();}); -} - -PchManagerClientProxy::PchManagerClientProxy(PchManagerClientProxy &&other) - : writeMessageBlock(std::move(other.writeMessageBlock)), - readMessageBlock(std::move(other.readMessageBlock)), - server(std::move(other.server)), - ioDevice(std::move(other.ioDevice)) -{ -} - -PchManagerClientProxy &PchManagerClientProxy::operator=(PchManagerClientProxy &&other) -{ - writeMessageBlock = std::move(other.writeMessageBlock); - readMessageBlock = std::move(other.readMessageBlock); - server = std::move(other.server); - ioDevice = std::move(other.ioDevice); - - return *this; + QObject::connect(ioDevice, &QIODevice::readyRead, [this]() { + PchManagerClientProxy::readMessages(); + }); } void PchManagerClientProxy::readMessages() diff --git a/src/libs/clangsupport/pchmanagerclientproxy.h b/src/libs/clangsupport/pchmanagerclientproxy.h index 8efacf504f0..516b2e3a86f 100644 --- a/src/libs/clangsupport/pchmanagerclientproxy.h +++ b/src/libs/clangsupport/pchmanagerclientproxy.h @@ -34,15 +34,16 @@ namespace ClangBackEnd { class PchManagerServerInterface; -class CLANGSUPPORT_EXPORT PchManagerClientProxy : public PchManagerClientInterface +class CLANGSUPPORT_EXPORT PchManagerClientProxy final : public PchManagerClientInterface { public: + explicit PchManagerClientProxy(PchManagerServerInterface *server, QLocalSocket *localSocket); explicit PchManagerClientProxy(PchManagerServerInterface *server, QIODevice *ioDevice); PchManagerClientProxy(const PchManagerClientProxy&) = delete; const PchManagerClientProxy &operator=(const PchManagerClientProxy&) = delete; - PchManagerClientProxy(PchManagerClientProxy&&other); - PchManagerClientProxy &operator=(PchManagerClientProxy&&other); + PchManagerClientProxy(PchManagerClientProxy &&other) = default; + PchManagerClientProxy &operator=(PchManagerClientProxy &&other) = default; void readMessages(); @@ -54,7 +55,6 @@ private: ClangBackEnd::WriteMessageBlock writeMessageBlock; ClangBackEnd::ReadMessageBlock readMessageBlock; PchManagerServerInterface *server = nullptr; - QIODevice *ioDevice = nullptr; }; } // namespace ClangBackEnd diff --git a/src/libs/clangsupport/pchmanagerserverproxy.cpp b/src/libs/clangsupport/pchmanagerserverproxy.cpp index dedbb23d50d..5f1fb03948a 100644 --- a/src/libs/clangsupport/pchmanagerserverproxy.cpp +++ b/src/libs/clangsupport/pchmanagerserverproxy.cpp @@ -38,6 +38,11 @@ namespace ClangBackEnd { +PchManagerServerProxy::PchManagerServerProxy(PchManagerClientInterface *client, + QLocalSocket *localSocket) + : BaseServerProxy(client, localSocket) +{} + PchManagerServerProxy::PchManagerServerProxy(PchManagerClientInterface *client, QIODevice *ioDevice) : BaseServerProxy(client, ioDevice) { diff --git a/src/libs/clangsupport/pchmanagerserverproxy.h b/src/libs/clangsupport/pchmanagerserverproxy.h index 570de91a03a..d13d88ee8e8 100644 --- a/src/libs/clangsupport/pchmanagerserverproxy.h +++ b/src/libs/clangsupport/pchmanagerserverproxy.h @@ -47,6 +47,7 @@ class CLANGSUPPORT_EXPORT PchManagerServerProxy final : public BaseServerProxy, public PchManagerServerInterface { public: + explicit PchManagerServerProxy(PchManagerClientInterface *client, QLocalSocket *localSocket); explicit PchManagerServerProxy(PchManagerClientInterface *client, QIODevice *ioDevice); void end() override; diff --git a/src/libs/clangsupport/progresscounter.h b/src/libs/clangsupport/progresscounter.h index 449754f9149..21a8e13b777 100644 --- a/src/libs/clangsupport/progresscounter.h +++ b/src/libs/clangsupport/progresscounter.h @@ -84,7 +84,7 @@ public: { Lock lock(m_mutex); - return m_total; + return m_progress; } private: diff --git a/src/libs/clangsupport/refactoringclientproxy.cpp b/src/libs/clangsupport/refactoringclientproxy.cpp index c2076418440..646cb0e161f 100644 --- a/src/libs/clangsupport/refactoringclientproxy.cpp +++ b/src/libs/clangsupport/refactoringclientproxy.cpp @@ -31,38 +31,30 @@ #include "clangrefactoringclientmessages.h" #include -#include +#include namespace ClangBackEnd { -RefactoringClientProxy::RefactoringClientProxy(RefactoringServerInterface *server, QIODevice *ioDevice) - : writeMessageBlock(ioDevice), - readMessageBlock(ioDevice), - server(server), - ioDevice(ioDevice) +RefactoringClientProxy::RefactoringClientProxy(RefactoringServerInterface *server, + QLocalSocket *localSocket) + : writeMessageBlock(localSocket) + , readMessageBlock(localSocket) + , server(server) +{ + QObject::connect(localSocket, &QIODevice::readyRead, [this]() { + RefactoringClientProxy::readMessages(); + }); +} + +RefactoringClientProxy::RefactoringClientProxy(RefactoringServerInterface *server, + QIODevice *ioDevice) + : writeMessageBlock(ioDevice) + , readMessageBlock(ioDevice) + , server(server) { QObject::connect(ioDevice, &QIODevice::readyRead, [this] () {RefactoringClientProxy::readMessages();}); } -RefactoringClientProxy::RefactoringClientProxy(RefactoringClientProxy &&other) - : writeMessageBlock(std::move(other.writeMessageBlock)), - readMessageBlock(std::move(other.readMessageBlock)), - server(std::move(other.server)), - ioDevice(std::move(other.ioDevice)) -{ - -} - -RefactoringClientProxy &RefactoringClientProxy::operator=(RefactoringClientProxy &&other) -{ - writeMessageBlock = std::move(other.writeMessageBlock); - readMessageBlock = std::move(other.readMessageBlock); - server = std::move(other.server); - ioDevice = std::move(other.ioDevice); - - return *this; -} - void RefactoringClientProxy::readMessages() { for (const MessageEnvelop &message : readMessageBlock.readAll()) diff --git a/src/libs/clangsupport/refactoringclientproxy.h b/src/libs/clangsupport/refactoringclientproxy.h index 45ce029120c..07cba05e8d6 100644 --- a/src/libs/clangsupport/refactoringclientproxy.h +++ b/src/libs/clangsupport/refactoringclientproxy.h @@ -39,12 +39,13 @@ class RefactoringServerInterface; class CLANGSUPPORT_EXPORT RefactoringClientProxy : public RefactoringClientInterface { public: + explicit RefactoringClientProxy(RefactoringServerInterface *server, QLocalSocket *localSocket); explicit RefactoringClientProxy(RefactoringServerInterface *server, QIODevice *ioDevice); RefactoringClientProxy(const RefactoringClientProxy&) = delete; const RefactoringClientProxy &operator=(const RefactoringClientProxy&) = delete; - RefactoringClientProxy(RefactoringClientProxy&&other); - RefactoringClientProxy &operator=(RefactoringClientProxy&&other); + RefactoringClientProxy(RefactoringClientProxy &&other) = default; + RefactoringClientProxy &operator=(RefactoringClientProxy &&other) = default; void readMessages(); @@ -60,7 +61,6 @@ private: ClangBackEnd::WriteMessageBlock writeMessageBlock; ClangBackEnd::ReadMessageBlock readMessageBlock; RefactoringServerInterface *server = nullptr; - QIODevice *ioDevice = nullptr; }; } // namespace ClangBackEnd diff --git a/src/libs/clangsupport/refactoringserverproxy.cpp b/src/libs/clangsupport/refactoringserverproxy.cpp index 3bc8fe20af5..2208f3a0ce3 100644 --- a/src/libs/clangsupport/refactoringserverproxy.cpp +++ b/src/libs/clangsupport/refactoringserverproxy.cpp @@ -34,7 +34,13 @@ namespace ClangBackEnd { -RefactoringServerProxy::RefactoringServerProxy(RefactoringClientInterface *client, QIODevice *ioDevice) +RefactoringServerProxy::RefactoringServerProxy(RefactoringClientInterface *client, + QLocalSocket *localSocket) + : BaseServerProxy(client, localSocket) +{} + +RefactoringServerProxy::RefactoringServerProxy(RefactoringClientInterface *client, + QIODevice *ioDevice) : BaseServerProxy(client, ioDevice) { } diff --git a/src/libs/clangsupport/refactoringserverproxy.h b/src/libs/clangsupport/refactoringserverproxy.h index 55ae20d4416..34861767d85 100644 --- a/src/libs/clangsupport/refactoringserverproxy.h +++ b/src/libs/clangsupport/refactoringserverproxy.h @@ -47,6 +47,8 @@ class CLANGSUPPORT_EXPORT RefactoringServerProxy final : public BaseServerProxy, public RefactoringServerInterface { public: + explicit RefactoringServerProxy(RefactoringClientInterface *client, + QLocalSocket *localSocket = {}); explicit RefactoringServerProxy(RefactoringClientInterface *client, QIODevice *ioDevice); void end() override; diff --git a/src/libs/clangsupport/writemessageblock.cpp b/src/libs/clangsupport/writemessageblock.cpp index 999c63e9b1f..b3fe4a51edb 100644 --- a/src/libs/clangsupport/writemessageblock.cpp +++ b/src/libs/clangsupport/writemessageblock.cpp @@ -29,16 +29,19 @@ #include #include -#include +#include #include namespace ClangBackEnd { WriteMessageBlock::WriteMessageBlock(QIODevice *ioDevice) - : m_messageCounter(0), - m_ioDevice(ioDevice) -{ -} + : m_ioDevice(ioDevice) +{} + +WriteMessageBlock::WriteMessageBlock(QLocalSocket *localSocket) + : m_ioDevice(localSocket) + , m_localSocket(localSocket) +{} void WriteMessageBlock::write(const MessageEnvelop &message) { @@ -74,10 +77,19 @@ void WriteMessageBlock::resetState() void WriteMessageBlock::setIoDevice(QIODevice *ioDevice) { m_ioDevice = ioDevice; + if (m_localSocket != ioDevice) + m_localSocket = nullptr; flushBlock(); } +void WriteMessageBlock::setLocalSocket(QLocalSocket *localSocket) +{ + m_localSocket = localSocket; + + setIoDevice(localSocket); +} + void WriteMessageBlock::flushBlock() { if (m_ioDevice) { @@ -85,6 +97,8 @@ void WriteMessageBlock::flushBlock() m_block.clear(); if (bytesWritten == -1) qWarning() << "Failed to write data:" << m_ioDevice->errorString(); + if (m_localSocket) + m_localSocket->flush(); } } diff --git a/src/libs/clangsupport/writemessageblock.h b/src/libs/clangsupport/writemessageblock.h index b75f0ce2944..8a126fed36e 100644 --- a/src/libs/clangsupport/writemessageblock.h +++ b/src/libs/clangsupport/writemessageblock.h @@ -32,6 +32,7 @@ QT_BEGIN_NAMESPACE class QVariant; class QDataStream; class QIODevice; +class QLocalSocket; QT_END_NAMESPACE namespace ClangBackEnd { @@ -42,6 +43,7 @@ class WriteMessageBlock { public: WriteMessageBlock(QIODevice *ioDevice = nullptr); + WriteMessageBlock(QLocalSocket *localSocket); void write(const MessageEnvelop &message); @@ -50,13 +52,15 @@ public: void resetState(); void setIoDevice(QIODevice *ioDevice); + void setLocalSocket(QLocalSocket *localSocket); void flushBlock(); private: QByteArray m_block; - qint64 m_messageCounter; - QIODevice *m_ioDevice; + qint64 m_messageCounter = 0; + QIODevice *m_ioDevice = {}; + QLocalSocket *m_localSocket = {}; }; } // namespace ClangBackEnd diff --git a/src/plugins/clangpchmanager/pchmanagerconnectionclient.cpp b/src/plugins/clangpchmanager/pchmanagerconnectionclient.cpp index 812445610e6..6db0db09745 100644 --- a/src/plugins/clangpchmanager/pchmanagerconnectionclient.cpp +++ b/src/plugins/clangpchmanager/pchmanagerconnectionclient.cpp @@ -87,9 +87,9 @@ QString PchManagerConnectionClient::outputName() const return QStringLiteral("PchManagerConnectionClient"); } -void PchManagerConnectionClient::newConnectedServer(QIODevice *ioDevice) +void PchManagerConnectionClient::newConnectedServer(QLocalSocket *localSocket) { - m_serverProxy.setIoDevice(ioDevice); + m_serverProxy.setLocalSocket(localSocket); } } // namespace ClangPchManager diff --git a/src/plugins/clangpchmanager/pchmanagerconnectionclient.h b/src/plugins/clangpchmanager/pchmanagerconnectionclient.h index 672b6ef7cff..7189c83c0b8 100644 --- a/src/plugins/clangpchmanager/pchmanagerconnectionclient.h +++ b/src/plugins/clangpchmanager/pchmanagerconnectionclient.h @@ -42,7 +42,7 @@ protected: void sendEndCommand() override; void resetState() override; QString outputName() const override; - void newConnectedServer(QIODevice *ioDevice) override; + void newConnectedServer(QLocalSocket *localSocket) override; private: ClangBackEnd::PchManagerServerProxy m_serverProxy; diff --git a/src/plugins/clangpchmanager/progressmanager.h b/src/plugins/clangpchmanager/progressmanager.h index cc6ab1946cb..0fdf94c2196 100644 --- a/src/plugins/clangpchmanager/progressmanager.h +++ b/src/plugins/clangpchmanager/progressmanager.h @@ -53,6 +53,8 @@ public: initialize(); m_promise->setExpectedResultCount(maximumProgress); + if (m_promise->expectedResultCount() != maximumProgress) + m_promise->setExpectedResultCount(maximumProgress); m_promise->setProgressValue(currentProgress); if (currentProgress >= maximumProgress) diff --git a/src/plugins/clangrefactoring/refactoringconnectionclient.cpp b/src/plugins/clangrefactoring/refactoringconnectionclient.cpp index 865c9d53d13..ff66ec20cbf 100644 --- a/src/plugins/clangrefactoring/refactoringconnectionclient.cpp +++ b/src/plugins/clangrefactoring/refactoringconnectionclient.cpp @@ -44,9 +44,8 @@ QString currentProcessId() RefactoringConnectionClient::RefactoringConnectionClient(RefactoringClientInterface *client) : ConnectionClient(Utils::TemporaryDirectory::masterDirectoryPath() - + QStringLiteral("/ClangRefactoringBackEnd-") - + currentProcessId()), - m_serverProxy(client, nullptr) + + QStringLiteral("/ClangRefactoringBackEnd-") + currentProcessId()) + , m_serverProxy(client) { m_processCreator.setTemporaryDirectoryPattern("clangrefactoringbackend-XXXXXX"); m_processCreator.setArguments({connectionName(), @@ -81,9 +80,9 @@ QString RefactoringConnectionClient::outputName() const return QStringLiteral("RefactoringConnectionClient"); } -void RefactoringConnectionClient::newConnectedServer(QIODevice *ioDevice) +void RefactoringConnectionClient::newConnectedServer(QLocalSocket *localSocket) { - m_serverProxy.setIoDevice(ioDevice); + m_serverProxy.setLocalSocket(localSocket); } } // namespace ClangBackEnd diff --git a/src/plugins/clangrefactoring/refactoringconnectionclient.h b/src/plugins/clangrefactoring/refactoringconnectionclient.h index 16734f7ed97..3db871e6a21 100644 --- a/src/plugins/clangrefactoring/refactoringconnectionclient.h +++ b/src/plugins/clangrefactoring/refactoringconnectionclient.h @@ -44,7 +44,7 @@ protected: void sendEndCommand() override; void resetState() override; QString outputName() const override; - void newConnectedServer(QIODevice *ioDevice) override; + void newConnectedServer(QLocalSocket *localSocket) override; private: RefactoringServerProxy m_serverProxy; diff --git a/tests/unit/unittest/readandwritemessageblock-test.cpp b/tests/unit/unittest/readandwritemessageblock-test.cpp index 1cedd2b5a40..a13def699d0 100644 --- a/tests/unit/unittest/readandwritemessageblock-test.cpp +++ b/tests/unit/unittest/readandwritemessageblock-test.cpp @@ -138,7 +138,7 @@ TEST_F(ReadAndWriteMessageBlock, WriteMessagesToWriteBlockWithoutIoDeviceAndSetI writeMessageBlock.write(ClangBackEnd::EndMessage()); writeMessageBlock.write(ClangBackEnd::EndMessage()); - writeMessageBlock.setIoDevice(nullptr); + writeMessageBlock.setLocalSocket(nullptr); buffer.seek(0); ASSERT_THAT(readMessageBlock.readAll(), IsEmpty()); From f009dad9ef2f286248d7da8678134f587bda22d0 Mon Sep 17 00:00:00 2001 From: Marco Bubke Date: Tue, 19 Feb 2019 20:46:08 +0100 Subject: [PATCH 27/59] ClangPchManager: Show extra progress for dependency building Task-number: QTCREATORBUG-21956 Change-Id: Id244c9ef9fc7825489daa143b21fcca78164d8c7 Reviewed-by: Ivan Donchevskii --- src/libs/clangsupport/clangsupport_global.h | 10 ++------- src/libs/clangsupport/progressmessage.h | 12 ++++++---- .../clangpchmanager/clangpchmanagerplugin.cpp | 17 +++++++++----- .../clangpchmanager/pchmanagerclient.cpp | 11 +++++++++- .../clangpchmanager/pchmanagerclient.h | 9 +++++--- .../clangpchmanagerbackendmain.cpp | 19 +++++++++++----- .../source/pchmanagerserver.cpp | 7 +++++- .../source/pchmanagerserver.h | 3 ++- tests/unit/unittest/pchmanagerclient-test.cpp | 16 ++++++++++---- tests/unit/unittest/pchmanagerserver-test.cpp | 22 +++++++++++++++---- tests/unit/unittest/projectupdater-test.cpp | 6 +++-- .../refactoringprojectupdater-test.cpp | 6 +++-- 12 files changed, 97 insertions(+), 41 deletions(-) diff --git a/src/libs/clangsupport/clangsupport_global.h b/src/libs/clangsupport/clangsupport_global.h index 59a4085deef..57ce18e195c 100644 --- a/src/libs/clangsupport/clangsupport_global.h +++ b/src/libs/clangsupport/clangsupport_global.h @@ -235,11 +235,5 @@ enum class SymbolTag : uchar using SymbolTags = Utils::SizedArray; -enum class ProgressType -{ - Invalid, - PrecompiledHeader, - Indexing -}; - -} +enum class ProgressType { Invalid, PrecompiledHeader, Indexing, DependencyCreation }; +} // namespace ClangBackEnd diff --git a/src/libs/clangsupport/progressmessage.h b/src/libs/clangsupport/progressmessage.h index e4d79c84161..75902a90c3c 100644 --- a/src/libs/clangsupport/progressmessage.h +++ b/src/libs/clangsupport/progressmessage.h @@ -36,23 +36,27 @@ class ProgressMessage public: ProgressMessage() = default; ProgressMessage(ProgressType progressType, int progress, int total) - : progressType(progressType), - progress(progress), - total(total) + : progress(progress) + , total(total) + , progressType(progressType) {} friend QDataStream &operator<<(QDataStream &out, const ProgressMessage &message) { out << message.progress; out << message.total; + out << static_cast(message.progressType); return out; } friend QDataStream &operator>>(QDataStream &in, ProgressMessage &message) { + int progressTupe; in >> message.progress; in >> message.total; + in >> progressTupe; + message.progressType = static_cast(progressTupe); return in; } @@ -69,9 +73,9 @@ public: } public: - ProgressType progressType = ProgressType::Invalid; int progress = 0; int total = 0; + ProgressType progressType = ProgressType::Invalid; }; DECLARE_MESSAGE(ProgressMessage) diff --git a/src/plugins/clangpchmanager/clangpchmanagerplugin.cpp b/src/plugins/clangpchmanager/clangpchmanagerplugin.cpp index 90ba8f62bc0..8f7ea722426 100644 --- a/src/plugins/clangpchmanager/clangpchmanagerplugin.cpp +++ b/src/plugins/clangpchmanager/clangpchmanagerplugin.cpp @@ -65,12 +65,19 @@ public: Sqlite::Database database{Utils::PathString{Core::ICore::userResourcePath() + "/symbol-experimental-v1.db"}, 1000ms}; ClangBackEnd::RefactoringDatabaseInitializer databaseInitializer{database}; ClangBackEnd::FilePathCaching filePathCache{database}; - ClangPchManager::ProgressManager progressManager{ - [] (QFutureInterface &promise) { - auto title = QCoreApplication::translate("ClangPchProgressManager", "Creating PCHs", "PCH stands for precompiled header"); - Core::ProgressManager::addTask(promise.future(), title, "pch creation", nullptr); + ClangPchManager::ProgressManager pchCreationProgressManager{[](QFutureInterface &promise) { + auto title = QCoreApplication::translate("ClangPchProgressManager", + "Creating PCHs", + "PCH stands for precompiled header"); + Core::ProgressManager::addTask(promise.future(), title, "pch creation", nullptr); }}; - PchManagerClient pchManagerClient{progressManager}; + ClangPchManager::ProgressManager dependencyCreationProgressManager{ + [](QFutureInterface &promise) { + auto title = QCoreApplication::translate("ClangPchProgressManager", + "Creating Dependencies"); + Core::ProgressManager::addTask(promise.future(), title, "dependency creation", nullptr); + }}; + PchManagerClient pchManagerClient{pchCreationProgressManager, dependencyCreationProgressManager}; PchManagerConnectionClient connectionClient{&pchManagerClient}; QtCreatorProjectUpdater projectUpdate{connectionClient.serverProxy(), pchManagerClient, diff --git a/src/plugins/clangpchmanager/pchmanagerclient.cpp b/src/plugins/clangpchmanager/pchmanagerclient.cpp index 56e64b2b56f..4b0b5430d7f 100644 --- a/src/plugins/clangpchmanager/pchmanagerclient.cpp +++ b/src/plugins/clangpchmanager/pchmanagerclient.cpp @@ -53,7 +53,16 @@ void PchManagerClient::precompiledHeadersUpdated(ClangBackEnd::PrecompiledHeader void PchManagerClient::progress(ClangBackEnd::ProgressMessage &&message) { - m_progressManager.setProgress(message.progress, message.total); + switch (message.progressType) { + case ClangBackEnd::ProgressType::PrecompiledHeader: + m_pchCreationProgressManager.setProgress(message.progress, message.total); + break; + case ClangBackEnd::ProgressType::DependencyCreation: + m_dependencyCreationProgressManager.setProgress(message.progress, message.total); + break; + default: + break; + } } void PchManagerClient::precompiledHeaderRemoved(const QString &projectPartId) diff --git a/src/plugins/clangpchmanager/pchmanagerclient.h b/src/plugins/clangpchmanager/pchmanagerclient.h index d7c0b68f713..ccbd03299af 100644 --- a/src/plugins/clangpchmanager/pchmanagerclient.h +++ b/src/plugins/clangpchmanager/pchmanagerclient.h @@ -42,8 +42,10 @@ class CLANGPCHMANAGER_EXPORT PchManagerClient final : public ClangBackEnd::PchMa { friend class PchManagerNotifierInterface; public: - PchManagerClient(ProgressManagerInterface &progressManager) - : m_progressManager(progressManager) + PchManagerClient(ProgressManagerInterface &pchCreationProgressManager, + ProgressManagerInterface &dependencyCreationProgressManager) + : m_pchCreationProgressManager(pchCreationProgressManager) + , m_dependencyCreationProgressManager(dependencyCreationProgressManager) {} void alive() override; @@ -78,7 +80,8 @@ private: ClangBackEnd::ProjectPartPchs m_projectPartPchs; std::vector m_notifiers; PchManagerConnectionClient *m_connectionClient=nullptr; - ProgressManagerInterface &m_progressManager; + ProgressManagerInterface &m_pchCreationProgressManager; + ProgressManagerInterface &m_dependencyCreationProgressManager; }; } // namespace ClangPchManager diff --git a/src/tools/clangpchmanagerbackend/clangpchmanagerbackendmain.cpp b/src/tools/clangpchmanagerbackend/clangpchmanagerbackendmain.cpp index f4afaf9210d..17af1a2bc31 100644 --- a/src/tools/clangpchmanagerbackend/clangpchmanagerbackendmain.cpp +++ b/src/tools/clangpchmanagerbackend/clangpchmanagerbackendmain.cpp @@ -224,12 +224,19 @@ struct Data // because we have a cycle dependency clangPchManagerServer, includeWatcher}; PrecompiledHeaderStorage<> preCompiledHeaderStorage{database}; - ClangBackEnd::ProgressCounter progressCounter{[&](int progress, int total) { - executeInLoop([&] { clangPchManagerServer.setProgress(progress, total); }); + ClangBackEnd::ProgressCounter pchCreationProgressCounter{[&](int progress, int total) { + executeInLoop([&] { + clangPchManagerServer.setPchCreationProgress(progress, total); + }); + }}; + ClangBackEnd::ProgressCounter dependencyCreationProgressCounter{[&](int progress, int total) { + executeInLoop([&] { + clangPchManagerServer.setDependencyCreationProgress(progress, total); + }); }}; ClangBackEnd::PchTaskQueue pchTaskQueue{systemTaskScheduler, projectTaskScheduler, - progressCounter, + pchCreationProgressCounter, preCompiledHeaderStorage, database}; ClangBackEnd::PchTasksMerger pchTaskMerger{pchTaskQueue}; @@ -248,19 +255,19 @@ struct Data // because we have a cycle dependency database}; ClangBackEnd::PchTaskGenerator pchTaskGenerator{buildDependencyProvider, pchTaskMerger, - progressCounter}; + dependencyCreationProgressCounter}; PchManagerServer clangPchManagerServer{includeWatcher, pchTaskGenerator, projectParts, generatedFiles}; TaskScheduler systemTaskScheduler{pchCreatorManager, pchTaskQueue, - progressCounter, + pchCreationProgressCounter, std::thread::hardware_concurrency(), ClangBackEnd::CallDoInMainThreadAfterFinished::No}; TaskScheduler projectTaskScheduler{pchCreatorManager, pchTaskQueue, - progressCounter, + pchCreationProgressCounter, std::thread::hardware_concurrency(), ClangBackEnd::CallDoInMainThreadAfterFinished::Yes}; }; diff --git a/src/tools/clangpchmanagerbackend/source/pchmanagerserver.cpp b/src/tools/clangpchmanagerbackend/source/pchmanagerserver.cpp index 06adccff5b4..999da264488 100644 --- a/src/tools/clangpchmanagerbackend/source/pchmanagerserver.cpp +++ b/src/tools/clangpchmanagerbackend/source/pchmanagerserver.cpp @@ -132,9 +132,14 @@ void PchManagerServer::pathsChanged(const FilePathIds &/*filePathIds*/) { } -void PchManagerServer::setProgress(int progress, int total) +void PchManagerServer::setPchCreationProgress(int progress, int total) { client()->progress({ProgressType::PrecompiledHeader, progress, total}); } +void PchManagerServer::setDependencyCreationProgress(int progress, int total) +{ + client()->progress({ProgressType::DependencyCreation, progress, total}); +} + } // namespace ClangBackEnd diff --git a/src/tools/clangpchmanagerbackend/source/pchmanagerserver.h b/src/tools/clangpchmanagerbackend/source/pchmanagerserver.h index 0c4bd0cc663..bf6b5bd7e76 100644 --- a/src/tools/clangpchmanagerbackend/source/pchmanagerserver.h +++ b/src/tools/clangpchmanagerbackend/source/pchmanagerserver.h @@ -60,7 +60,8 @@ public: void pathsWithIdsChanged(const Utils::SmallStringVector &ids) override; void pathsChanged(const FilePathIds &filePathIds) override; - void setProgress(int progress, int total); + void setPchCreationProgress(int progress, int total); + void setDependencyCreationProgress(int progress, int total); private: ClangPathWatcherInterface &m_fileSystemWatcher; diff --git a/tests/unit/unittest/pchmanagerclient-test.cpp b/tests/unit/unittest/pchmanagerclient-test.cpp index d35e595b04b..bd482d73c16 100644 --- a/tests/unit/unittest/pchmanagerclient-test.cpp +++ b/tests/unit/unittest/pchmanagerclient-test.cpp @@ -53,9 +53,11 @@ using testing::Not; class PchManagerClient : public ::testing::Test { protected: - NiceMock mockProgressManager; + NiceMock mockPchCreationProgressManager; + NiceMock mockDependencyCreationProgressManager; + ClangPchManager::PchManagerClient client{mockPchCreationProgressManager, + mockDependencyCreationProgressManager}; NiceMock mockPchManagerServer; - ClangPchManager::PchManagerClient client{mockProgressManager}; NiceMock mockPchManagerNotifier{client}; Sqlite::Database database{":memory:", Sqlite::JournalMode::Memory}; ClangBackEnd::RefactoringDatabaseInitializer initializer{database}; @@ -158,11 +160,17 @@ TEST_F(PchManagerClient, ProjectPartPchForProjectPartIdIsUpdated) 42); } -TEST_F(PchManagerClient, SetProgress) +TEST_F(PchManagerClient, SetPchCreationProgress) { - EXPECT_CALL(mockProgressManager, setProgress(10, 20)); + EXPECT_CALL(mockPchCreationProgressManager, setProgress(10, 20)); client.progress({ClangBackEnd::ProgressType::PrecompiledHeader, 10, 20}); } +TEST_F(PchManagerClient, SetDependencyCreationProgress) +{ + EXPECT_CALL(mockDependencyCreationProgressManager, setProgress(30, 40)); + + client.progress({ClangBackEnd::ProgressType::DependencyCreation, 30, 40}); } +} // namespace diff --git a/tests/unit/unittest/pchmanagerserver-test.cpp b/tests/unit/unittest/pchmanagerserver-test.cpp index 0cb6e3d1baf..5a2ca172c00 100644 --- a/tests/unit/unittest/pchmanagerserver-test.cpp +++ b/tests/unit/unittest/pchmanagerserver-test.cpp @@ -176,12 +176,26 @@ TEST_F(PchManagerServer, UpdateProjectPartQueueByPathIds) server.pathsWithIdsChanged({projectPartId1}); } -TEST_F(PchManagerServer, SetProgress) +TEST_F(PchManagerServer, SetPchCreationProgress) { - EXPECT_CALL(mockPchManagerClient, progress(AllOf(Field(&ClangBackEnd::ProgressMessage::progress, 20), - Field(&ClangBackEnd::ProgressMessage::total, 30)))); + EXPECT_CALL(mockPchManagerClient, + progress(AllOf(Field(&ClangBackEnd::ProgressMessage::progressType, + ClangBackEnd::ProgressType::PrecompiledHeader), + Field(&ClangBackEnd::ProgressMessage::progress, 20), + Field(&ClangBackEnd::ProgressMessage::total, 30)))); - server.setProgress(20, 30); + server.setPchCreationProgress(20, 30); +} + +TEST_F(PchManagerServer, SetDependencyCreationProgress) +{ + EXPECT_CALL(mockPchManagerClient, + progress(AllOf(Field(&ClangBackEnd::ProgressMessage::progressType, + ClangBackEnd::ProgressType::DependencyCreation), + Field(&ClangBackEnd::ProgressMessage::progress, 20), + Field(&ClangBackEnd::ProgressMessage::total, 30)))); + + server.setDependencyCreationProgress(20, 30); } TEST_F(PchManagerServer, RemoveToolChainsArguments) diff --git a/tests/unit/unittest/projectupdater-test.cpp b/tests/unit/unittest/projectupdater-test.cpp index 0ae47387d61..f41ddf89d4e 100644 --- a/tests/unit/unittest/projectupdater-test.cpp +++ b/tests/unit/unittest/projectupdater-test.cpp @@ -135,8 +135,10 @@ protected: Sqlite::Database database{":memory:", Sqlite::JournalMode::Memory}; ClangBackEnd::RefactoringDatabaseInitializer initializer{database}; ClangBackEnd::FilePathCaching filePathCache{database}; - NiceMock mockProgressManager; - ClangPchManager::PchManagerClient pchManagerClient{mockProgressManager}; + NiceMock mockPchCreationProgressManager; + NiceMock mockDependencyCreationProgressManager; + ClangPchManager::PchManagerClient pchManagerClient{mockPchCreationProgressManager, + mockDependencyCreationProgressManager}; MockPchManagerNotifier mockPchManagerNotifier{pchManagerClient}; NiceMock mockPchManagerServer; ClangPchManager::ProjectUpdater updater{mockPchManagerServer, filePathCache}; diff --git a/tests/unit/unittest/refactoringprojectupdater-test.cpp b/tests/unit/unittest/refactoringprojectupdater-test.cpp index ceb6d4b15bf..bab2377993c 100644 --- a/tests/unit/unittest/refactoringprojectupdater-test.cpp +++ b/tests/unit/unittest/refactoringprojectupdater-test.cpp @@ -87,8 +87,10 @@ protected: ClangBackEnd::RefactoringDatabaseInitializer initializer{database}; ClangBackEnd::FilePathCaching filePathCache{database}; NiceMock mockRefactoringServer; - NiceMock mockProgressManager; - ClangPchManager::PchManagerClient pchManagerClient{mockProgressManager}; + NiceMock mockPchCreationProgressManager; + NiceMock mockDependencyCreationProgressManager; + ClangPchManager::PchManagerClient pchManagerClient{mockPchCreationProgressManager, + mockDependencyCreationProgressManager}; MockCppModelManager mockCppModelManager; ClangRefactoring::RefactoringProjectUpdater updater{mockRefactoringServer, pchManagerClient, mockCppModelManager, filePathCache}; Utils::SmallString projectPartId; From 1886c5e19b8021c7f72e6962b9ef1523aa673585 Mon Sep 17 00:00:00 2001 From: Marco Bubke Date: Wed, 20 Feb 2019 16:54:09 +0100 Subject: [PATCH 28/59] Clang: Fix progress bar Task-number: QTCREATORBUG-21950 Task-number: QTCREATORBUG-21957 Change-Id: Ide39355a3f244f02b9e7fea544d0c1dd5f959e56 Reviewed-by: Ivan Donchevskii --- src/plugins/clangpchmanager/progressmanager.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/plugins/clangpchmanager/progressmanager.h b/src/plugins/clangpchmanager/progressmanager.h index 0fdf94c2196..9dc9fc03664 100644 --- a/src/plugins/clangpchmanager/progressmanager.h +++ b/src/plugins/clangpchmanager/progressmanager.h @@ -52,9 +52,8 @@ public: if (!m_promise) initialize(); - m_promise->setExpectedResultCount(maximumProgress); - if (m_promise->expectedResultCount() != maximumProgress) - m_promise->setExpectedResultCount(maximumProgress); + if (m_promise->progressMaximum() != maximumProgress) + m_promise->setProgressRange(0, maximumProgress); m_promise->setProgressValue(currentProgress); if (currentProgress >= maximumProgress) From 0a3aa12962e47db2421ad09d149118b920e404c8 Mon Sep 17 00:00:00 2001 From: Ivan Donchevskii Date: Fri, 22 Feb 2019 12:01:04 +0100 Subject: [PATCH 29/59] Clang: Follow symbol with Ctrl+click on invalid cursors When cursor is invalid try to follow it with built-in code model and highlight the token in case of success. Fixes: QTCREATORBUG-21637 Change-Id: I4c765882817fa150a155074c9d71beceb5905af8 Reviewed-by: Nikolai Kosjar --- .../clangcodemodel/clangfollowsymbol.cpp | 23 ++++++++++++++----- 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/src/plugins/clangcodemodel/clangfollowsymbol.cpp b/src/plugins/clangcodemodel/clangfollowsymbol.cpp index 96df23ab20a..f1113de164d 100644 --- a/src/plugins/clangcodemodel/clangfollowsymbol.cpp +++ b/src/plugins/clangcodemodel/clangfollowsymbol.cpp @@ -28,6 +28,7 @@ #include #include +#include #include #include @@ -183,12 +184,22 @@ void ClangFollowSymbol::findLink(const CppTools::CursorInEditor &data, return processLinkCallback(Utils::Link()); if (!resolveTarget) { - processLinkCallback(linkAtCursor(cursor, - data.filePath().toString(), - static_cast(line), - static_cast(column), - processor)); - return; + Utils::Link link = linkAtCursor(cursor, + data.filePath().toString(), + static_cast(line), + static_cast(column), + processor); + if (link == Utils::Link()) { + CppTools::FollowSymbolUnderCursor followSymbol; + return followSymbol.findLink(data, + std::move(processLinkCallback), + false, + snapshot, + documentFromSemanticInfo, + symbolFinder, + inNextSplit); + } + return processLinkCallback(link); } QFuture infoFuture From 8a93074d0ef711b8bba6545a8bc270315661a36e Mon Sep 17 00:00:00 2001 From: Ivan Donchevskii Date: Wed, 20 Feb 2019 08:43:29 +0100 Subject: [PATCH 30/59] ClangFormat: Fix the indentation for lines starting with ')' Fix the insetred text position for such cases. In the 'smart indentation mode" do not indent empty lines above the current one but apply the formatting for them instead. Change-Id: I4cfe7f9778bac5e311aa339e2fcfc717f436cb20 Reviewed-by: Marco Bubke --- .../clangformat/clangformatbaseindenter.cpp | 24 ++++++++++++------- .../clangformat/clangformatbaseindenter.h | 1 + tests/unit/unittest/clangformat-test.cpp | 13 ++++++++++ 3 files changed, 30 insertions(+), 8 deletions(-) diff --git a/src/plugins/clangformat/clangformatbaseindenter.cpp b/src/plugins/clangformat/clangformatbaseindenter.cpp index 7a87eabcd79..c295a8a650a 100644 --- a/src/plugins/clangformat/clangformatbaseindenter.cpp +++ b/src/plugins/clangformat/clangformatbaseindenter.cpp @@ -136,7 +136,7 @@ int forceIndentWithExtraText(QByteArray &buffer, const QTextBlock &block, bool s int utf8Offset = Utils::Text::utf8NthLineOffset(block.document(), buffer, block.blockNumber() + 1); - if (firstNonWhitespace > 0) + if (firstNonWhitespace >= 0) utf8Offset += firstNonWhitespace; else utf8Offset += blockText.length(); @@ -336,6 +336,7 @@ ClangFormatBaseIndenter::ClangFormatBaseIndenter(QTextDocument *doc) TextEditor::Replacements ClangFormatBaseIndenter::replacements(QByteArray buffer, const QTextBlock &startBlock, const QTextBlock &endBlock, + int cursorPositionInEditor, ReplacementsToKeep replacementsToKeep, const QChar &typedChar, bool secondTry) const @@ -353,17 +354,22 @@ TextEditor::Replacements ClangFormatBaseIndenter::replacements(QByteArray buffer if (replacementsToKeep == ReplacementsToKeep::IndentAndBefore) rangeStart = formattingRangeStart(startBlock, buffer, lastSaveRevision()); - if (replacementsToKeep == ReplacementsToKeep::IndentAndBefore) { - buffer.insert(utf8Offset - 1, " //"); - utf8Offset += 3; - } - adjustFormatStyleForLineBreak(style, replacementsToKeep); if (typedChar == QChar::Null) { - for (int index = startBlock.blockNumber(); index <= endBlock.blockNumber(); ++index) { + if (replacementsToKeep == ReplacementsToKeep::IndentAndBefore) { + buffer.insert(utf8Offset - 1, " //"); + utf8Offset += 3; utf8Length += forceIndentWithExtraText(buffer, - m_doc->findBlockByNumber(index), + cursorPositionInEditor < 0 + ? endBlock + : m_doc->findBlock(cursorPositionInEditor), secondTry); + } else { + for (int index = startBlock.blockNumber(); index <= endBlock.blockNumber(); ++index) { + utf8Length += forceIndentWithExtraText(buffer, + m_doc->findBlockByNumber(index), + secondTry); + } } } @@ -394,6 +400,7 @@ TextEditor::Replacements ClangFormatBaseIndenter::replacements(QByteArray buffer return replacements(originalBuffer, startBlock, endBlock, + cursorPositionInEditor, replacementsToKeep, typedChar, true); @@ -468,6 +475,7 @@ TextEditor::Replacements ClangFormatBaseIndenter::indentsFor(QTextBlock startBlo return replacements(buffer, startBlock, endBlock, + cursorPositionInEditor, replacementsToKeep, typedChar); } diff --git a/src/plugins/clangformat/clangformatbaseindenter.h b/src/plugins/clangformat/clangformatbaseindenter.h index ed63ff6efa3..b412b57d6d4 100644 --- a/src/plugins/clangformat/clangformatbaseindenter.h +++ b/src/plugins/clangformat/clangformatbaseindenter.h @@ -87,6 +87,7 @@ private: TextEditor::Replacements replacements(QByteArray buffer, const QTextBlock &startBlock, const QTextBlock &endBlock, + int cursorPositionInEditor, ReplacementsToKeep replacementsToKeep, const QChar &typedChar = QChar::Null, bool secondTry = false) const; diff --git a/tests/unit/unittest/clangformat-test.cpp b/tests/unit/unittest/clangformat-test.cpp index c0ff7dcd2ce..115ecaf763e 100644 --- a/tests/unit/unittest/clangformat-test.cpp +++ b/tests/unit/unittest/clangformat-test.cpp @@ -496,6 +496,19 @@ TEST_F(ClangFormat, IndentAndFormatCompleteStatementOnClosingScope) "}")); } +TEST_F(ClangFormat, IndentAndFormatWithEmptyLines) +{ + insertLines({"foo(a,", + " ", + ")"}); + + extendedIndenter.indentBlock(doc.findBlockByNumber(2), QChar::Null, TextEditor::TabSettings()); + + ASSERT_THAT(documentLines(), ElementsAre("foo(a,", + "", + " )")); +} + TEST_F(ClangFormat, FormatBasicFile) { insertLines({"int main()", From 1a65acf639e5a357eabd9cb6c8457dadf4ccd0a5 Mon Sep 17 00:00:00 2001 From: Ivan Donchevskii Date: Thu, 21 Feb 2019 10:26:08 +0100 Subject: [PATCH 31/59] ClangFormat: Warn about invalid option and restore the last style Do not save the configuration which contains errors. Change-Id: I050b22f7e589e5c39909fe1f611e56ead03d49ee Reviewed-by: Nikolai Kosjar Reviewed-by: Marco Bubke --- src/plugins/clangformat/clangformatconfigwidget.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/plugins/clangformat/clangformatconfigwidget.cpp b/src/plugins/clangformat/clangformatconfigwidget.cpp index f0d4808cf5c..8389ab5d5ed 100644 --- a/src/plugins/clangformat/clangformatconfigwidget.cpp +++ b/src/plugins/clangformat/clangformatconfigwidget.cpp @@ -38,6 +38,7 @@ #include #include +#include #include @@ -219,6 +220,17 @@ void ClangFormatConfigWidget::apply() } const QByteArray text = tableToYAML(m_ui->clangFormatOptionsTable); + clang::format::FormatStyle style; + style.Language = clang::format::FormatStyle::LK_Cpp; + const std::error_code error = clang::format::parseConfiguration(text.data(), &style); + if (error.value() != static_cast(clang::format::ParseError::Success)) { + QMessageBox::warning(this, + tr("Error in ClangFormat configuration"), + QString::fromStdString(error.message())); + fillTable(); + return; + } + QString filePath; if (m_project) filePath = m_project->projectDirectory().appendPath(Constants::SETTINGS_FILE_NAME).toString(); From c5e4d73431bd361de9e52537a7020f85f231d3d1 Mon Sep 17 00:00:00 2001 From: Ivan Donchevskii Date: Thu, 21 Feb 2019 12:13:46 +0100 Subject: [PATCH 32/59] ClangFormat: Fix crashes when new project is created Indenter is used by wizards so make sure it works. Change-Id: If26eae322e26bf2e32cb86acf45e7b3d33b67e98 Reviewed-by: Marco Bubke --- src/plugins/clangformat/clangformatbaseindenter.cpp | 6 ++++-- src/plugins/clangformat/clangformatindenter.cpp | 5 ++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/plugins/clangformat/clangformatbaseindenter.cpp b/src/plugins/clangformat/clangformatbaseindenter.cpp index c295a8a650a..a53eb50adb2 100644 --- a/src/plugins/clangformat/clangformatbaseindenter.cpp +++ b/src/plugins/clangformat/clangformatbaseindenter.cpp @@ -357,8 +357,10 @@ TextEditor::Replacements ClangFormatBaseIndenter::replacements(QByteArray buffer adjustFormatStyleForLineBreak(style, replacementsToKeep); if (typedChar == QChar::Null) { if (replacementsToKeep == ReplacementsToKeep::IndentAndBefore) { - buffer.insert(utf8Offset - 1, " //"); - utf8Offset += 3; + if (utf8Offset > 0) { + buffer.insert(utf8Offset - 1, " //"); + utf8Offset += 3; + } utf8Length += forceIndentWithExtraText(buffer, cursorPositionInEditor < 0 ? endBlock diff --git a/src/plugins/clangformat/clangformatindenter.cpp b/src/plugins/clangformat/clangformatindenter.cpp index ef9dbf5d1ca..42cedb7b6c9 100644 --- a/src/plugins/clangformat/clangformatindenter.cpp +++ b/src/plugins/clangformat/clangformatindenter.cpp @@ -84,7 +84,10 @@ Utils::optional ClangFormatIndenter::tabSettings() const int ClangFormatIndenter::lastSaveRevision() const { - return qobject_cast(m_doc->documentLayout())->lastSaveRevision; + auto *layout = qobject_cast(m_doc->documentLayout()); + if (!layout) + return 0; + return layout->lastSaveRevision; } bool ClangFormatIndenter::formatOnSave() const From 308a48323ed955c8204745fdb2d16e7762452627 Mon Sep 17 00:00:00 2001 From: Ivan Donchevskii Date: Thu, 21 Feb 2019 13:44:23 +0100 Subject: [PATCH 33/59] ClangFormat: Fix handling more complex styles Change-Id: I8c30c90a81bef786cdd0946351bf2cf46cc906ee Reviewed-by: Marco Bubke --- src/plugins/clangformat/clangformatconfigwidget.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/plugins/clangformat/clangformatconfigwidget.cpp b/src/plugins/clangformat/clangformatconfigwidget.cpp index 8389ab5d5ed..6e0080943ef 100644 --- a/src/plugins/clangformat/clangformatconfigwidget.cpp +++ b/src/plugins/clangformat/clangformatconfigwidget.cpp @@ -63,10 +63,6 @@ static void readTable(QTableWidget *table, std::istringstream &stream) if (firstLetter == std::string::npos || line.at(firstLetter) == '#') continue; - // Increase indent where it already exists. - if (firstLetter > 0 && firstLetter < 5) - line = " " + line; - table->insertRow(table->rowCount()); const size_t colonPos = line.find_first_of(':'); auto *keyItem = new QTableWidgetItem; @@ -104,8 +100,6 @@ static QByteArray tableToYAML(QTableWidget *table) auto *valueItem = table->item(i, 1); QByteArray itemText = keyItem->text().toUtf8(); - // Change the indent back to 2 spaces - itemText.replace(" ", " "); if (!valueItem->text().isEmpty() || !itemText.trimmed().startsWith('-')) itemText += ": "; itemText += valueItem->text().toUtf8() + '\n'; From 2501100c1f8ba4ae760237c1de3159f33a887121 Mon Sep 17 00:00:00 2001 From: Ivan Donchevskii Date: Thu, 21 Feb 2019 13:45:18 +0100 Subject: [PATCH 34/59] ClangFormat: Fix configuration files handling 1. Fallback to the base style from the invalid config file: If the .clang-format file from the earlier clang version is used and can't be parsed by LibFormat try to find a base style and generate the updated config based on that information. 2. Do not create new .clang-format configuration for each project. Rely on the global one until the user explicitly creates the configuration for the project. Fixes: QTCREATORBUG-22004 Change-Id: I75bd89eebc3ebae57c1f1de94da2e78924ae510c Reviewed-by: Marco Bubke --- src/plugins/clangformat/clangformatutils.cpp | 72 ++++++++++++++++---- 1 file changed, 58 insertions(+), 14 deletions(-) diff --git a/src/plugins/clangformat/clangformatutils.cpp b/src/plugins/clangformat/clangformatutils.cpp index 6b151020d68..babe94da24f 100644 --- a/src/plugins/clangformat/clangformatutils.cpp +++ b/src/plugins/clangformat/clangformatutils.cpp @@ -106,19 +106,44 @@ static Utils::FileName globalPath() return Utils::FileName::fromString(Core::ICore::userResourcePath()); } -static bool configForFileExists(Utils::FileName fileName) +static QString configForFile(Utils::FileName fileName) { + Utils::FileName topProjectPath = projectPath(); + if (topProjectPath.isEmpty()) + return QString(); + QDir projectDir(fileName.parentDir().toString()); while (!projectDir.exists(Constants::SETTINGS_FILE_NAME) && !projectDir.exists(Constants::SETTINGS_FILE_ALT_NAME)) { - if (!projectDir.cdUp()) - return false; + if (projectDir.path() == topProjectPath.toString() + || !Utils::FileName::fromString(projectDir.path()).isChildOf(topProjectPath) + || !projectDir.cdUp()) { + return QString(); + } } - return true; + + if (projectDir.exists(Constants::SETTINGS_FILE_NAME)) + return projectDir.filePath(Constants::SETTINGS_FILE_NAME); + return projectDir.filePath(Constants::SETTINGS_FILE_ALT_NAME); } -static clang::format::FormatStyle constructStyle(bool isGlobal) +static clang::format::FormatStyle constructStyle(bool isGlobal, + const QByteArray &baseStyle = QByteArray()) { + if (!baseStyle.isEmpty()) { + // Try to get the style for this base style. + Expected style = getStyle(baseStyle.toStdString(), + "dummy.cpp", + baseStyle.toStdString()); + if (style) + return *style; + + handleAllErrors(style.takeError(), [](const ErrorInfoBase &) { + // do nothing + }); + // Fallthrough to the default style. + } + FormatStyle style = getLLVMStyle(); style.BreakBeforeBraces = FormatStyle::BS_Custom; @@ -151,18 +176,37 @@ void createStyleFileIfNeeded(bool isGlobal) } } +static QByteArray configBaseStyleName(const QString &configFile) +{ + if (configFile.isEmpty()) + return QByteArray(); + + QFile config(configFile); + if (!config.open(QIODevice::ReadOnly)) + return QByteArray(); + + const QByteArray content = config.readAll(); + const char basedOnStyle[] = "BasedOnStyle:"; + int basedOnStyleIndex = content.indexOf(basedOnStyle); + if (basedOnStyleIndex < 0) + return QByteArray(); + + basedOnStyleIndex += sizeof(basedOnStyle) - 1; + const int endOfLineIndex = content.indexOf('\n', basedOnStyleIndex); + return content + .mid(basedOnStyleIndex, endOfLineIndex < 0 ? -1 : endOfLineIndex - basedOnStyleIndex) + .trimmed(); +} + clang::format::FormatStyle styleForFile(Utils::FileName fileName) { bool isGlobal = false; - if (!configForFileExists(fileName)) { - if (fileName.isChildOf(projectPath()) && CppCodeStyleSettings::currentProjectCodeStyle()) { - fileName = projectPath(); - } else { - fileName = globalPath(); - isGlobal = true; - } + QString configFile = configForFile(fileName); + if (configFile.isEmpty()) { + Utils::FileName path = fileName = globalPath(); fileName.appendPath(Constants::SAMPLE_FILE_NAME); - createStyleFileIfNeeded(isGlobal); + createStyleFileIfNeeded(true); + configFile = path.appendPath(Constants::SETTINGS_FILE_NAME).toString(); } Expected style = format::getStyle("file", @@ -175,7 +219,7 @@ clang::format::FormatStyle styleForFile(Utils::FileName fileName) // do nothing }); - return constructStyle(isGlobal); + return constructStyle(isGlobal, configBaseStyleName(configFile)); } clang::format::FormatStyle currentProjectStyle() From 3b79fafb3f7bbcbe68418be747009d00f0221a43 Mon Sep 17 00:00:00 2001 From: Orgad Shaneh Date: Fri, 22 Feb 2019 12:55:02 +0200 Subject: [PATCH 35/59] GccToolChain: Pass any -m flag for macro inspection There are *many* -m flags, and most of them affect the preprocessor macros. It doesn't make sense to have an endless list of "known" -m flags (which missed for example -mabi=*). Instead, just pass all of them to the compiler. Some lists: https://gcc.gnu.org/onlinedocs/gcc/x86-Options.html https://gcc.gnu.org/onlinedocs/gcc/MIPS-Options.html Change-Id: I1b412f6b75ef8e2dab4e172fb77f94dd76d12802 Reviewed-by: Christian Kandeler --- src/plugins/projectexplorer/gcctoolchain.cpp | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/plugins/projectexplorer/gcctoolchain.cpp b/src/plugins/projectexplorer/gcctoolchain.cpp index f36a6b9440e..f1e0ea4cb46 100644 --- a/src/plugins/projectexplorer/gcctoolchain.cpp +++ b/src/plugins/projectexplorer/gcctoolchain.cpp @@ -402,15 +402,7 @@ ToolChain::MacroInspectionRunner GccToolChain::createMacroInspectionRunner() con || a == "-gcc-toolchain" || a == "-target") { if (++iArg < allFlags.length()) arguments << a << allFlags.at(iArg); - } else if (a == "-m128bit-long-double" || a == "-m32" || a == "-m3dnow" - || a == "-m3dnowa" || a == "-m64" || a == "-m96bit-long-double" - || a == "-mabm" || a == "-maes" || a.startsWith("-march=") || a == "-mavx" - || a.startsWith("-masm=") || a.startsWith("-mfloat-abi") || a == "-mcx16" - || a == "-mfma" || a == "-mfma4" || a == "-mlwp" || a == "-mpclmul" - || a == "-mpopcnt" || a == "-msse" || a == "-msse2" || a == "-msse2avx" - || a == "-msse3" || a == "-msse4" || a == "-msse4.1" || a == "-msse4.2" - || a == "-msse4a" || a == "-mssse3" || a.startsWith("-mtune=") - || a == "-mxop" || a == "-Os" || a == "-O0" || a == "-O1" || a == "-O2" + } else if (a.startsWith("-m") || a == "-Os" || a == "-O0" || a == "-O1" || a == "-O2" || a == "-O3" || a == "-ffinite-math-only" || a == "-fshort-double" || a == "-fshort-wchar" || a == "-fsignaling-nans" || a == "-fno-inline" || a == "-fno-exceptions" || a == "-fstack-protector" From c6b58a063f1e3e92b3126511380416c6c6c299b4 Mon Sep 17 00:00:00 2001 From: Ivan Donchevskii Date: Thu, 21 Feb 2019 15:00:49 +0100 Subject: [PATCH 36/59] ClangFormat: Show .clang-format file as text instead of the table Change-Id: I8b912ec6f29dfe7059ac6ab3888a6c3698769fc1 Reviewed-by: Marco Bubke --- .../clangformat/clangformatconfigwidget.cpp | 85 ++----------------- .../clangformat/clangformatconfigwidget.ui | 2 +- 2 files changed, 9 insertions(+), 78 deletions(-) diff --git a/src/plugins/clangformat/clangformatconfigwidget.cpp b/src/plugins/clangformat/clangformatconfigwidget.cpp index 6e0080943ef..dd66a53bd2a 100644 --- a/src/plugins/clangformat/clangformatconfigwidget.cpp +++ b/src/plugins/clangformat/clangformatconfigwidget.cpp @@ -23,7 +23,6 @@ ** ****************************************************************************/ - #include "clangformatconfigwidget.h" #include "clangformatconstants.h" @@ -46,73 +45,7 @@ using namespace ProjectExplorer; namespace ClangFormat { -static void readTable(QTableWidget *table, std::istringstream &stream) -{ - table->horizontalHeader()->hide(); - table->verticalHeader()->hide(); - - table->setColumnCount(2); - table->setRowCount(0); - - std::string line; - while (std::getline(stream, line)) { - if (line == "---" || line == "...") - continue; - - const size_t firstLetter = line.find_first_not_of(' '); - if (firstLetter == std::string::npos || line.at(firstLetter) == '#') - continue; - - table->insertRow(table->rowCount()); - const size_t colonPos = line.find_first_of(':'); - auto *keyItem = new QTableWidgetItem; - auto *valueItem = new QTableWidgetItem; - - keyItem->setFlags(keyItem->flags() & ~Qt::ItemFlags(Qt::ItemIsEditable)); - table->setItem(table->rowCount() - 1, 0, keyItem); - table->setItem(table->rowCount() - 1, 1, valueItem); - - if (colonPos == std::string::npos) { - keyItem->setText(QString::fromStdString(line)); - valueItem->setFlags(valueItem->flags() & ~Qt::ItemFlags(Qt::ItemIsEditable)); - continue; - } - - keyItem->setText(QString::fromStdString(line.substr(0, colonPos))); - - const size_t optionValueStart = line.find_first_not_of(' ', colonPos + 1); - if (optionValueStart == std::string::npos) - valueItem->setFlags(valueItem->flags() & ~Qt::ItemFlags(Qt::ItemIsEditable)); - else - valueItem->setText(QString::fromStdString(line.substr(optionValueStart))); - } - - table->resizeColumnToContents(0); - table->resizeColumnToContents(1); -} - -static QByteArray tableToYAML(QTableWidget *table) -{ - QByteArray text; - text += "---\n"; - for (int i = 0; i < table->rowCount(); ++i) { - auto *keyItem = table->item(i, 0); - auto *valueItem = table->item(i, 1); - - QByteArray itemText = keyItem->text().toUtf8(); - if (!valueItem->text().isEmpty() || !itemText.trimmed().startsWith('-')) - itemText += ": "; - itemText += valueItem->text().toUtf8() + '\n'; - - text += itemText; - } - text += "...\n"; - - return text; -} - -ClangFormatConfigWidget::ClangFormatConfigWidget(ProjectExplorer::Project *project, - QWidget *parent) +ClangFormatConfigWidget::ClangFormatConfigWidget(ProjectExplorer::Project *project, QWidget *parent) : CodeStyleEditorWidget(parent) , m_project(project) , m_ui(std::make_unique()) @@ -159,8 +92,7 @@ void ClangFormatConfigWidget::initialize() m_ui->applyButton->hide(); m_ui->verticalLayout->addStretch(1); - connect(m_ui->createFileButton, &QPushButton::clicked, - this, [this]() { + connect(m_ui->createFileButton, &QPushButton::clicked, this, [this]() { createStyleFileIfNeeded(false); initialize(); }); @@ -181,8 +113,8 @@ void ClangFormatConfigWidget::initialize() m_ui->projectHasClangFormat->hide(); } else { m_ui->projectHasClangFormat->setText( - tr("Current project has its own .clang-format file " - "and can be configured in Projects > Code Style > C++.")); + tr("Current project has its own .clang-format file " + "and can be configured in Projects > Code Style > C++.")); } createStyleFileIfNeeded(true); showGlobalCheckboxes(); @@ -197,8 +129,7 @@ void ClangFormatConfigWidget::fillTable() clang::format::FormatStyle style = m_project ? currentProjectStyle() : currentGlobalStyle(); std::string configText = clang::format::configurationAsText(style); - std::istringstream stream(configText); - readTable(m_ui->clangFormatOptionsTable, stream); + m_ui->clangFormatOptionsTable->setPlainText(QString::fromStdString(configText)); } ClangFormatConfigWidget::~ClangFormatConfigWidget() = default; @@ -213,10 +144,10 @@ void ClangFormatConfigWidget::apply() settings.write(); } - const QByteArray text = tableToYAML(m_ui->clangFormatOptionsTable); + const QString text = m_ui->clangFormatOptionsTable->toPlainText(); clang::format::FormatStyle style; style.Language = clang::format::FormatStyle::LK_Cpp; - const std::error_code error = clang::format::parseConfiguration(text.data(), &style); + const std::error_code error = clang::format::parseConfiguration(text.toStdString(), &style); if (error.value() != static_cast(clang::format::ParseError::Success)) { QMessageBox::warning(this, tr("Error in ClangFormat configuration"), @@ -234,7 +165,7 @@ void ClangFormatConfigWidget::apply() if (!file.open(QFile::WriteOnly)) return; - file.write(text); + file.write(text.toUtf8()); file.close(); } diff --git a/src/plugins/clangformat/clangformatconfigwidget.ui b/src/plugins/clangformat/clangformatconfigwidget.ui index 2094bca1090..9586f14d868 100644 --- a/src/plugins/clangformat/clangformatconfigwidget.ui +++ b/src/plugins/clangformat/clangformatconfigwidget.ui @@ -55,7 +55,7 @@ - + From 956543e462fcb965f3ad637ac1e38ff6c80c7f3c Mon Sep 17 00:00:00 2001 From: Ivan Donchevskii Date: Fri, 22 Feb 2019 09:48:46 +0100 Subject: [PATCH 37/59] ClangFormat: Add the preview text editor to the settings Allows the user to see how the current style applies to the code snippet. The action is triggered by the 'Apply' button. Change-Id: I820d989519cfdfb6e617ed6e8e9e5751be6619ea Reviewed-by: Marco Bubke Reviewed-by: Leena Miettinen --- .../clangformat/clangformat_dependencies.pri | 2 +- .../clangformat/clangformatconfigwidget.cpp | 35 ++++ .../clangformat/clangformatconfigwidget.h | 10 +- .../clangformat/clangformatconfigwidget.ui | 6 +- src/plugins/cppeditor/cpphighlighter.cpp | 2 +- src/plugins/cppeditor/cpphighlighter.h | 8 +- .../cpptools/cppcodestylesettingspage.cpp | 166 +----------------- src/plugins/cpptools/cpptoolsconstants.h | 158 +++++++++++++++++ 8 files changed, 213 insertions(+), 174 deletions(-) diff --git a/src/plugins/clangformat/clangformat_dependencies.pri b/src/plugins/clangformat/clangformat_dependencies.pri index 5f3f81e1328..6822c5d66be 100644 --- a/src/plugins/clangformat/clangformat_dependencies.pri +++ b/src/plugins/clangformat/clangformat_dependencies.pri @@ -5,4 +5,4 @@ QTC_LIB_DEPENDS += \ QTC_PLUGIN_DEPENDS += \ cpptools \ projectexplorer \ - texteditor + cppeditor diff --git a/src/plugins/clangformat/clangformatconfigwidget.cpp b/src/plugins/clangformat/clangformatconfigwidget.cpp index dd66a53bd2a..6aa14b9a71a 100644 --- a/src/plugins/clangformat/clangformatconfigwidget.cpp +++ b/src/plugins/clangformat/clangformatconfigwidget.cpp @@ -26,6 +26,7 @@ #include "clangformatconfigwidget.h" #include "clangformatconstants.h" +#include "clangformatindenter.h" #include "clangformatsettings.h" #include "clangformatutils.h" #include "ui_clangformatconfigwidget.h" @@ -33,8 +34,14 @@ #include #include +#include +#include #include #include +#include +#include +#include +#include #include #include @@ -81,6 +88,17 @@ void ClangFormatConfigWidget::initialize() m_ui->applyButton->show(); hideGlobalCheckboxes(); + m_preview = new TextEditor::SnippetEditorWidget(this); + m_ui->horizontalLayout_2->addWidget(m_preview); + m_preview->setPlainText(QLatin1String(CppTools::Constants::DEFAULT_CODE_STYLE_SNIPPETS[0])); + m_preview->textDocument()->setIndenter(new ClangFormatIndenter(m_preview->document())); + m_preview->textDocument()->setFontSettings(TextEditor::TextEditorSettings::fontSettings()); + m_preview->textDocument()->setSyntaxHighlighter(new CppEditor::CppHighlighter); + + TextEditor::DisplaySettings displaySettings = m_preview->displaySettings(); + displaySettings.m_visualizeWhitespace = true; + m_preview->setDisplaySettings(displaySettings); + QLayoutItem *lastItem = m_ui->verticalLayout->itemAt(m_ui->verticalLayout->count() - 1); if (lastItem->spacerItem()) m_ui->verticalLayout->removeItem(lastItem); @@ -101,9 +119,11 @@ void ClangFormatConfigWidget::initialize() m_ui->createFileButton->hide(); + Utils::FileName fileName; if (m_project) { m_ui->projectHasClangFormat->hide(); connect(m_ui->applyButton, &QPushButton::clicked, this, &ClangFormatConfigWidget::apply); + fileName = m_project->projectFilePath().appendPath("snippet.cpp"); } else { const Project *currentProject = SessionManager::startupProject(); if (!currentProject @@ -119,9 +139,21 @@ void ClangFormatConfigWidget::initialize() createStyleFileIfNeeded(true); showGlobalCheckboxes(); m_ui->applyButton->hide(); + fileName = Utils::FileName::fromString(Core::ICore::userResourcePath()) + .appendPath("snippet.cpp"); } + m_preview->textDocument()->indenter()->setFileName(fileName); fillTable(); + updatePreview(); +} + +void ClangFormatConfigWidget::updatePreview() +{ + QTextCursor cursor(m_preview->document()); + cursor.setPosition(0); + cursor.movePosition(QTextCursor::End, QTextCursor::KeepAnchor); + m_preview->textDocument()->autoFormatOrIndent(cursor); } void ClangFormatConfigWidget::fillTable() @@ -153,6 +185,7 @@ void ClangFormatConfigWidget::apply() tr("Error in ClangFormat configuration"), QString::fromStdString(error.message())); fillTable(); + updatePreview(); return; } @@ -167,6 +200,8 @@ void ClangFormatConfigWidget::apply() file.write(text.toUtf8()); file.close(); + + updatePreview(); } } // namespace ClangFormat diff --git a/src/plugins/clangformat/clangformatconfigwidget.h b/src/plugins/clangformat/clangformatconfigwidget.h index 7d3818b7a52..58570d9bf68 100644 --- a/src/plugins/clangformat/clangformatconfigwidget.h +++ b/src/plugins/clangformat/clangformatconfigwidget.h @@ -29,7 +29,12 @@ #include -namespace ProjectExplorer { class Project; } +namespace ProjectExplorer { +class Project; +} +namespace TextEditor { +class SnippetEditorWidget; +} namespace ClangFormat { @@ -54,7 +59,10 @@ private: void hideGlobalCheckboxes(); void showGlobalCheckboxes(); + void updatePreview(); + ProjectExplorer::Project *m_project; + TextEditor::SnippetEditorWidget *m_preview; std::unique_ptr m_ui; }; diff --git a/src/plugins/clangformat/clangformatconfigwidget.ui b/src/plugins/clangformat/clangformatconfigwidget.ui index 9586f14d868..41e40ef1fdc 100644 --- a/src/plugins/clangformat/clangformatconfigwidget.ui +++ b/src/plugins/clangformat/clangformatconfigwidget.ui @@ -55,7 +55,11 @@ - + + + + + diff --git a/src/plugins/cppeditor/cpphighlighter.cpp b/src/plugins/cppeditor/cpphighlighter.cpp index 075791b021d..a7531acf1ed 100644 --- a/src/plugins/cppeditor/cpphighlighter.cpp +++ b/src/plugins/cppeditor/cpphighlighter.cpp @@ -35,7 +35,7 @@ #include -using namespace CppEditor::Internal; +using namespace CppEditor; using namespace TextEditor; using namespace CPlusPlus; diff --git a/src/plugins/cppeditor/cpphighlighter.h b/src/plugins/cppeditor/cpphighlighter.h index e43ce63172b..a982191b7ec 100644 --- a/src/plugins/cppeditor/cpphighlighter.h +++ b/src/plugins/cppeditor/cpphighlighter.h @@ -25,6 +25,8 @@ #pragma once +#include "cppeditor_global.h" + #include #include @@ -33,10 +35,7 @@ namespace CppEditor { -namespace Internal { - - -class CppHighlighter : public TextEditor::SyntaxHighlighter +class CPPEDITOR_EXPORT CppHighlighter : public TextEditor::SyntaxHighlighter { Q_OBJECT @@ -58,5 +57,4 @@ private: CPlusPlus::LanguageFeatures m_languageFeatures = CPlusPlus::LanguageFeatures::defaultFeatures(); }; -} // namespace Internal } // namespace CppEditor diff --git a/src/plugins/cpptools/cppcodestylesettingspage.cpp b/src/plugins/cpptools/cppcodestylesettingspage.cpp index 39517e6e353..981a0bda617 100644 --- a/src/plugins/cpptools/cppcodestylesettingspage.cpp +++ b/src/plugins/cpptools/cppcodestylesettingspage.cpp @@ -49,170 +49,6 @@ #include #include -static const char *defaultCodeStyleSnippets[] = { - "#include \n" - "\n" - "class Complex\n" - " {\n" - "public:\n" - " Complex(double re, double im)\n" - " : _re(re), _im(im)\n" - " {}\n" - " double modulus() const\n" - " {\n" - " return sqrt(_re * _re + _im * _im);\n" - " }\n" - "private:\n" - " double _re;\n" - " double _im;\n" - " };\n" - "\n" - "void bar(int i)\n" - " {\n" - " static int counter = 0;\n" - " counter += i;\n" - " }\n" - "\n" - "namespace Foo\n" - " {\n" - " namespace Bar\n" - " {\n" - " void foo(int a, int b)\n" - " {\n" - " for (int i = 0; i < a; i++)\n" - " {\n" - " if (i < b)\n" - " bar(i);\n" - " else\n" - " {\n" - " bar(i);\n" - " bar(b);\n" - " }\n" - " }\n" - " }\n" - " } // namespace Bar\n" - " } // namespace Foo\n" - , - "#include \n" - "\n" - "class Complex\n" - " {\n" - "public:\n" - " Complex(double re, double im)\n" - " : _re(re), _im(im)\n" - " {}\n" - " double modulus() const\n" - " {\n" - " return sqrt(_re * _re + _im * _im);\n" - " }\n" - "private:\n" - " double _re;\n" - " double _im;\n" - " };\n" - "\n" - "void bar(int i)\n" - " {\n" - " static int counter = 0;\n" - " counter += i;\n" - " }\n" - "\n" - "namespace Foo\n" - " {\n" - " namespace Bar\n" - " {\n" - " void foo(int a, int b)\n" - " {\n" - " for (int i = 0; i < a; i++)\n" - " {\n" - " if (i < b)\n" - " bar(i);\n" - " else\n" - " {\n" - " bar(i);\n" - " bar(b);\n" - " }\n" - " }\n" - " }\n" - " } // namespace Bar\n" - " } // namespace Foo\n" - , - "namespace Foo\n" - "{\n" - "namespace Bar\n" - "{\n" - "class FooBar\n" - " {\n" - "public:\n" - " FooBar(int a)\n" - " : _a(a)\n" - " {}\n" - " int calculate() const\n" - " {\n" - " if (a > 10)\n" - " {\n" - " int b = 2 * a;\n" - " return a * b;\n" - " }\n" - " return -a;\n" - " }\n" - "private:\n" - " int _a;\n" - " };\n" - "}\n" - "}\n" - , - "#include \"bar.h\"\n" - "\n" - "int foo(int a)\n" - " {\n" - " switch (a)\n" - " {\n" - " case 1:\n" - " bar(1);\n" - " break;\n" - " case 2:\n" - " {\n" - " bar(2);\n" - " break;\n" - " }\n" - " case 3:\n" - " default:\n" - " bar(3);\n" - " break;\n" - " }\n" - " return 0;\n" - " }\n" - , - "void foo() {\n" - " if (a &&\n" - " b)\n" - " c;\n" - "\n" - " while (a ||\n" - " b)\n" - " break;\n" - " a = b +\n" - " c;\n" - " myInstance.longMemberName +=\n" - " foo;\n" - " myInstance.longMemberName += bar +\n" - " foo;\n" - "}\n" - , - "int *foo(const Bar &b1, Bar &&b2, int*, int *&rpi)\n" - "{\n" - " int*pi = 0;\n" - " int*const*const cpcpi = π\n" - " int*const*pcpi = π\n" - " int**const cppi = π\n" - "\n" - " void (*foo)(char *s) = 0;\n" - " int (*bar)[] = 0;\n" - "\n" - " return pi;\n" - "}\n" -}; - using namespace TextEditor; namespace CppTools { @@ -270,7 +106,7 @@ CppCodeStylePreferencesWidget::CppCodeStylePreferencesWidget(QWidget *parent) << m_ui->previewTextEditBraces << m_ui->previewTextEditSwitch << m_ui->previewTextEditPadding << m_ui->previewTextEditPointerReferences; for (int i = 0; i < m_previews.size(); ++i) - m_previews[i]->setPlainText(QLatin1String(defaultCodeStyleSnippets[i])); + m_previews[i]->setPlainText(QLatin1String(Constants::DEFAULT_CODE_STYLE_SNIPPETS[i])); decorateEditors(TextEditorSettings::fontSettings()); connect(TextEditorSettings::instance(), &TextEditorSettings::fontSettingsChanged, diff --git a/src/plugins/cpptools/cpptoolsconstants.h b/src/plugins/cpptools/cpptoolsconstants.h index 2e1aebfd432..781f5ebdf89 100644 --- a/src/plugins/cpptools/cpptoolsconstants.h +++ b/src/plugins/cpptools/cpptoolsconstants.h @@ -105,5 +105,163 @@ constexpr const char TIDY_DOCUMENTATION_URL_TEMPLATE[] constexpr const char CLAZY_DOCUMENTATION_URL_TEMPLATE[] = "https://github.com/KDE/clazy/blob/master/docs/checks/README-%1.md"; +static const char *DEFAULT_CODE_STYLE_SNIPPETS[] + = {"#include \n" + "\n" + "class Complex\n" + " {\n" + "public:\n" + " Complex(double re, double im)\n" + " : _re(re), _im(im)\n" + " {}\n" + " double modulus() const\n" + " {\n" + " return sqrt(_re * _re + _im * _im);\n" + " }\n" + "private:\n" + " double _re;\n" + " double _im;\n" + " };\n" + "\n" + "void bar(int i)\n" + " {\n" + " static int counter = 0;\n" + " counter += i;\n" + " }\n" + "\n" + "namespace Foo\n" + " {\n" + " namespace Bar\n" + " {\n" + " void foo(int a, int b)\n" + " {\n" + " for (int i = 0; i < a; i++)\n" + " {\n" + " if (i < b)\n" + " bar(i);\n" + " else\n" + " {\n" + " bar(i);\n" + " bar(b);\n" + " }\n" + " }\n" + " }\n" + " } // namespace Bar\n" + " } // namespace Foo\n", + "#include \n" + "\n" + "class Complex\n" + " {\n" + "public:\n" + " Complex(double re, double im)\n" + " : _re(re), _im(im)\n" + " {}\n" + " double modulus() const\n" + " {\n" + " return sqrt(_re * _re + _im * _im);\n" + " }\n" + "private:\n" + " double _re;\n" + " double _im;\n" + " };\n" + "\n" + "void bar(int i)\n" + " {\n" + " static int counter = 0;\n" + " counter += i;\n" + " }\n" + "\n" + "namespace Foo\n" + " {\n" + " namespace Bar\n" + " {\n" + " void foo(int a, int b)\n" + " {\n" + " for (int i = 0; i < a; i++)\n" + " {\n" + " if (i < b)\n" + " bar(i);\n" + " else\n" + " {\n" + " bar(i);\n" + " bar(b);\n" + " }\n" + " }\n" + " }\n" + " } // namespace Bar\n" + " } // namespace Foo\n", + "namespace Foo\n" + "{\n" + "namespace Bar\n" + "{\n" + "class FooBar\n" + " {\n" + "public:\n" + " FooBar(int a)\n" + " : _a(a)\n" + " {}\n" + " int calculate() const\n" + " {\n" + " if (a > 10)\n" + " {\n" + " int b = 2 * a;\n" + " return a * b;\n" + " }\n" + " return -a;\n" + " }\n" + "private:\n" + " int _a;\n" + " };\n" + "}\n" + "}\n", + "#include \"bar.h\"\n" + "\n" + "int foo(int a)\n" + " {\n" + " switch (a)\n" + " {\n" + " case 1:\n" + " bar(1);\n" + " break;\n" + " case 2:\n" + " {\n" + " bar(2);\n" + " break;\n" + " }\n" + " case 3:\n" + " default:\n" + " bar(3);\n" + " break;\n" + " }\n" + " return 0;\n" + " }\n", + "void foo() {\n" + " if (a &&\n" + " b)\n" + " c;\n" + "\n" + " while (a ||\n" + " b)\n" + " break;\n" + " a = b +\n" + " c;\n" + " myInstance.longMemberName +=\n" + " foo;\n" + " myInstance.longMemberName += bar +\n" + " foo;\n" + "}\n", + "int *foo(const Bar &b1, Bar &&b2, int*, int *&rpi)\n" + "{\n" + " int*pi = 0;\n" + " int*const*const cpcpi = π\n" + " int*const*pcpi = π\n" + " int**const cppi = π\n" + "\n" + " void (*foo)(char *s) = 0;\n" + " int (*bar)[] = 0;\n" + "\n" + " return pi;\n" + "}\n"}; + } // namespace Constants } // namespace CppTools From 4d40254619bf06915eb26d3d24d158db0996fa4a Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Thu, 21 Feb 2019 17:16:46 +0100 Subject: [PATCH 38/59] Qmake: Make sure generated qrc files are treated as such That is, they show up in the project tree only if "Hide generated files" is not selected. Task-number: QTCREATORBUG-20103 Change-Id: I63ec2ff5b696e54e07353fe53981ad83573d461a Reviewed-by: hjk --- src/plugins/projectexplorer/projectmodels.cpp | 5 +++-- src/plugins/qmakeprojectmanager/qmakenodetreebuilder.cpp | 5 ++++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/plugins/projectexplorer/projectmodels.cpp b/src/plugins/projectexplorer/projectmodels.cpp index d90e3495244..49a9258f619 100644 --- a/src/plugins/projectexplorer/projectmodels.cpp +++ b/src/plugins/projectexplorer/projectmodels.cpp @@ -362,6 +362,8 @@ void FlatModel::saveExpandData() void FlatModel::addFolderNode(WrapperNode *parent, FolderNode *folderNode, QSet *seen) { for (Node *node : folderNode->nodes()) { + if (m_filterGeneratedFiles && node->isGenerated()) + continue; if (FolderNode *subFolderNode = node->asFolderNode()) { const bool isHidden = m_filterProjects && !subFolderNode->showInSimpleTree(); if (!isHidden && !seen->contains(subFolderNode)) { @@ -374,8 +376,7 @@ void FlatModel::addFolderNode(WrapperNode *parent, FolderNode *folderNode, QSet< addFolderNode(parent, subFolderNode, seen); } } else if (FileNode *fileNode = node->asFileNode()) { - const bool isHidden = m_filterGeneratedFiles && fileNode->isGenerated(); - if (!isHidden && !seen->contains(fileNode)) { + if (!seen->contains(fileNode)) { seen->insert(fileNode); parent->appendChild(new WrapperNode(fileNode)); } diff --git a/src/plugins/qmakeprojectmanager/qmakenodetreebuilder.cpp b/src/plugins/qmakeprojectmanager/qmakenodetreebuilder.cpp index b4e3b28abb9..253f9939d2b 100644 --- a/src/plugins/qmakeprojectmanager/qmakenodetreebuilder.cpp +++ b/src/plugins/qmakeprojectmanager/qmakenodetreebuilder.cpp @@ -167,7 +167,10 @@ static void createTree(const QmakePriFile *pri, QmakePriFileNode *node, const Fi int eid = vfs->idForFileName(file.toString(), QMakeVfs::VfsExact); vfs->readFile(eid, &contents, &errorMessage); } - vfolder->addNode(std::make_unique(file, false, contents, vfolder.get())); + const QString baseName = file.toFileInfo().completeBaseName(); + const bool generated = baseName.startsWith("qmake_") + || baseName.endsWith("_qmlcache"); + vfolder->addNode(std::make_unique(file, generated, contents, vfolder.get())); } } else { for (const FileName &fn : newFilePaths) { From 1487997551fb982d6c2c9a95b6ff43cfad5ddbcf Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Mon, 18 Feb 2019 15:34:43 +0100 Subject: [PATCH 39/59] Qt plugin wizard: Fix excess whitespace Amends 075e1da67e. Fixes: QTCREATORBUG-21974 Change-Id: I4216b06ac9753e552e34575ff10f3789ff5ad8dc Reviewed-by: Robert Loehning Reviewed-by: Alessandro Portale --- src/plugins/qmakeprojectmanager/wizards/libraryparameters.cpp | 4 +++- .../qmakeprojectmanager/wizards/librarywizarddialog.cpp | 2 +- tests/system/suite_APTW/tst_APTW03/test.py | 4 ++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/plugins/qmakeprojectmanager/wizards/libraryparameters.cpp b/src/plugins/qmakeprojectmanager/wizards/libraryparameters.cpp index aa46476ae03..83217ce2bf3 100644 --- a/src/plugins/qmakeprojectmanager/wizards/libraryparameters.cpp +++ b/src/plugins/qmakeprojectmanager/wizards/libraryparameters.cpp @@ -32,6 +32,8 @@ #include #include +#include + namespace QmakeProjectManager { namespace Internal { @@ -150,7 +152,7 @@ void LibraryParameters::generateCode(QtProjectParameters:: Type t, } QTC_ASSERT(nameIndex != -1, continue); sourceStr << '\n' << namespaceIndent << signature.left(nameIndex); - if (signature.at(nameIndex - 1) != ' ') + if (!std::strchr("&* ", signature.at(nameIndex - 1).toLatin1())) sourceStr << ' '; sourceStr << unqualifiedClassName << "::" << signature.mid(nameIndex) << '\n'; sourceStr << namespaceIndent << "{\n" << indent diff --git a/src/plugins/qmakeprojectmanager/wizards/librarywizarddialog.cpp b/src/plugins/qmakeprojectmanager/wizards/librarywizarddialog.cpp index 0381e2670a6..2aed6d43cd0 100644 --- a/src/plugins/qmakeprojectmanager/wizards/librarywizarddialog.cpp +++ b/src/plugins/qmakeprojectmanager/wizards/librarywizarddialog.cpp @@ -56,7 +56,7 @@ using QSL = QStringList; static const PluginBaseClasses pluginBaseClasses[] = { {"QAccessiblePlugin", "QtGui", - QSL{"QAccessibleInterface * create(const QString &key, QObject *object)"}, + QSL{"QAccessibleInterface *create(const QString &key, QObject *object)"}, "QtCore", "accessible", "QAccessibleFactoryInterface"}, {"QGenericPlugin", "QtGui", QSL{"QObject *create(const QString &name, const QString &spec)"}, "QtCore", "generic", "QGenericPluginFactoryInterface"}, diff --git a/tests/system/suite_APTW/tst_APTW03/test.py b/tests/system/suite_APTW/tst_APTW03/test.py index bab90c9459d..6c508e09ca7 100644 --- a/tests/system/suite_APTW/tst_APTW03/test.py +++ b/tests/system/suite_APTW/tst_APTW03/test.py @@ -103,7 +103,7 @@ def main(): continue editor = getEditorForFileSuffix("%s.cpp" % className.lower()) initialContent = str(editor.plainText) - test.verify("QObject * %s::create(" % className in initialContent, + test.verify("QObject *%s::create(" % className in initialContent, "Verifying whether pure virtual function has been added to the source file.") if not openDocument("%s.Headers.%s\.h" % (projectName, className.lower())): test.fatal("Could not open %s.h - continuing." % className.lower()) @@ -131,7 +131,7 @@ def main(): "Verifying whether event() definition has been added to the source file.") # add return to not run into build issues of missing return values addReturn(editor, "bool %s::event.*" % className, "true") - addReturn(editor, "QObject \* %s::create.*" % className, "0") + addReturn(editor, "QObject \*%s::create.*" % className, "0") placeCursorToLine(editor, 'static_assert\(false, .*', True) invokeContextMenuItem(editor, "Toggle Comment Selection") virtualFunctionsAdded = True From 52ec46a60fae6cfbcae51c30de7c66f1ac31597e Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Fri, 22 Feb 2019 10:37:36 +0100 Subject: [PATCH 40/59] Fix build of command-line qbs with qbs The plugin path we pass as a define to the qbs sources contained the "/ qbs/plugins" suffix which qbs already adds itself. Therefore, the command-line qbs was not functional. Change-Id: I2bfb967f998e69bbe4da760a1f517e1f40e4f055 Reviewed-by: Christian Stenger Reviewed-by: Joerg Bornemann --- qbs/modules/qbsbuildconfig/qbsbuildconfig.qbs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qbs/modules/qbsbuildconfig/qbsbuildconfig.qbs b/qbs/modules/qbsbuildconfig/qbsbuildconfig.qbs index 845ce4139c6..4a0d6cab1d0 100644 --- a/qbs/modules/qbsbuildconfig/qbsbuildconfig.qbs +++ b/qbs/modules/qbsbuildconfig/qbsbuildconfig.qbs @@ -25,7 +25,7 @@ Module { property string relativeLibexecPath: FileInfo.relativePath('/' + appInstallDir, '/' + libexecInstallDir) property string relativePluginsPath: FileInfo.relativePath('/' + appInstallDir, - '/' + pluginsInstallDir) + '/' + qtc.ide_plugin_path) property string relativeSearchPath: FileInfo.relativePath('/' + appInstallDir, '/' + resourcesInstallDir) } From 3621079f7623696da23dba8dcde38b4ee962cb40 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Tue, 19 Feb 2019 12:43:01 +0100 Subject: [PATCH 41/59] Squish: Fix tst_APT03 This patch amends 80cd9cfa8a. Change-Id: I9d70708e76cc1cf409d4b9a177ccf58ae3ecc496 Reviewed-by: Robert Loehning Reviewed-by: Christian Stenger --- tests/system/suite_APTW/tst_APTW03/test.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/tests/system/suite_APTW/tst_APTW03/test.py b/tests/system/suite_APTW/tst_APTW03/test.py index 6c508e09ca7..521a3f1772e 100644 --- a/tests/system/suite_APTW/tst_APTW03/test.py +++ b/tests/system/suite_APTW/tst_APTW03/test.py @@ -85,11 +85,7 @@ def main(): checkSimpleCppLib("SampleApp1", False) checkSimpleCppLib("SampleApp2", True) - pluginTargets = Targets.desktopTargetClasses() - pluginTargets.remove(Targets.DESKTOP_4_8_7_DEFAULT) - if platform.system() in ('Microsoft', 'Windows'): - # No C++11 in GCC 4.9 - pluginTargets.remove(Targets.DESKTOP_5_4_1_GCC) + pluginTargets = (Targets.DESKTOP_5_6_1_DEFAULT, Targets.DESKTOP_5_10_1_DEFAULT) projectName, className = createNewQtPlugin(tempDir(), "SampleApp3", "MyPlugin", pluginTargets) virtualFunctionsAdded = False for kit, config in iterateBuildConfigs("Debug"): From 87f9429807c540038cb11cc7b41d079c592450fa Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Thu, 21 Feb 2019 07:33:15 +0100 Subject: [PATCH 42/59] Squish: Adapt to changed menu entry Change-Id: I4d3d49c4feb11cbdca9390748d99891928a35c00 Reviewed-by: Robert Loehning --- tests/system/suite_debugger/tst_cli_output_console/test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/system/suite_debugger/tst_cli_output_console/test.py b/tests/system/suite_debugger/tst_cli_output_console/test.py index c1f6b2d595a..9774ea59b23 100644 --- a/tests/system/suite_debugger/tst_cli_output_console/test.py +++ b/tests/system/suite_debugger/tst_cli_output_console/test.py @@ -85,7 +85,7 @@ def main(): test.log("Debugging application") isMsvc = isMsvcConfig(kit) - invokeMenuItem("Debug", "Start Debugging", "Start debugging of \"%s\"" % project) + invokeMenuItem("Debug", "Start Debugging", "Start debugging of startup project") handleDebuggerWarnings(config, isMsvc) ensureChecked(":Qt Creator_AppOutput_Core::Internal::OutputPaneToggleButton") outputWindow = waitForObject(":Qt Creator_Core::OutputWindow") From a53032d6a597779bc98a5c4d0bff34338dd6395e Mon Sep 17 00:00:00 2001 From: Orgad Shaneh Date: Mon, 25 Feb 2019 22:39:22 +0200 Subject: [PATCH 43/59] CppTools: Move code style snippets to a separate header Include it only where used. Resolves many "unused static variable" warnings. Change-Id: Ie1e578d9b9511f963e359d87f7740b4981975dbd Reviewed-by: Christian Stenger --- .../clangformat/clangformatconfigwidget.cpp | 2 +- .../cpptools/cppcodestylesettingspage.cpp | 1 + src/plugins/cpptools/cppcodestylesnippets.h | 190 ++++++++++++++++++ src/plugins/cpptools/cpptools.pro | 1 + src/plugins/cpptools/cpptools.qbs | 1 + src/plugins/cpptools/cpptoolsconstants.h | 158 --------------- 6 files changed, 194 insertions(+), 159 deletions(-) create mode 100644 src/plugins/cpptools/cppcodestylesnippets.h diff --git a/src/plugins/clangformat/clangformatconfigwidget.cpp b/src/plugins/clangformat/clangformatconfigwidget.cpp index 6aa14b9a71a..faaf6d937ff 100644 --- a/src/plugins/clangformat/clangformatconfigwidget.cpp +++ b/src/plugins/clangformat/clangformatconfigwidget.cpp @@ -35,7 +35,7 @@ #include #include -#include +#include #include #include #include diff --git a/src/plugins/cpptools/cppcodestylesettingspage.cpp b/src/plugins/cpptools/cppcodestylesettingspage.cpp index 981a0bda617..ef62ad1fa32 100644 --- a/src/plugins/cpptools/cppcodestylesettingspage.cpp +++ b/src/plugins/cpptools/cppcodestylesettingspage.cpp @@ -26,6 +26,7 @@ #include "cppcodestylesettingspage.h" #include "cppcodestylepreferences.h" +#include "cppcodestylesnippets.h" #include "cpppointerdeclarationformatter.h" #include "cppqtstyleindenter.h" #include "cpptoolsconstants.h" diff --git a/src/plugins/cpptools/cppcodestylesnippets.h b/src/plugins/cpptools/cppcodestylesnippets.h new file mode 100644 index 00000000000..b1f8ce199c5 --- /dev/null +++ b/src/plugins/cpptools/cppcodestylesnippets.h @@ -0,0 +1,190 @@ +/**************************************************************************** +** +** Copyright (C) 2019 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. +** +****************************************************************************/ + +#pragma once + +namespace CppTools { +namespace Constants { + +static const char *DEFAULT_CODE_STYLE_SNIPPETS[] + = {"#include \n" + "\n" + "class Complex\n" + " {\n" + "public:\n" + " Complex(double re, double im)\n" + " : _re(re), _im(im)\n" + " {}\n" + " double modulus() const\n" + " {\n" + " return sqrt(_re * _re + _im * _im);\n" + " }\n" + "private:\n" + " double _re;\n" + " double _im;\n" + " };\n" + "\n" + "void bar(int i)\n" + " {\n" + " static int counter = 0;\n" + " counter += i;\n" + " }\n" + "\n" + "namespace Foo\n" + " {\n" + " namespace Bar\n" + " {\n" + " void foo(int a, int b)\n" + " {\n" + " for (int i = 0; i < a; i++)\n" + " {\n" + " if (i < b)\n" + " bar(i);\n" + " else\n" + " {\n" + " bar(i);\n" + " bar(b);\n" + " }\n" + " }\n" + " }\n" + " } // namespace Bar\n" + " } // namespace Foo\n", + "#include \n" + "\n" + "class Complex\n" + " {\n" + "public:\n" + " Complex(double re, double im)\n" + " : _re(re), _im(im)\n" + " {}\n" + " double modulus() const\n" + " {\n" + " return sqrt(_re * _re + _im * _im);\n" + " }\n" + "private:\n" + " double _re;\n" + " double _im;\n" + " };\n" + "\n" + "void bar(int i)\n" + " {\n" + " static int counter = 0;\n" + " counter += i;\n" + " }\n" + "\n" + "namespace Foo\n" + " {\n" + " namespace Bar\n" + " {\n" + " void foo(int a, int b)\n" + " {\n" + " for (int i = 0; i < a; i++)\n" + " {\n" + " if (i < b)\n" + " bar(i);\n" + " else\n" + " {\n" + " bar(i);\n" + " bar(b);\n" + " }\n" + " }\n" + " }\n" + " } // namespace Bar\n" + " } // namespace Foo\n", + "namespace Foo\n" + "{\n" + "namespace Bar\n" + "{\n" + "class FooBar\n" + " {\n" + "public:\n" + " FooBar(int a)\n" + " : _a(a)\n" + " {}\n" + " int calculate() const\n" + " {\n" + " if (a > 10)\n" + " {\n" + " int b = 2 * a;\n" + " return a * b;\n" + " }\n" + " return -a;\n" + " }\n" + "private:\n" + " int _a;\n" + " };\n" + "}\n" + "}\n", + "#include \"bar.h\"\n" + "\n" + "int foo(int a)\n" + " {\n" + " switch (a)\n" + " {\n" + " case 1:\n" + " bar(1);\n" + " break;\n" + " case 2:\n" + " {\n" + " bar(2);\n" + " break;\n" + " }\n" + " case 3:\n" + " default:\n" + " bar(3);\n" + " break;\n" + " }\n" + " return 0;\n" + " }\n", + "void foo() {\n" + " if (a &&\n" + " b)\n" + " c;\n" + "\n" + " while (a ||\n" + " b)\n" + " break;\n" + " a = b +\n" + " c;\n" + " myInstance.longMemberName +=\n" + " foo;\n" + " myInstance.longMemberName += bar +\n" + " foo;\n" + "}\n", + "int *foo(const Bar &b1, Bar &&b2, int*, int *&rpi)\n" + "{\n" + " int*pi = 0;\n" + " int*const*const cpcpi = π\n" + " int*const*pcpi = π\n" + " int**const cppi = π\n" + "\n" + " void (*foo)(char *s) = 0;\n" + " int (*bar)[] = 0;\n" + "\n" + " return pi;\n" + "}\n"}; + +} // namespace Constants +} // namespace CppTools diff --git a/src/plugins/cpptools/cpptools.pro b/src/plugins/cpptools/cpptools.pro index a55e805af4e..04b7ce1adcc 100644 --- a/src/plugins/cpptools/cpptools.pro +++ b/src/plugins/cpptools/cpptools.pro @@ -26,6 +26,7 @@ HEADERS += \ cppcodestylepreferencesfactory.h \ cppcodestylesettings.h \ cppcodestylesettingspage.h \ + cppcodestylesnippets.h \ cppcompletionassist.h \ cppcompletionassistprocessor.h \ cppcompletionassistprovider.h \ diff --git a/src/plugins/cpptools/cpptools.qbs b/src/plugins/cpptools/cpptools.qbs index 89062d3a21c..85e086ddf92 100644 --- a/src/plugins/cpptools/cpptools.qbs +++ b/src/plugins/cpptools/cpptools.qbs @@ -82,6 +82,7 @@ Project { "cppcodestylesettingspage.cpp", "cppcodestylesettingspage.h", "cppcodestylesettingspage.ui", + "cppcodestylesnippets.h", "cppcompletionassist.cpp", "cppcompletionassist.h", "cppcompletionassistprocessor.cpp", diff --git a/src/plugins/cpptools/cpptoolsconstants.h b/src/plugins/cpptools/cpptoolsconstants.h index 781f5ebdf89..2e1aebfd432 100644 --- a/src/plugins/cpptools/cpptoolsconstants.h +++ b/src/plugins/cpptools/cpptoolsconstants.h @@ -105,163 +105,5 @@ constexpr const char TIDY_DOCUMENTATION_URL_TEMPLATE[] constexpr const char CLAZY_DOCUMENTATION_URL_TEMPLATE[] = "https://github.com/KDE/clazy/blob/master/docs/checks/README-%1.md"; -static const char *DEFAULT_CODE_STYLE_SNIPPETS[] - = {"#include \n" - "\n" - "class Complex\n" - " {\n" - "public:\n" - " Complex(double re, double im)\n" - " : _re(re), _im(im)\n" - " {}\n" - " double modulus() const\n" - " {\n" - " return sqrt(_re * _re + _im * _im);\n" - " }\n" - "private:\n" - " double _re;\n" - " double _im;\n" - " };\n" - "\n" - "void bar(int i)\n" - " {\n" - " static int counter = 0;\n" - " counter += i;\n" - " }\n" - "\n" - "namespace Foo\n" - " {\n" - " namespace Bar\n" - " {\n" - " void foo(int a, int b)\n" - " {\n" - " for (int i = 0; i < a; i++)\n" - " {\n" - " if (i < b)\n" - " bar(i);\n" - " else\n" - " {\n" - " bar(i);\n" - " bar(b);\n" - " }\n" - " }\n" - " }\n" - " } // namespace Bar\n" - " } // namespace Foo\n", - "#include \n" - "\n" - "class Complex\n" - " {\n" - "public:\n" - " Complex(double re, double im)\n" - " : _re(re), _im(im)\n" - " {}\n" - " double modulus() const\n" - " {\n" - " return sqrt(_re * _re + _im * _im);\n" - " }\n" - "private:\n" - " double _re;\n" - " double _im;\n" - " };\n" - "\n" - "void bar(int i)\n" - " {\n" - " static int counter = 0;\n" - " counter += i;\n" - " }\n" - "\n" - "namespace Foo\n" - " {\n" - " namespace Bar\n" - " {\n" - " void foo(int a, int b)\n" - " {\n" - " for (int i = 0; i < a; i++)\n" - " {\n" - " if (i < b)\n" - " bar(i);\n" - " else\n" - " {\n" - " bar(i);\n" - " bar(b);\n" - " }\n" - " }\n" - " }\n" - " } // namespace Bar\n" - " } // namespace Foo\n", - "namespace Foo\n" - "{\n" - "namespace Bar\n" - "{\n" - "class FooBar\n" - " {\n" - "public:\n" - " FooBar(int a)\n" - " : _a(a)\n" - " {}\n" - " int calculate() const\n" - " {\n" - " if (a > 10)\n" - " {\n" - " int b = 2 * a;\n" - " return a * b;\n" - " }\n" - " return -a;\n" - " }\n" - "private:\n" - " int _a;\n" - " };\n" - "}\n" - "}\n", - "#include \"bar.h\"\n" - "\n" - "int foo(int a)\n" - " {\n" - " switch (a)\n" - " {\n" - " case 1:\n" - " bar(1);\n" - " break;\n" - " case 2:\n" - " {\n" - " bar(2);\n" - " break;\n" - " }\n" - " case 3:\n" - " default:\n" - " bar(3);\n" - " break;\n" - " }\n" - " return 0;\n" - " }\n", - "void foo() {\n" - " if (a &&\n" - " b)\n" - " c;\n" - "\n" - " while (a ||\n" - " b)\n" - " break;\n" - " a = b +\n" - " c;\n" - " myInstance.longMemberName +=\n" - " foo;\n" - " myInstance.longMemberName += bar +\n" - " foo;\n" - "}\n", - "int *foo(const Bar &b1, Bar &&b2, int*, int *&rpi)\n" - "{\n" - " int*pi = 0;\n" - " int*const*const cpcpi = π\n" - " int*const*pcpi = π\n" - " int**const cppi = π\n" - "\n" - " void (*foo)(char *s) = 0;\n" - " int (*bar)[] = 0;\n" - "\n" - " return pi;\n" - "}\n"}; - } // namespace Constants } // namespace CppTools From 41da97fb2cfb88baa7872d370e1e9665c85432d2 Mon Sep 17 00:00:00 2001 From: hjk Date: Mon, 25 Feb 2019 16:16:02 +0100 Subject: [PATCH 44/59] Debugger: Do not make std::string layout assumptions ... when non-std allocator is used. Task-number: QTCREATORBUG-22040 Change-Id: I67785095f50058851c358a45ef19e0c41743fe4f Reviewed-by: Orgad Shaneh Reviewed-by: hjk Reviewed-by: Christian Stenger --- share/qtcreator/debugger/stdtypes.py | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/share/qtcreator/debugger/stdtypes.py b/share/qtcreator/debugger/stdtypes.py index 154e0ad67e0..8810e099127 100644 --- a/share/qtcreator/debugger/stdtypes.py +++ b/share/qtcreator/debugger/stdtypes.py @@ -1024,7 +1024,20 @@ def qdump__std__basic_string(d, value): def qdump__std____cxx11__basic_string(d, value): innerType = value.type[0] - (data, size) = value.split("pI") + try: + allocator = value.type[2].name + except: + allocator = '' + if allocator == 'std::allocator<%s>' % innerType.name: + (data, size) = value.split("pI") + else: + try: + data = value["_M_dataplus"]["_M_p"] + size = int(value["_M_string_length"]) + except: + d.putEmptyValue() + d.putPlainChildren(value) + return d.check(0 <= size) #and size <= alloc and alloc <= 100*1000*1000) d.putCharArrayHelper(data, size, innerType, d.currentItemFormat()) From 478002acb7f03e00ba00a6acd3eca81dbc75b14c Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar Date: Fri, 22 Feb 2019 13:35:04 +0100 Subject: [PATCH 45/59] ProjectExplorer: Avoid querying network compilers ...in case the network compiler is the first in PATH. If e.g. /usr/lib/icecc/bin comes first in system PATH and it's the compiler being auto-detected findLocalCompiler() returned /usr/lib/icecc/bin instead of the real local compiler. The "compilerPath" that findLocalCompiler() got was always additionally prepended to the "env" it got. The additionally prepended one was successfully skipped, but then it run into the original one. Fix this by ensuring that findLocalCompiler() filters out all network compilers and not only the first one. Change-Id: Ia44eef67497d760714d72e8a28620f423c2860d2 Reviewed-by: Christian Kandeler --- src/plugins/projectexplorer/gcctoolchain.cpp | 22 ++++++++------------ 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/src/plugins/projectexplorer/gcctoolchain.cpp b/src/plugins/projectexplorer/gcctoolchain.cpp index f1e0ea4cb46..26763ed5d55 100644 --- a/src/plugins/projectexplorer/gcctoolchain.cpp +++ b/src/plugins/projectexplorer/gcctoolchain.cpp @@ -52,7 +52,6 @@ #include #include -#include #include namespace { @@ -343,6 +342,11 @@ bool GccToolChain::isValid() const return fi.isExecutable(); } +static bool isNetworkCompiler(const QString &dirPath) +{ + return dirPath.contains("icecc") || dirPath.contains("distcc"); +} + static Utils::FileName findLocalCompiler(const Utils::FileName &compilerPath, const Environment &env) { @@ -351,21 +355,13 @@ static Utils::FileName findLocalCompiler(const Utils::FileName &compilerPath, // Get the path to the compiler, ignoring direct calls to icecc and distcc as we cannot // do anything about those. - const Utils::FileName compilerDir = compilerPath.parentDir(); - const QString compilerDirString = compilerDir.toString(); - if (!compilerDirString.contains("icecc") && !compilerDirString.contains("distcc")) + if (!isNetworkCompiler(compilerPath.parentDir().toString())) return compilerPath; - FileNameList pathComponents = env.path(); - auto it = std::find_if(pathComponents.begin(), pathComponents.end(), - [compilerDir](const FileName &p) { - return p == compilerDir; + // Filter out network compilers + const FileNameList pathComponents = Utils::filtered(env.path(), [] (const FileName &dirPath) { + return !isNetworkCompiler(dirPath.toString()); }); - if (it != pathComponents.end()) { - std::rotate(pathComponents.begin(), it, pathComponents.end()); - pathComponents.removeFirst(); // remove directory of compilerPath - // No need to put it at the end again, it is in PATH anyway... - } // This effectively searches the PATH twice, once via pathComponents and once via PATH itself: // searchInPath filters duplicates, so that will not hurt. From 9cb67fc0f4dc6eb9e04ea896b14861863c92cc5a Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Tue, 26 Feb 2019 10:37:52 +0100 Subject: [PATCH 46/59] QtOutputFormatter: Fix double invocation of file finder It's hard to imagine that that was intentional. Change-Id: I9459e0043e31bd92179aad3aa8712c233ed17084 Reviewed-by: hjk --- src/plugins/qtsupport/qtoutputformatter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/qtsupport/qtoutputformatter.cpp b/src/plugins/qtsupport/qtoutputformatter.cpp index c5a4d7a427b..cb98654858c 100644 --- a/src/plugins/qtsupport/qtoutputformatter.cpp +++ b/src/plugins/qtsupport/qtoutputformatter.cpp @@ -228,7 +228,7 @@ void QtOutputFormatter::handleLink(const QString &href) if (qmlLineMatch.hasMatch()) { const QUrl fileUrl = QUrl(qmlLineMatch.captured(1)); const int line = qmlLineMatch.captured(2).toInt(); - openEditor(d->projectFinder.findFile(d->projectFinder.findFile(fileUrl)), line); + openEditor(d->projectFinder.findFile(fileUrl), line); return; } From 2cfa3502c3c9347ba903eba35cb6fc894e4ceb6a Mon Sep 17 00:00:00 2001 From: hjk Date: Tue, 26 Feb 2019 14:24:37 +0100 Subject: [PATCH 47/59] Debugger: Remove identical CDB implementation of loadDumpers Change-Id: I83582821f0670f65c8f325c54707947741a3df17 Reviewed-by: Christian Stenger --- share/qtcreator/debugger/cdbbridge.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/share/qtcreator/debugger/cdbbridge.py b/share/qtcreator/debugger/cdbbridge.py index 9b1dd07810a..1e59452ffd7 100644 --- a/share/qtcreator/debugger/cdbbridge.py +++ b/share/qtcreator/debugger/cdbbridge.py @@ -458,10 +458,6 @@ class Dumper(DumperBase): def report(self, stuff): sys.stdout.write(stuff + "\n") - def loadDumpers(self, args): - msg = self.setupDumpers() - self.reportResult(msg, args) - def findValueByExpression(self, exp): return cdbext.parseAndEvaluate(exp) From eecf75e7bf625332c33476ea8ab11a43e5da2837 Mon Sep 17 00:00:00 2001 From: hjk Date: Tue, 26 Feb 2019 18:15:43 +0100 Subject: [PATCH 48/59] ProjectExplorer: Raise maximum of parallel jobs Now to 999 instead of the default of 99. Change-Id: I58adea913a846d8b775bcacaa7973bde18488ef3 Reviewed-by: Christian Kandeler Reviewed-by: Leena Miettinen --- src/plugins/projectexplorer/makestep.ui | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/plugins/projectexplorer/makestep.ui b/src/plugins/projectexplorer/makestep.ui index 0ce98f0bae4..b6ddcc68972 100644 --- a/src/plugins/projectexplorer/makestep.ui +++ b/src/plugins/projectexplorer/makestep.ui @@ -79,6 +79,9 @@ 1 + + 999 + From 86e16c9e142c9b8bc7ae7f98aeb51892eab36fa3 Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Wed, 27 Feb 2019 09:32:09 +0100 Subject: [PATCH 49/59] Qmake: Add special CONFIG variable "qtc_run" when parsing project files The idea is that some of the more intrusive prf files in Qt can skip themselves when they encounter this condition. Task-number: QTCREATORBUG-17521 Change-Id: I09a33b2d3c5dee1232803d46c521cc9fd29e1898 Reviewed-by: Joerg Bornemann --- src/plugins/qmakeprojectmanager/qmakeparsernodes.cpp | 1 + src/plugins/qtsupport/profilereader.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/src/plugins/qmakeprojectmanager/qmakeparsernodes.cpp b/src/plugins/qmakeprojectmanager/qmakeparsernodes.cpp index c0034972d65..1a401ee953b 100644 --- a/src/plugins/qmakeprojectmanager/qmakeparsernodes.cpp +++ b/src/plugins/qmakeprojectmanager/qmakeparsernodes.cpp @@ -1246,6 +1246,7 @@ static bool evaluateOne(const QmakeEvalInput &input, ProFile *pro, QStringList basecfgs = reader->values(build + QLatin1String(".CONFIG")); basecfgs += build; basecfgs += QLatin1String("build_pass"); + basecfgs += "qtc_run"; basevars[QLatin1String("BUILD_PASS")] = QStringList(build); QStringList buildname = reader->values(build + QLatin1String(".name")); basevars[QLatin1String("BUILD_NAME")] = (buildname.isEmpty() ? QStringList(build) : buildname); diff --git a/src/plugins/qtsupport/profilereader.cpp b/src/plugins/qtsupport/profilereader.cpp index ba0eb7dd902..9c04012b056 100644 --- a/src/plugins/qtsupport/profilereader.cpp +++ b/src/plugins/qtsupport/profilereader.cpp @@ -79,6 +79,7 @@ ProFileReader::ProFileReader(QMakeGlobals *option, QMakeVfs *vfs) , ProFileEvaluator(option, this, vfs, this) , m_ignoreLevel(0) { + setExtraConfigs(QStringList("qtc_run")); } ProFileReader::~ProFileReader() From f6c276daf03c59326bdf1fec3a44c48307912fae Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Wed, 27 Feb 2019 14:34:18 +0100 Subject: [PATCH 50/59] Macro expander: Do not use RunConfiguration::runnable() ... to get the current executable. That leads to an infinite loop if the argument or working directory fields reference the %{CurrentRun:Executable:Path} variable, as these fields also get evaluated in RunConfiguration::runnable(). Fixes: QTCREATORBUG-18317 Change-Id: Ic249f8ff78d170110947e370045144817b179341 Reviewed-by: hjk --- src/plugins/projectexplorer/projectexplorer.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/plugins/projectexplorer/projectexplorer.cpp b/src/plugins/projectexplorer/projectexplorer.cpp index 4b700e89a21..eebd7c91ed1 100644 --- a/src/plugins/projectexplorer/projectexplorer.cpp +++ b/src/plugins/projectexplorer/projectexplorer.cpp @@ -44,6 +44,7 @@ #include "projectexplorersettingspage.h" #include "projectmanager.h" #include "removetaskhandler.h" +#include "runconfigurationaspects.h" #include "kitfeatureprovider.h" #include "kitmanager.h" #include "kitoptionspage.h" @@ -1586,8 +1587,14 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er tr("The currently active run configuration's executable (if applicable)."), []() -> QString { if (Target *target = activeTarget()) { - if (RunConfiguration *rc = target->activeRunConfiguration()) - return rc->runnable().executable; + if (RunConfiguration *rc = target->activeRunConfiguration()) { + // TODO: This duplicates code and is not always correct, but see + // QTCREATORBUG-18317. + // Solution: Re-introduce RunConfiguration::executable()? + if (auto executableAspect = rc->aspect()) + return executableAspect->executable().toString(); + return QString(); + } } return QString(); }); From 8a0f7bcfd5ddf0727304f531d021e9ff0b991b01 Mon Sep 17 00:00:00 2001 From: David Schulz Date: Thu, 7 Feb 2019 13:40:39 +0100 Subject: [PATCH 51/59] TextEditor: add option to remember highlighter definition Add a button to the multiple definition found info that saves the definition of the current highlighter for the open document. Change-Id: I04b1b7571a864d781747547a1d315ec25bb6b5a1 Reviewed-by: Christian Stenger Reviewed-by: Leena Miettinen --- src/plugins/texteditor/highlighter.cpp | 94 +++++++++++++++++-- src/plugins/texteditor/highlighter.h | 10 +- .../texteditor/highlightersettings.cpp | 7 +- .../texteditor/highlightersettingspage.cpp | 3 + .../texteditor/highlightersettingspage.ui | 24 +++++ src/plugins/texteditor/texteditor.cpp | 18 +++- src/plugins/texteditor/texteditorconstants.h | 2 + 7 files changed, 145 insertions(+), 13 deletions(-) diff --git a/src/plugins/texteditor/highlighter.cpp b/src/plugins/texteditor/highlighter.cpp index 857c0f88cc7..b21af3644c8 100644 --- a/src/plugins/texteditor/highlighter.cpp +++ b/src/plugins/texteditor/highlighter.cpp @@ -43,6 +43,10 @@ using namespace TextEditor; +static const char kDefinitionForMimeType[] = "definitionForMimeType"; +static const char kDefinitionForExtension[] = "definitionForExtension"; +static const char kDefinitionForFilePath[] = "definitionForFilePath"; + KSyntaxHighlighting::Repository *highlightRepository() { static KSyntaxHighlighting::Repository *repository = nullptr; @@ -107,18 +111,24 @@ Highlighter::Definition Highlighter::definitionForDocument(const TextDocument *d if (mimeType.isValid()) definition = Highlighter::definitionForMimeType(mimeType.name()); if (!definition.isValid()) - definition = Highlighter::definitionForFileName(document->filePath().fileName()); + definition = Highlighter::definitionForFilePath(document->filePath()); return definition; } Highlighter::Definition Highlighter::definitionForMimeType(const QString &mimeType) { + const Definitions definitions = definitionsForMimeType(mimeType); + if (definitions.size() == 1) + return definitions.first(); return highlightRepository()->definitionForMimeType(mimeType); } -Highlighter::Definition Highlighter::definitionForFileName(const QString &fileName) +Highlighter::Definition Highlighter::definitionForFilePath(const Utils::FileName &fileName) { - return highlightRepository()->definitionForFileName(fileName); + const Definitions definitions = definitionsForFileName(fileName); + if (definitions.size() == 1) + return definitions.first(); + return highlightRepository()->definitionForFileName(fileName.fileName()); } Highlighter::Definition Highlighter::definitionForName(const QString &name) @@ -133,18 +143,88 @@ Highlighter::Definitions Highlighter::definitionsForDocument(const TextDocument if (mimeType.isValid()) definitions = Highlighter::definitionsForMimeType(mimeType.name()); if (definitions.isEmpty()) - definitions = Highlighter::definitionsForFileName(document->filePath().fileName()); + definitions = Highlighter::definitionsForFileName(document->filePath()); return definitions; } +static Highlighter::Definition definitionForSetting(const QString &settingsKey, + const QString &mapKey) +{ + QSettings *settings = Core::ICore::settings(); + settings->beginGroup(Constants::HIGHLIGHTER_SETTINGS_CATEGORY); + const QString &definitionName = settings->value(settingsKey).toMap().value(mapKey).toString(); + settings->endGroup(); + return Highlighter::definitionForName(definitionName); +} + Highlighter::Definitions Highlighter::definitionsForMimeType(const QString &mimeType) { - return highlightRepository()->definitionsForMimeType(mimeType).toList(); + Definitions definitions = highlightRepository()->definitionsForMimeType(mimeType).toList(); + if (definitions.size() > 1) { + const Definition &rememberedDefinition = definitionForSetting(kDefinitionForMimeType, + mimeType); + if (rememberedDefinition.isValid() && definitions.contains(rememberedDefinition)) + definitions = {rememberedDefinition}; + } + return definitions; } -Highlighter::Definitions Highlighter::definitionsForFileName(const QString &fileName) +Highlighter::Definitions Highlighter::definitionsForFileName(const Utils::FileName &fileName) { - return highlightRepository()->definitionsForFileName(fileName).toList(); + Definitions definitions + = highlightRepository()->definitionsForFileName(fileName.fileName()).toList(); + + if (definitions.size() > 1) { + const QString &fileExtension = fileName.toFileInfo().completeSuffix(); + const Definition &rememberedDefinition + = fileExtension.isEmpty() + ? definitionForSetting(kDefinitionForFilePath, + fileName.toFileInfo().canonicalFilePath()) + : definitionForSetting(kDefinitionForExtension, fileExtension); + if (rememberedDefinition.isValid() && definitions.contains(rememberedDefinition)) + definitions = {rememberedDefinition}; + } + + return definitions; +} + +void Highlighter::rememberDefintionForDocument(const Highlighter::Definition &definition, + const TextDocument *document) +{ + if (!definition.isValid()) + return; + const QString &mimeType = document->mimeType(); + const QString &fileExtension = document->filePath().toFileInfo().completeSuffix(); + const QString &path = document->filePath().toFileInfo().canonicalFilePath(); + QSettings *settings = Core::ICore::settings(); + settings->beginGroup(Constants::HIGHLIGHTER_SETTINGS_CATEGORY); + if (!mimeType.isEmpty()) { + const QString id(kDefinitionForMimeType); + QMap map = settings->value(id).toMap(); + map.insert(mimeType, definition.name()); + settings->setValue(id, map); + } else if (!fileExtension.isEmpty()) { + const QString id(kDefinitionForExtension); + QMap map = settings->value(id).toMap(); + map.insert(fileExtension, definition.name()); + settings->setValue(id, map); + } else if (!path.isEmpty()) { + const QString id(kDefinitionForFilePath); + QMap map = settings->value(id).toMap(); + map.insert(document->filePath().toFileInfo().absoluteFilePath(), definition.name()); + settings->setValue(id, map); + } + settings->endGroup(); +} + +void Highlighter::clearDefintionForDocumentCache() +{ + QSettings *settings = Core::ICore::settings(); + settings->beginGroup(Constants::HIGHLIGHTER_SETTINGS_CATEGORY); + settings->remove(kDefinitionForMimeType); + settings->remove(kDefinitionForExtension); + settings->remove(kDefinitionForFilePath); + settings->endGroup(); } void Highlighter::addCustomHighlighterPath(const Utils::FileName &path) diff --git a/src/plugins/texteditor/highlighter.h b/src/plugins/texteditor/highlighter.h index 776f92faf35..92e7e136c18 100644 --- a/src/plugins/texteditor/highlighter.h +++ b/src/plugins/texteditor/highlighter.h @@ -38,6 +38,8 @@ class TextDocument; class Highlighter : public SyntaxHighlighter, public KSyntaxHighlighting::AbstractHighlighter { + Q_OBJECT + Q_INTERFACES(KSyntaxHighlighting::AbstractHighlighter) public: using Definition = KSyntaxHighlighting::Definition; using Definitions = QList; @@ -45,12 +47,16 @@ public: static Definition definitionForDocument(const TextDocument *document); static Definition definitionForMimeType(const QString &mimeType); - static Definition definitionForFileName(const QString &fileName); + static Definition definitionForFilePath(const Utils::FileName &fileName); static Definition definitionForName(const QString &name); static Definitions definitionsForDocument(const TextDocument *document); static Definitions definitionsForMimeType(const QString &mimeType); - static Definitions definitionsForFileName(const QString &fileName); + static Definitions definitionsForFileName(const Utils::FileName &fileName); + + static void rememberDefintionForDocument(const Definition &definition, + const TextDocument *document); + static void clearDefintionForDocumentCache(); static void addCustomHighlighterPath(const Utils::FileName &path); static void updateDefinitions(std::function callback = nullptr); diff --git a/src/plugins/texteditor/highlightersettings.cpp b/src/plugins/texteditor/highlightersettings.cpp index 76b88b063ab..84afbd79ded 100644 --- a/src/plugins/texteditor/highlightersettings.cpp +++ b/src/plugins/texteditor/highlightersettings.cpp @@ -25,6 +25,8 @@ #include "highlightersettings.h" +#include "texteditorconstants.h" + #include #include #include @@ -97,7 +99,6 @@ namespace { static const QLatin1String kDefinitionFilesPath("UserDefinitionFilesPath"); static const QLatin1String kIgnoredFilesPatterns("IgnoredFilesPatterns"); -static const QLatin1String kGroupPostfix("HighlighterSettings"); QString groupSpecifier(const QString &postFix, const QString &category) { @@ -113,7 +114,7 @@ using namespace Internal; void HighlighterSettings::toSettings(const QString &category, QSettings *s) const { - const QString &group = groupSpecifier(kGroupPostfix, category); + const QString &group = groupSpecifier(Constants::HIGHLIGHTER_SETTINGS_CATEGORY, category); s->beginGroup(group); s->setValue(kDefinitionFilesPath, m_definitionFilesPath); s->setValue(kIgnoredFilesPatterns, ignoredFilesPatterns()); @@ -122,7 +123,7 @@ void HighlighterSettings::toSettings(const QString &category, QSettings *s) cons void HighlighterSettings::fromSettings(const QString &category, QSettings *s) { - const QString &group = groupSpecifier(kGroupPostfix, category); + const QString &group = groupSpecifier(Constants::HIGHLIGHTER_SETTINGS_CATEGORY, category); s->beginGroup(group); m_definitionFilesPath = s->value(kDefinitionFilesPath, QString()).toString(); if (!s->contains(kDefinitionFilesPath)) diff --git a/src/plugins/texteditor/highlightersettingspage.cpp b/src/plugins/texteditor/highlightersettingspage.cpp index ec9d34ee65c..86a1a7fdbf3 100644 --- a/src/plugins/texteditor/highlightersettingspage.cpp +++ b/src/plugins/texteditor/highlightersettingspage.cpp @@ -112,6 +112,9 @@ QWidget *HighlighterSettingsPage::widget() label->setText(tr("Update finished")); }); }); + connect(m_d->m_page->resetCache, &QPushButton::clicked, []() { + Highlighter::clearDefintionForDocumentCache(); + }); settingsToUI(); } diff --git a/src/plugins/texteditor/highlightersettingspage.ui b/src/plugins/texteditor/highlightersettingspage.ui index bcc5d5fe11b..fcd4919b128 100644 --- a/src/plugins/texteditor/highlightersettingspage.ui +++ b/src/plugins/texteditor/highlightersettingspage.ui @@ -110,6 +110,30 @@ + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Reset Remembered Definitions + + + + + diff --git a/src/plugins/texteditor/texteditor.cpp b/src/plugins/texteditor/texteditor.cpp index 235ac7f673e..0d92b2d16f1 100644 --- a/src/plugins/texteditor/texteditor.cpp +++ b/src/plugins/texteditor/texteditor.cpp @@ -613,6 +613,7 @@ public: void reconfigure(); void updateSyntaxInfoBar(const Highlighter::Definitions &definitions, const QString &fileName); void configureGenericHighlighter(const KSyntaxHighlighting::Definition &definition); + void rememberCurrentSyntaxDefinition(); public: TextEditorWidget *q; @@ -3306,6 +3307,11 @@ void TextEditorWidgetPrivate::updateSyntaxInfoBar(const Highlighter::Definitions this->configureGenericHighlighter(Highlighter::definitionForName(definition)); }); + info.setCustomButtonInfo(BaseTextEditor::tr("Remember My Choice"), [multiple, this]() { + m_document->infoBar()->removeInfo(multiple); + rememberCurrentSyntaxDefinition(); + }); + infoBar->removeInfo(missing); infoBar->addInfo(info); } else { @@ -3333,6 +3339,16 @@ void TextEditorWidgetPrivate::configureGenericHighlighter( m_document->setFontSettings(TextEditorSettings::fontSettings()); } +void TextEditorWidgetPrivate::rememberCurrentSyntaxDefinition() +{ + auto highlighter = qobject_cast(m_document->syntaxHighlighter()); + if (!highlighter) + return; + const Highlighter::Definition &definition = highlighter->definition(); + if (definition.isValid()) + Highlighter::rememberDefintionForDocument(definition, m_document.data()); +} + bool TextEditorWidget::codeFoldingVisible() const { return d->m_codeFoldingVisible; @@ -8543,7 +8559,7 @@ QString TextEditorWidget::textAt(int from, int to) const void TextEditorWidget::configureGenericHighlighter() { - const Highlighter::Definitions definitions = Highlighter::definitionsForDocument(textDocument()); + Highlighter::Definitions definitions = Highlighter::definitionsForDocument(textDocument()); d->configureGenericHighlighter(definitions.isEmpty() ? Highlighter::Definition() : definitions.first()); d->updateSyntaxInfoBar(definitions, textDocument()->filePath().fileName()); diff --git a/src/plugins/texteditor/texteditorconstants.h b/src/plugins/texteditor/texteditorconstants.h index 949b4934570..78c9c1cb714 100644 --- a/src/plugins/texteditor/texteditorconstants.h +++ b/src/plugins/texteditor/texteditorconstants.h @@ -214,6 +214,8 @@ const char TEXT_EDITOR_DISPLAY_SETTINGS[] = "D.DisplaySettings"; const char TEXT_EDITOR_HIGHLIGHTER_SETTINGS[] = "E.HighlighterSettings"; const char TEXT_EDITOR_SNIPPETS_SETTINGS[] = "F.SnippetsSettings"; +const char HIGHLIGHTER_SETTINGS_CATEGORY[] = "HighlighterSettings"; + const char SNIPPET_EDITOR_ID[] = "TextEditor.SnippetEditor"; const char TEXT_SNIPPET_GROUP_ID[] = "Text"; From 17b3e45b8cb86a72ff0208dbe28b47034c95921e Mon Sep 17 00:00:00 2001 From: Orgad Shaneh Date: Thu, 28 Feb 2019 09:01:15 +0200 Subject: [PATCH 52/59] VCS: Fix display of diff/show commands in progress bar MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In 6ae0e8d2c7f5d1bb3d3240bdfba3cd68eb093252 we added 2 arguments that precede the diff sub-command (-c diff.color=false). When display name is not set, ShellCommand uses the binary followed by the first argument, so it now showed "Git -c" instead of "Git Diff". Change-Id: Ie584837bd87fd529e0cd015025fc3bf1a69d085c Reviewed-by: André Hartmann Reviewed-by: Xiaofeng Wang Reviewed-by: Tobias Hunger --- src/plugins/git/gitclient.cpp | 5 ++++- src/plugins/mercurial/mercurialclient.cpp | 1 + src/plugins/vcsbase/vcsbasediffeditorcontroller.cpp | 7 +++++++ src/plugins/vcsbase/vcsbasediffeditorcontroller.h | 1 + 4 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/plugins/git/gitclient.cpp b/src/plugins/git/gitclient.cpp index d28c6bb2630..9fdd6a27905 100644 --- a/src/plugins/git/gitclient.cpp +++ b/src/plugins/git/gitclient.cpp @@ -291,6 +291,7 @@ GitDiffEditorController::GitDiffEditorController(IDocument *document, const QStr { connect(&m_decorator, &DescriptionWidgetDecorator::branchListRequested, this, &GitDiffEditorController::updateBranchList); + setDisplayName("Git Diff"); } void GitDiffEditorController::updateBranchList() @@ -514,7 +515,9 @@ public: GitDiffEditorController(document, dir), m_id(id), m_state(Idle) - { } + { + setDisplayName("Git Show"); + } void reload() override; void processCommandOutput(const QString &output) override; diff --git a/src/plugins/mercurial/mercurialclient.cpp b/src/plugins/mercurial/mercurialclient.cpp index 4e3f6e37e35..f311d824c3f 100644 --- a/src/plugins/mercurial/mercurialclient.cpp +++ b/src/plugins/mercurial/mercurialclient.cpp @@ -68,6 +68,7 @@ protected: MercurialDiffEditorController::MercurialDiffEditorController(IDocument *document, const QString &workingDirectory): VcsBaseDiffEditorController(document, MercurialPlugin::client(), workingDirectory) { + setDisplayName("Hg Diff"); } void MercurialDiffEditorController::runCommand(const QList &args, QTextCodec *codec) diff --git a/src/plugins/vcsbase/vcsbasediffeditorcontroller.cpp b/src/plugins/vcsbase/vcsbasediffeditorcontroller.cpp index 6ece9c8b9d9..cb41e7e7d25 100644 --- a/src/plugins/vcsbase/vcsbasediffeditorcontroller.cpp +++ b/src/plugins/vcsbase/vcsbasediffeditorcontroller.cpp @@ -98,6 +98,7 @@ public: const QString m_directory; QString m_startupFile; QString m_output; + QString m_displayName; QPointer m_command; QPointer m_commandResultProxy; QFutureWatcher> *m_processWatcher = nullptr; @@ -251,6 +252,7 @@ void VcsBaseDiffEditorController::runCommand(const QList &args, uns d->cancelReload(); d->m_command = new VcsCommand(workingDirectory(), d->m_client->processEnvironment()); + d->m_command->setDisplayName(d->m_displayName); d->m_command->setCodec(codec ? codec : EditorManager::defaultTextCodec()); d->m_commandResultProxy = new VcsCommandResultProxy(d->m_command.data(), d); d->m_command->addFlags(flags); @@ -289,6 +291,11 @@ QString VcsBaseDiffEditorController::startupFile() const return d->m_startupFile; } +void VcsBaseDiffEditorController::setDisplayName(const QString &displayName) +{ + d->m_displayName = displayName; +} + } // namespace VcsBase #include "vcsbasediffeditorcontroller.moc" diff --git a/src/plugins/vcsbase/vcsbasediffeditorcontroller.h b/src/plugins/vcsbase/vcsbasediffeditorcontroller.h index eb6e97157f0..8b4668dbf05 100644 --- a/src/plugins/vcsbase/vcsbasediffeditorcontroller.h +++ b/src/plugins/vcsbase/vcsbasediffeditorcontroller.h @@ -53,6 +53,7 @@ protected: QString workingDirectory() const; void setStartupFile(const QString &startupFile); QString startupFile() const; + void setDisplayName(const QString &displayName); private: friend class VcsBaseDiffEditorControllerPrivate; From c581931b7001a10c185b029f3e947c3812b5c5d6 Mon Sep 17 00:00:00 2001 From: David Schulz Date: Thu, 14 Feb 2019 14:14:22 +0100 Subject: [PATCH 53/59] Fix assert in IoUtils::resolvePath Having an empty base dir should not assert when passing an absolute path file name without drive letter. Change-Id: Ic9f1278df1a8ba938d893f4d21ce1c0bf9053632 Reviewed-by: Christian Stenger Reviewed-by: Christian Kandeler --- src/shared/proparser/ioutils.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/shared/proparser/ioutils.cpp b/src/shared/proparser/ioutils.cpp index 0552bd10972..b0a52d33ebd 100644 --- a/src/shared/proparser/ioutils.cpp +++ b/src/shared/proparser/ioutils.cpp @@ -101,8 +101,8 @@ QString IoUtils::resolvePath(const QString &baseDir, const QString &fileName) return QDir::cleanPath(fileName); #ifdef Q_OS_WIN // Add drive to otherwise-absolute path: if (fileName.at(0).unicode() == '/' || fileName.at(0).unicode() == '\\') { - Q_ASSERT(isAbsolutePath(baseDir)); - return QDir::cleanPath(baseDir.left(2) + fileName); + return isAbsolutePath(baseDir) ? QDir::cleanPath(baseDir.left(2) + fileName) + : QDir::cleanPath(fileName); } #endif // Q_OS_WIN return QDir::cleanPath(baseDir + QLatin1Char('/') + fileName); From b9e26fcd376e0002e8f24abbd0baa94642025a1b Mon Sep 17 00:00:00 2001 From: hjk Date: Wed, 27 Feb 2019 13:33:33 +0100 Subject: [PATCH 54/59] Debugger: Load dumpers after possible user defined modules with CDB As is done for GDB and LLDB. Fixes: QTCREATORBUG-20481 Change-Id: I13e73789e175fdca675c25378a856a5482d9e8fa (cherry picked from commit 0523a7f38bca76ae56798a48573fc50343b2b402) Reviewed-by: David Schulz --- src/plugins/debugger/cdb/cdbengine.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/plugins/debugger/cdb/cdbengine.cpp b/src/plugins/debugger/cdb/cdbengine.cpp index 5e62bf5bb6d..287a4cded69 100644 --- a/src/plugins/debugger/cdb/cdbengine.cpp +++ b/src/plugins/debugger/cdb/cdbengine.cpp @@ -2763,10 +2763,6 @@ void CdbEngine::setupScripting(const DebuggerResponse &response) runCommand({"from cdbbridge import Dumper", ScriptCommand}); runCommand({"print(dir())", ScriptCommand}); runCommand({"theDumper = Dumper()", ScriptCommand}); - runCommand({"theDumper.loadDumpers(None)", ScriptCommand, - [this](const DebuggerResponse &response) { - watchHandler()->addDumpers(response.data["result"]["dumpers"]); - }}); const QString path = stringSetting(ExtraDumperFile); if (!path.isEmpty() && QFileInfo(path).isReadable()) { @@ -2779,6 +2775,11 @@ void CdbEngine::setupScripting(const DebuggerResponse &response) for (const auto &command : commands.split('\n', QString::SkipEmptyParts)) runCommand({command, ScriptCommand}); } + + runCommand({"theDumper.loadDumpers(None)", ScriptCommand, + [this](const DebuggerResponse &response) { + watchHandler()->addDumpers(response.data["result"]["dumpers"]); + }}); } void CdbEngine::mergeStartParametersSourcePathMap() From 04aac85e2623395d4c6ed4d88a5dc1b8a1103649 Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Thu, 28 Feb 2019 12:05:35 +0100 Subject: [PATCH 55/59] Update 4.8.2 changes file Change-Id: I38369e2404150da9a9edb198cdecaab50d1f137f Reviewed-by: Leena Miettinen --- dist/changes-4.8.2.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/dist/changes-4.8.2.md b/dist/changes-4.8.2.md index 22a930d9a40..ef7316c7c73 100644 --- a/dist/changes-4.8.2.md +++ b/dist/changes-4.8.2.md @@ -7,6 +7,10 @@ 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/v4.8.1..v4.8.2 +General + +* Fixed UI for choosing executable for external tools (QTCREATORBUG-21937) + Editing * Fixed highlighting of search results of regular expression search @@ -20,6 +24,10 @@ Autotools Projects C++ Support * Fixed crash when expanding macros (QTCREATORBUG-21642) +* Fixed crash in preprocessor (QTCREATORBUG-21981) +* Fixed infinite loop when resolving pointer types (QTCREATORBUG-22010) +* Fixed cursor position after completion of functions without arguments + (QTCREATORBUG-21841) QML Support @@ -38,6 +46,7 @@ Debugging Qt Quick Designer * Added support for more JavaScript functions in `.ui.qml` files +* Fixed crash with gradients and Qt Quick 5.12 (QDS-472) Test Integration @@ -55,16 +64,20 @@ macOS Android * Fixed upload of GDB server on some devices (QTCREATORBUG-21317) +* Fixed crash on exiting debugger (QTCREATORBUG-21684) Credits for these changes go to: +Andre Hartmann André Pönitz Christian Kandeler Christian Stenger David Schulz Eike Ziller Ivan Donchevskii +Kirill Burtsev Leena Miettinen Liang Qi +Nikolai Kosjar Oliver Wolff Raoul Hecky Robert Löhning From 114acbbba06ef98120cc5513a9600b7d437cc87c Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Wed, 27 Feb 2019 15:45:17 +0100 Subject: [PATCH 56/59] Properly import qmake projects The code simply picked one matching toolchain and set it on the temporary kit, ignoring the fact that we have pairs of toolchains (C and C++). So the second one was set to some random value and typically did not match the first one, resulting in a broken Kit. We now collect both types of toolchains. Fixes: QTCREATORBUG-18153 Fixes: QTCREATORBUG-19423 Change-Id: I348e5467f30d449cc344946ec7e87d4ca5ddfbd1 Reviewed-by: Christian Stenger --- .../qmakeprojectimporter.cpp | 26 ++++++++++++++----- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/src/plugins/qmakeprojectmanager/qmakeprojectimporter.cpp b/src/plugins/qmakeprojectmanager/qmakeprojectimporter.cpp index c97bab5a38c..a04657aa407 100644 --- a/src/plugins/qmakeprojectmanager/qmakeprojectimporter.cpp +++ b/src/plugins/qmakeprojectmanager/qmakeprojectimporter.cpp @@ -265,19 +265,30 @@ void QmakeProjectImporter::deleteDirectoryData(void *directoryData) const delete static_cast(directoryData); } -static ToolChain *preferredToolChain(BaseQtVersion *qtVersion, const FileName &ms, - const QMakeStepConfig::TargetArchConfig &archConfig) +static const QList preferredToolChains(BaseQtVersion *qtVersion, const FileName &ms, + const QMakeStepConfig::TargetArchConfig &archConfig) { const FileName spec = ms.isEmpty() ? qtVersion->mkspec() : ms; const QList toolchains = ToolChainManager::toolChains(); QList qtAbis = qtVersion->qtAbis(); - return findOr(toolchains, toolchains.isEmpty() ? nullptr : toolchains.first(), - [&](ToolChain *tc) { + const auto matcher = [&](const ToolChain *tc) { return qtAbis.contains(tc->targetAbi()) - && tc->suggestedMkspecList().contains(spec) - && QMakeStepConfig::targetArchFor(tc->targetAbi(), qtVersion) == archConfig; + && tc->suggestedMkspecList().contains(spec) + && QMakeStepConfig::targetArchFor(tc->targetAbi(), qtVersion) == archConfig; + }; + ToolChain * const cxxToolchain = findOrDefault(toolchains, [matcher](const ToolChain *tc) { + return tc->language() == ProjectExplorer::Constants::CXX_LANGUAGE_ID && matcher(tc); }); + ToolChain * const cToolchain = findOrDefault(toolchains, [matcher](const ToolChain *tc) { + return tc->language() == ProjectExplorer::Constants::C_LANGUAGE_ID && matcher(tc); + }); + QList chosenToolchains; + for (ToolChain * const tc : {cxxToolchain, cToolchain}) { + if (tc) + chosenToolchains << tc; + }; + return chosenToolchains; } Kit *QmakeProjectImporter::createTemporaryKit(const QtProjectImporter::QtVersionData &data, @@ -288,7 +299,8 @@ Kit *QmakeProjectImporter::createTemporaryKit(const QtProjectImporter::QtVersion Q_UNUSED(osType); // TODO use this to select the right toolchain? return QtProjectImporter::createTemporaryKit(data, [&data, parsedSpec, archConfig](Kit *k) -> void { - ToolChainKitInformation::setToolChain(k, preferredToolChain(data.qt, parsedSpec, archConfig)); + for (ToolChain * const tc : preferredToolChains(data.qt, parsedSpec, archConfig)) + ToolChainKitInformation::setToolChain(k, tc); if (parsedSpec != data.qt->mkspec()) QmakeKitInformation::setMkspec(k, parsedSpec); }); From 31c2956e2b26a6924e0b05666c6abbad1ab37988 Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Thu, 28 Feb 2019 16:05:39 +0100 Subject: [PATCH 57/59] Fix updating translations files Broke with 791d791f2ca80dc623e6dac78c9f469e442516c3 Change-Id: I254d45fa50a34d39378eab8f0d2c365c92835cc8 Fixes: QTCREATORBUG-22058 Reviewed-by: Leena Miettinen --- share/qtcreator/translations/translations.pro | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/share/qtcreator/translations/translations.pro b/share/qtcreator/translations/translations.pro index 0df9762fccd..0df2d53ad4a 100644 --- a/share/qtcreator/translations/translations.pro +++ b/share/qtcreator/translations/translations.pro @@ -73,7 +73,8 @@ plugin_sources -= src/plugins/plugins.pro \ shared_sources = $$files($$IDE_SOURCE_TREE/src/shared/*) shared_sources ~= s,^$$re_escape($$IDE_SOURCE_TREE/),,g$$i_flag shared_sources -= \ - src/shared/qbs + src/shared/qbs \ + src/shared/shared.pro sources = src/app src/libs $$plugin_sources $$shared_sources share/qtcreator/qmldesigner for(path, INCLUDEPATH): include_options *= -I$$shell_quote($$path) From 4a1cb7695cb00f2ada73aa096b08974c2347b753 Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Fri, 1 Mar 2019 10:37:03 +0100 Subject: [PATCH 58/59] Update qbs submodule To HEAD of 1.13 branch. Change-Id: Ib4085dfa8a6adeebdba3ec7144c34026aeae2b48 Reviewed-by: Christian Stenger --- src/shared/qbs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shared/qbs b/src/shared/qbs index bceae1097f6..50eb4d183cc 160000 --- a/src/shared/qbs +++ b/src/shared/qbs @@ -1 +1 @@ -Subproject commit bceae1097f6a57f1339ea3a4e6827d6195860d31 +Subproject commit 50eb4d183ccb526874cefe73c7f4c2129769aa4a From aa14e396f03232ce97a723aaf18ab89f7dfad698 Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Mon, 18 Feb 2019 15:05:13 +0100 Subject: [PATCH 59/59] BaseFileFind: Coding style Use braced initializer lists, range-based for, more const, more auto, more unique_ptr, avoid sender(). Change-Id: Id43c81c498247a6d3722fab1937c83d80e701ec2 Reviewed-by: Xing Xiong Reviewed-by: Marco Bubke --- src/plugins/texteditor/basefilefind.cpp | 74 +++++++++++++------------ src/plugins/texteditor/basefilefind.h | 7 ++- 2 files changed, 42 insertions(+), 39 deletions(-) diff --git a/src/plugins/texteditor/basefilefind.cpp b/src/plugins/texteditor/basefilefind.cpp index 39e85f50311..a910de019c0 100644 --- a/src/plugins/texteditor/basefilefind.cpp +++ b/src/plugins/texteditor/basefilefind.cpp @@ -65,18 +65,17 @@ public: InternalEngine() : m_widget(new QWidget) {} ~InternalEngine() override { delete m_widget;} QString title() const override { return TextEditor::SearchEngine::tr("Internal"); } - QString toolTip() const override { return QString(); } + QString toolTip() const override { return {}; } QWidget *widget() const override { return m_widget; } - QVariant parameters() const override { return QVariant(); } + QVariant parameters() const override { return {}; } void readSettings(QSettings * /*settings*/) override {} void writeSettings(QSettings * /*settings*/) const override {} QFuture executeSearch( const TextEditor::FileFindParameters ¶meters, BaseFileFind *baseFileFind) override { - auto func = parameters.flags & FindRegularExpression - ? Utils::findInFilesRegExp - : Utils::findInFiles; + const auto func = parameters.flags & FindRegularExpression ? Utils::findInFilesRegExp + : Utils::findInFiles; return func(parameters.text, baseFileFind->files(parameters.nameFilters, parameters.exclusionFilters, @@ -112,7 +111,8 @@ public: class BaseFileFindPrivate { public: - ~BaseFileFindPrivate() { delete m_internalSearchEngine; } + BaseFileFindPrivate() : m_internalSearchEngine(std::make_unique()) {} + QPointer m_currentFindSupport; QLabel *m_resultLabel = nullptr; @@ -125,7 +125,7 @@ public: QPointer m_filterCombo; QPointer m_exclusionCombo; QVector m_searchEngines; - SearchEngine *m_internalSearchEngine; + std::unique_ptr m_internalSearchEngine; int m_currentSearchEngineIndex = -1; }; @@ -182,8 +182,7 @@ void SearchEngine::setEnabled(bool enabled) BaseFileFind::BaseFileFind() : d(new BaseFileFindPrivate) { - d->m_internalSearchEngine = new InternalEngine; - addSearchEngine(d->m_internalSearchEngine); + addSearchEngine(d->m_internalSearchEngine.get()); } BaseFileFind::~BaseFileFind() @@ -200,14 +199,14 @@ QStringList BaseFileFind::fileNameFilters() const { if (d->m_filterCombo) return splitFilterUiText(d->m_filterCombo->currentText()); - return QStringList(); + return {}; } QStringList BaseFileFind::fileExclusionFilters() const { if (d->m_exclusionCombo) return splitFilterUiText(d->m_exclusionCombo->currentText()); - return QStringList(); + return {}; } SearchEngine *BaseFileFind::currentSearchEngine() const @@ -233,11 +232,11 @@ void BaseFileFind::setCurrentSearchEngine(int index) static void displayResult(QFutureWatcher *watcher, SearchResult *search, int index) { - FileSearchResultList results = watcher->resultAt(index); + const FileSearchResultList results = watcher->resultAt(index); QList items; - foreach (const FileSearchResult &result, results) { + for (const FileSearchResult &result : results) { SearchResultItem item; - item.path = QStringList() << QDir::toNativeSeparators(result.fileName); + item.path = QStringList(QDir::toNativeSeparators(result.fileName)); item.mainRange.begin.line = result.lineNumber; item.mainRange.begin.column = result.matchStart; item.mainRange.end = item.mainRange.begin; @@ -258,7 +257,7 @@ void BaseFileFind::runNewSearch(const QString &txt, FindFlags findFlags, updateComboEntries(d->m_filterCombo, true); if (d->m_exclusionCombo) updateComboEntries(d->m_exclusionCombo, true); - QString tooltip = toolTip(); + const QString tooltip = toolTip(); SearchResult *search = SearchResultWindow::instance()->startNewSearch( label(), @@ -276,20 +275,26 @@ void BaseFileFind::runNewSearch(const QString &txt, FindFlags findFlags, parameters.searchEngineParameters = currentSearchEngine()->parameters(); parameters.searchEngineIndex = d->m_currentSearchEngineIndex; search->setUserData(qVariantFromValue(parameters)); - connect(search, &SearchResult::activated, this, &BaseFileFind::openEditor); + connect(search, &SearchResult::activated, this, [this, search](const SearchResultItem &item) { + openEditor(search, item); + }); if (searchMode == SearchResultWindow::SearchAndReplace) connect(search, &SearchResult::replaceButtonClicked, this, &BaseFileFind::doReplace); connect(search, &SearchResult::visibilityChanged, this, &BaseFileFind::hideHighlightAll); - connect(search, &SearchResult::searchAgainRequested, this, &BaseFileFind::searchAgain); + connect(search, &SearchResult::searchAgainRequested, this, [this, search] { + searchAgain(search); + }); connect(this, &BaseFileFind::enabledChanged, search, &SearchResult::requestEnabledCheck); - connect(search, &SearchResult::requestEnabledCheck, this, &BaseFileFind::recheckEnabled); + connect(search, &SearchResult::requestEnabledCheck, this, [this, search] { + recheckEnabled(search); + }); runSearch(search); } void BaseFileFind::runSearch(SearchResult *search) { - FileFindParameters parameters = search->userData().value(); + const FileFindParameters parameters = search->userData().value(); auto label = new CountingLabel; connect(search, &SearchResult::countChanged, label, &CountingLabel::updateCount); auto statusLabel = new CountingLabel; @@ -341,7 +346,7 @@ void BaseFileFind::doReplace(const QString &text, const QList &items, bool preserveCase) { - QStringList files = replaceAll(text, items, preserveCase); + const QStringList files = replaceAll(text, items, preserveCase); if (!files.isEmpty()) { Utils::FadingIndicator::showText(ICore::mainWindow(), tr("%n occurrences replaced.", nullptr, items.size()), @@ -391,7 +396,7 @@ QList> BaseFileFind::createPatternWidgets() void BaseFileFind::writeCommonSettings(QSettings *settings) { - std::function fromNativeSeparators = [](const QStringList &files) { + const auto fromNativeSeparators = [](const QStringList &files) -> QStringList { return Utils::transform(files, &QDir::fromNativeSeparators); }; @@ -404,7 +409,7 @@ void BaseFileFind::writeCommonSettings(QSettings *settings) settings->setValue("currentExclusionFilter", QDir::fromNativeSeparators(d->m_exclusionCombo->currentText())); - foreach (SearchEngine *searchEngine, d->m_searchEngines) + for (const SearchEngine *searchEngine : qAsConst(d->m_searchEngines)) searchEngine->writeSettings(settings); settings->setValue("currentSearchEngineIndex", d->m_currentSearchEngineIndex); } @@ -412,13 +417,13 @@ void BaseFileFind::writeCommonSettings(QSettings *settings) void BaseFileFind::readCommonSettings(QSettings *settings, const QString &defaultFilter, const QString &defaultExclusionFilter) { - std::function toNativeSeparators = [](const QStringList &files) { + const auto toNativeSeparators = [](const QStringList &files) -> QStringList { return Utils::transform(files, &QDir::toNativeSeparators); }; - QStringList filters = settings->value("filters").toStringList(); - if (filters.isEmpty()) - filters << defaultFilter; + const QStringList filterSetting = settings->value("filters").toStringList(); + const QStringList filters = filterSetting.isEmpty() ? QStringList(defaultFilter) + : filterSetting; const QVariant currentFilter = settings->value("currentFilter"); d->m_filterSetting = currentFilter.isValid() ? currentFilter.toString() : filters.first(); @@ -436,16 +441,15 @@ void BaseFileFind::readCommonSettings(QSettings *settings, const QString &defaul if (d->m_exclusionCombo) syncComboWithSettings(d->m_exclusionCombo, d->m_exclusionSetting); - foreach (SearchEngine* searchEngine, d->m_searchEngines) + for (SearchEngine* searchEngine : qAsConst(d->m_searchEngines)) searchEngine->readSettings(settings); const int currentSearchEngineIndex = settings->value("currentSearchEngineIndex", 0).toInt(); syncSearchEngineCombo(currentSearchEngineIndex); } -void BaseFileFind::openEditor(const SearchResultItem &item) +void BaseFileFind::openEditor(SearchResult *result, const SearchResultItem &item) { - auto result = qobject_cast(sender()); - FileFindParameters parameters = result->userData().value(); + const FileFindParameters parameters = result->userData().value(); IEditor *openedEditor = d->m_searchEngines[parameters.searchEngineIndex]->openEditor(item, parameters); if (!openedEditor) @@ -468,16 +472,14 @@ void BaseFileFind::hideHighlightAll(bool visible) d->m_currentFindSupport->clearHighlights(); } -void BaseFileFind::searchAgain() +void BaseFileFind::searchAgain(SearchResult *search) { - auto search = qobject_cast(sender()); search->restart(); runSearch(search); } -void BaseFileFind::recheckEnabled() +void BaseFileFind::recheckEnabled(SearchResult *search) { - auto search = qobject_cast(sender()); if (!search) return; search->setSearchAgainEnabled(isEnabled()); @@ -493,7 +495,7 @@ QStringList BaseFileFind::replaceAll(const QString &text, RefactoringChanges refactoring; QHash > changes; - foreach (const SearchResultItem &item, items) + for (const SearchResultItem &item : items) changes[QDir::fromNativeSeparators(item.path.first())].append(item); // Checking for files without write permissions @@ -523,7 +525,7 @@ QStringList BaseFileFind::replaceAll(const QString &text, ChangeSet changeSet; RefactoringFilePtr file = refactoring.file(fileName); QSet > processed; - foreach (const SearchResultItem &item, changeItems) { + for (const SearchResultItem &item : changeItems) { const QPair &p = qMakePair(item.mainRange.begin.line, item.mainRange.begin.column); if (processed.contains(p)) diff --git a/src/plugins/texteditor/basefilefind.h b/src/plugins/texteditor/basefilefind.h index 32595b0398b..1297e1a2ace 100644 --- a/src/plugins/texteditor/basefilefind.h +++ b/src/plugins/texteditor/basefilefind.h @@ -67,6 +67,7 @@ class TEXTEDITOR_EXPORT SearchEngine : public QObject public: SearchEngine(QObject *parent = nullptr); ~SearchEngine() override; + virtual QString title() const = 0; virtual QString toolTip() const = 0; // add %1 placeholder where the find flags should be put virtual QWidget *widget() const = 0; @@ -132,13 +133,13 @@ signals: void currentSearchEngineChanged(); private: - void openEditor(const Core::SearchResultItem &item); + void openEditor(Core::SearchResult *result, const Core::SearchResultItem &item); void doReplace(const QString &txt, const QList &items, bool preserveCase); void hideHighlightAll(bool visible); - void searchAgain(); - void recheckEnabled(); + void searchAgain(Core::SearchResult *search); + void recheckEnabled(Core::SearchResult *search); void runNewSearch(const QString &txt, Core::FindFlags findFlags, Core::SearchResultWindow::SearchMode searchMode);