Merge remote-tracking branch 'origin/3.5'

Conflicts:
	scripts/deployqtHelper_mac.sh

Change-Id: Ia0d5fef8c28e0bfb3b0c703ad3652e2d70d9e7d1
This commit is contained in:
Oswald Buddenhagen
2015-07-17 17:25:26 +02:00
133 changed files with 1755 additions and 1198 deletions

View File

@@ -127,7 +127,7 @@ FakeVim
Todo
* Added option to excluding file patterns from parsing
* Added option to exclude file patterns from parsing
Beautifier

View File

@@ -83,7 +83,7 @@
#include <QMutableVectorIterator>
#include <QQuickView>
#include <designersupport.h>
#include <designersupportdelegate.h>
namespace {

View File

@@ -63,7 +63,7 @@
#include "dummycontextobject.h"
#include <designersupport.h>
#include <designersupportdelegate.h>
namespace QmlDesigner {

View File

@@ -37,7 +37,7 @@
#include "qt5rendernodeinstanceserver.h"
#include "qt5testnodeinstanceserver.h"
#include <designersupport.h>
#include <designersupportdelegate.h>
#if defined(Q_OS_UNIX)
#include <unistd.h>

View File

@@ -34,7 +34,7 @@
#include <QQuickItem>
#include <QQuickView>
#include <designersupport.h>
#include <designersupportdelegate.h>
#include <addimportcontainer.h>
#include <createscenecommand.h>
#include <reparentinstancescommand.h>

View File

@@ -34,7 +34,7 @@
#include <QtGlobal>
#include "nodeinstanceserver.h"
#include "designersupport.h"
#include <designersupportdelegate.h>
QT_BEGIN_NAMESPACE
class QQuickItem;

View File

@@ -36,7 +36,7 @@
#include "removesharedmemorycommand.h"
#include <QQuickView>
#include <QQuickItem>
#include <designersupport.h>
#include <designersupportdelegate.h>
namespace QmlDesigner {

View File

@@ -63,7 +63,7 @@
#include "dummycontextobject.h"
#include <designersupport.h>
#include <designersupportdelegate.h>
namespace QmlDesigner {

View File

@@ -65,7 +65,7 @@
#include "dummycontextobject.h"
#include <designersupport.h>
#include <designersupportdelegate.h>
namespace QmlDesigner {

View File

@@ -36,7 +36,7 @@
#include "objectnodeinstance.h"
#include <QQuickItem>
#include <designersupport.h>
#include <designersupportdelegate.h>
namespace QmlDesigner {
namespace Internal {

View File

@@ -0,0 +1,5 @@
#if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0))
#include <private/qquickdesignersupport_p.h>
#else
#include <designersupport.h>
#endif

View File

@@ -57,7 +57,7 @@
#include <private/qquickstateoperations_p.h>
#include <designersupport.h>
#include <designersupportdelegate.h>
namespace QmlDesigner {

View File

@@ -0,0 +1,39 @@
# This pri file is used to deploy files that are not compiled while building
# Qt Creator. It handles copying of files into the build directory if using
# a shadow build and adds the respective install target as well.
#
# Usage: Define variables (details below) and include this pri file afterwards.
#
# STATIC_BASE - base directory for the files listed in STATIC_FILES
# STATIC_FILES - list of files to be deployed
include(../../qtcreator.pri)
# used in custom compilers which just copy files
defineReplace(stripStaticBase) {
return($$relative_path($$1, $$STATIC_BASE))
}
# handle conditional copying; copydata will be set by qtcreator.pri
!isEmpty(STATIC_FILES) {
isEmpty(STATIC_BASE): \
error("Using STATIC_FILES without having STATIC_BASE set")
!isEmpty(copydata) {
copy2build.input += STATIC_FILES
copy2build.output = $$IDE_DATA_PATH/${QMAKE_FUNC_FILE_IN_stripStaticBase}
isEmpty(vcproj):copy2build.variable_out = PRE_TARGETDEPS
win32:copy2build.commands = $$QMAKE_COPY \"${QMAKE_FILE_IN}\" \"${QMAKE_FILE_OUT}\"
unix:copy2build.commands = $$QMAKE_COPY ${QMAKE_FILE_IN} ${QMAKE_FILE_OUT}
copy2build.name = COPY ${QMAKE_FILE_IN}
copy2build.config += no_link
QMAKE_EXTRA_COMPILERS += copy2build
}
!osx {
static.files = $$STATIC_FILES
static.base = $$STATIC_BASE
static.path = $$QTC_PREFIX/share/qtcreator
INSTALLS += static
}
}

View File

@@ -1,5 +1,3 @@
include(../../qtcreator.pri)
TEMPLATE = app
TARGET = phony_target
CONFIG -= qt sdk separate_debug_info gdb_dwarf_index
@@ -23,6 +21,9 @@ isEmpty(vcproj) {
QMAKE_EXTRA_COMPILERS += phony_src
}
STATIC_BASE = $$PWD
# files/folders that are conditionally "deployed" to the build directory
DATA_DIRS = \
welcomescreen \
examplebrowser \
@@ -46,28 +47,14 @@ macx: DATA_DIRS += scripts
for(data_dir, DATA_DIRS) {
files = $$files($$PWD/$$data_dir/*, true)
# Info.plist.in are handled below
for(file, files):!contains(file, ".*/Info\\.plist\\.in$"):!exists($$file/*):FILES += $$file
for(file, files):!contains(file, ".*/Info\\.plist\\.in$"):!exists($$file/*): \
STATIC_FILES += $$file
}
# conditionally deployed data
!isEmpty(copydata) {
copy2build.input = FILES
copy2build.output = $$IDE_DATA_PATH/${QMAKE_FUNC_FILE_IN_stripSrcDir}
isEmpty(vcproj):copy2build.variable_out = PRE_TARGETDEPS
win32:copy2build.commands = $$QMAKE_COPY \"${QMAKE_FILE_IN}\" \"${QMAKE_FILE_OUT}\"
unix:copy2build.commands = $$QMAKE_COPY ${QMAKE_FILE_IN} ${QMAKE_FILE_OUT}
copy2build.name = COPY ${QMAKE_FILE_IN}
copy2build.CONFIG += no_link
QMAKE_EXTRA_COMPILERS += copy2build
}
include(static.pri)
!macx {
for(data_dir, DATA_DIRS) {
eval($${data_dir}.files = $$quote($$PWD/$$data_dir))
eval($${data_dir}.path = $$QTC_PREFIX/share/qtcreator)
INSTALLS += $$data_dir
}
} else {
# stuff that cannot be handled by static.pri
osx {
# do version magic for app bundles
dumpinfo.input = qml/qmldump/Info.plist.in
dumpinfo.output = $$IDE_DATA_PATH/qml/qmldump/Info.plist

View File

@@ -4,7 +4,7 @@ import QtQuick.Window %{QtQuickWindowVersion}
Window {
visible: true
@if %{QmlUISplit}
@if %{IsUiFileInUse}
MainForm {
anchors.fill: parent
mouseArea.onClicked: {

View File

@@ -1,7 +1,7 @@
<RCC>
<qresource prefix="/">
<file>main.qml</file>
@if %{QmlUISplit}
@if %{IsUiFileInUse}
<file>MainForm.ui.qml</file>
@endif
</qresource>

View File

@@ -16,7 +16,9 @@
{ "key": "MainCppFileName", "value": "%{JS: 'main.' + Util.preferredSuffix('text/x-c++src')}" },
{ "key": "QtQuickVersion", "value": "%{JS: %{QtVersion}.qtQuickVersion}" },
{ "key": "QtQuickWindowVersion", "value": "%{JS: %{QtVersion}.qtQuickWindowVersion}" },
{ "key": "QtQuickFeature", "value": "QtSupport.Wizards.FeatureQtQuick.%{QtQuickVersion}" }
{ "key": "QtQuickFeature", "value": "QtSupport.Wizards.FeatureQtQuick.%{QtQuickVersion}" },
{ "key": "UiSupport", "value": "%{JS: '%{QtQuickVersion}' !== '2.3' }" },
{ "key": "IsUiFileInUse", "value": "%{JS: %{UiSupport} && %{QmlUiSplit} }" }
],
"pages":
@@ -69,12 +71,13 @@
}
},
{
"name": "QmlUISplit",
"name": "QmlUiSplit",
"trDisplayName": "With ui.qml file",
"type": "CheckBox",
"visible": "%{UiSupport}",
"data":
{
"checked": false
"checked": true
}
}
]
@@ -115,7 +118,7 @@
},
{
"source": "MainForm.ui.qml",
"condition": "%{QmlUISplit}"
"condition": "%{IsUiFileInUse}"
},
{
"source": "qml.qrc"

View File

@@ -1,6 +1,6 @@
import QtQuick %{QtQuickVersion}
import QtQuick.Controls %{QtQuickControlsVersion}
@if %{QmlUISplit}
@if %{IsUiFileInUse}
import QtQuick.Dialogs %{QtQuickDialogsVersion}
@endif
@@ -24,7 +24,7 @@ ApplicationWindow {
}
}
@if %{QmlUISplit}
@if %{IsUiFileInUse}
MainForm {
anchors.fill: parent
button1.onClicked: messageDialog.show(qsTr("Button 1 pressed"))

View File

@@ -1,7 +1,7 @@
<RCC>
<qresource prefix="/">
<file>main.qml</file>
@if %{QmlUISplit}
@if %{IsUiFileInUse}
<file>MainForm.ui.qml</file>
@endif
</qresource>

View File

@@ -18,7 +18,9 @@
{ "key": "QtQuickControlsVersion", "value": "%{JS: %{QtVersion}.qtQuickControlsVersion}" },
{ "key": "QtQuickDialogsVersion", "value": "%{JS: %{QtVersion}.qtQuickDialogsVersion}" },
{ "key": "QtQuickLayoutsVersion", "value": "%{JS: %{QtVersion}.qtQuickLayoutsVersion}" },
{ "key": "QtQuickFeature", "value": "QtSupport.Wizards.FeatureQtQuick.%{QtQuickVersion}" }
{ "key": "QtQuickFeature", "value": "QtSupport.Wizards.FeatureQtQuick.%{QtQuickVersion}" },
{ "key": "UiSupport", "value": "%{JS: '%{QtQuickVersion}' !== '2.3' }" },
{ "key": "IsUiFileInUse", "value": "%{JS: %{UiSupport} && %{QmlUiSplit} }" }
],
"pages":
@@ -77,9 +79,10 @@
}
},
{
"name": "QmlUISplit",
"name": "QmlUiSplit",
"trDisplayName": "With ui.qml file",
"type": "CheckBox",
"visible": "%{UiSupport}",
"data":
{
"checked": true
@@ -132,7 +135,7 @@
},
{
"source": "MainForm.ui.qml",
"condition": "%{QmlUISplit}"
"condition": "%{IsUiFileInUse}"
},
{
"source": "qml.qrc"

View File

@@ -15,7 +15,9 @@
{ "key": "QmlProjectFileName", "value": "%{JS: Util.fileName('%{ProjectDirectory}/%{ProjectName}', 'qmlproject')}" },
{ "key": "MainQmlFileName", "value": "%{JS: Util.fileName('%{ProjectName}', 'qml')}" },
{ "key": "QtQuickVersion", "value": "%{JS: %{QtVersion}.qtQuickVersion}" },
{ "key": "QtQuickWindowVersion", "value": "%{JS: %{QtVersion}.qtQuickWindowVersion}" }
{ "key": "QtQuickWindowVersion", "value": "%{JS: %{QtVersion}.qtQuickWindowVersion}" },
{ "key": "UiSupport", "value": "%{JS: '%{QtQuickVersion}' !== '2.3' }" },
{ "key": "IsUiFileInUse", "value": "%{JS: %{UiSupport} && %{QmlUiSplit} }" }
],
"pages":
@@ -67,9 +69,10 @@
}
},
{
"name": "QmlUISplit",
"name": "QmlUiSplit",
"trDisplayName": "With ui.qml file",
"type": "CheckBox",
"visible": "%{UiSupport}",
"data":
{
"checked": false
@@ -102,7 +105,7 @@
{
"source": "../../qmake/qtquickapplication/MainForm.ui.qml",
"target": "%{ProjectDirectory}/MainForm.ui.qml",
"condition": "%{QmlUISplit}"
"condition": "%{IsUiFileInUse}"
},
{
"source": "../../git.ignore",

View File

@@ -17,7 +17,9 @@
{ "key": "QtQuickVersion", "value": "%{JS: %{QtVersion}.qtQuickVersion}" },
{ "key": "QtQuickControlsVersion", "value": "%{JS: %{QtVersion}.qtQuickControlsVersion}" },
{ "key": "QtQuickDialogsVersion", "value": "%{JS: %{QtVersion}.qtQuickDialogsVersion}" },
{ "key": "QtQuickLayoutsVersion", "value": "%{JS: %{QtVersion}.qtQuickLayoutsVersion}" }
{ "key": "QtQuickLayoutsVersion", "value": "%{JS: %{QtVersion}.qtQuickLayoutsVersion}" },
{ "key": "UiSupport", "value": "%{JS: '%{QtQuickVersion}' !== '2.3' }" },
{ "key": "IsUiFileInUse", "value": "%{JS: %{UiSupport} && %{QmlUiSplit} }" }
],
"pages":
@@ -75,9 +77,10 @@
}
},
{
"name": "QmlUISplit",
"name": "QmlUiSplit",
"trDisplayName": "With ui.qml file",
"type": "CheckBox",
"visible": "%{UiSupport}",
"data":
{
"checked": true
@@ -110,7 +113,7 @@
{
"source": "../../qmake/qtquickcontrolsapplication/MainForm.ui.qml",
"target": "%{ProjectDirectory}/MainForm.ui.qml",
"condition": "%{QmlUISplit}"
"condition": "%{IsUiFileInUse}"
},
{
"source": "../../git.ignore",

View File

@@ -76,7 +76,7 @@ bool operator<(const RegisterProjectPartsForCodeCompletionCommand &first, const
QDebug operator<<(QDebug debug, const RegisterProjectPartsForCodeCompletionCommand &command)
{
debug.nospace() << "RegisterProjectPartsForCodeCompletion(";
debug.nospace() << "RegisterProjectPartsForCodeCompletionCommand(";
for (const ProjectPartContainer &projectContainer : command.projectContainers())
debug.nospace() << projectContainer<< ", ";
@@ -88,7 +88,7 @@ QDebug operator<<(QDebug debug, const RegisterProjectPartsForCodeCompletionComma
void PrintTo(const RegisterProjectPartsForCodeCompletionCommand &command, ::std::ostream* os)
{
*os << "RegisterProjectPartsForCodeCompletion(";
*os << "RegisterProjectPartsForCodeCompletionCommand(";
for (const ProjectPartContainer &projectContainer : command.projectContainers())
PrintTo(projectContainer, os);

View File

@@ -42,44 +42,44 @@ namespace ClangBackEnd {
UnregisterProjectPartsForCodeCompletionCommand::UnregisterProjectPartsForCodeCompletionCommand(const Utf8StringVector &filePaths)
: filePaths_(filePaths)
: projectPartIds_(filePaths)
{
}
const Utf8StringVector &UnregisterProjectPartsForCodeCompletionCommand::filePaths() const
const Utf8StringVector &UnregisterProjectPartsForCodeCompletionCommand::projectPartIds() const
{
return filePaths_;
return projectPartIds_;
}
QDataStream &operator<<(QDataStream &out, const UnregisterProjectPartsForCodeCompletionCommand &command)
{
out << command.filePaths_;
out << command.projectPartIds_;
return out;
}
QDataStream &operator>>(QDataStream &in, UnregisterProjectPartsForCodeCompletionCommand &command)
{
in >> command.filePaths_;
in >> command.projectPartIds_;
return in;
}
bool operator==(const UnregisterProjectPartsForCodeCompletionCommand &first, const UnregisterProjectPartsForCodeCompletionCommand &second)
{
return first.filePaths_ == second.filePaths_;
return first.projectPartIds_ == second.projectPartIds_;
}
bool operator<(const UnregisterProjectPartsForCodeCompletionCommand &first, const UnregisterProjectPartsForCodeCompletionCommand &second)
{
return compareContainer(first.filePaths_, second.filePaths_);
return compareContainer(first.projectPartIds_, second.projectPartIds_);
}
QDebug operator<<(QDebug debug, const UnregisterProjectPartsForCodeCompletionCommand &command)
{
debug.nospace() << "UnregisterProjectPartsForCodeCompletionCommand(";
for (const Utf8String &fileNames_ : command.filePaths())
for (const Utf8String &fileNames_ : command.projectPartIds())
debug.nospace() << fileNames_ << ", ";
debug.nospace() << ")";
@@ -91,7 +91,7 @@ void PrintTo(const UnregisterProjectPartsForCodeCompletionCommand &command, ::st
{
*os << "UnregisterProjectPartsForCodeCompletionCommand(";
for (const Utf8String &fileNames_ : command.filePaths())
for (const Utf8String &fileNames_ : command.projectPartIds())
*os << fileNames_.constData() << ", ";
*os << ")";

View File

@@ -49,12 +49,12 @@ class CMBIPC_EXPORT UnregisterProjectPartsForCodeCompletionCommand
public:
UnregisterProjectPartsForCodeCompletionCommand() = default;
UnregisterProjectPartsForCodeCompletionCommand(const Utf8StringVector &filePaths);
UnregisterProjectPartsForCodeCompletionCommand(const Utf8StringVector &projectPartIds);
const Utf8StringVector &filePaths() const;
const Utf8StringVector &projectPartIds() const;
private:
Utf8StringVector filePaths_;
Utf8StringVector projectPartIds_;
};
CMBIPC_EXPORT QDataStream &operator<<(QDataStream &out, const UnregisterProjectPartsForCodeCompletionCommand &command);

View File

@@ -38,15 +38,11 @@
namespace ClangBackEnd {
CodeCompletion::CodeCompletion(const Utf8String &text,
const Utf8String &hint,
const Utf8String &snippet,
quint32 priority,
Kind completionKind,
Availability availability,
bool hasParameters)
: text_(text),
hint_(hint),
snippet_(snippet),
priority_(priority),
completionKind_(completionKind),
availability_(availability),
@@ -63,15 +59,6 @@ const Utf8String &CodeCompletion::text() const
{
return text_;
}
const Utf8String &CodeCompletion::hint() const
{
return hint_;
}
const Utf8String &CodeCompletion::snippet() const
{
return snippet_;
}
void CodeCompletion::setCompletionKind(CodeCompletion::Kind completionKind)
{
@@ -136,8 +123,6 @@ quint32 &CodeCompletion::availabilityAsInt()
QDataStream &operator<<(QDataStream &out, const CodeCompletion &command)
{
out << command.text_;
out << command.hint_;
out << command.snippet_;
out << command.chunks_;
out << command.priority_;
out << command.completionKind_;
@@ -150,8 +135,6 @@ QDataStream &operator<<(QDataStream &out, const CodeCompletion &command)
QDataStream &operator>>(QDataStream &in, CodeCompletion &command)
{
in >> command.text_;
in >> command.hint_;
in >> command.snippet_;
in >> command.chunks_;
in >> command.priority_;
in >> command.completionKindAsInt();
@@ -213,8 +196,6 @@ QDebug operator<<(QDebug debug, const CodeCompletion &command)
debug.nospace() << "CodeCompletion(";
debug.nospace() << command.text_ << ", ";
debug.nospace() << command.hint_ << ", ";
debug.nospace() << command.snippet_ << ", ";
debug.nospace() << command.priority_ << ", ";
debug.nospace() << completionKindToString(command.completionKind_) << ", ";
debug.nospace() << availabilityToString(command.availability_) << ", ";
@@ -230,8 +211,6 @@ void PrintTo(const CodeCompletion &command, ::std::ostream* os)
*os << "CodeCompletion(";
*os << command.text_.constData() << ", ";
*os << command.hint_.constData() << ", ";
*os << command.snippet_.constData() << ", ";
*os << command.priority_ << ", ";
*os << completionKindToString(command.completionKind_) << ", ";
*os << availabilityToString(command.availability_) << ", ";

View File

@@ -80,8 +80,6 @@ public:
public:
CodeCompletion() = default;
CodeCompletion(const Utf8String &text,
const Utf8String &hint = Utf8String(),
const Utf8String &snippet = Utf8String(),
quint32 priority = 0,
Kind completionKind = Other,
Availability availability = Available,
@@ -90,9 +88,6 @@ public:
void setText(const Utf8String &text);
const Utf8String &text() const;
const Utf8String &hint() const;
const Utf8String &snippet() const;
void setCompletionKind(Kind completionKind);
Kind completionKind() const;
@@ -114,8 +109,6 @@ private:
private:
Utf8String text_;
Utf8String hint_;
Utf8String snippet_;
QVector<CodeCompletionChunk> chunks_;
quint32 priority_ = 0;
Kind completionKind_ = Other;

View File

@@ -86,53 +86,83 @@ QList<FormattedText> AnsiEscapeCodeHandler::parseText(const FormattedText &input
DefaultBackgroundColor = 49
};
QList<FormattedText> outputData;
QTextCharFormat charFormat = m_previousFormatClosed ? input.format : m_previousFormat;
const QString escape = QLatin1String("\x1b[");
const int escapePos = input.text.indexOf(escape);
if (escapePos < 0) {
outputData << FormattedText(input.text, charFormat);
return outputData;
} else if (escapePos != 0) {
outputData << FormattedText(input.text.left(escapePos), charFormat);
}
const QChar semicolon = QLatin1Char(';');
const QChar colorTerminator = QLatin1Char('m');
const QChar eraseToEol = QLatin1Char('K');
// strippedText always starts with "\e["
QString strippedText = input.text.mid(escapePos);
QList<FormattedText> outputData;
QTextCharFormat charFormat = m_previousFormatClosed ? input.format : m_previousFormat;
QString strippedText;
if (m_pendingText.isEmpty()) {
strippedText = input.text;
} else {
strippedText = m_pendingText.append(input.text);
m_pendingText.clear();
}
while (!strippedText.isEmpty()) {
while (strippedText.startsWith(escape)) {
strippedText.remove(0, 2);
QTC_ASSERT(m_pendingText.isEmpty(), break);
const int escapePos = strippedText.indexOf(escape[0]);
if (escapePos < 0) {
outputData << FormattedText(strippedText, charFormat);
break;
} else if (escapePos != 0) {
outputData << FormattedText(strippedText.left(escapePos), charFormat);
strippedText.remove(0, escapePos);
}
QTC_ASSERT(strippedText[0] == escape[0], break);
while (!strippedText.isEmpty() && escape[0] == strippedText[0]) {
if (escape.startsWith(strippedText)) {
// control secquence is not complete
m_pendingText += strippedText;
strippedText.clear();
break;
}
if (!strippedText.startsWith(escape)) {
// not a control sequence
m_pendingText.clear();
outputData << FormattedText(strippedText.left(1), charFormat);
strippedText.remove(0, 1);
continue;
}
m_pendingText += strippedText.mid(0, escape.length());
strippedText.remove(0, escape.length());
// \e[K is not supported. Just strip it.
if (strippedText.startsWith(eraseToEol)) {
m_pendingText.clear();
strippedText.remove(0, 1);
continue;
}
// get the number
QString strNumber;
QStringList numbers;
while (strippedText.at(0).isDigit() || strippedText.at(0) == semicolon) {
while (!strippedText.isEmpty()) {
if (strippedText.at(0).isDigit()) {
strNumber += strippedText.at(0);
} else {
numbers << strNumber;
if (!strNumber.isEmpty())
numbers << strNumber;
if (strNumber.isEmpty() || strippedText.at(0) != semicolon)
break;
strNumber.clear();
}
m_pendingText += strippedText.mid(0, 1);
strippedText.remove(0, 1);
}
if (!strNumber.isEmpty())
numbers << strNumber;
if (strippedText.isEmpty())
break;
// remove terminating char
if (!strippedText.startsWith(colorTerminator)) {
m_pendingText.clear();
strippedText.remove(0, 1);
continue;
break;
}
// got consistent control sequence, ok to clear pending text
m_pendingText.clear();
strippedText.remove(0, 1);
if (numbers.isEmpty()) {
@@ -224,17 +254,6 @@ QList<FormattedText> AnsiEscapeCodeHandler::parseText(const FormattedText &input
}
}
}
if (strippedText.isEmpty())
break;
int index = strippedText.indexOf(escape);
if (index > 0) {
outputData << FormattedText(strippedText.left(index), charFormat);
strippedText.remove(0, index);
} else if (index == -1) {
outputData << FormattedText(strippedText, charFormat);
break;
}
}
return outputData;
}

View File

@@ -62,6 +62,7 @@ private:
bool m_previousFormatClosed;
QTextCharFormat m_previousFormat;
QString m_pendingText;
};
} // namespace Utils

View File

@@ -380,7 +380,7 @@ QList<EnvironmentItem> Environment::diff(const Environment &other) const
if (thisIt == constEnd()) {
result.append(EnvironmentItem(otherIt.key(), otherIt.value()));
++otherIt;
} else if (otherIt == constEnd()) {
} else if (otherIt == other.constEnd()) {
EnvironmentItem item(thisIt.key(), QString());
item.unset = true;
result.append(item);
@@ -394,7 +394,8 @@ QList<EnvironmentItem> Environment::diff(const Environment &other) const
result.append(EnvironmentItem(otherIt.key(), otherIt.value()));
++otherIt;
} else {
result.append(EnvironmentItem(otherIt.key(), otherIt.value()));
if (thisIt.value() != otherIt.value())
result.append(EnvironmentItem(otherIt.key(), otherIt.value()));
++otherIt;
++thisIt;
}

View File

@@ -274,7 +274,7 @@ QString MacroExpander::expand(const QString &stringWithVariables) const
if (d->m_lockDepth == 0)
d->m_aborted = false;
if (d->m_lockDepth > 3) { // Limit recursion.
if (d->m_lockDepth > 10) { // Limit recursion.
d->m_aborted = true;
return QString();
}

View File

@@ -770,15 +770,6 @@ QModelIndex TreeItem::index() const
return m_model->indexForItem(this);
}
void TreeItem::setModel(TreeModel *model)
{
if (m_model == model)
return;
m_model = model;
foreach (TreeItem *item, m_children)
item->setModel(model);
}
void TreeItem::walkTree(TreeItemVisitor *visitor)
{
if (visitor->preVisit(this)) {
@@ -972,6 +963,9 @@ int TreeModel::topLevelItemCount() const
void TreeModel::setRootItem(TreeItem *item)
{
QTC_ASSERT(item, return);
QTC_ASSERT(item->m_model == 0, return);
QTC_ASSERT(item->m_parent == 0, return);
QTC_CHECK(m_root);
if (m_root) {
QTC_CHECK(m_root->m_parent == 0);
@@ -980,7 +974,7 @@ void TreeModel::setRootItem(TreeItem *item)
delete m_root;
}
m_root = item;
item->setModel(this);
item->propagateModel(this);
emit layoutChanged();
}

View File

@@ -101,7 +101,6 @@ public:
QModelIndex index() const;
TreeModel *model() const { return m_model; }
void setModel(TreeModel *model);
void walkTree(TreeItemVisitor *visitor);
void walkTree(std::function<void(TreeItem *)> f);
@@ -117,7 +116,6 @@ private:
TreeModel *m_model; // Not owned.
QVector<TreeItem *> m_children; // Owned.
QStringList *m_displays;
mutable bool m_populated;
Qt::ItemFlags m_flags;
friend class TreeModel;

View File

@@ -1302,7 +1302,7 @@ void AndroidConfigurations::updateAutomaticKitList()
}
QHash<Abi, QList<QtSupport::BaseQtVersion *> > qtVersionsForArch;
foreach (QtSupport::BaseQtVersion *qtVersion, QtSupport::QtVersionManager::versions()) {
foreach (QtSupport::BaseQtVersion *qtVersion, QtSupport::QtVersionManager::unsortedVersions()) {
if (qtVersion->type() != QLatin1String(Constants::ANDROIDQT))
continue;
QList<Abi> qtAbis = qtVersion->qtAbis();

View File

@@ -30,10 +30,13 @@
#include "clangassistproposalitem.h"
#include "completionchunkstotextconverter.h"
#include <cplusplus/MatchingText.h>
#include <cplusplus/Token.h>
#include <texteditor/completionsettings.h>
#include <texteditor/textdocument.h>
#include <texteditor/texteditor.h>
#include <texteditor/texteditorsettings.h>
@@ -64,6 +67,21 @@ bool ClangAssistProposalItem::prematurelyApplies(const QChar &typedChar) const
return applies;
}
static bool hasOnlyBlanksBeforeCursorInLine(QTextCursor textCursor)
{
textCursor.movePosition(QTextCursor::StartOfLine, QTextCursor::KeepAnchor);
const auto textBeforeCursor = textCursor.selectedText();
const auto nonSpace = std::find_if(textBeforeCursor.cbegin(),
textBeforeCursor.cend(),
[] (const QChar &signBeforeCursor) {
return !signBeforeCursor.isSpace();
});
return nonSpace == textBeforeCursor.cend();
}
void ClangAssistProposalItem::applyContextualContent(TextEditor::TextEditorWidget *editorWidget,
int basePosition) const
{
@@ -86,6 +104,17 @@ void ClangAssistProposalItem::applyContextualContent(TextEditor::TextEditorWidge
if (m_typedChar == QLatin1Char('/')) // Eat the slash
m_typedChar = QChar();
}
} else if (ccr.completionKind() == CodeCompletion::KeywordCompletionKind) {
CompletionChunksToTextConverter converter;
converter.setAddPlaceHolderPositions(true);
converter.setAddSpaces(true);
converter.setAddExtraVerticalSpaceBetweenBraces(true);
converter.parseChunks(ccr.chunks());
toInsert = converter.text();
if (converter.hasPlaceholderPositions())
cursorOffset = converter.placeholderPositions().at(0) - converter.text().size();
} else if (!ccr.text().isEmpty()) {
const TextEditor::CompletionSettings &completionSettings =
TextEditor::TextEditorSettings::instance()->completionSettings();
@@ -165,7 +194,7 @@ void ClangAssistProposalItem::applyContextualContent(TextEditor::TextEditorWidge
const int endsPosition = editorWidget->position(TextEditor::EndOfLinePosition);
const QString existingText = editorWidget->textAt(editorWidget->position(), endsPosition - editorWidget->position());
int existLength = 0;
if (!existingText.isEmpty()) {
if (!existingText.isEmpty() && ccr.completionKind() != CodeCompletion::KeywordCompletionKind) {
// Calculate the exist length in front of the extra chars
existLength = toInsert.length() - (editorWidget->position() - basePosition);
while (!existingText.startsWith(toInsert.right(existLength))) {
@@ -189,6 +218,18 @@ void ClangAssistProposalItem::applyContextualContent(TextEditor::TextEditorWidge
editorWidget->replace(length, toInsert);
if (cursorOffset)
editorWidget->setCursorPosition(editorWidget->position() + cursorOffset);
// indent the statement
if (ccr.completionKind() == CodeCompletion::KeywordCompletionKind) {
auto selectionCursor = editorWidget->textCursor();
selectionCursor.setPosition(basePosition);
selectionCursor.setPosition(basePosition + toInsert.size(), QTextCursor::KeepAnchor);
auto basePositionCursor = editorWidget->textCursor();
basePositionCursor.setPosition(basePosition);
if (hasOnlyBlanksBeforeCursorInLine(basePositionCursor))
editorWidget->textDocument()->autoIndent(selectionCursor);
}
}
void ClangAssistProposalItem::keepCompletionOperator(unsigned compOp)

View File

@@ -39,15 +39,6 @@
namespace ClangCodeModel {
namespace Internal {
namespace {
const ClangAssistProposalItem &toClangAssistProposalItem(TextEditor::AssistProposalItem *assistProposalItem)
{
return *static_cast<ClangAssistProposalItem*>(assistProposalItem);
}
}
bool ClangAssistProposalModel::replaceDotForArrow(TextEditor::IAssistProposalModel *model)
{
auto clangAssistProposalModel = static_cast<ClangAssistProposalModel*>(model);

View File

@@ -157,7 +157,7 @@ void IpcReceiver::translationUnitDoesNotExist(const TranslationUnitDoesNotExistC
void IpcReceiver::projectPartsDoNotExist(const ProjectPartsDoNotExistCommand &command)
{
QTC_CHECK(!"Got ProjectDoesNotExistCommand");
QTC_CHECK(!"Got ProjectPartsDoNotExistCommand");
qCDebug(log) << "<<< ERROR:" << command;
}
@@ -223,10 +223,8 @@ IpcCommunicator::IpcCommunicator()
connect(Core::EditorManager::instance(), &Core::EditorManager::editorAboutToClose,
this, &IpcCommunicator::onEditorAboutToClose);
connect(Core::ICore::instance(), &Core::ICore::coreAboutToClose, [this]() {
m_sendMode = IgnoreSendRequests;
});
connect(Core::ICore::instance(), &Core::ICore::coreAboutToClose,
this, &IpcCommunicator::onCoreAboutToClose);
initializeBackend();
}
@@ -376,6 +374,11 @@ void IpcCommunicator::onEditorAboutToClose(Core::IEditor *editor)
m_ipcReceiver.deleteProcessorsOfEditorWidget(textEditor->editorWidget());
}
void IpcCommunicator::onCoreAboutToClose()
{
m_sendMode = IgnoreSendRequests;
}
void IpcCommunicator::initializeBackendWithCurrentData()
{
registerEmptyProjectForProjectLessFiles();

View File

@@ -143,6 +143,7 @@ private:
void onBackendRestarted();
void onEditorAboutToClose(Core::IEditor *editor);
void onCoreAboutToClose();
IpcReceiver m_ipcReceiver;
ClangBackEnd::ConnectionClient m_connection;

View File

@@ -33,6 +33,7 @@
#include "clangutils.h"
#include <cpptools/cppmodelmanager.h>
#include <cpptools/cpptoolsreuse.h>
#include <cpptools/cppworkingcopy.h>
#include <texteditor/texteditor.h>
@@ -58,7 +59,9 @@ ClangCompletionAssistInterface::ClangCompletionAssistInterface(
, m_languageFeatures(features)
, m_textEditorWidget(textEditorWidget)
{
m_unsavedFiles = Utils::createUnsavedFiles(CppTools::CppModelManager::instance()->workingCopy());
m_unsavedFiles = Utils::createUnsavedFiles(
CppTools::CppModelManager::instance()->workingCopy(),
CppTools::modifiedFiles());
}
bool ClangCompletionAssistInterface::objcEnabled() const

View File

@@ -37,6 +37,7 @@
#include "clangcompletioncontextanalyzer.h"
#include "clangfunctionhintmodel.h"
#include "clangutils.h"
#include "completionchunkstotextconverter.h"
#include <utils/qtcassert.h>
@@ -86,22 +87,25 @@ QList<AssistProposalItem *> toAssistProposalItems(const CodeCompletions &complet
if (slotCompletion && ccr.completionKind() != CodeCompletion::SlotCompletionKind)
continue;
const QString txt(ccr.text().toString());
ClangAssistProposalItem *item = items.value(txt, 0);
QString name;
if (ccr.completionKind() == CodeCompletion::KeywordCompletionKind)
name = CompletionChunksToTextConverter::convertToName(ccr.chunks());
else
name = ccr.text().toString();
ClangAssistProposalItem *item = items.value(name, 0);
if (item) {
item->addOverload(ccr);
} else {
item = new ClangAssistProposalItem;
items.insert(txt, item);
item->setText(txt);
item->setDetail(ccr.hint().toString());
items.insert(name, item);
item->setText(name);
item->setOrder(ccr.priority());
const QString snippet = ccr.snippet().toString();
if (!snippet.isEmpty())
item->setData(snippet);
else
item->setData(qVariantFromValue(ccr));
if (ccr.completionKind() == CodeCompletion::KeywordCompletionKind)
item->setDetail(CompletionChunksToTextConverter::convertToToolTip(ccr.chunks()));
item->setData(QVariant::fromValue(ccr));
}
// FIXME: show the effective accessebility instead of availability

View File

@@ -88,24 +88,28 @@ ClangEditorDocumentParser::ClangEditorDocumentParser(const QString &filePath)
{
}
void ClangEditorDocumentParser::update(CppTools::WorkingCopy workingCopy)
void ClangEditorDocumentParser::updateHelper(const BaseEditorDocumentParser::InMemoryInfo &info)
{
QTC_ASSERT(m_marker, return);
QMutexLocker lock(m_marker->mutex());
QMutexLocker lock2(&m_mutex);
updateProjectPart();
const QStringList options = createOptions(filePath(), projectPart(), true);
// Determine project part
State state_ = state();
state_.projectPart = determineProjectPart(filePath(), configuration(), state_);
setState(state_);
// Determine command line arguments
const QStringList options = createOptions(filePath(), state_.projectPart, true);
qCDebug(log, "Reparse options (cmd line equivalent): %s",
commandLine(options, filePath()).toUtf8().constData());
QTime t; t.start();
// Run
QTime t; t.start();
QMutexLocker lock(m_marker->mutex());
m_marker->setFileName(filePath());
m_marker->setCompilationOptions(options);
const Internal::UnsavedFiles unsavedFiles = Utils::createUnsavedFiles(workingCopy);
const Internal::UnsavedFiles unsavedFiles = Utils::createUnsavedFiles(info.workingCopy,
info.modifiedFiles);
m_marker->reparse(unsavedFiles);
qCDebug(log) << "Reparse took" << t.elapsed() << "ms.";
}

View File

@@ -46,13 +46,13 @@ class ClangEditorDocumentParser : public CppTools::BaseEditorDocumentParser
public:
ClangEditorDocumentParser(const QString &filePath);
void update(CppTools::WorkingCopy workingCopy) override;
QList<Diagnostic> diagnostics() const;
QList<SemanticMarker::Range> ifdefedOutBlocks() const;
SemanticMarker::Ptr semanticMarker() const;
private:
void updateHelper(const BaseEditorDocumentParser::InMemoryInfo &info) override;
SemanticMarker::Ptr m_marker;
};

View File

@@ -144,9 +144,6 @@ ClangEditorDocumentProcessor::~ClangEditorDocumentProcessor()
void ClangEditorDocumentProcessor::run()
{
// Run clang parser
const CppTools::WorkingCopy workingCopy
= CppTools::CppModelManager::instance()->workingCopy();
disconnect(&m_parserWatcher, &QFutureWatcher<void>::finished,
this, &ClangEditorDocumentProcessor::onParserFinished);
m_parserWatcher.cancel();
@@ -155,7 +152,9 @@ void ClangEditorDocumentProcessor::run()
m_parserRevision = revision();
connect(&m_parserWatcher, &QFutureWatcher<void>::finished,
this, &ClangEditorDocumentProcessor::onParserFinished);
const QFuture<void> future = QtConcurrent::run(&runParser, parser(), workingCopy);
const QFuture<void> future = QtConcurrent::run(&runParser,
parser(),
ClangEditorDocumentParser::InMemoryInfo(true));
m_parserWatcher.setFuture(future);
// Run builtin processor

View File

@@ -76,7 +76,7 @@ QString ClangFunctionHintModel::text(int index) const
hintText += prettyMethod.mid(end).toHtmlEscaped());
return hintText;
#endif
return CompletionChunksToTextConverter::convert(m_functionSymbols.at(index).chunks());
return CompletionChunksToTextConverter::convertToFunctionSignature(m_functionSymbols.at(index).chunks());
}
int ClangFunctionHintModel::activeArgument(const QString &prefix) const

View File

@@ -32,7 +32,6 @@
#include <clang-c/Index.h>
#include <coreplugin/documentmanager.h>
#include <coreplugin/icore.h>
#include <coreplugin/idocument.h>
@@ -58,15 +57,9 @@ namespace Utils {
Q_LOGGING_CATEGORY(verboseRunLog, "qtc.clangcodemodel.verboserun")
UnsavedFiles createUnsavedFiles(WorkingCopy workingCopy)
UnsavedFiles createUnsavedFiles(const WorkingCopy &workingCopy,
const ::Utils::FileNameList &modifiedFiles)
{
// TODO: change the modelmanager to hold one working copy, and amend it every time we ask for one.
// TODO: Reason: the UnsavedFile needs a QByteArray.
QSet< ::Utils::FileName> modifiedFiles;
foreach (IDocument *doc, DocumentManager::modifiedDocuments())
modifiedFiles.insert(doc->filePath());
UnsavedFiles result;
QHashIterator< ::Utils::FileName, QPair<QByteArray, unsigned> > wcIter = workingCopy.iterator();
while (wcIter.hasNext()) {

View File

@@ -43,7 +43,9 @@ namespace Utils {
Q_DECLARE_LOGGING_CATEGORY(verboseRunLog)
ClangCodeModel::Internal::UnsavedFiles createUnsavedFiles(CppTools::WorkingCopy workingCopy);
ClangCodeModel::Internal::UnsavedFiles createUnsavedFiles(
const CppTools::WorkingCopy &workingCopy,
const ::Utils::FileNameList &modifiedFiles);
QStringList createClangOptions(const CppTools::ProjectPart::Ptr &pPart,
CppTools::ProjectFile::Kind fileKind);

View File

@@ -30,15 +30,53 @@
#include "completionchunkstotextconverter.h"
#include <algorithm>
#include <functional>
namespace ClangCodeModel {
namespace Internal {
void CompletionChunksToTextConverter::parseChunks(const QVector<ClangBackEnd::CodeCompletionChunk> &codeCompletionChunks)
{
m_text.clear();
m_placeholderPositions.clear();
for (const auto &codeCompletionChunk : codeCompletionChunks)
parse(codeCompletionChunk);
m_codeCompletionChunks = codeCompletionChunks;
addExtraVerticalSpaceBetweenBraces();
std::for_each(m_codeCompletionChunks.cbegin(),
m_codeCompletionChunks.cend(),
[this] (const ClangBackEnd::CodeCompletionChunk &chunk)
{
parse(chunk);
m_previousCodeCompletionChunk = chunk;
});
}
void CompletionChunksToTextConverter::setAddPlaceHolderText(bool addPlaceHolderText)
{
m_addPlaceHolderText = addPlaceHolderText;
}
void CompletionChunksToTextConverter::setAddPlaceHolderPositions(bool addPlaceHolderPositions)
{
m_addPlaceHolderPositions = addPlaceHolderPositions;
}
void CompletionChunksToTextConverter::setAddResultType(bool addResultType)
{
m_addResultType = addResultType;
}
void CompletionChunksToTextConverter::setAddSpaces(bool addSpaces)
{
m_addSpaces = addSpaces;
}
void CompletionChunksToTextConverter::setAddExtraVerticalSpaceBetweenBraces(bool addExtraVerticalSpaceBetweenBraces)
{
m_addExtraVerticalSpaceBetweenBraces = addExtraVerticalSpaceBetweenBraces;
}
const QString &CompletionChunksToTextConverter::text() const
@@ -46,9 +84,42 @@ const QString &CompletionChunksToTextConverter::text() const
return m_text;
}
QString CompletionChunksToTextConverter::convert(const QVector<ClangBackEnd::CodeCompletionChunk> &codeCompletionChunks)
const std::vector<int> &CompletionChunksToTextConverter::placeholderPositions() const
{
return m_placeholderPositions;
}
bool CompletionChunksToTextConverter::hasPlaceholderPositions() const
{
return m_placeholderPositions.size() > 0;
}
QString CompletionChunksToTextConverter::convertToFunctionSignature(const QVector<ClangBackEnd::CodeCompletionChunk> &codeCompletionChunks)
{
CompletionChunksToTextConverter converter;
converter.setAddPlaceHolderText(true);
converter.setAddResultType(true);
converter.parseChunks(codeCompletionChunks);
return converter.text();
}
QString CompletionChunksToTextConverter::convertToName(const QVector<ClangBackEnd::CodeCompletionChunk> &codeCompletionChunks)
{
CompletionChunksToTextConverter converter;
converter.parseChunks(codeCompletionChunks);
return converter.text();
}
QString CompletionChunksToTextConverter::convertToToolTip(const QVector<ClangBackEnd::CodeCompletionChunk> &codeCompletionChunks)
{
CompletionChunksToTextConverter converter;
converter.setAddPlaceHolderText(true);
converter.setAddSpaces(true);
converter.setAddExtraVerticalSpaceBetweenBraces(true);
converter.parseChunks(codeCompletionChunks);
@@ -62,17 +133,26 @@ void CompletionChunksToTextConverter::parse(const ClangBackEnd::CodeCompletionCh
switch (codeCompletionChunk.kind()) {
case CodeCompletionChunk::ResultType: parseResultType(codeCompletionChunk.text()); break;
case CodeCompletionChunk::Optional: parseOptional(codeCompletionChunk); break;
case CodeCompletionChunk::Placeholder: parsePlaceHolder(codeCompletionChunk); break;
case CodeCompletionChunk::LeftParen: parseLeftParen(codeCompletionChunk); break;
case CodeCompletionChunk::LeftBrace: parseLeftBrace(codeCompletionChunk); break;
default: parseText(codeCompletionChunk.text()); break;
}
}
void CompletionChunksToTextConverter::parseResultType(const Utf8String &resultTypeText)
{
m_text += resultTypeText.toString() + QChar(QChar::Space);
if (m_addResultType)
m_text += resultTypeText.toString() + QChar(QChar::Space);
}
void CompletionChunksToTextConverter::parseText(const Utf8String &text)
{
if (canAddSpace()
&& m_previousCodeCompletionChunk.kind() == ClangBackEnd::CodeCompletionChunk::RightBrace) {
m_text += QChar(QChar::Space);
}
m_text += text.toString();
}
@@ -80,11 +160,91 @@ void CompletionChunksToTextConverter::parseOptional(const ClangBackEnd::CodeComp
{
m_text += QStringLiteral("<i>");
m_text += convert(optionalCodeCompletionChunk.optionalChunks());
m_text += convertToFunctionSignature(optionalCodeCompletionChunk.optionalChunks());
m_text += QStringLiteral("</i>");
}
void CompletionChunksToTextConverter::parsePlaceHolder(const ClangBackEnd::CodeCompletionChunk &codeCompletionChunk)
{
if (m_addPlaceHolderText)
m_text += codeCompletionChunk.text().toString();
if (m_addPlaceHolderPositions)
m_placeholderPositions.push_back(m_text.size());
}
void CompletionChunksToTextConverter::parseLeftParen(const ClangBackEnd::CodeCompletionChunk &codeCompletionChunk)
{
if (canAddSpace())
m_text += QChar(QChar::Space);
m_text += codeCompletionChunk.text().toString();
}
void CompletionChunksToTextConverter::parseLeftBrace(const ClangBackEnd::CodeCompletionChunk &codeCompletionChunk)
{
if (canAddSpace())
m_text += QChar(QChar::Space);
m_text += codeCompletionChunk.text().toString();
}
void CompletionChunksToTextConverter::addExtraVerticalSpaceBetweenBraces()
{
if (m_addExtraVerticalSpaceBetweenBraces)
addExtraVerticalSpaceBetweenBraces(m_codeCompletionChunks.begin());
}
void CompletionChunksToTextConverter::addExtraVerticalSpaceBetweenBraces(const QVector<ClangBackEnd::CodeCompletionChunk>::iterator &begin)
{
using ClangBackEnd::CodeCompletionChunk;
const auto leftBraceCompare = [] (const CodeCompletionChunk &chunk) {
return chunk.kind() == CodeCompletionChunk::LeftBrace;
};
const auto rightBraceCompare = [] (const CodeCompletionChunk &chunk) {
return chunk.kind() == CodeCompletionChunk::RightBrace;
};
const auto verticalSpaceCompare = [] (const CodeCompletionChunk &chunk) {
return chunk.kind() == CodeCompletionChunk::VerticalSpace;
};
auto leftBrace = std::find_if(begin, m_codeCompletionChunks.end(), leftBraceCompare);
if (leftBrace != m_codeCompletionChunks.end()) {
auto rightBrace = std::find_if(leftBrace, m_codeCompletionChunks.end(), rightBraceCompare);
if (rightBrace != m_codeCompletionChunks.end()) {
auto verticalSpaceCount = std::count_if(leftBrace, rightBrace, verticalSpaceCompare);
if (verticalSpaceCount <= 1) {
auto distance = std::distance(leftBrace, rightBrace);
CodeCompletionChunk verticalSpaceChunck(CodeCompletionChunk::VerticalSpace,
Utf8StringLiteral("\n"));
auto verticalSpace = m_codeCompletionChunks.insert(std::next(leftBrace),
verticalSpaceChunck);
std::advance(verticalSpace, distance);
rightBrace = verticalSpace;
}
auto begin = std::next(rightBrace);
if (begin != m_codeCompletionChunks.end())
addExtraVerticalSpaceBetweenBraces(begin);
}
}
}
bool CompletionChunksToTextConverter::canAddSpace() const
{
return m_addSpaces
&& m_previousCodeCompletionChunk.kind() != ClangBackEnd::CodeCompletionChunk::HorizontalSpace
&& m_previousCodeCompletionChunk.kind() != ClangBackEnd::CodeCompletionChunk::RightAngle;
}
} // namespace Internal
} // namespace ClangCodeModel

View File

@@ -37,6 +37,8 @@
#include <QString>
#include <vector>
namespace ClangCodeModel {
namespace Internal {
@@ -45,18 +47,42 @@ class CompletionChunksToTextConverter
public:
void parseChunks(const QVector<ClangBackEnd::CodeCompletionChunk> &codeCompletionChunks);
void setAddPlaceHolderText(bool addPlaceHolderText);
void setAddPlaceHolderPositions(bool addPlaceHolderPositions);
void setAddResultType(bool addResultType);
void setAddSpaces(bool addSpaces);
void setAddExtraVerticalSpaceBetweenBraces(bool addExtraVerticalSpaceBetweenBraces);
const QString &text() const;
const std::vector<int> &placeholderPositions() const;
bool hasPlaceholderPositions() const;
static QString convert(const QVector<ClangBackEnd::CodeCompletionChunk> &codeCompletionChunks);
static QString convertToFunctionSignature(const QVector<ClangBackEnd::CodeCompletionChunk> &codeCompletionChunks);
static QString convertToName(const QVector<ClangBackEnd::CodeCompletionChunk> &codeCompletionChunks);
static QString convertToToolTip(const QVector<ClangBackEnd::CodeCompletionChunk> &codeCompletionChunks);
private:
void parse(const ClangBackEnd::CodeCompletionChunk & codeCompletionChunk);
void parseResultType(const Utf8String &text);
void parseText(const Utf8String &text);
void parseOptional(const ClangBackEnd::CodeCompletionChunk & optionalCodeCompletionChunk);
void parseOptional(const ClangBackEnd::CodeCompletionChunk &optionalCodeCompletionChunk);
void parsePlaceHolder(const ClangBackEnd::CodeCompletionChunk &codeCompletionChunk);
void parseLeftParen(const ClangBackEnd::CodeCompletionChunk &codeCompletionChunk);
void parseLeftBrace(const ClangBackEnd::CodeCompletionChunk &codeCompletionChunk);
void addExtraVerticalSpaceBetweenBraces();
void addExtraVerticalSpaceBetweenBraces(const QVector<ClangBackEnd::CodeCompletionChunk>::iterator &);
bool canAddSpace() const;
private:
std::vector<int> m_placeholderPositions;
QVector<ClangBackEnd::CodeCompletionChunk> m_codeCompletionChunks;
ClangBackEnd::CodeCompletionChunk m_previousCodeCompletionChunk;
QString m_text;
bool m_addPlaceHolderText = false;
bool m_addPlaceHolderPositions = false;
bool m_addResultType = false;
bool m_addSpaces = false;
bool m_addExtraVerticalSpaceBetweenBraces = false;
};
} // namespace Internal

View File

@@ -71,10 +71,15 @@ using namespace ClangCodeModel::Internal;
namespace {
QString _(const char text[]) { return QString::fromUtf8(text); }
QString _(const char text[])
{ return QString::fromUtf8(text); }
QString qrcPath(const QByteArray relativeFilePath)
{ return QLatin1String(":/unittests/ClangCodeModel/") + QString::fromUtf8(relativeFilePath); }
QString fileName(const QString &filePath)
{ return QFileInfo(filePath).fileName(); }
struct LogOutput
{
LogOutput(const QString &text) : text(text.toUtf8()) {}
@@ -260,8 +265,8 @@ QString toString(const FileContainer &fileContainer)
{
QString out;
QTextStream ts(&out);
ts << " Path: " << QFileInfo(fileContainer.filePath().toString()).fileName()
<< " ProjectPart: " << fileContainer.projectPartId().toString() << "\n";
ts << " Path: " << fileName(fileContainer.filePath().toString())
<< " ProjectPart: " << fileName(fileContainer.projectPartId().toString()) << "\n";
return out;
}
@@ -279,7 +284,7 @@ QString toString(const ProjectPartContainer &projectPartContainer)
QString out;
QTextStream ts(&out);
ts << " ProjectPartContainer"
<< " id: " << QFileInfo(projectPartContainer.projectPartId().toString()).fileName();
<< " id: " << fileName(projectPartContainer.projectPartId().toString());
return out;
}
@@ -330,7 +335,7 @@ QString toString(const UnregisterProjectPartsForCodeCompletionCommand &command)
QTextStream ts(&out);
ts << "UnregisterProjectPartsForCodeCompletionCommand\n"
<< command.filePaths().join(Utf8String::fromUtf8(",")).toByteArray() << "\n";
<< command.projectPartIds().join(Utf8String::fromUtf8(",")).toByteArray() << "\n";
return out;
}

View File

@@ -180,7 +180,7 @@ void EditorManagerPlaceHolder::currentModeChanged(IMode *mode)
static EditorManager *m_instance = 0;
static EditorManagerPrivate *d;
static int extractNumericSuffix(QString *fileName)
static int extractNumericSuffix(QString *fileName, QString *postfix = 0)
{
int i = fileName->length() - 1;
for (; i >= 0; --i) {
@@ -195,6 +195,8 @@ static int extractNumericSuffix(QString *fileName)
const QString suffix = fileName->mid(i + 1);
const int result = suffix.toInt(&ok);
if (suffix.isEmpty() || ok) {
if (postfix)
*postfix = fileName->mid(i);
fileName->truncate(i);
return result;
}
@@ -2552,25 +2554,15 @@ IEditor *EditorManager::openEditorAt(const QString &fileName, int line, int colu
fileName, line, column, editorId, flags, newEditor);
}
// Extract line number suffix. Return the suffix (e.g. ":132") and truncates the filename accordingly.
QString EditorManager::splitLineNumber(QString *fileName)
// Extract line and column number suffix. Return the suffix (e.g. ":132") and truncates the filename accordingly.
QString EditorManager::splitLineAndColumnNumber(QString *fileName)
{
int i = fileName->length() - 1;
for (; i >= 0; --i) {
if (!fileName->at(i).isNumber())
break;
}
if (i == -1)
return QString();
const QChar c = fileName->at(i);
if (c == QLatin1Char(':') || c == QLatin1Char('+')) {
const QString result = fileName->mid(i + 1);
bool ok;
result.toInt(&ok);
if (result.isEmpty() || ok) {
fileName->truncate(i);
return QString(c) + result;
}
QString postfix;
if (extractNumericSuffix(fileName, &postfix)) {
QString previousPostfix;
if (extractNumericSuffix(fileName, &previousPostfix))
postfix.prepend(previousPostfix);
return postfix;
}
return QString();
}

View File

@@ -109,7 +109,7 @@ public:
};
Q_DECLARE_FLAGS(OpenEditorFlags, OpenEditorFlag)
static QString splitLineNumber(QString *fileName);
static QString splitLineAndColumnNumber(QString *fileName);
static IEditor *openEditor(const QString &fileName, Id editorId = Id(),
OpenEditorFlags flags = NoFlags, bool *newEditor = 0);
static IEditor *openEditorAt(const QString &fileName, int line, int column = 0,

View File

@@ -103,7 +103,7 @@ QList<LocatorFilterEntry> BaseFileFilter::matchesFor(QFutureInterface<LocatorFil
QList<LocatorFilterEntry> betterEntries;
QList<LocatorFilterEntry> goodEntries;
QString needle = trimWildcards(QDir::fromNativeSeparators(origEntry));
const QString lineNoSuffix = EditorManager::splitLineNumber(&needle);
const QString lineNoSuffix = EditorManager::splitLineAndColumnNumber(&needle);
QStringMatcher matcher(needle, Qt::CaseInsensitive);
const QChar asterisk = QLatin1Char('*');
QRegExp regexp(asterisk + needle+ asterisk, Qt::CaseInsensitive, QRegExp::Wildcard);

View File

@@ -119,7 +119,7 @@ QList<LocatorFilterEntry> FileSystemFilter::matchesFor(QFutureInterface<LocatorF
}
// file names can match with +linenumber or :linenumber
name = entry;
const QString lineNoSuffix = EditorManager::splitLineNumber(&name);
const QString lineNoSuffix = EditorManager::splitLineAndColumnNumber(&name);
name = QFileInfo(name).fileName();
foreach (const QString &file, files) {
if (future.isCanceled())

View File

@@ -64,7 +64,7 @@ QList<LocatorFilterEntry> OpenDocumentsFilter::matchesFor(QFutureInterface<Locat
QList<LocatorFilterEntry> goodEntries;
QList<LocatorFilterEntry> betterEntries;
QString entry = entry_;
const QString lineNoSuffix = EditorManager::splitLineNumber(&entry);
const QString lineNoSuffix = EditorManager::splitLineAndColumnNumber(&entry);
const QChar asterisk = QLatin1Char('*');
QString pattern = QString(asterisk);
pattern += entry;

View File

@@ -268,9 +268,11 @@ void CppEditorDocument::setPreprocessorSettings(const CppTools::ProjectPart::Ptr
{
CppTools::BaseEditorDocumentParser *parser = processor()->parser();
QTC_ASSERT(parser, return);
if (parser->projectPart() != projectPart || parser->editorDefines() != defines) {
parser->setProjectPart(projectPart);
parser->setEditorDefines(defines);
if (parser->projectPart() != projectPart || parser->configuration().editorDefines != defines) {
CppTools::BaseEditorDocumentParser::Configuration config = parser->configuration();
config.manuallySetProjectPart = projectPart;
config.editorDefines = defines;
parser->setConfiguration(config);
emit preprocessorSettingsChanged(!defines.trimmed().isEmpty());
}

View File

@@ -1832,7 +1832,7 @@ NameAST *nameUnderCursor(const QList<AST *> &path)
bool canLookupDefinition(const CppQuickFixInterface &interface, const NameAST *nameAst)
{
QTC_ASSERT(nameAst, return false);
QTC_ASSERT(nameAst && nameAst->name, return false);
// Find the enclosing scope
unsigned line, column;
@@ -1909,7 +1909,7 @@ void AddIncludeForUndefinedIdentifier::match(const CppQuickFixInterface &interfa
QuickFixOperations &result)
{
const NameAST *nameAst = nameUnderCursor(interface.path());
if (!nameAst)
if (!nameAst || !nameAst->name)
return;
if (canLookupDefinition(interface, nameAst))
@@ -5852,7 +5852,7 @@ bool onConnectOrDisconnectCall(AST *ast, const ExpressionListAST **arguments)
return false;
const IdExpressionAST *idExpr = call->base_expression->asIdExpression();
if (!idExpr)
if (!idExpr || !idExpr->name || !idExpr->name->name)
return false;
const ExpressionListAST *args = call->expression_list;

View File

@@ -31,6 +31,7 @@
#include "baseeditordocumentparser.h"
#include "baseeditordocumentprocessor.h"
#include "cpptoolsreuse.h"
#include "editordocumenthandle.h"
namespace CppTools {
@@ -44,15 +45,18 @@ namespace CppTools {
It's meant to be used in the C++ editor to get precise results by using
the "best" project part for a file.
Derived classes are expected to implement update() by using the protected
mutex, updateProjectPart() and by respecting the options set by the client.
Derived classes are expected to implement updateHelper() this way:
\list
\li Get a copy of the configuration and the last state.
\li Work on the data and do whatever is necessary. At least, update
the project part with the help of determineProjectPart().
\li Ensure the new state is set before updateHelper() returns.
\endlist
*/
BaseEditorDocumentParser::BaseEditorDocumentParser(const QString &filePath)
: m_mutex(QMutex::Recursive)
, m_filePath(filePath)
, m_usePrecompiledHeaders(false)
, m_editorDefinesChangedSinceLastUpdate(false)
: m_filePath(filePath)
{
}
@@ -65,44 +69,39 @@ QString BaseEditorDocumentParser::filePath() const
return m_filePath;
}
BaseEditorDocumentParser::Configuration BaseEditorDocumentParser::configuration() const
{
QMutexLocker locker(&m_stateAndConfigurationMutex);
return m_configuration;
}
void BaseEditorDocumentParser::setConfiguration(const Configuration &configuration)
{
QMutexLocker locker(&m_stateAndConfigurationMutex);
m_configuration = configuration;
}
void BaseEditorDocumentParser::update(const InMemoryInfo &info)
{
QMutexLocker locker(&m_updateIsRunning);
updateHelper(info);
}
BaseEditorDocumentParser::State BaseEditorDocumentParser::state() const
{
QMutexLocker locker(&m_stateAndConfigurationMutex);
return m_state;
}
void BaseEditorDocumentParser::setState(const State &state)
{
QMutexLocker locker(&m_stateAndConfigurationMutex);
m_state = state;
}
ProjectPart::Ptr BaseEditorDocumentParser::projectPart() const
{
QMutexLocker locker(&m_mutex);
return m_projectPart;
}
void BaseEditorDocumentParser::setProjectPart(ProjectPart::Ptr projectPart)
{
QMutexLocker locker(&m_mutex);
m_manuallySetProjectPart = projectPart;
}
bool BaseEditorDocumentParser::usePrecompiledHeaders() const
{
QMutexLocker locker(&m_mutex);
return m_usePrecompiledHeaders;
}
void BaseEditorDocumentParser::setUsePrecompiledHeaders(bool usePrecompiledHeaders)
{
QMutexLocker locker(&m_mutex);
m_usePrecompiledHeaders = usePrecompiledHeaders;
}
QByteArray BaseEditorDocumentParser::editorDefines() const
{
QMutexLocker locker(&m_mutex);
return m_editorDefines;
}
void BaseEditorDocumentParser::setEditorDefines(const QByteArray &editorDefines)
{
QMutexLocker locker(&m_mutex);
if (editorDefines != m_editorDefines) {
m_editorDefines = editorDefines;
m_editorDefinesChangedSinceLastUpdate = true;
}
return state().projectPart;
}
BaseEditorDocumentParser *BaseEditorDocumentParser::get(const QString &filePath)
@@ -115,43 +114,44 @@ BaseEditorDocumentParser *BaseEditorDocumentParser::get(const QString &filePath)
return 0;
}
void BaseEditorDocumentParser::updateProjectPart()
ProjectPart::Ptr BaseEditorDocumentParser::determineProjectPart(const QString &filePath,
const Configuration &config,
const State &state)
{
if (m_manuallySetProjectPart) {
m_projectPart = m_manuallySetProjectPart;
return;
}
if (config.manuallySetProjectPart)
return config.manuallySetProjectPart;
ProjectPart::Ptr projectPart = state.projectPart;
CppModelManager *cmm = CppModelManager::instance();
QList<ProjectPart::Ptr> projectParts = cmm->projectPart(m_filePath);
QList<ProjectPart::Ptr> projectParts = cmm->projectPart(filePath);
if (projectParts.isEmpty()) {
if (m_projectPart)
if (projectPart)
// File is not directly part of any project, but we got one before. We will re-use it,
// because re-calculating this can be expensive when the dependency table is big.
return;
return projectPart;
// Fall-back step 1: Get some parts through the dependency table:
projectParts = cmm->projectPartFromDependencies(Utils::FileName::fromString(m_filePath));
projectParts = cmm->projectPartFromDependencies(Utils::FileName::fromString(filePath));
if (projectParts.isEmpty())
// Fall-back step 2: Use fall-back part from the model manager:
m_projectPart = cmm->fallbackProjectPart();
projectPart = cmm->fallbackProjectPart();
else
m_projectPart = projectParts.first();
projectPart = projectParts.first();
} else {
if (!projectParts.contains(m_projectPart))
if (!projectParts.contains(projectPart))
// Apparently the project file changed, so update our project part.
m_projectPart = projectParts.first();
projectPart = projectParts.first();
}
return projectPart;
}
bool BaseEditorDocumentParser::editorDefinesChanged() const
BaseEditorDocumentParser::InMemoryInfo::InMemoryInfo(bool withModifiedFiles)
: workingCopy(CppTools::CppModelManager::instance()->workingCopy())
{
return m_editorDefinesChangedSinceLastUpdate;
}
void BaseEditorDocumentParser::resetEditorDefinesChanged()
{
m_editorDefinesChangedSinceLastUpdate = false;
if (withModifiedFiles)
modifiedFiles = CppTools::modifiedFiles();
}
} // namespace CppTools

View File

@@ -33,6 +33,7 @@
#include "cppmodelmanager.h"
#include "cpptools_global.h"
#include "cppworkingcopy.h"
#include <QObject>
@@ -42,45 +43,54 @@ class CPPTOOLS_EXPORT BaseEditorDocumentParser : public QObject
{
Q_OBJECT
public:
static BaseEditorDocumentParser *get(const QString &filePath);
struct Configuration {
bool usePrecompiledHeaders = false;
QByteArray editorDefines;
ProjectPart::Ptr manuallySetProjectPart;
};
public:
BaseEditorDocumentParser(const QString &filePath);
virtual ~BaseEditorDocumentParser();
QString filePath() const;
Configuration configuration() const;
void setConfiguration(const Configuration &configuration);
virtual void update(WorkingCopy workingCopy) = 0;
struct CPPTOOLS_EXPORT InMemoryInfo {
InMemoryInfo(bool withModifiedFiles);
WorkingCopy workingCopy;
Utils::FileNameList modifiedFiles;
};
void update(const InMemoryInfo &info);
ProjectPart::Ptr projectPart() const;
void setProjectPart(ProjectPart::Ptr projectPart);
bool usePrecompiledHeaders() const;
void setUsePrecompiledHeaders(bool usePrecompiledHeaders);
QByteArray editorDefines() const;
void setEditorDefines(const QByteArray &editorDefines);
public:
static BaseEditorDocumentParser *get(const QString &filePath);
protected:
void updateProjectPart();
struct State {
QByteArray editorDefines;
ProjectPart::Ptr projectPart;
};
State state() const;
void setState(const State &state);
bool editorDefinesChanged() const;
void resetEditorDefinesChanged();
static ProjectPart::Ptr determineProjectPart(const QString &filePath,
const Configuration &config,
const State &state);
protected:
mutable QMutex m_mutex;
mutable QMutex m_stateAndConfigurationMutex;
private:
virtual void updateHelper(const InMemoryInfo &inMemoryInfo) = 0;
const QString m_filePath;
ProjectPart::Ptr m_projectPart;
ProjectPart::Ptr m_manuallySetProjectPart;
bool m_usePrecompiledHeaders;
QByteArray m_editorDefines;
bool m_editorDefinesChangedSinceLastUpdate;
Configuration m_configuration;
State m_state;
mutable QMutex m_updateIsRunning;
};
} // namespace CppTools

View File

@@ -31,6 +31,7 @@
#include "baseeditordocumentprocessor.h"
#include "cppworkingcopy.h"
#include "cpptoolsreuse.h"
#include "editordocumenthandle.h"
#include <utils/qtcassert.h>
@@ -118,7 +119,7 @@ QList<QTextEdit::ExtraSelection> BaseEditorDocumentProcessor::toTextEditorSelect
void BaseEditorDocumentProcessor::runParser(QFutureInterface<void> &future,
BaseEditorDocumentParser *parser,
WorkingCopy workingCopy)
BaseEditorDocumentParser::InMemoryInfo info)
{
future.setProgressRange(0, 1);
if (future.isCanceled()) {
@@ -126,7 +127,7 @@ void BaseEditorDocumentProcessor::runParser(QFutureInterface<void> &future,
return;
}
parser->update(workingCopy);
parser->update(info);
CppModelManager::instance()
->finishedRefreshingSourceFiles(QSet<QString>() << parser->filePath());

View File

@@ -86,7 +86,7 @@ protected:
static void runParser(QFutureInterface<void> &future,
CppTools::BaseEditorDocumentParser *parser,
CppTools::WorkingCopy workingCopy);
BaseEditorDocumentParser::InMemoryInfo info);
// Convenience
QString filePath() const { return m_baseTextDocument->filePath().toString(); }

View File

@@ -40,19 +40,22 @@ using namespace CppTools::Internal;
BuiltinEditorDocumentParser::BuiltinEditorDocumentParser(const QString &filePath)
: BaseEditorDocumentParser(filePath)
, m_forceSnapshotInvalidation(false)
, m_releaseSourceAndAST(true)
{
qRegisterMetaType<CPlusPlus::Snapshot>("CPlusPlus::Snapshot");
}
void BuiltinEditorDocumentParser::update(WorkingCopy workingCopy)
void BuiltinEditorDocumentParser::updateHelper(const InMemoryInfo &info)
{
QMutexLocker locker(&m_mutex);
if (filePath().isEmpty())
return;
const Configuration baseConfig = configuration();
const bool releaseSourceAndAST_ = releaseSourceAndAST();
State baseState = state();
ExtraState state = extraState();
WorkingCopy workingCopy = info.workingCopy;
bool invalidateSnapshot = false, invalidateConfig = false, editorDefinesChanged_ = false;
CppModelManager *modelManager = CppModelManager::instance();
@@ -62,52 +65,52 @@ void BuiltinEditorDocumentParser::update(WorkingCopy workingCopy)
QString projectConfigFile;
LanguageFeatures features = LanguageFeatures::defaultFeatures();
updateProjectPart();
baseState.projectPart = determineProjectPart(filePath(), baseConfig, baseState);
if (m_forceSnapshotInvalidation) {
if (state.forceSnapshotInvalidation) {
invalidateSnapshot = true;
m_forceSnapshotInvalidation = false;
state.forceSnapshotInvalidation = false;
}
if (const ProjectPart::Ptr part = projectPart()) {
if (const ProjectPart::Ptr part = baseState.projectPart) {
configFile += part->toolchainDefines;
configFile += part->projectDefines;
headerPaths = part->headerPaths;
projectConfigFile = part->projectConfigFile;
if (usePrecompiledHeaders())
if (baseConfig.usePrecompiledHeaders)
precompiledHeaders = part->precompiledHeaders;
features = part->languageFeatures;
}
if (configFile != m_configFile) {
m_configFile = configFile;
if (configFile != state.configFile) {
state.configFile = configFile;
invalidateSnapshot = true;
invalidateConfig = true;
}
if (editorDefinesChanged()) {
if (baseConfig.editorDefines != baseState.editorDefines) {
baseState.editorDefines = baseConfig.editorDefines;
invalidateSnapshot = true;
editorDefinesChanged_ = true;
resetEditorDefinesChanged();
}
if (headerPaths != m_headerPaths) {
m_headerPaths = headerPaths;
if (headerPaths != state.headerPaths) {
state.headerPaths = headerPaths;
invalidateSnapshot = true;
}
if (projectConfigFile != m_projectConfigFile) {
m_projectConfigFile = projectConfigFile;
if (projectConfigFile != state.projectConfigFile) {
state.projectConfigFile = projectConfigFile;
invalidateSnapshot = true;
}
if (precompiledHeaders != m_precompiledHeaders) {
m_precompiledHeaders = precompiledHeaders;
if (precompiledHeaders != state.precompiledHeaders) {
state.precompiledHeaders = precompiledHeaders;
invalidateSnapshot = true;
}
unsigned rev = 0;
if (Document::Ptr doc = document())
if (Document::Ptr doc = state.snapshot.document(filePath()))
rev = doc->revision();
else
invalidateSnapshot = true;
@@ -115,26 +118,26 @@ void BuiltinEditorDocumentParser::update(WorkingCopy workingCopy)
Snapshot globalSnapshot = modelManager->snapshot();
if (invalidateSnapshot) {
m_snapshot = Snapshot();
state.snapshot = Snapshot();
} else {
// Remove changed files from the snapshot
QSet<Utils::FileName> toRemove;
foreach (const Document::Ptr &doc, m_snapshot) {
foreach (const Document::Ptr &doc, state.snapshot) {
const Utils::FileName fileName = Utils::FileName::fromString(doc->fileName());
if (workingCopy.contains(fileName)) {
if (workingCopy.get(fileName).second != doc->editorRevision())
addFileAndDependencies(&toRemove, fileName);
addFileAndDependencies(&state.snapshot, &toRemove, fileName);
continue;
}
Document::Ptr otherDoc = globalSnapshot.document(fileName);
if (!otherDoc.isNull() && otherDoc->revision() != doc->revision())
addFileAndDependencies(&toRemove, fileName);
addFileAndDependencies(&state.snapshot, &toRemove, fileName);
}
if (!toRemove.isEmpty()) {
invalidateSnapshot = true;
foreach (const Utils::FileName &fileName, toRemove)
m_snapshot.remove(fileName);
state.snapshot.remove(fileName);
}
}
@@ -142,19 +145,19 @@ void BuiltinEditorDocumentParser::update(WorkingCopy workingCopy)
if (invalidateSnapshot) {
const QString configurationFileName = modelManager->configurationFileName();
if (invalidateConfig)
m_snapshot.remove(configurationFileName);
if (!m_snapshot.contains(configurationFileName))
workingCopy.insert(configurationFileName, m_configFile);
m_snapshot.remove(filePath());
state.snapshot.remove(configurationFileName);
if (!state.snapshot.contains(configurationFileName))
workingCopy.insert(configurationFileName, state.configFile);
state.snapshot.remove(filePath());
static const QString editorDefinesFileName
= CppModelManager::editorConfigurationFileName();
if (editorDefinesChanged_) {
m_snapshot.remove(editorDefinesFileName);
workingCopy.insert(editorDefinesFileName, editorDefines());
state.snapshot.remove(editorDefinesFileName);
workingCopy.insert(editorDefinesFileName, baseState.editorDefines);
}
CppSourceProcessor sourceProcessor(m_snapshot, [&](const Document::Ptr &doc) {
CppSourceProcessor sourceProcessor(state.snapshot, [&](const Document::Ptr &doc) {
const QString fileName = doc->fileName();
const bool isInEditor = fileName == filePath();
Document::Ptr otherDoc = modelManager->document(fileName);
@@ -163,68 +166,64 @@ void BuiltinEditorDocumentParser::update(WorkingCopy workingCopy)
newRev = qMax(rev + 1, newRev);
doc->setRevision(newRev);
modelManager->emitDocumentUpdated(doc);
if (m_releaseSourceAndAST)
if (releaseSourceAndAST_)
doc->releaseSourceAndAST();
});
Snapshot globalSnapshot = modelManager->snapshot();
globalSnapshot.remove(filePath());
sourceProcessor.setGlobalSnapshot(globalSnapshot);
sourceProcessor.setWorkingCopy(workingCopy);
sourceProcessor.setHeaderPaths(m_headerPaths);
sourceProcessor.setHeaderPaths(state.headerPaths);
sourceProcessor.setLanguageFeatures(features);
sourceProcessor.run(configurationFileName);
if (!m_projectConfigFile.isEmpty())
sourceProcessor.run(m_projectConfigFile);
if (usePrecompiledHeaders()) {
foreach (const QString &precompiledHeader, m_precompiledHeaders)
if (!state.projectConfigFile.isEmpty())
sourceProcessor.run(state.projectConfigFile);
if (baseConfig.usePrecompiledHeaders) {
foreach (const QString &precompiledHeader, state.precompiledHeaders)
sourceProcessor.run(precompiledHeader);
}
if (!editorDefines().isEmpty())
if (!baseState.editorDefines.isEmpty())
sourceProcessor.run(editorDefinesFileName);
sourceProcessor.run(filePath(), usePrecompiledHeaders() ? m_precompiledHeaders
: QStringList());
m_snapshot = sourceProcessor.snapshot();
Snapshot newSnapshot = m_snapshot.simplified(document());
for (Snapshot::const_iterator i = m_snapshot.begin(), ei = m_snapshot.end(); i != ei; ++i) {
sourceProcessor.run(filePath(), baseConfig.usePrecompiledHeaders ? state.precompiledHeaders
: QStringList());
state.snapshot = sourceProcessor.snapshot();
Snapshot newSnapshot = state.snapshot.simplified(state.snapshot.document(filePath()));
for (Snapshot::const_iterator i = state.snapshot.begin(), ei = state.snapshot.end(); i != ei; ++i) {
if (Client::isInjectedFile(i.key().toString()))
newSnapshot.insert(i.value());
}
m_snapshot = newSnapshot;
m_snapshot.updateDependencyTable();
emit finished(document(), m_snapshot);
state.snapshot = newSnapshot;
state.snapshot.updateDependencyTable();
}
setState(baseState);
setExtraState(state);
if (invalidateSnapshot)
emit finished(state.snapshot.document(filePath()), state.snapshot);
}
void BuiltinEditorDocumentParser::releaseResources()
{
QMutexLocker locker(&m_mutex);
m_snapshot = Snapshot();
m_forceSnapshotInvalidation = true;
ExtraState s = extraState();
s.snapshot = Snapshot();
s.forceSnapshotInvalidation = true;
setExtraState(s);
}
Document::Ptr BuiltinEditorDocumentParser::document() const
{
QMutexLocker locker(&m_mutex);
return m_snapshot.document(filePath());
return extraState().snapshot.document(filePath());
}
Snapshot BuiltinEditorDocumentParser::snapshot() const
{
QMutexLocker locker(&m_mutex);
return m_snapshot;
return extraState().snapshot;
}
ProjectPart::HeaderPaths BuiltinEditorDocumentParser::headerPaths() const
{
QMutexLocker locker(&m_mutex);
return m_headerPaths;
}
void BuiltinEditorDocumentParser::setReleaseSourceAndAST(bool onoff)
{
QMutexLocker locker(&m_mutex);
m_releaseSourceAndAST = onoff;
return extraState().headerPaths;
}
BuiltinEditorDocumentParser *BuiltinEditorDocumentParser::get(const QString &filePath)
@@ -234,12 +233,39 @@ BuiltinEditorDocumentParser *BuiltinEditorDocumentParser::get(const QString &fil
return 0;
}
void BuiltinEditorDocumentParser::addFileAndDependencies(QSet<Utils::FileName> *toRemove,
void BuiltinEditorDocumentParser::addFileAndDependencies(Snapshot *snapshot,
QSet<Utils::FileName> *toRemove,
const Utils::FileName &fileName) const
{
QTC_ASSERT(snapshot, return);
toRemove->insert(fileName);
if (fileName != Utils::FileName::fromString(filePath())) {
Utils::FileNameList deps = m_snapshot.filesDependingOn(fileName);
Utils::FileNameList deps = snapshot->filesDependingOn(fileName);
toRemove->unite(QSet<Utils::FileName>::fromList(deps));
}
}
BuiltinEditorDocumentParser::ExtraState BuiltinEditorDocumentParser::extraState() const
{
QMutexLocker locker(&m_stateAndConfigurationMutex);
return m_extraState;
}
void BuiltinEditorDocumentParser::setExtraState(const ExtraState &extraState)
{
QMutexLocker locker(&m_stateAndConfigurationMutex);
m_extraState = extraState;
}
bool BuiltinEditorDocumentParser::releaseSourceAndAST() const
{
QMutexLocker locker(&m_stateAndConfigurationMutex);
return m_releaseSourceAndAST;
}
void BuiltinEditorDocumentParser::setReleaseSourceAndAST(bool release)
{
QMutexLocker locker(&m_stateAndConfigurationMutex);
m_releaseSourceAndAST = release;
}

View File

@@ -37,7 +37,6 @@
#include <cplusplus/CppDocument.h>
#include <QMutex>
#include <QString>
namespace CppTools {
@@ -49,14 +48,14 @@ class CPPTOOLS_EXPORT BuiltinEditorDocumentParser : public BaseEditorDocumentPar
public:
BuiltinEditorDocumentParser(const QString &filePath);
void update(WorkingCopy workingCopy) override;
void releaseResources();
bool releaseSourceAndAST() const;
void setReleaseSourceAndAST(bool release);
CPlusPlus::Document::Ptr document() const;
CPlusPlus::Snapshot snapshot() const;
ProjectPart::HeaderPaths headerPaths() const;
void setReleaseSourceAndAST(bool onoff);
void releaseResources();
signals:
void finished(CPlusPlus::Document::Ptr document, CPlusPlus::Snapshot snapshot);
@@ -65,18 +64,26 @@ public:
static BuiltinEditorDocumentParser *get(const QString &filePath);
private:
void addFileAndDependencies(QSet<Utils::FileName> *toRemove, const Utils::FileName &fileName) const;
void updateHelper(const InMemoryInfo &info) override;
void addFileAndDependencies(CPlusPlus::Snapshot *snapshot,
QSet<Utils::FileName> *toRemove,
const Utils::FileName &fileName) const;
private:
QByteArray m_configFile;
struct ExtraState {
QByteArray configFile;
ProjectPart::HeaderPaths m_headerPaths;
QString m_projectConfigFile;
QStringList m_precompiledHeaders;
ProjectPart::HeaderPaths headerPaths;
QString projectConfigFile;
QStringList precompiledHeaders;
CPlusPlus::Snapshot m_snapshot;
bool m_forceSnapshotInvalidation;
bool m_releaseSourceAndAST;
CPlusPlus::Snapshot snapshot;
bool forceSnapshotInvalidation = false;
};
ExtraState extraState() const;
void setExtraState(const ExtraState &extraState);
bool m_releaseSourceAndAST = true;
ExtraState m_extraState;
};
} // namespace CppTools

View File

@@ -43,8 +43,8 @@
#include <cplusplus/CppDocument.h>
#include <cplusplus/SimpleLexer.h>
#include <utils/QtConcurrentTools>
#include <utils/qtcassert.h>
#include <utils/runextensions.h>
#include <QLoggingCategory>
@@ -134,7 +134,10 @@ BuiltinEditorDocumentProcessor::BuiltinEditorDocumentProcessor(
using namespace Internal;
QSharedPointer<CppCodeModelSettings> cms = CppToolsPlugin::instance()->codeModelSettings();
m_parser.setUsePrecompiledHeaders(cms->pchUsage() != CppCodeModelSettings::PchUse_None);
BaseEditorDocumentParser::Configuration config = m_parser.configuration();
config.usePrecompiledHeaders = cms->pchUsage() != CppCodeModelSettings::PchUse_None;
m_parser.setConfiguration(config);
if (m_semanticHighlighter) {
m_semanticHighlighter->setHighlightingRunner(
@@ -163,7 +166,9 @@ BuiltinEditorDocumentProcessor::~BuiltinEditorDocumentProcessor()
void BuiltinEditorDocumentProcessor::run()
{
m_parserFuture = QtConcurrent::run(&runParser, parser(), CppTools::CppModelManager::instance()->workingCopy());
m_parserFuture = QtConcurrent::run(&runParser,
parser(),
BuiltinEditorDocumentParser::InMemoryInfo(false));
}
BaseEditorDocumentParser *BuiltinEditorDocumentProcessor::parser()

View File

@@ -162,7 +162,7 @@ void indexFindErrors(QFutureInterface<void> &future, const ParseParams params)
// Parse the file as precisely as possible
BuiltinEditorDocumentParser parser(file);
parser.setReleaseSourceAndAST(false);
parser.update(params.workingCopy);
parser.update(BuiltinEditorDocumentParser::InMemoryInfo(false));
CPlusPlus::Document::Ptr document = parser.document();
QTC_ASSERT(document, return);

View File

@@ -2188,7 +2188,7 @@ void CppCompletionAssistInterface::getCppSpecifics() const
m_gotCppSpecifics = true;
if (BuiltinEditorDocumentParser *parser = BuiltinEditorDocumentParser::get(fileName())) {
parser->update(m_workingCopy);
parser->update(BuiltinEditorDocumentParser::InMemoryInfo(false));
m_snapshot = parser->snapshot();
m_headerPaths = parser->headerPaths();
if (Document::Ptr document = parser->document())

View File

@@ -167,13 +167,11 @@ private:
const QString &m_filePath;
};
void waitForProcessedEditorDocument(const QString &filePath)
ProjectPart::Ptr projectPartOfEditorDocument(const QString &filePath)
{
CppEditorDocumentHandle *editorDocument
= CppModelManager::instance()->cppEditorDocument(filePath);
QVERIFY(editorDocument);
while (editorDocument->processor()->isParserRunning())
QCoreApplication::processEvents();
auto *editorDocument = CppModelManager::instance()->cppEditorDocument(filePath);
QTC_ASSERT(editorDocument, return ProjectPart::Ptr());
return editorDocument->processor()->parser()->projectPart();
}
} // anonymous namespace
@@ -914,8 +912,10 @@ void CppToolsPlugin::test_modelmanager_precompiled_headers()
auto *parser = BuiltinEditorDocumentParser::get(fileName);
QVERIFY(parser);
parser->setUsePrecompiledHeaders(true);
parser->update(mm->workingCopy());
BaseEditorDocumentParser::Configuration config = parser->configuration();
config.usePrecompiledHeaders = true;
parser->setConfiguration(config);
parser->update(BuiltinEditorDocumentParser::InMemoryInfo(false));
// Check if defines from pch are considered
Document::Ptr document = mm->document(fileName);
@@ -995,8 +995,10 @@ void CppToolsPlugin::test_modelmanager_defines_per_editor()
const QString filePath = editor->document()->filePath().toString();
BaseEditorDocumentParser *parser = BaseEditorDocumentParser::get(filePath);
parser->setEditorDefines(editorDefines.toUtf8());
parser->update(mm->workingCopy());
BaseEditorDocumentParser::Configuration config = parser->configuration();
config.editorDefines = editorDefines.toUtf8();
parser->setConfiguration(config);
parser->update(BuiltinEditorDocumentParser::InMemoryInfo(false));
Document::Ptr doc = mm->document(main1File);
QCOMPARE(nameOfFirstDeclaration(doc), firstDeclarationName);
@@ -1006,7 +1008,6 @@ void CppToolsPlugin::test_modelmanager_defines_per_editor()
void CppToolsPlugin::test_modelmanager_updateEditorsAfterProjectUpdate()
{
ModelManagerTestHelper helper;
CppModelManager *mm = CppModelManager::instance();
MyTestDataDir testDataDirectory(_("testdata_defines"));
const QString fileA = testDataDirectory.file(_("main1.cpp")); // content not relevant
@@ -1017,10 +1018,8 @@ void CppToolsPlugin::test_modelmanager_updateEditorsAfterProjectUpdate()
QVERIFY(editorA);
EditorCloser closerA(editorA);
QCOMPARE(Core::DocumentModel::openedDocuments().size(), 1);
CppEditorDocumentHandle *editorDocumentA = mm->cppEditorDocument(fileA);
QVERIFY(editorDocumentA);
ProjectPart::Ptr documentAProjectPart = editorDocumentA->processor()->parser()->projectPart();
QVERIFY(TestCase::waitForProcessedEditorDocument(fileA));
ProjectPart::Ptr documentAProjectPart = projectPartOfEditorDocument(fileA);
QVERIFY(!documentAProjectPart->project);
// Open file B in editor
@@ -1028,10 +1027,8 @@ void CppToolsPlugin::test_modelmanager_updateEditorsAfterProjectUpdate()
QVERIFY(editorB);
EditorCloser closerB(editorB);
QCOMPARE(Core::DocumentModel::openedDocuments().size(), 2);
CppEditorDocumentHandle *editorDocumentB = mm->cppEditorDocument(fileB);
QVERIFY(editorDocumentB);
ProjectPart::Ptr documentBProjectPart = editorDocumentB->processor()->parser()->projectPart();
QVERIFY(TestCase::waitForProcessedEditorDocument(fileB));
ProjectPart::Ptr documentBProjectPart = projectPartOfEditorDocument(fileB);
QVERIFY(!documentBProjectPart->project);
// Switch back to document A
@@ -1053,16 +1050,14 @@ void CppToolsPlugin::test_modelmanager_updateEditorsAfterProjectUpdate()
helper.updateProjectInfo(pi);
// ... and check for updated editor document A
while (editorDocumentA->processor()->isParserRunning())
QCoreApplication::processEvents();
documentAProjectPart = editorDocumentA->processor()->parser()->projectPart();
QVERIFY(TestCase::waitForProcessedEditorDocument(fileA));
documentAProjectPart = projectPartOfEditorDocument(fileA);
QCOMPARE(documentAProjectPart->project, project);
// Switch back to document B and check if that's updated, too
Core::EditorManager::activateEditor(editorB);
while (editorDocumentB->processor()->isParserRunning())
QCoreApplication::processEvents();
documentBProjectPart = editorDocumentB->processor()->parser()->projectPart();
QVERIFY(TestCase::waitForProcessedEditorDocument(fileB));
documentBProjectPart = projectPartOfEditorDocument(fileB);
QCOMPARE(documentBProjectPart->project, project);
}
@@ -1131,7 +1126,7 @@ void CppToolsPlugin::test_modelmanager_documentsAndRevisions()
TextEditor::BaseTextEditor *editor1;
QVERIFY(helper.openBaseTextEditor(filePath1, &editor1));
helper.closeEditorAtEndOfTestCase(editor1);
waitForProcessedEditorDocument(filePath1);
QVERIFY(TestCase::waitForProcessedEditorDocument(filePath1));
VERIFY_DOCUMENT_REVISION(modelManager->document(filePath1), 2U);
VERIFY_DOCUMENT_REVISION(modelManager->document(filePath2), 1U);
@@ -1144,7 +1139,7 @@ void CppToolsPlugin::test_modelmanager_documentsAndRevisions()
TextEditor::BaseTextEditor *editor2;
QVERIFY(helper.openBaseTextEditor(filePath2, &editor2));
helper.closeEditorAtEndOfTestCase(editor2);
waitForProcessedEditorDocument(filePath2);
QVERIFY(TestCase::waitForProcessedEditorDocument(filePath2));
VERIFY_DOCUMENT_REVISION(modelManager->document(filePath1), 3U);
VERIFY_DOCUMENT_REVISION(modelManager->document(filePath2), 3U);

View File

@@ -137,6 +137,7 @@ void CppToolsPlugin::test_cppsourceprocessor_includes_cyclic()
const QString filePath = editor->document()->filePath().toString();
auto *processor = BaseEditorDocumentProcessor::get(filePath);
QVERIFY(processor);
QVERIFY(TestCase::waitForProcessedEditorDocument(filePath));
Snapshot snapshot = processor->snapshot();
QCOMPARE(snapshot.size(), 3); // Configuration file included

View File

@@ -32,6 +32,7 @@
#include "cpptoolsplugin.h"
#include <coreplugin/documentmanager.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/idocument.h>
#include <texteditor/convenience.h>
@@ -287,4 +288,13 @@ bool skipFileDueToSizeLimit(const QFileInfo &fileInfo, int limitInMB)
return false;
}
Utils::FileNameList modifiedFiles()
{
Utils::FileNameList files;
foreach (Core::IDocument *doc, Core::DocumentManager::modifiedDocuments())
files.append(doc->filePath());
files.removeDuplicates();
return files;
}
} // CppTools

View File

@@ -44,6 +44,10 @@ class QStringRef;
class QTextCursor;
QT_END_NAMESPACE
namespace Utils {
class FileNameList;
} // namespace Utils
namespace CPlusPlus {
class Macro;
class Symbol;
@@ -52,6 +56,8 @@ class LookupContext;
namespace CppTools {
Utils::FileNameList CPPTOOLS_EXPORT modifiedFiles();
void CPPTOOLS_EXPORT moveCursorToEndOfIdentifier(QTextCursor *tc);
void CPPTOOLS_EXPORT moveCursorToStartOfIdentifier(QTextCursor *tc);

View File

@@ -29,6 +29,10 @@
****************************************************************************/
#include "cpptoolstestcase.h"
#include "baseeditordocumentparser.h"
#include "baseeditordocumentprocessor.h"
#include "editordocumenthandle.h"
#include "cppmodelmanager.h"
#include "cppworkingcopy.h"
@@ -140,6 +144,31 @@ bool TestCase::garbageCollectGlobalSnapshot()
return globalSnapshot().isEmpty();
}
static bool waitForProcessedEditorDocument_internal(CppEditorDocumentHandle *editorDocument,
int timeOutInMs)
{
QTC_ASSERT(editorDocument, return false);
QTime timer;
timer.start();
forever {
if (!editorDocument->processor()->isParserRunning())
return true;
if (timer.elapsed() > timeOutInMs)
return false;
QCoreApplication::processEvents();
QThread::msleep(20);
}
}
bool TestCase::waitForProcessedEditorDocument(const QString &filePath, int timeOutInMs)
{
auto *editorDocument = CppModelManager::instance()->cppEditorDocument(filePath);
return waitForProcessedEditorDocument_internal(editorDocument, timeOutInMs);
}
bool TestCase::parseFiles(const QSet<QString> &filePaths)
{
CppModelManager::instance()->updateSourceFiles(filePaths).waitForFinished();

View File

@@ -95,6 +95,8 @@ public:
static CPlusPlus::Snapshot globalSnapshot();
static bool garbageCollectGlobalSnapshot();
static bool waitForProcessedEditorDocument(const QString &filePath, int timeOutInMs = 5000);
enum { defaultTimeOutInMs = 30 * 1000 /*= 30 secs*/ };
static bool waitUntilCppModelManagerIsAwareOf(
ProjectExplorer::Project *project,

View File

@@ -802,6 +802,7 @@ bool Breakpoint::isOneShot() const { return parameters().oneShot; }
void Breakpoint::removeAlienBreakpoint()
{
b->m_state = BreakpointRemoveProceeding;
b->deleteThis();
}

View File

@@ -137,23 +137,23 @@ enum BreakpointPathUsage
enum BreakpointParts
{
NoParts = 0,
FileAndLinePart = 0x1,
FunctionPart = 0x2,
AddressPart = 0x4,
ExpressionPart = 0x8,
ConditionPart = 0x10,
IgnoreCountPart = 0x20,
ThreadSpecPart = 0x40,
ModulePart = 0x80,
TracePointPart = 0x100,
NoParts = 0,
FileAndLinePart = (1 << 0),
FunctionPart = (1 << 1),
AddressPart = (1 << 2),
ExpressionPart = (1 << 3),
ConditionPart = (1 << 4),
IgnoreCountPart = (1 << 5),
ThreadSpecPart = (1 << 6),
ModulePart = (1 << 7),
TracePointPart = (1 << 8),
EnabledPart = 0x200,
TypePart = 0x400,
PathUsagePart = 0x800,
CommandPart = 0x1000,
MessagePart = 0x2000,
OneShotPart = 0x4000,
EnabledPart = (1 << 9),
TypePart = (1 << 10),
PathUsagePart = (1 << 11),
CommandPart = (1 << 12),
MessagePart = (1 << 13),
OneShotPart = (1 << 14),
AllConditionParts = ConditionPart|IgnoreCountPart|ThreadSpecPart
|OneShotPart,

View File

@@ -383,13 +383,17 @@ void BreakpointDialog::setPartsEnabled(unsigned partsMask)
m_lineEditModule->setEnabled(partsMask & ModulePart);
m_labelTracepoint->setEnabled(partsMask & TracePointPart);
m_labelTracepoint->hide();
m_checkBoxTracepoint->setEnabled(partsMask & TracePointPart);
m_checkBoxTracepoint->hide();
m_labelCommands->setEnabled(partsMask & TracePointPart);
m_textEditCommands->setEnabled(partsMask & TracePointPart);
m_labelCommands->setEnabled(partsMask & CommandPart);
m_textEditCommands->setEnabled(partsMask & CommandPart);
m_labelMessage->setEnabled(partsMask & TracePointPart);
m_labelMessage->hide();
m_lineEditMessage->setEnabled(partsMask & TracePointPart);
m_lineEditMessage->hide();
}
void BreakpointDialog::clearOtherParts(unsigned partsMask)
@@ -420,9 +424,10 @@ void BreakpointDialog::clearOtherParts(unsigned partsMask)
if (partsMask & OneShotPart)
m_checkBoxOneShot->setChecked(false);
if (invertedPartsMask & CommandPart)
m_textEditCommands->clear();
if (invertedPartsMask & TracePointPart) {
m_checkBoxTracepoint->setChecked(false);
m_textEditCommands->clear();
m_lineEditMessage->clear();
}
}
@@ -456,9 +461,10 @@ void BreakpointDialog::getParts(unsigned partsMask, BreakpointParameters *data)
if (partsMask & OneShotPart)
data->oneShot = m_checkBoxOneShot->isChecked();
if (partsMask & CommandPart)
data->command = m_textEditCommands->toPlainText().trimmed();
if (partsMask & TracePointPart) {
data->tracepoint = m_checkBoxTracepoint->isChecked();
data->command = m_textEditCommands->toPlainText().trimmed();
data->message = m_lineEditMessage->text();
}
}
@@ -467,7 +473,6 @@ void BreakpointDialog::setParts(unsigned mask, const BreakpointParameters &data)
{
m_checkBoxEnabled->setChecked(data.enabled);
m_comboBoxPathUsage->setCurrentIndex(data.pathUsage);
m_textEditCommands->setPlainText(data.command);
m_lineEditMessage->setText(data.message);
if (mask & FileAndLinePart) {
@@ -508,6 +513,8 @@ void BreakpointDialog::setParts(unsigned mask, const BreakpointParameters &data)
m_checkBoxOneShot->setChecked(data.oneShot);
if (mask & TracePointPart)
m_checkBoxTracepoint->setChecked(data.tracepoint);
if (mask & CommandPart)
m_textEditCommands->setPlainText(data.command);
}
void BreakpointDialog::typeChanged(int)
@@ -521,10 +528,10 @@ void BreakpointDialog::typeChanged(int)
case LastBreakpointType:
break;
case BreakpointByFileAndLine:
getParts(FileAndLinePart|ModulePart|AllConditionParts|TracePointPart, &m_savedParameters);
getParts(FileAndLinePart|ModulePart|AllConditionParts|TracePointPart|CommandPart, &m_savedParameters);
break;
case BreakpointByFunction:
getParts(FunctionPart|ModulePart|AllConditionParts|TracePointPart, &m_savedParameters);
getParts(FunctionPart|ModulePart|AllConditionParts|TracePointPart|CommandPart, &m_savedParameters);
break;
case BreakpointAtThrow:
case BreakpointAtCatch:
@@ -537,10 +544,10 @@ void BreakpointDialog::typeChanged(int)
break;
case BreakpointByAddress:
case WatchpointAtAddress:
getParts(AddressPart|AllConditionParts|TracePointPart, &m_savedParameters);
getParts(AddressPart|AllConditionParts|TracePointPart|CommandPart, &m_savedParameters);
break;
case WatchpointAtExpression:
getParts(ExpressionPart|AllConditionParts|TracePointPart, &m_savedParameters);
getParts(ExpressionPart|AllConditionParts|TracePointPart|CommandPart, &m_savedParameters);
break;
case BreakpointOnQmlSignalEmit:
getParts(FunctionPart, &m_savedParameters);
@@ -552,14 +559,14 @@ void BreakpointDialog::typeChanged(int)
case LastBreakpointType:
break;
case BreakpointByFileAndLine:
setParts(FileAndLinePart|AllConditionParts|ModulePart|TracePointPart, m_savedParameters);
setPartsEnabled(FileAndLinePart|AllConditionParts|ModulePart|TracePointPart);
clearOtherParts(FileAndLinePart|AllConditionParts|ModulePart|TracePointPart);
setParts(FileAndLinePart|AllConditionParts|ModulePart|TracePointPart|CommandPart, m_savedParameters);
setPartsEnabled(FileAndLinePart|AllConditionParts|ModulePart|TracePointPart|CommandPart);
clearOtherParts(FileAndLinePart|AllConditionParts|ModulePart|TracePointPart|CommandPart);
break;
case BreakpointByFunction:
setParts(FunctionPart|AllConditionParts|ModulePart|TracePointPart, m_savedParameters);
setPartsEnabled(FunctionPart|AllConditionParts|ModulePart|TracePointPart);
clearOtherParts(FunctionPart|AllConditionParts|ModulePart|TracePointPart);
setParts(FunctionPart|AllConditionParts|ModulePart|TracePointPart|CommandPart, m_savedParameters);
setPartsEnabled(FunctionPart|AllConditionParts|ModulePart|TracePointPart|CommandPart);
clearOtherParts(FunctionPart|AllConditionParts|ModulePart|TracePointPart|CommandPart);
break;
case BreakpointAtThrow:
case BreakpointAtCatch:
@@ -567,8 +574,8 @@ void BreakpointDialog::typeChanged(int)
case BreakpointAtExec:
//case BreakpointAtVFork:
case BreakpointAtSysCall:
clearOtherParts(AllConditionParts|ModulePart|TracePointPart);
setPartsEnabled(AllConditionParts|TracePointPart);
clearOtherParts(AllConditionParts|ModulePart|TracePointPart|CommandPart);
setPartsEnabled(AllConditionParts|TracePointPart|CommandPart);
break;
case BreakpointAtJavaScriptThrow:
clearOtherParts(AllParts);
@@ -581,14 +588,14 @@ void BreakpointDialog::typeChanged(int)
break;
case BreakpointByAddress:
case WatchpointAtAddress:
setParts(AddressPart|AllConditionParts|TracePointPart, m_savedParameters);
setPartsEnabled(AddressPart|AllConditionParts|TracePointPart);
clearOtherParts(AddressPart|AllConditionParts|TracePointPart);
setParts(AddressPart|AllConditionParts|TracePointPart|CommandPart, m_savedParameters);
setPartsEnabled(AddressPart|AllConditionParts|TracePointPart|CommandPart);
clearOtherParts(AddressPart|AllConditionParts|TracePointPart|CommandPart);
break;
case WatchpointAtExpression:
setParts(ExpressionPart|AllConditionParts|TracePointPart, m_savedParameters);
setPartsEnabled(ExpressionPart|AllConditionParts|TracePointPart);
clearOtherParts(ExpressionPart|AllConditionParts|TracePointPart);
setParts(ExpressionPart|AllConditionParts|TracePointPart|CommandPart, m_savedParameters);
setPartsEnabled(ExpressionPart|AllConditionParts|TracePointPart|CommandPart);
clearOtherParts(ExpressionPart|AllConditionParts|TracePointPart|CommandPart);
break;
case BreakpointOnQmlSignalEmit:
setParts(FunctionPart, m_savedParameters);

View File

@@ -134,6 +134,29 @@ Location::Location(const StackFrame &frame, bool marker)
}
class LocationMark : public TextMark
{
public:
LocationMark(DebuggerEngine *engine, const QString &file, int line)
: TextMark(file, line, Constants::TEXT_MARK_CATEGORY_LOCATION), m_engine(engine)
{}
private:
bool isDraggable() const { return true; }
void dragToLine(int line)
{
if (m_engine) {
ContextData data;
data.fileName = fileName();
data.lineNumber = line;
m_engine->executeJumpToLine(data);
}
}
QPointer<DebuggerEngine> m_engine;
};
//////////////////////////////////////////////////////////////////////
//
// DebuggerEnginePrivate
@@ -319,7 +342,7 @@ public:
DisassemblerAgent m_disassemblerAgent;
MemoryAgent m_memoryAgent;
QScopedPointer<TextMark> m_locationMark;
QScopedPointer<LocationMark> m_locationMark;
QTimer m_locationTimer;
bool m_isStateDebugging;
@@ -610,7 +633,7 @@ void DebuggerEngine::gotoLocation(const Location &loc)
editor->document()->setProperty(Constants::OPENED_BY_DEBUGGER, true);
if (loc.needsMarker()) {
d->m_locationMark.reset(new TextMark(file, line, Constants::TEXT_MARK_CATEGORY_LOCATION));
d->m_locationMark.reset(new LocationMark(this, file, line));
d->m_locationMark->setIcon(Internal::locationMarkIcon());
d->m_locationMark->setPriority(TextMark::HighPriority);
}
@@ -1976,13 +1999,18 @@ bool DebuggerEngine::canHandleToolTip(const DebuggerToolTipContext &context) con
return state() == InferiorStopOk && context.isCppEditor;
}
void DebuggerEngine::updateWatchData(const QByteArray &iname)
void DebuggerEngine::updateItem(const QByteArray &iname)
{
UpdateParameters params;
params.partialVariable = iname;
doUpdateLocals(params);
}
void DebuggerEngine::expandItem(const QByteArray &iname)
{
updateItem(iname);
}
} // namespace Internal
} // namespace Debugger

View File

@@ -65,6 +65,7 @@ class MemoryAgent;
class WatchData;
class WatchItem;
class BreakHandler;
class LocationMark;
class ModulesHandler;
class RegisterHandler;
class StackHandler;
@@ -191,7 +192,8 @@ public:
DebuggerRunParameters &runParameters();
virtual bool canHandleToolTip(const DebuggerToolTipContext &) const;
virtual void updateWatchData(const QByteArray &iname);
virtual void expandItem(const QByteArray &iname); // Called when item in tree gets expanded.
virtual void updateItem(const QByteArray &iname); // Called for fresh watch items.
virtual void selectWatchData(const QByteArray &iname);
virtual void startDebugger(DebuggerRunControl *runControl);
@@ -440,6 +442,7 @@ private:
virtual void setState(DebuggerState state, bool forced = false);
friend class DebuggerEnginePrivate;
friend class LocationMark;
DebuggerEnginePrivate *d;
};

View File

@@ -252,8 +252,10 @@ void DebuggerItemManager::autoDetectGdbOrLldbDebuggers()
foreach (const QString &base, path) {
dir.setPath(base);
foreach (const QString &entry, dir.entryList()) {
if (entry.startsWith(QLatin1String("lldb-platform-")))
if (entry.startsWith(QLatin1String("lldb-platform-"))
|| entry.startsWith(QLatin1String("lldb-gdbserver-"))) {
continue;
}
suspects.append(FileName::fromString(dir.absoluteFilePath(entry)));
}
}

View File

@@ -782,6 +782,16 @@ void DebuggerCommand::arg(const char *name, const char *value)
args.append("\",");
}
void DebuggerCommand::arg(const char *name, const QList<int> &list)
{
beginList(name);
foreach (int item, list) {
args.append(QByteArray::number(item));
args.append(',');
}
endList();
}
void DebuggerCommand::arg(const char *value)
{
args.append("\"");
@@ -823,5 +833,13 @@ void DebuggerCommand::endGroup()
args += "},";
}
QByteArray DebuggerCommand::arguments() const
{
QByteArray result = args;
if (result.endsWith(','))
result.chop(1);
return result;
}
} // namespace Internal
} // namespace Debugger

View File

@@ -32,6 +32,7 @@
#define DEBUGGER_PROTOCOL_H
#include <QByteArray>
#include <QList>
#include <QString>
#include <functional>
@@ -64,10 +65,13 @@ public:
void arg(const char *name, const QString &value);
void arg(const char *name, const QByteArray &value);
void arg(const char *name, const char *value);
void arg(const char *name, const QList<int> &list);
void beginList(const char *name = 0);
void endList();
void beginGroup(const char *name = 0);
void endGroup();
QByteArray arguments() const;
QByteArray function;
QByteArray args;

View File

@@ -1222,7 +1222,7 @@ static void slotTooltipOverrideRequested
m_tooltips.push_back(tooltip);
tooltip->setState(PendingUnshown);
if (engine->canHandleToolTip(context)) {
engine->updateWatchData(context.iname);
engine->updateItem(context.iname);
} else {
ToolTip::show(point, DebuggerToolTipManager::tr("Expression too complex"),
Internal::mainWindow());

View File

@@ -59,8 +59,6 @@ void GdbAttachEngine::setupEngine()
if (!runParameters().workingDirectory.isEmpty())
m_gdbProc.setWorkingDirectory(runParameters().workingDirectory);
if (runParameters().environment.size())
m_gdbProc.setEnvironment(runParameters().environment);
startGdb();
}

View File

@@ -130,7 +130,6 @@ GdbCoreEngine::readExecutableNameFromCore(const QString &debuggerCommand, const
CoreInfo cinfo;
#if 0
ElfReader reader(coreFile);
cinfo.isCore = false;
cinfo.rawStringFromCore = QString::fromLocal8Bit(reader.readCoreName(&cinfo.isCore));
cinfo.foundExecutableName = findExecutableFromName(cinfo.rawStringFromCore, coreFile);
#else
@@ -161,7 +160,6 @@ GdbCoreEngine::readExecutableNameFromCore(const QString &debuggerCommand, const
}
}
}
cinfo.isCore = false;
#endif
return cinfo;
}

View File

@@ -50,7 +50,7 @@ public:
{
QString rawStringFromCore;
QString foundExecutableName; // empty if no corresponding exec could be found
bool isCore;
bool isCore = false;
};
static CoreInfo readExecutableNameFromCore(const QString &debuggerCmd, const QString &coreFile);

View File

@@ -598,8 +598,9 @@ void GdbEngine::handleResponse(const QByteArray &buff)
// This also triggers when a temporary breakpoint is hit.
// We do not really want that, as this loses all information.
// FIXME: Use a special marker for this case?
if (!bp.isOneShot())
bp.removeAlienBreakpoint();
// if (!bp.isOneShot()) ... is not sufficient.
// It keeps temporary "Jump" breakpoints alive.
bp.removeAlienBreakpoint();
}
} else if (asyncClass == "cmd-param-changed") {
// New since 2012-08-09
@@ -4260,6 +4261,18 @@ void GdbEngine::loadInitScript()
}
}
void GdbEngine::setEnvironmentVariables()
{
Environment sysEnv = Environment::systemEnvironment();
Environment runEnv = runParameters().environment;
foreach (const EnvironmentItem &item, sysEnv.diff(runEnv)) {
if (item.unset)
postCommand("unset environment " + item.name.toUtf8());
else
postCommand("-gdb-set environment " + item.name.toUtf8() + '=' + item.value.toUtf8());
}
}
void GdbEngine::reloadDebuggingHelpers()
{
runCommand("reloadDumpers");
@@ -4570,7 +4583,7 @@ bool GdbEngine::prepareCommand()
QtcProcess::SplitError perr;
rp.processArgs = QtcProcess::prepareArgs(rp.processArgs, &perr,
HostOsInfo::hostOs(),
&rp.environment, &rp.workingDirectory).toWindowsArgs();
nullptr, &rp.workingDirectory).toWindowsArgs();
if (perr != QtcProcess::SplitOk) {
// perr == BadQuoting is never returned on Windows
// FIXME? QTCREATORBUG-2809

View File

@@ -103,6 +103,7 @@ protected: ////////// Gdb Process Management //////////
void handleGdbExit(const DebuggerResponse &response);
void loadInitScript();
void setEnvironmentVariables();
// Something went wrong with the adapter *before* adapterStarted() was emitted.
// Make sure to clean up everything before emitting this signal.

View File

@@ -57,6 +57,7 @@ GdbPlainEngine::GdbPlainEngine(const DebuggerRunParameters &startParameters)
void GdbPlainEngine::setupInferior()
{
QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state());
setEnvironmentVariables();
if (!runParameters().processArgs.isEmpty()) {
QString args = runParameters().processArgs;
postCommand("-exec-arguments " + toLocalEncoding(args));
@@ -127,9 +128,6 @@ void GdbPlainEngine::setupEngine()
if (!runParameters().workingDirectory.isEmpty())
m_gdbProc.setWorkingDirectory(runParameters().workingDirectory);
Utils::Environment env = runParameters().environment;
if (env.size())
m_gdbProc.setEnvironment(env);
startGdb(gdbArgs);
}

View File

@@ -91,8 +91,6 @@ void GdbRemoteServerEngine::setupEngine()
}
if (!runParameters().workingDirectory.isEmpty())
m_gdbProc.setWorkingDirectory(runParameters().workingDirectory);
if (runParameters().environment.size())
m_gdbProc.setEnvironment(runParameters().environment);
if (runParameters().remoteSetupNeeded)
notifyEngineRequestRemoteSetup();
@@ -186,6 +184,8 @@ void GdbRemoteServerEngine::setupInferior()
if (!args.isEmpty())
postCommand("-exec-arguments " + args.toLocal8Bit());
setEnvironmentVariables();
// This has to be issued before 'target remote'. On pre-7.0 the
// command is not present and will result in ' No symbol table is
// loaded. Use the "file" command.' as gdb tries to set the

View File

@@ -182,7 +182,7 @@ bool LldbEngine::prepareCommand()
QtcProcess::SplitError perr;
rp.processArgs = QtcProcess::prepareArgs(rp.processArgs, &perr,
HostOsInfo::hostOs(),
&rp.environment, &rp.workingDirectory).toWindowsArgs();
nullptr, &rp.workingDirectory).toWindowsArgs();
if (perr != QtcProcess::SplitOk) {
// perr == BadQuoting is never returned on Windows
// FIXME? QTCREATORBUG-2809
@@ -290,6 +290,17 @@ void LldbEngine::startLldbStage2()
void LldbEngine::setupInferior()
{
Environment sysEnv = Environment::systemEnvironment();
Environment runEnv = runParameters().environment;
foreach (const EnvironmentItem &item, sysEnv.diff(runEnv)) {
DebuggerCommand cmd("executeDebuggerCommand");
if (item.unset)
cmd.arg("command", "settings remove target.env-vars " + item.name.toUtf8());
else
cmd.arg("command", "settings set target.env-vars " + item.name.toUtf8() + '=' + item.value.toUtf8());
runCommand(cmd);
}
const QString path = stringSetting(ExtraDumperFile);
if (!path.isEmpty() && QFileInfo(path).isReadable()) {
DebuggerCommand cmd("addDumperModule");
@@ -300,7 +311,7 @@ void LldbEngine::setupInferior()
const QString commands = stringSetting(ExtraDumperCommands);
if (!commands.isEmpty()) {
DebuggerCommand cmd("executeDebuggerCommand");
cmd.arg("commands", commands.toUtf8());
cmd.arg("command", commands.toUtf8());
runCommand(cmd);
}

View File

@@ -394,7 +394,7 @@ void PdbEngine::assignValueInDebugger(WatchItem *, const QString &expression, co
updateLocals();
}
void PdbEngine::updateWatchData(const QByteArray &iname)
void PdbEngine::updateItem(const QByteArray &iname)
{
Q_UNUSED(iname);
updateAll();

View File

@@ -96,7 +96,7 @@ private:
bool supportsThreads() const { return true; }
bool isSynchronous() const { return true; }
void updateWatchData(const QByteArray &iname);
void updateItem(const QByteArray &iname);
QString mainPythonFile() const;
QString pythonInterpreter() const;

View File

@@ -114,12 +114,20 @@ bool QmlCppEngine::canHandleToolTip(const DebuggerToolTipContext &ctx) const
return success;
}
void QmlCppEngine::updateWatchData(const QByteArray &iname)
void QmlCppEngine::updateItem(const QByteArray &iname)
{
if (iname.startsWith("inspect."))
m_qmlEngine->updateWatchData(iname);
m_qmlEngine->updateItem(iname);
else
m_activeEngine->updateWatchData(iname);
m_activeEngine->updateItem(iname);
}
void QmlCppEngine::expandItem(const QByteArray &iname)
{
if (iname.startsWith("inspect."))
m_qmlEngine->expandItem(iname);
else
m_activeEngine->expandItem(iname);
}
void QmlCppEngine::selectWatchData(const QByteArray &iname)

View File

@@ -48,7 +48,8 @@ public:
bool canDisplayTooltip() const;
bool canHandleToolTip(const DebuggerToolTipContext &) const;
void updateWatchData(const QByteArray &iname);
void updateItem(const QByteArray &iname);
void expandItem(const QByteArray &iname);
void selectWatchData(const QByteArray &iname);
void watchPoint(const QPoint &);

File diff suppressed because it is too large Load Diff

View File

@@ -77,8 +77,6 @@ private slots:
void appStartupFailed(const QString &errorMessage);
void appendMessage(const QString &msg, Utils::OutputFormat);
void synchronizeWatchers();
private:
void notifyEngineRemoteServerRunning(const QByteArray &, int pid);
void notifyEngineRemoteSetupFinished(const RemoteSetupResult &result);
@@ -131,7 +129,9 @@ private:
void reloadSourceFiles();
void reloadFullStack() {}
void updateWatchData(const QByteArray &iname);
void updateAll();
void updateItem(const QByteArray &iname);
void expandItem(const QByteArray &iname);
void selectWatchData(const QByteArray &iname);
void executeDebuggerCommand(const QString &command, DebuggerLanguages languages);
bool evaluateScript(const QString &expression);

View File

@@ -645,7 +645,12 @@ template <class T>
void readNumericVectorHelper(std::vector<double> *v, const QByteArray &ba)
{
const T *p = (const T *) ba.data();
std::copy(p, p + ba.size() / sizeof(T), std::back_insert_iterator<std::vector<double> >(*v));
const int n = ba.size() / sizeof(T);
v->resize(n);
// Losing precision in case of 64 bit ints is ok here, as the result
// is only used to plot data.
for (int i = 0; i != n; ++i)
(*v)[i] = static_cast<double>(p[i]);
}
void readNumericVector(std::vector<double> *v, const QByteArray &rawData, DebuggerEncoding encoding)

View File

@@ -301,7 +301,6 @@ public:
SeparatedView *m_separatedView; // Not owned.
QSet<QByteArray> m_expandedINames;
QSet<QByteArray> m_fetchTriggered;
QTimer m_requestUpdateTimer;
QHash<QString, DisplayFormats> m_reportedTypeFormats; // Type name -> Dumper Formats
@@ -331,7 +330,7 @@ WatchModel::WatchModel(WatchHandler *handler, DebuggerEngine *engine)
this, &WatchModel::updateStarted);
connect(action(SortStructMembers), &SavedAction::valueChanged,
m_engine, &DebuggerEngine::updateAll);
m_engine, &DebuggerEngine::updateLocals);
connect(action(ShowStdNamespace), &SavedAction::valueChanged,
m_engine, &DebuggerEngine::updateAll);
connect(action(ShowQtNamespace), &SavedAction::valueChanged,
@@ -670,20 +669,16 @@ bool WatchItem::canFetchMore() const
return false;
if (!model->m_contentsValid && !isInspect())
return false;
return !model->m_fetchTriggered.contains(iname);
return true;
}
void WatchItem::fetchMore()
{
WatchModel *model = watchModel();
if (model->m_fetchTriggered.contains(iname))
return;
model->m_expandedINames.insert(iname);
model->m_fetchTriggered.insert(iname);
if (children().isEmpty()) {
setChildrenNeeded();
model->m_engine->updateWatchData(iname);
model->m_engine->expandItem(iname);
}
}
@@ -940,12 +935,12 @@ bool WatchModel::setData(const QModelIndex &idx, const QVariant &value, int role
case LocalsTypeFormatRole:
setTypeFormat(item->type, value.toInt());
m_engine->updateWatchData(item->iname);
m_engine->updateLocals();
break;
case LocalsIndividualFormatRole: {
setIndividualFormat(item->iname, value.toInt());
m_engine->updateWatchData(item->iname);
m_engine->updateLocals();
break;
}
}
@@ -1177,6 +1172,8 @@ void WatchModel::insertItem(WatchItem *item)
if (!found)
parent->appendChild(item);
item->update();
item->walkTree([this](TreeItem *sub) { showEditValue(static_cast<WatchItem *>(sub)); });
}
@@ -1304,14 +1301,14 @@ void WatchHandler::watchExpression(const QString &exp0, const QString &name)
item->exp = exp;
item->name = name.isEmpty() ? exp0 : name;
item->iname = watcherName(exp);
m_model->insertItem(item);
saveWatchers();
if (m_model->m_engine->state() == DebuggerNotReady) {
item->setAllUnneeded();
item->setValue(QString(QLatin1Char(' ')));
m_model->insertItem(item);
} else {
m_model->m_engine->updateWatchData(item->iname);
m_model->m_engine->updateItem(item->iname);
}
updateWatchersWindow();
}
@@ -1665,7 +1662,6 @@ QString WatchHandler::editorContents()
void WatchHandler::scheduleResetLocation()
{
m_model->m_fetchTriggered.clear();
m_model->m_contentsValid = false;
m_model->m_resetLocationScheduled = true;
}

View File

@@ -240,7 +240,7 @@ private:
bool m_submitActionTriggered;
};
} // namespace Git
} // namespace Internal
} // namespace Git
#endif // GITPLUGIN_H

View File

@@ -60,7 +60,7 @@ QVariant QtKitInformation::defaultValue(ProjectExplorer::Kit *k) const
Q_UNUSED(k);
// find "Qt in PATH":
QList<BaseQtVersion *> versionList = QtVersionManager::versions();
QList<BaseQtVersion *> versionList = QtVersionManager::unsortedVersions();
BaseQtVersion *result = findOrDefault(versionList, [](const BaseQtVersion *v) {
return v->autodetectionSource() == QLatin1String("PATH");
});
@@ -174,7 +174,7 @@ int QtKitInformation::qtVersionId(const ProjectExplorer::Kit *k)
id = -1;
} else {
QString source = data.toString();
foreach (BaseQtVersion *v, QtVersionManager::versions()) {
foreach (BaseQtVersion *v, QtVersionManager::unsortedVersions()) {
if (v->autodetectionSource() != source)
continue;
id = v->uniqueId();

View File

@@ -354,7 +354,7 @@ void QtVersionManager::updateFromInstaller(bool emitSignal)
qDebug() << "";
}
}
foreach (BaseQtVersion *qtVersion, QtVersionManager::versions()) {
foreach (BaseQtVersion *qtVersion, m_versions) {
if (qtVersion->autodetectionSource().startsWith(QLatin1String("SDK."))) {
if (!sdkVersions.contains(qtVersion->autodetectionSource())) {
if (debug)
@@ -515,6 +515,13 @@ int QtVersionManager::getUniqueId()
return m_idcount++;
}
QList<BaseQtVersion *> QtVersionManager::unsortedVersions()
{
QList<BaseQtVersion *> versions;
QTC_ASSERT(isLoaded(), return versions);
return m_versions.values();
}
QList<BaseQtVersion *> QtVersionManager::versions()
{
QList<BaseQtVersion *> versions;

View File

@@ -56,6 +56,9 @@ public:
static QList<BaseQtVersion *> versions();
static QList<BaseQtVersion *> validVersions();
// Sorting is slow due to needing to potentially run qmake --query for each version
static QList<BaseQtVersion *> unsortedVersions();
// Note: DO NOT STORE THIS POINTER!
// The QtVersionManager will delete it at random times and you will
// need to get a new pointer by calling this function again!

Some files were not shown because too many files have changed in this diff Show More