Merge remote-tracking branch 'origin/4.4'

Conflicts:
	src/plugins/debugger/debuggerdialogs.cpp
	src/plugins/debugger/gdb/remotegdbserveradapter.cpp

Change-Id: I1ae77869887a8d9ef2a33439f2733315db9e0cf0
This commit is contained in:
Eike Ziller
2017-09-19 12:00:16 +02:00
40 changed files with 9999 additions and 6050 deletions

View File

@@ -1177,7 +1177,7 @@ class DumperBase:
n = arrayByteSize // innerType.size() n = arrayByteSize // innerType.size()
p = value.address() p = value.address()
if displayFormat != RawFormat and p: if displayFormat != RawFormat and p:
if innerType.name in ('char', 'wchar_t', 'unsigned char', 'signed char'): if innerType.name in ('char', 'wchar_t', 'unsigned char', 'signed char', 'CHAR', 'WCHAR'):
self.putCharArrayHelper(p, n, innerType, self.currentItemFormat(), self.putCharArrayHelper(p, n, innerType, self.currentItemFormat(),
makeExpandable = False) makeExpandable = False)
else: else:
@@ -1256,7 +1256,7 @@ class DumperBase:
# This is shared by pointer and array formatting. # This is shared by pointer and array formatting.
def tryPutSimpleFormattedPointer(self, ptr, typeName, innerType, displayFormat, limit): def tryPutSimpleFormattedPointer(self, ptr, typeName, innerType, displayFormat, limit):
if displayFormat == AutomaticFormat: if displayFormat == AutomaticFormat:
if innerType.name in ('char', 'signed char', 'unsigned char'): if innerType.name in ('char', 'signed char', 'unsigned char', 'CHAR'):
# Use UTF-8 as default for char *. # Use UTF-8 as default for char *.
self.putType(typeName) self.putType(typeName)
(elided, shown, data) = self.readToFirstZero(ptr, 1, limit) (elided, shown, data) = self.readToFirstZero(ptr, 1, limit)
@@ -1265,7 +1265,7 @@ class DumperBase:
self.putArrayData(ptr, shown, innerType) self.putArrayData(ptr, shown, innerType)
return True return True
if innerType.name == 'wchar_t': if innerType.name in ('wchar_t', 'WCHAR'):
self.putType(typeName) self.putType(typeName)
charSize = self.lookupType('wchar_t').size() charSize = self.lookupType('wchar_t').size()
(elided, data) = self.encodeCArray(ptr, charSize, limit) (elided, data) = self.encodeCArray(ptr, charSize, limit)
@@ -1415,7 +1415,7 @@ class DumperBase:
#warn('INNER: %s' % innerType.name) #warn('INNER: %s' % innerType.name)
if self.autoDerefPointers: if self.autoDerefPointers:
# Generic pointer type with AutomaticFormat, but never dereference char types: # Generic pointer type with AutomaticFormat, but never dereference char types:
if innerType.name not in ('char', 'signed char', 'unsigned char', 'wchar_t'): if innerType.name not in ('char', 'signed char', 'unsigned char', 'wchar_t', 'CHAR', 'WCHAR'):
self.putDerefedPointer(value) self.putDerefedPointer(value)
return return

View File

@@ -1062,6 +1062,11 @@ class Dumper(DumperBase):
cmd = 'set variable (%s)=%s' % (expr, value) cmd = 'set variable (%s)=%s' % (expr, value)
gdb.execute(cmd) gdb.execute(cmd)
def appendSolibSearchPath(self, args):
new = list(map(self.hexdecode, args['path']))
old = [gdb.parameter('solib-search-path')]
gdb.execute('set solib-search-path %s' % args['separator'].join(old + new))
def watchPoint(self, args): def watchPoint(self, args):
self.reportToken(args) self.reportToken(args)
ns = self.qtNamespace() ns = self.qtNamespace()

File diff suppressed because it is too large Load Diff

View File

@@ -255,8 +255,8 @@ static inline int classify5(const char *s, LanguageFeatures features)
} }
} }
} }
else if (features.cxxEnabled && s[0] == 'f') { else if (s[0] == 'f') {
if (s[1] == 'a') { if (features.cxxEnabled && s[1] == 'a') {
if (s[2] == 'l') { if (s[2] == 'l') {
if (s[3] == 's') { if (s[3] == 's') {
if (s[4] == 'e') { if (s[4] == 'e') {

View File

@@ -106,7 +106,11 @@ Declaration::Declaration(Clone *clone, Subst *subst, Declaration *original)
, _initializer(clone->stringLiteral(original->_initializer)) , _initializer(clone->stringLiteral(original->_initializer))
{ {
const char* nameId = nullptr; const char* nameId = nullptr;
if (const Identifier* identifier = name()->identifier()) const Name *theName = name();
if (!theName)
return;
if (const Identifier* identifier = theName->identifier())
nameId = identifier->chars(); nameId = identifier->chars();
else else
return; return;

View File

@@ -57,7 +57,9 @@ void WriteMessageBlock::write(const MessageEnvelop &message)
++m_messageCounter; ++m_messageCounter;
m_ioDevice->write(block); const qint64 bytesWritten = m_ioDevice->write(block);
if (bytesWritten == -1)
qWarning() << "Failed to write data:" << m_ioDevice->errorString();
} }
qint64 WriteMessageBlock::counter() const qint64 WriteMessageBlock::counter() const

View File

@@ -353,7 +353,7 @@ static const Terminal knownTerminals[] =
{"urxvt", "-e"}, {"urxvt", "-e"},
{"xfce4-terminal", "-x"}, {"xfce4-terminal", "-x"},
{"konsole", "-e"}, {"konsole", "-e"},
{"gnome-terminal", "-x"} {"gnome-terminal", "--"}
}; };
QString ConsoleProcess::defaultTerminalEmulator() QString ConsoleProcess::defaultTerminalEmulator()

View File

@@ -309,7 +309,7 @@ static void processOutput(TestOutputReader *outputreader, const QString &msg,
break; break;
} }
for (const QString &line : msg.mid(start).split('\n')) for (const QString &line : msg.mid(start).split('\n'))
outputreader->processOutput(line.toUtf8() + '\n'); outputreader->processOutput(line.toUtf8());
break; break;
} }
case Utils::OutputFormat::StdErrFormatSameLine: case Utils::OutputFormat::StdErrFormatSameLine:

View File

@@ -154,8 +154,14 @@ static QList<CMakeTool *> autoDetectCMakeTools()
path.removeDuplicates(); path.removeDuplicates();
if (HostOsInfo::isWindowsHost()) { if (HostOsInfo::isWindowsHost()) {
path.append("C:/Program Files/CMake"); const QString progFiles = QLatin1String(qgetenv("ProgramFiles"));
path.append("C:/Program Files (x86)/CMake"); path.append(progFiles + "/CMake");
path.append(progFiles + "/CMake/bin");
const QString progFilesX86 = QLatin1String(qgetenv("ProgramFiles(x86)"));
if (!progFilesX86.isEmpty()) {
path.append(progFilesX86 + "/CMake");
path.append(progFilesX86 + "/CMake/bin");
}
} }
if (HostOsInfo::isMacHost()) { if (HostOsInfo::isMacHost()) {

View File

@@ -249,7 +249,7 @@ CMakeConfig ServerModeReader::takeParsedConfiguration()
} }
static void addCMakeVFolder(FolderNode *base, const Utils::FileName &basePath, int priority, static void addCMakeVFolder(FolderNode *base, const Utils::FileName &basePath, int priority,
const QString &displayName, QList<FileNode *> &files) const QString &displayName, const QList<FileNode *> &files)
{ {
if (files.isEmpty()) if (files.isEmpty())
return; return;
@@ -264,6 +264,17 @@ static void addCMakeVFolder(FolderNode *base, const Utils::FileName &basePath, i
fn->compress(); fn->compress();
} }
static QList<FileNode *> removeKnownNodes(const QSet<Utils::FileName> &knownFiles, const QList<FileNode *> &files)
{
return Utils::filtered(files, [&knownFiles](const FileNode *n) {
if (knownFiles.contains(n->filePath())) {
delete n;
return false;
}
return true;
});
}
static void addCMakeInputs(FolderNode *root, static void addCMakeInputs(FolderNode *root,
const Utils::FileName &sourceDir, const Utils::FileName &sourceDir,
const Utils::FileName &buildDir, const Utils::FileName &buildDir,
@@ -274,13 +285,19 @@ static void addCMakeInputs(FolderNode *root,
ProjectNode *cmakeVFolder = new CMakeInputsNode(root->filePath()); ProjectNode *cmakeVFolder = new CMakeInputsNode(root->filePath());
root->addNode(cmakeVFolder); root->addNode(cmakeVFolder);
addCMakeVFolder(cmakeVFolder, sourceDir, 1000, QString(), sourceInputs); QSet<Utils::FileName> knownFiles;
root->forEachGenericNode([&knownFiles](const Node *n) {
if (n->listInProject())
knownFiles.insert(n->filePath());
});
addCMakeVFolder(cmakeVFolder, sourceDir, 1000, QString(), removeKnownNodes(knownFiles, sourceInputs));
addCMakeVFolder(cmakeVFolder, buildDir, 100, addCMakeVFolder(cmakeVFolder, buildDir, 100,
QCoreApplication::translate("CMakeProjectManager::Internal::ServerModeReader", "<Build Directory>"), QCoreApplication::translate("CMakeProjectManager::Internal::ServerModeReader", "<Build Directory>"),
buildInputs); removeKnownNodes(knownFiles, buildInputs));
addCMakeVFolder(cmakeVFolder, Utils::FileName(), 10, addCMakeVFolder(cmakeVFolder, Utils::FileName(), 10,
QCoreApplication::translate("CMakeProjectManager::Internal::ServerModeReader", "<Other Locations>"), QCoreApplication::translate("CMakeProjectManager::Internal::ServerModeReader", "<Other Locations>"),
rootInputs); removeKnownNodes(knownFiles, rootInputs));
} }
void ServerModeReader::generateProjectTree(CMakeProjectNode *root, void ServerModeReader::generateProjectTree(CMakeProjectNode *root,
@@ -311,15 +328,15 @@ void ServerModeReader::generateProjectTree(CMakeProjectNode *root,
if (topLevel) if (topLevel)
root->setDisplayName(topLevel->name); root->setDisplayName(topLevel->name);
if (!cmakeFilesSource.isEmpty() || !cmakeFilesBuild.isEmpty() || !cmakeFilesOther.isEmpty())
addCMakeInputs(root, m_parameters.sourceDirectory, m_parameters.buildDirectory,
cmakeFilesSource, cmakeFilesBuild, cmakeFilesOther);
QHash<Utils::FileName, ProjectNode *> cmakeListsNodes = addCMakeLists(root, cmakeLists); QHash<Utils::FileName, ProjectNode *> cmakeListsNodes = addCMakeLists(root, cmakeLists);
QList<FileNode *> knownHeaders; QList<FileNode *> knownHeaders;
addProjects(cmakeListsNodes, m_projects, knownHeaders); addProjects(cmakeListsNodes, m_projects, knownHeaders);
addHeaderNodes(root, knownHeaders, allFiles); addHeaderNodes(root, knownHeaders, allFiles);
if (!cmakeFilesSource.isEmpty() || !cmakeFilesBuild.isEmpty() || !cmakeFilesOther.isEmpty())
addCMakeInputs(root, m_parameters.sourceDirectory, m_parameters.buildDirectory,
cmakeFilesSource, cmakeFilesBuild, cmakeFilesOther);
} }
void ServerModeReader::updateCodeModel(CppTools::RawProjectParts &rpps) void ServerModeReader::updateCodeModel(CppTools::RawProjectParts &rpps)

View File

@@ -4443,9 +4443,12 @@ void GdbEngine::setupInferior()
// if (!remoteArch.isEmpty()) // if (!remoteArch.isEmpty())
// postCommand("set architecture " + remoteArch); // postCommand("set architecture " + remoteArch);
const QString solibSearchPath = rp.solibSearchPath.join(HostOsInfo::pathListSeparator()); if (!rp.solibSearchPath.isEmpty()) {
if (!solibSearchPath.isEmpty()) DebuggerCommand cmd("appendSolibSearchPath");
runCommand({"set solib-search-path " + solibSearchPath}); cmd.arg("path", rp.solibSearchPath);
cmd.arg("separator", HostOsInfo::pathListSeparator());
runCommand(cmd);
}
if (!args.isEmpty()) if (!args.isEmpty())
runCommand({"-exec-arguments " + args}); runCommand({"-exec-arguments " + args});

View File

@@ -4422,7 +4422,7 @@ bool FakeVimHandler::Private::handleNoSubMode(const Input &input)
} else if (g.gflag && input.is('t')) { } else if (g.gflag && input.is('t')) {
handleExCommand("tabnext"); handleExCommand("tabnext");
} else if (g.gflag && input.is('T')) { } else if (g.gflag && input.is('T')) {
handleExCommand("tabprev"); handleExCommand("tabprevious");
} else if (input.isControl('t')) { } else if (input.isControl('t')) {
handleExCommand("pop"); handleExCommand("pop");
} else if (!g.gflag && input.is('u') && !isVisualMode()) { } else if (!g.gflag && input.is('u') && !isVisualMode()) {
@@ -5565,7 +5565,7 @@ bool FakeVimHandler::Private::handleExSubstituteCommand(const ExCommand &cmd)
bool FakeVimHandler::Private::handleExTabNextCommand(const ExCommand &cmd) bool FakeVimHandler::Private::handleExTabNextCommand(const ExCommand &cmd)
{ {
if (cmd.cmd != "tabnext" && cmd.cmd != "tabn") if (!cmd.matches("tabn", "tabnext"))
return false; return false;
emit q->tabNextRequested(q); emit q->tabNextRequested(q);
@@ -5574,7 +5574,7 @@ bool FakeVimHandler::Private::handleExTabNextCommand(const ExCommand &cmd)
bool FakeVimHandler::Private::handleExTabPreviousCommand(const ExCommand &cmd) bool FakeVimHandler::Private::handleExTabPreviousCommand(const ExCommand &cmd)
{ {
if (cmd.cmd != "tabprevious" && cmd.cmd != "tabp") if (!cmd.matches("tabp", "tabprevious"))
return false; return false;
emit q->tabPreviousRequested(q); emit q->tabPreviousRequested(q);

View File

@@ -26,7 +26,6 @@
#include "gerritpushdialog.h" #include "gerritpushdialog.h"
#include "ui_gerritpushdialog.h" #include "ui_gerritpushdialog.h"
#include "branchcombobox.h" #include "branchcombobox.h"
#include "gerritserver.h"
#include "../gitplugin.h" #include "../gitplugin.h"
#include "../gitclient.h" #include "../gitclient.h"
@@ -129,6 +128,7 @@ GerritPushDialog::GerritPushDialog(const QString &workingDir, const QString &rev
m_ui->repositoryLabel->setText(QDir::toNativeSeparators(workingDir)); m_ui->repositoryLabel->setText(QDir::toNativeSeparators(workingDir));
m_ui->remoteComboBox->setRepository(workingDir); m_ui->remoteComboBox->setRepository(workingDir);
m_ui->remoteComboBox->setParameters(parameters); m_ui->remoteComboBox->setParameters(parameters);
m_ui->remoteComboBox->setAllowDups(true);
PushItemDelegate *delegate = new PushItemDelegate(m_ui->commitView); PushItemDelegate *delegate = new PushItemDelegate(m_ui->commitView);
delegate->setParent(this); delegate->setParent(this);

View File

@@ -80,6 +80,11 @@ void GerritRemoteChooser::setFallbackEnabled(bool value)
m_enableFallback = value; m_enableFallback = value;
} }
void GerritRemoteChooser::setAllowDups(bool value)
{
m_allowDups = value;
}
bool GerritRemoteChooser::setCurrentRemote(const QString &remoteName) bool GerritRemoteChooser::setCurrentRemote(const QString &remoteName)
{ {
for (int i = 0, total = m_remoteComboBox->count(); i < total; ++i) { for (int i = 0, total = m_remoteComboBox->count(); i < total; ++i) {
@@ -118,9 +123,11 @@ bool GerritRemoteChooser::updateRemotes(bool forceReload)
void GerritRemoteChooser::addRemote(const GerritServer &server, const QString &name) void GerritRemoteChooser::addRemote(const GerritServer &server, const QString &name)
{ {
for (auto remote : m_remotes) { if (!m_allowDups) {
if (remote.second == server) for (auto remote : m_remotes) {
return; if (remote.second == server)
return;
}
} }
m_remoteComboBox->addItem(server.host + QString(" (%1)").arg(name)); m_remoteComboBox->addItem(server.host + QString(" (%1)").arg(name));
m_remotes.push_back({ name, server }); m_remotes.push_back({ name, server });

View File

@@ -48,6 +48,7 @@ public:
void setRepository(const QString &repository); void setRepository(const QString &repository);
void setParameters(QSharedPointer<GerritParameters> parameters); void setParameters(QSharedPointer<GerritParameters> parameters);
void setFallbackEnabled(bool value); void setFallbackEnabled(bool value);
void setAllowDups(bool value);
bool setCurrentRemote(const QString &remoteName); bool setCurrentRemote(const QString &remoteName);
bool updateRemotes(bool forceReload); bool updateRemotes(bool forceReload);
@@ -68,6 +69,7 @@ private:
QToolButton *m_resetRemoteButton = nullptr; QToolButton *m_resetRemoteButton = nullptr;
bool m_updatingRemotes = false; bool m_updatingRemotes = false;
bool m_enableFallback = false; bool m_enableFallback = false;
bool m_allowDups = false;
using NameAndServer = std::pair<QString, GerritServer>; using NameAndServer = std::pair<QString, GerritServer>;
std::vector<NameAndServer> m_remotes; std::vector<NameAndServer> m_remotes;
}; };

View File

@@ -629,6 +629,16 @@ void HelpPlugin::highlightSearchTermsInContextHelp()
void HelpPlugin::handleHelpRequest(const QUrl &url, HelpManager::HelpViewerLocation location) void HelpPlugin::handleHelpRequest(const QUrl &url, HelpManager::HelpViewerLocation location)
{ {
static const QString qtcreatorUnversionedID = "org.qt-project.qtcreator";
if (url.host() == qtcreatorUnversionedID) {
// QtHelp doesn't know about versions, add the version number and use that
QUrl versioned = url;
versioned.setHost(qtcreatorUnversionedID + "."
+ QString::fromLatin1(Core::Constants::IDE_VERSION_LONG).remove('.'));
handleHelpRequest(versioned, location);
return;
}
if (HelpViewer::launchWithExternalApp(url)) if (HelpViewer::launchWithExternalApp(url))
return; return;
@@ -639,7 +649,7 @@ void HelpPlugin::handleHelpRequest(const QUrl &url, HelpManager::HelpViewerLocat
|| address.startsWith("qthelp://com.trolltech.")) { || address.startsWith("qthelp://com.trolltech.")) {
// local help not installed, resort to external web help // local help not installed, resort to external web help
QString urlPrefix = "http://doc.qt.io/"; QString urlPrefix = "http://doc.qt.io/";
if (url.authority() == "org.qt-project.qtcreator") if (url.authority().startsWith(qtcreatorUnversionedID))
urlPrefix.append(QString::fromLatin1("qtcreator")); urlPrefix.append(QString::fromLatin1("qtcreator"));
else else
urlPrefix.append("qt-5"); urlPrefix.append("qt-5");

View File

@@ -378,7 +378,9 @@ void ProjectTree::applyTreeManager(FolderNode *folder)
bool ProjectTree::hasNode(const Node *node) bool ProjectTree::hasNode(const Node *node)
{ {
return Utils::contains(SessionManager::projects(), [node](const Project *p) { return Utils::contains(SessionManager::projects(), [node](const Project *p) {
return p && p->rootProjectNode() && p->rootProjectNode()->findNode([node](const Node *n) { return n == node; }); return p && p->rootProjectNode() && (
p->containerNode() == node
|| p->rootProjectNode()->findNode([node](const Node *n) { return n == node; }));
}); });
} }

View File

@@ -332,7 +332,7 @@ void MoveManipulator::clear()
m_beginVerticalCenterHash.clear(); m_beginVerticalCenterHash.clear();
} }
void MoveManipulator::reparentTo(FormEditorItem *newParent) void MoveManipulator::reparentTo(FormEditorItem *newParent, ReparentFlag flag)
{ {
deleteSnapLines(); deleteSnapLines();
@@ -348,7 +348,8 @@ void MoveManipulator::reparentTo(FormEditorItem *newParent)
&& newParent->qmlItemNode().modelNode().hasParentProperty()) { && newParent->qmlItemNode().modelNode().hasParentProperty()) {
ModelNode grandParent = newParent->qmlItemNode().modelNode().parentProperty().parentModelNode(); ModelNode grandParent = newParent->qmlItemNode().modelNode().parentProperty().parentModelNode();
if (grandParent.metaInfo().isLayoutable() if (grandParent.metaInfo().isLayoutable()
&& !NodeHints::fromModelNode(grandParent).isStackedContainer()) && !NodeHints::fromModelNode(grandParent).isStackedContainer()
&& flag == DoNotEnforceReparent)
newParent = m_view.data()->scene()->itemForQmlItemNode(QmlItemNode(grandParent)); newParent = m_view.data()->scene()->itemForQmlItemNode(QmlItemNode(grandParent));
} }

View File

@@ -48,6 +48,11 @@ public:
UseBaseState UseBaseState
}; };
enum ReparentFlag {
DoNotEnforceReparent,
EnforceReparent
};
MoveManipulator(LayerItem *layerItem, FormEditorView *view); MoveManipulator(LayerItem *layerItem, FormEditorView *view);
~MoveManipulator(); ~MoveManipulator();
void setItems(const QList<FormEditorItem*> &itemList); void setItems(const QList<FormEditorItem*> &itemList);
@@ -57,7 +62,7 @@ public:
void begin(const QPointF& beginPoint); void begin(const QPointF& beginPoint);
void update(const QPointF& updatePoint, Snapper::Snapping useSnapping, State stateToBeManipulated = UseCurrentState); void update(const QPointF& updatePoint, Snapper::Snapping useSnapping, State stateToBeManipulated = UseCurrentState);
void reparentTo(FormEditorItem *newParent); void reparentTo(FormEditorItem *newParent, ReparentFlag flag = DoNotEnforceReparent);
void end(); void end();
void end(Snapper::Snapping useSnapping); void end(Snapper::Snapping useSnapping);

View File

@@ -113,7 +113,7 @@ void MoveTool::mouseMoveEvent(const QList<QGraphicsItem*> &itemList,
if (m_movingItems.count() > 1 if (m_movingItems.count() > 1
|| (movingItem->qmlItemNode().canBereparentedTo(containerItem->qmlItemNode()))) || (movingItem->qmlItemNode().canBereparentedTo(containerItem->qmlItemNode())))
m_moveManipulator.reparentTo(containerItem); m_moveManipulator.reparentTo(containerItem, MoveManipulator::EnforceReparent);
} }
} }

View File

@@ -71,13 +71,6 @@ void SelectionTool::mousePressEvent(const QList<QGraphicsItem*> &itemList,
m_itemAlreadySelected = toQmlItemNodeList(view()->selectedModelNodes()).contains(formEditorItem->qmlItemNode()) m_itemAlreadySelected = toQmlItemNodeList(view()->selectedModelNodes()).contains(formEditorItem->qmlItemNode())
|| !view()->hasSingleSelectedModelNode(); || !view()->hasSingleSelectedModelNode();
if (event->modifiers().testFlag(Qt::ControlModifier))
m_singleSelectionManipulator.select(SingleSelectionManipulator::InvertSelection);
else if (event->modifiers().testFlag(Qt::ShiftModifier))
m_singleSelectionManipulator.select(SingleSelectionManipulator::InvertSelection);
else
m_singleSelectionManipulator.select(SingleSelectionManipulator::ReplaceSelection);
} else { } else {
if (event->modifiers().testFlag(Qt::AltModifier)) { if (event->modifiers().testFlag(Qt::AltModifier)) {
m_singleSelectionManipulator.begin(event->scenePos()); m_singleSelectionManipulator.begin(event->scenePos());
@@ -168,6 +161,12 @@ void SelectionTool::mouseReleaseEvent(const QList<QGraphicsItem*> &itemList,
{ {
if (event->button() == Qt::LeftButton) { if (event->button() == Qt::LeftButton) {
if (m_singleSelectionManipulator.isActive()) { if (m_singleSelectionManipulator.isActive()) {
if (event->modifiers().testFlag(Qt::ControlModifier))
m_singleSelectionManipulator.select(SingleSelectionManipulator::InvertSelection);
else if (event->modifiers().testFlag(Qt::ShiftModifier))
m_singleSelectionManipulator.select(SingleSelectionManipulator::InvertSelection);
else
m_singleSelectionManipulator.select(SingleSelectionManipulator::ReplaceSelection);
m_singleSelectionManipulator.end(event->scenePos()); m_singleSelectionManipulator.end(event->scenePos());
} else if (m_rubberbandSelectionManipulator.isActive()) { } else if (m_rubberbandSelectionManipulator.isActive()) {

View File

@@ -53,6 +53,19 @@ bool JobQueue::add(const JobRequest &job)
return false; return false;
} }
if (!m_documents.hasDocument(job.filePath, job.projectPartId)) {
qCDebug(jobsLog) << "Not adding / cancelling due to already closed document:" << job;
cancelJobRequest(job);
return false;
}
const Document document = m_documents.document(job.filePath, job.projectPartId);
if (!document.isIntact()) {
qCDebug(jobsLog) << "Not adding / cancelling due not intact document:" << job;
cancelJobRequest(job);
return false;
}
qCDebug(jobsLog) << "Adding" << job; qCDebug(jobsLog) << "Adding" << job;
m_queue.append(job); m_queue.append(job);
@@ -90,7 +103,7 @@ void JobQueue::removeExpiredRequests()
m_queue = cleanedRequests; m_queue = cleanedRequests;
} }
bool JobQueue::isJobRequestExpired(const JobRequest &jobRequest) const bool JobQueue::isJobRequestExpired(const JobRequest &jobRequest)
{ {
const JobRequest::ExpirationReasons expirationReasons = jobRequest.expirationReasons; const JobRequest::ExpirationReasons expirationReasons = jobRequest.expirationReasons;
const UnsavedFiles unsavedFiles = m_documents.unsavedFiles(); const UnsavedFiles unsavedFiles = m_documents.unsavedFiles();
@@ -120,7 +133,8 @@ bool JobQueue::isJobRequestExpired(const JobRequest &jobRequest) const
const Document document const Document document
= m_documents.document(jobRequest.filePath, jobRequest.projectPartId); = m_documents.document(jobRequest.filePath, jobRequest.projectPartId);
if (!document.isIntact()) { if (!document.isIntact()) {
qCDebug(jobsLog) << "Removing due to not intact translation unit:" << jobRequest; qCDebug(jobsLog) << "Removing/Cancelling due to not intact document:" << jobRequest;
cancelJobRequest(jobRequest);
return true; return true;
} }
@@ -174,6 +188,12 @@ void JobQueue::prioritizeRequests()
std::stable_sort(m_queue.begin(), m_queue.end(), lessThan); std::stable_sort(m_queue.begin(), m_queue.end(), lessThan);
} }
void JobQueue::cancelJobRequest(const JobRequest &jobRequest)
{
if (m_cancelJobRequest)
m_cancelJobRequest(jobRequest);
}
static bool passesPreconditions(const JobRequest &request, const Document &document) static bool passesPreconditions(const JobRequest &request, const Document &document)
{ {
using Condition = JobRequest::Condition; using Condition = JobRequest::Condition;
@@ -280,6 +300,11 @@ void JobQueue::setIsJobRunningForJobRequestHandler(
m_isJobRunningForJobRequestHandler = isJobRunningHandler; m_isJobRunningForJobRequestHandler = isJobRunningHandler;
} }
void JobQueue::setCancelJobRequest(const JobQueue::CancelJobRequest &cancelJobRequest)
{
m_cancelJobRequest = cancelJobRequest;
}
JobRequests &JobQueue::queue() JobRequests &JobQueue::queue()
{ {
return m_queue; return m_queue;

View File

@@ -51,17 +51,21 @@ public:
void setIsJobRunningForJobRequestHandler( void setIsJobRunningForJobRequestHandler(
const IsJobRunningForJobRequestHandler &isJobRunningHandler); const IsJobRunningForJobRequestHandler &isJobRunningHandler);
using CancelJobRequest = std::function<void(const JobRequest &)>;
void setCancelJobRequest(const CancelJobRequest &cancelJobRequest);
public: // for tests public: // for tests
JobRequests &queue(); JobRequests &queue();
int size() const; int size() const;
void prioritizeRequests(); void prioritizeRequests();
private: private:
void cancelJobRequest(const JobRequest &jobRequest);
bool isJobRunningForTranslationUnit(const Utf8String &translationUnitId); bool isJobRunningForTranslationUnit(const Utf8String &translationUnitId);
bool isJobRunningForJobRequest(const JobRequest &jobRequest); bool isJobRunningForJobRequest(const JobRequest &jobRequest);
JobRequests takeJobRequestsToRunNow(); JobRequests takeJobRequestsToRunNow();
void removeExpiredRequests(); void removeExpiredRequests();
bool isJobRequestExpired(const JobRequest &jobRequest) const; bool isJobRequestExpired(const JobRequest &jobRequest);
private: private:
Documents &m_documents; Documents &m_documents;
@@ -69,6 +73,7 @@ private:
IsJobRunningForTranslationUnitHandler m_isJobRunningForTranslationUnitHandler; IsJobRunningForTranslationUnitHandler m_isJobRunningForTranslationUnitHandler;
IsJobRunningForJobRequestHandler m_isJobRunningForJobRequestHandler; IsJobRunningForJobRequestHandler m_isJobRunningForJobRequestHandler;
CancelJobRequest m_cancelJobRequest;
JobRequests m_queue; JobRequests m_queue;
}; };

View File

@@ -29,6 +29,9 @@
#include "clangiasyncjob.h" #include "clangiasyncjob.h"
#include "projects.h" #include "projects.h"
#include <clangsupport/cmbcodecompletedmessage.h>
#include <clangsupport/referencesmessage.h>
#include <QDebug> #include <QDebug>
#include <QFutureSynchronizer> #include <QFutureSynchronizer>
#include <QLoggingCategory> #include <QLoggingCategory>
@@ -54,6 +57,9 @@ Jobs::Jobs(Documents &documents,
m_queue.setIsJobRunningForJobRequestHandler([this](const JobRequest &jobRequest) { m_queue.setIsJobRunningForJobRequestHandler([this](const JobRequest &jobRequest) {
return isJobRunningForJobRequest(jobRequest); return isJobRunningForJobRequest(jobRequest);
}); });
m_queue.setCancelJobRequest([this](const JobRequest &jobRequest) {
return cancelJobRequest(jobRequest);
});
} }
Jobs::~Jobs() Jobs::~Jobs()
@@ -197,4 +203,29 @@ bool Jobs::isJobRunningForJobRequest(const JobRequest &jobRequest) const
return Utils::anyOf(m_running.values(), hasJobRequest); return Utils::anyOf(m_running.values(), hasJobRequest);
} }
void Jobs::cancelJobRequest(const JobRequest &jobRequest)
{
// TODO: Consider to refactor this. Jobs should not know anything about
// concrete messages. On the other hand, having this here avoids
// duplication in multiple job classes.
// If a job request with a ticket number is cancelled, the plugin side
// must get back some results in order to clean up the state there.
switch (jobRequest.type) {
case JobRequest::Type::RequestReferences:
m_client.references(ReferencesMessage(FileContainer(),
QVector<SourceRangeContainer>(),
false,
jobRequest.ticketNumber));
break;
case JobRequest::Type::CompleteCode:
m_client.codeCompleted(CodeCompletedMessage(CodeCompletions(),
CompletionCorrection::NoCorrection,
jobRequest.ticketNumber));
break;
default:
break;
}
}
} // namespace ClangBackEnd } // namespace ClangBackEnd

View File

@@ -80,6 +80,7 @@ public /*for tests*/:
bool isJobRunningForJobRequest(const JobRequest &jobRequest) const; bool isJobRunningForJobRequest(const JobRequest &jobRequest) const;
private: private:
void cancelJobRequest(const JobRequest &jobRequest);
JobRequests runJobs(const JobRequests &jobRequest); JobRequests runJobs(const JobRequests &jobRequest);
bool runJob(const JobRequest &jobRequest); bool runJob(const JobRequest &jobRequest);
void onJobFinished(IAsyncJob *asyncJob); void onJobFinished(IAsyncJob *asyncJob);

View File

@@ -1314,7 +1314,13 @@ void tst_Dumpers::dumper()
"\n#define BREAK qtcDebugBreakFunction();" "\n#define BREAK qtcDebugBreakFunction();"
"\n\nvoid unused(const void *first,...) { (void) first; }" "\n\nvoid unused(const void *first,...) { (void) first; }"
"\n#else" "\n#else"
"\n#include <stdint.h>\n"; "\n#include <stdint.h>"
"\n#ifndef _WIN32"
"\ntypedef char CHAR;"
"\ntypedef char *PCHAR;"
"\ntypedef wchar_t WCHAR;"
"\ntypedef wchar_t *PWCHAR;"
"\n#endif\n";
if (m_debuggerEngine == LldbEngine) if (m_debuggerEngine == LldbEngine)
//#ifdef Q_OS_MAC //#ifdef Q_OS_MAC
@@ -5211,7 +5217,9 @@ void tst_Dumpers::dumper_data()
"char s[] = \"aöa\";\n" "char s[] = \"aöa\";\n"
"char t[] = \"aöax\";\n" "char t[] = \"aöax\";\n"
"wchar_t w[] = L\"aöa\";\n" "wchar_t w[] = L\"aöa\";\n"
"unused(&s, &t, &w);\n") "CHAR ch[] = \"aöa\";\n"
"WCHAR wch[] = L\"aöa\";\n"
"unused(&s, &t, &w, &ch, &wch);\n")
+ CheckType("s", "char [5]") % NoCdbEngine + CheckType("s", "char [5]") % NoCdbEngine
+ CheckType("s", "char [4]") % CdbEngine + CheckType("s", "char [4]") % CdbEngine
@@ -5219,7 +5227,12 @@ void tst_Dumpers::dumper_data()
+ CheckType("t", "char [6]") % NoCdbEngine + CheckType("t", "char [6]") % NoCdbEngine
+ CheckType("t", "char [5]") % CdbEngine + CheckType("t", "char [5]") % CdbEngine
+ Check("t.0", "[0]", "97", "char") + Check("t.0", "[0]", "97", "char")
+ CheckType("w", "wchar_t [4]"); + CheckType("w", "wchar_t [4]")
+ Check("ch.0", "[0]", "97", "CHAR")
+ CheckType("ch", "CHAR [5]") % NoCdbEngine
+ CheckType("ch", "CHAR [4]") % CdbEngine
+ Check("wch.0", "[0]", "97", "WCHAR")
+ CheckType("wch", "WCHAR [4]");
QTest::newRow("CharPointers") QTest::newRow("CharPointers")

View File

@@ -2,7 +2,7 @@ Prerequisites - general information
----------------------------------- -----------------------------------
Squish tests inside this folder have several prerequisites to get them running. Squish tests inside this folder have several prerequisites to get them running.
First - and most important - you have to own a valid Squish license. Currently it's recommended to use Squish 6.0. First - and most important - you have to own a valid Squish license. At least Squish 6.0 is required.
Second - some of the test suites/test cases expect a build of Qt 4.8.7 to be available: Second - some of the test suites/test cases expect a build of Qt 4.8.7 to be available:
1. Download the source code from: 1. Download the source code from:

View File

@@ -61,11 +61,13 @@ def __openCodeModelOptions__():
clickItem(":Options_QListView", "C++", 14, 15, 0, Qt.LeftButton) clickItem(":Options_QListView", "C++", 14, 15, 0, Qt.LeftButton)
clickOnTab(":Options.qt_tabwidget_tabbar_QTabBar", "Code Model") clickOnTab(":Options.qt_tabwidget_tabbar_QTabBar", "Code Model")
def checkCodeModelSettings(useClang): def getCodeModelString(useClang):
codeModelName = "built-in" codeModelName = "built-in"
if useClang: if useClang:
codeModelName = "Clang" codeModelName = "Clang"
test.log("Testing code model: %s" % codeModelName) return "Testing code model: %s" % codeModelName
def checkCodeModelSettings(useClang):
__openCodeModelOptions__() __openCodeModelOptions__()
test.verify(verifyChecked("{name='ignorePCHCheckBox' type='QCheckBox' visible='1'}"), test.verify(verifyChecked("{name='ignorePCHCheckBox' type='QCheckBox' visible='1'}"),
"Verifying whether 'Ignore pre-compiled headers' is checked by default.") "Verifying whether 'Ignore pre-compiled headers' is checked by default.")

View File

@@ -231,3 +231,13 @@ class Qt5Path:
path = "Docs/Qt-5.%d" % qtMinorVersion path = "Docs/Qt-5.%d" % qtMinorVersion
return os.path.join(Qt5Path.__createPlatformQtPath__(qtMinorVersion), path) return os.path.join(Qt5Path.__createPlatformQtPath__(qtMinorVersion), path)
class TestSection:
def __init__(self, description):
self.description = description
def __enter__(self):
test.startSection(self.description)
def __exit__(self, exc_type, exc_value, traceback):
test.endSection()

View File

@@ -44,89 +44,90 @@ def triggerCompletion(editorWidget):
# entry of test # entry of test
def main(): def main():
for useClang in [False, True]: for useClang in [False, True]:
if not startCreator(useClang): with TestSection(getCodeModelString(useClang)):
continue if not startCreator(useClang):
# create qt quick application continue
# create qt quick application
# Step 1: Open test .pro project. # Step 1: Open test .pro project.
createNewQtQuickApplication(tempDir(), "SampleApp") createNewQtQuickApplication(tempDir(), "SampleApp")
checkCodeModelSettings(useClang) checkCodeModelSettings(useClang)
changeAutocompleteToManual(False) changeAutocompleteToManual(False)
# Step 2: Open .cpp file in Edit mode. # Step 2: Open .cpp file in Edit mode.
if not openDocument("SampleApp.Sources.main\\.cpp"): if not openDocument("SampleApp.Sources.main\\.cpp"):
test.fatal("Could not open main.cpp") test.fatal("Could not open main.cpp")
invokeMenuItem("File", "Exit") invokeMenuItem("File", "Exit")
return return
test.verify(checkIfObjectExists(":Qt Creator_CppEditor::Internal::CPPEditorWidget"), test.verify(checkIfObjectExists(":Qt Creator_CppEditor::Internal::CPPEditorWidget"),
"Step 2: Verifying if: .cpp file is opened in Edit mode.") "Step 2: Verifying if: .cpp file is opened in Edit mode.")
# Step 3: Insert text "re" to new line in Editor mode and press Ctrl+Space. # Step 3: Insert text "re" to new line in Editor mode and press Ctrl+Space.
editorWidget = findObject(":Qt Creator_CppEditor::Internal::CPPEditorWidget") editorWidget = findObject(":Qt Creator_CppEditor::Internal::CPPEditorWidget")
if not placeCursorToLine(editorWidget, "QGuiApplication app(argc, argv);"): if not placeCursorToLine(editorWidget, "QGuiApplication app(argc, argv);"):
earlyExit("Did not find first line in function block.") earlyExit("Did not find first line in function block.")
return return
type(editorWidget, "<Return>") type(editorWidget, "<Return>")
type(editorWidget, "re") type(editorWidget, "re")
triggerCompletion(editorWidget) triggerCompletion(editorWidget)
functionName = "realpath" functionName = "realpath"
if platform.system() in ('Windows', 'Microsoft'): if platform.system() in ('Windows', 'Microsoft'):
functionName = "realloc" functionName = "realloc"
waitForObjectItem(":popupFrame_Proposal_QListView", functionName) waitForObjectItem(":popupFrame_Proposal_QListView", functionName)
doubleClickItem(":popupFrame_Proposal_QListView", functionName, 5, 5, 0, Qt.LeftButton) doubleClickItem(":popupFrame_Proposal_QListView", functionName, 5, 5, 0, Qt.LeftButton)
test.compare(str(lineUnderCursor(editorWidget)).strip(), functionName + "()", test.compare(str(lineUnderCursor(editorWidget)).strip(), functionName + "()",
"Step 3: Verifying if: The list of suggestions is opened. It is " "Step 3: Verifying if: The list of suggestions is opened. It is "
"possible to select one of the suggestions.") "possible to select one of the suggestions.")
# Step 4: Insert text "voi" to new line and press Tab. # Step 4: Insert text "voi" to new line and press Tab.
resetLine(editorWidget) resetLine(editorWidget)
type(editorWidget, "voi") type(editorWidget, "voi")
try: try:
waitForObjectItem(":popupFrame_Proposal_QListView", "void") waitForObjectItem(":popupFrame_Proposal_QListView", "void")
type(waitForObject(":popupFrame_Proposal_QListView"), "<Tab>") type(waitForObject(":popupFrame_Proposal_QListView"), "<Tab>")
test.compare(str(lineUnderCursor(editorWidget)).strip(), "void", test.compare(str(lineUnderCursor(editorWidget)).strip(), "void",
"Step 4: Verifying if: Word 'void' is completed because only one option is available.") "Step 4: Verifying if: Word 'void' is completed because only one option is available.")
except: except:
test.fail("The expected completion popup was not shown.") test.fail("The expected completion popup was not shown.")
# Step 4.5: Insert text "2." to new line and verify that code completion is not triggered (QTCREATORBUG-16188) # Step 4.5: Insert text "2." to new line and verify that code completion is not triggered (QTCREATORBUG-16188)
resetLine(editorWidget) resetLine(editorWidget)
lineWithFloat = "float fl = 2." lineWithFloat = "float fl = 2."
type(editorWidget, lineWithFloat) type(editorWidget, lineWithFloat)
try: try:
waitForObject(":popupFrame_Proposal_QListView", 5000) waitForObject(":popupFrame_Proposal_QListView", 5000)
test.fail("Typing a float value triggered code completion") test.fail("Typing a float value triggered code completion")
except: except:
test.compare(str(lineUnderCursor(editorWidget)), " " + lineWithFloat, test.compare(str(lineUnderCursor(editorWidget)), " " + lineWithFloat,
"Typing a float value does not trigger code completion") "Typing a float value does not trigger code completion")
triggerCompletion(editorWidget) triggerCompletion(editorWidget)
try: try:
waitForObject(":popupFrame_Proposal_QListView", 5000) waitForObject(":popupFrame_Proposal_QListView", 5000)
if useClang and JIRA.isBugStillOpen(16607): if useClang and JIRA.isBugStillOpen(16607):
test.xfail("User can trigger code completion manually in a float value") test.xfail("User can trigger code completion manually in a float value")
else: else:
test.fail("User can trigger code completion manually in a float value") test.fail("User can trigger code completion manually in a float value")
except: except:
test.passes("User can't trigger code completion manually in a float value") test.passes("User can't trigger code completion manually in a float value")
# Step 5: From "Tools -> Options -> Text Editor -> Completion" select Activate completion Manually, # Step 5: From "Tools -> Options -> Text Editor -> Completion" select Activate completion Manually,
# uncheck Autocomplete common prefix and press Apply and then Ok . Return to Edit mode. # uncheck Autocomplete common prefix and press Apply and then Ok . Return to Edit mode.
test.log("Step 5: Change Code Completion settings") test.log("Step 5: Change Code Completion settings")
changeAutocompleteToManual() changeAutocompleteToManual()
# Step 6: Insert text "ret" and press Ctrl+Space. # Step 6: Insert text "ret" and press Ctrl+Space.
editorWidget = waitForObject(":Qt Creator_CppEditor::Internal::CPPEditorWidget") editorWidget = waitForObject(":Qt Creator_CppEditor::Internal::CPPEditorWidget")
resetLine(editorWidget) resetLine(editorWidget)
type(editorWidget, "retu") type(editorWidget, "retu")
triggerCompletion(editorWidget) triggerCompletion(editorWidget)
try: try:
proposal = "return" proposal = "return"
if useClang: if useClang:
# clang adds a whitespace because the function needs to return a value # clang adds a whitespace because the function needs to return a value
proposal += " " proposal += " "
waitForObjectItem(":popupFrame_Proposal_QListView", proposal) waitForObjectItem(":popupFrame_Proposal_QListView", proposal)
except: except:
test.fail("Could not find proposal popup.") test.fail("Could not find proposal popup.")
type(editorWidget, "<Right>") type(editorWidget, "<Right>")
type(editorWidget, "<Backspace>") type(editorWidget, "<Backspace>")
test.compare(str(lineUnderCursor(editorWidget)).strip(), "retu", test.compare(str(lineUnderCursor(editorWidget)).strip(), "retu",
"Step 6: Verifying if: Suggestion is displayed but text is not " "Step 6: Verifying if: Suggestion is displayed but text is not "
"completed automatically even there is only one suggestion.") "completed automatically even there is only one suggestion.")
invokeMenuItem('File', 'Revert "main.cpp" to Saved') invokeMenuItem('File', 'Revert "main.cpp" to Saved')
clickButton(waitForObject(":Revert to Saved.Proceed_QPushButton")) clickButton(waitForObject(":Revert to Saved.Proceed_QPushButton"))
# exit qt creator # exit qt creator
invokeMenuItem("File", "Save All") invokeMenuItem("File", "Save All")
invokeMenuItem("File", "Exit") invokeMenuItem("File", "Exit")

View File

@@ -28,61 +28,62 @@ source("../../shared/qtcreator.py")
# entry of test # entry of test
def main(): def main():
for useClang in [False, True]: for useClang in [False, True]:
if not startCreator(useClang): with TestSection(getCodeModelString(useClang)):
continue if not startCreator(useClang):
# create qt quick application continue
# create qt quick application
# Step 1: Open test .pro project. # Step 1: Open test .pro project.
createNewQtQuickApplication(tempDir(), "SampleApp") createNewQtQuickApplication(tempDir(), "SampleApp")
checkCodeModelSettings(useClang) checkCodeModelSettings(useClang)
# Step 2: Open .cpp file in Edit mode. # Step 2: Open .cpp file in Edit mode.
if not openDocument("SampleApp.Sources.main\\.cpp"): if not openDocument("SampleApp.Sources.main\\.cpp"):
test.fatal("Could not open main.cpp") test.fatal("Could not open main.cpp")
invokeMenuItem("File", "Exit") invokeMenuItem("File", "Exit")
return return
test.verify(checkIfObjectExists(":Qt Creator_CppEditor::Internal::CPPEditorWidget"), test.verify(checkIfObjectExists(":Qt Creator_CppEditor::Internal::CPPEditorWidget"),
"Step 2: Verifying if: .cpp file is opened in Edit mode.") "Step 2: Verifying if: .cpp file is opened in Edit mode.")
# Steps 3&4: Insert text "class" to new line in Editor mode and press Ctrl+Space. # Steps 3&4: Insert text "class" to new line in Editor mode and press Ctrl+Space.
# Focus "class derived from QObject" in the list and press Tab or Enter to complete the code. # Focus "class derived from QObject" in the list and press Tab or Enter to complete the code.
editorWidget = findObject(":Qt Creator_CppEditor::Internal::CPPEditorWidget") editorWidget = findObject(":Qt Creator_CppEditor::Internal::CPPEditorWidget")
mouseClick(editorWidget, 5, 5, 0, Qt.LeftButton) mouseClick(editorWidget, 5, 5, 0, Qt.LeftButton)
type(editorWidget, "<Return>") type(editorWidget, "<Return>")
type(editorWidget, "<Up>") type(editorWidget, "<Up>")
type(editorWidget, "class") type(editorWidget, "class")
if useClang and JIRA.isBugStillOpen(18769): if useClang and JIRA.isBugStillOpen(18769):
snooze(4) snooze(4)
if platform.system() == "Darwin": if platform.system() == "Darwin":
type(editorWidget, "<Meta+Space>") type(editorWidget, "<Meta+Space>")
else: else:
type(editorWidget, "<Ctrl+Space>") type(editorWidget, "<Ctrl+Space>")
listView = waitForObject(":popupFrame_Proposal_QListView") listView = waitForObject(":popupFrame_Proposal_QListView")
shownProposals = dumpItems(listView.model()) shownProposals = dumpItems(listView.model())
usedProposal = "class derived from QObject" usedProposal = "class derived from QObject"
expectedProposals = ["class", "class ", "class template", expectedProposals = ["class", "class ", "class template",
usedProposal, "class derived from QWidget"] usedProposal, "class derived from QWidget"]
test.compare(len(shownProposals), len(expectedProposals), "Number of proposed templates") test.compare(len(shownProposals), len(expectedProposals), "Number of proposed templates")
test.compare(set(shownProposals), set(expectedProposals), test.compare(set(shownProposals), set(expectedProposals),
"Expected proposals shown, ignoring order?") "Expected proposals shown, ignoring order?")
doubleClickItem(listView, usedProposal, 5, 5, 0, Qt.LeftButton) doubleClickItem(listView, usedProposal, 5, 5, 0, Qt.LeftButton)
pattern = ("(?<=class)\s+name\s*:\s*public\s+QObject\s*\{\s*Q_OBJECT\s+" pattern = ("(?<=class)\s+name\s*:\s*public\s+QObject\s*\{\s*Q_OBJECT\s+"
"public:\s+name\(\)\s*\{\}\s+virtual\s+~name\(\)\s*\{\}\s+\};") "public:\s+name\(\)\s*\{\}\s+virtual\s+~name\(\)\s*\{\}\s+\};")
test.verify(re.search(pattern, str(editorWidget.plainText)), test.verify(re.search(pattern, str(editorWidget.plainText)),
"Code with several variables is inserted?") "Code with several variables is inserted?")
# Step 5: Press Tab to move between the variables and specify values for them. For example write "Myname" for variable "name". # Step 5: Press Tab to move between the variables and specify values for them. For example write "Myname" for variable "name".
type(editorWidget, "<Tab>") type(editorWidget, "<Tab>")
type(editorWidget, "<Tab>") type(editorWidget, "<Tab>")
type(editorWidget, "<Tab>") type(editorWidget, "<Tab>")
type(editorWidget, "Myname") type(editorWidget, "Myname")
result = re.search(pattern.replace("name", "Myname"), str(editorWidget.plainText)) result = re.search(pattern.replace("name", "Myname"), str(editorWidget.plainText))
if result: if result:
test.passes("Step 5: Verifying if: A value for a variable is inserted and all " test.passes("Step 5: Verifying if: A value for a variable is inserted and all "
"instances of the variable within the snippet are renamed.") "instances of the variable within the snippet are renamed.")
else: else:
test.fail("Step 5: Seems that not all instances of variable had been renamed " test.fail("Step 5: Seems that not all instances of variable had been renamed "
"- Content of editor:\n%s" % editorWidget.plainText) "- Content of editor:\n%s" % editorWidget.plainText)
invokeMenuItem('File', 'Revert "main.cpp" to Saved') invokeMenuItem('File', 'Revert "main.cpp" to Saved')
clickButton(waitForObject(":Revert to Saved.Proceed_QPushButton")) clickButton(waitForObject(":Revert to Saved.Proceed_QPushButton"))
snooze(1) # 'Close "main.cpp"' might still be disabled snooze(1) # 'Close "main.cpp"' might still be disabled
# editor must be closed to get the second code model applied on re-opening the file # editor must be closed to get the second code model applied on re-opening the file
invokeMenuItem('File', 'Close "main.cpp"') invokeMenuItem('File', 'Close "main.cpp"')
# exit qt creator # exit qt creator
invokeMenuItem("File", "Exit") invokeMenuItem("File", "Exit")

View File

@@ -76,44 +76,45 @@ def main():
"do while" : ["", "int dummy = 0;", "do", "++dummy;", "while (dummy < 10);"] "do while" : ["", "int dummy = 0;", "do", "++dummy;", "while (dummy < 10);"]
} }
for useClang in [False, True]: for useClang in [False, True]:
if not startCreator(useClang): with TestSection(getCodeModelString(useClang)):
continue if not startCreator(useClang):
projectName = createNewNonQtProject() continue
checkCodeModelSettings(useClang) projectName = createNewNonQtProject()
openDocument("%s.Sources.main\\.cpp" % projectName) checkCodeModelSettings(useClang)
editor = getEditorForFileSuffix("main.cpp") openDocument("%s.Sources.main\\.cpp" % projectName)
if not editor: editor = getEditorForFileSuffix("main.cpp")
test.fatal("Failed to get an editor - leaving test.") if not editor:
invokeMenuItem("File", "Exit") test.fatal("Failed to get an editor - leaving test.")
return invokeMenuItem("File", "Exit")
return
originalContent = str(editor.plainText) originalContent = str(editor.plainText)
for case, codeLines in code.items(): for case, codeLines in code.items():
funcSuffix = case.title().replace(" ", "") funcSuffix = case.title().replace(" ", "")
test.log("Testing: Extract Function for '%s'" % case) test.log("Testing: Extract Function for '%s'" % case)
if not placeCursorToLine(editor, "{"): if not placeCursorToLine(editor, "{"):
continue continue
typeLines(editor, codeLines) typeLines(editor, codeLines)
if not placeCursorToLine(editor, codeLines[2]): if not placeCursorToLine(editor, codeLines[2]):
revertMainCpp()
continue
type(editor, home)
markText(editor, "Right", 2)
snooze(1) # avoid timing issue with the parser
invokeContextMenuItem(editor, 'Refactor', 'Extract Function')
funcEdit = waitForObject("{buddy={text='Function name' type='QLabel' unnamed='1' "
"visible='1' window=%s} type='Utils::FancyLineEdit' "
"unnamed='1' visible='1'}" % inputDialog)
replaceEditorContent(funcEdit, "myFunc%s" % funcSuffix)
clickButton(waitForObject("{text='OK' type='QPushButton' unnamed='1' visible='1' window=%s}"
% inputDialog))
waitFor("'void myFunc%s' in str(editor.plainText)" % funcSuffix, 2500)
# verify the change
modifiedCode = str(editor.plainText)
expectedCode = constructExpectedCode(originalContent, codeLines, funcSuffix)
test.compare(modifiedCode, expectedCode, "Verifying whether code matches expected.")
# reverting to initial state of main.cpp
revertMainCpp() revertMainCpp()
continue snooze(1) # "Close All" might be disabled
type(editor, home) invokeMenuItem('File', 'Close All')
markText(editor, "Right", 2) invokeMenuItem('File', 'Exit')
snooze(1) # avoid timing issue with the parser
invokeContextMenuItem(editor, 'Refactor', 'Extract Function')
funcEdit = waitForObject("{buddy={text='Function name' type='QLabel' unnamed='1' "
"visible='1' window=%s} type='Utils::FancyLineEdit' "
"unnamed='1' visible='1'}" % inputDialog)
replaceEditorContent(funcEdit, "myFunc%s" % funcSuffix)
clickButton(waitForObject("{text='OK' type='QPushButton' unnamed='1' visible='1' window=%s}"
% inputDialog))
waitFor("'void myFunc%s' in str(editor.plainText)" % funcSuffix, 2500)
# verify the change
modifiedCode = str(editor.plainText)
expectedCode = constructExpectedCode(originalContent, codeLines, funcSuffix)
test.compare(modifiedCode, expectedCode, "Verifying whether code matches expected.")
# reverting to initial state of main.cpp
revertMainCpp()
snooze(1) # "Close All" might be disabled
invokeMenuItem('File', 'Close All')
invokeMenuItem('File', 'Exit')

View File

@@ -36,41 +36,42 @@ def main():
templateDir = prepareTemplate(sourceExample) templateDir = prepareTemplate(sourceExample)
examplePath = os.path.join(templateDir, proFile) examplePath = os.path.join(templateDir, proFile)
for useClang in [False, True]: for useClang in [False, True]:
if not startCreator(useClang): with TestSection(getCodeModelString(useClang)):
continue if not startCreator(useClang):
# open example project continue
openQmakeProject(examplePath) # open example project
# wait for parsing to complete openQmakeProject(examplePath)
progressBarWait(30000) # wait for parsing to complete
checkCodeModelSettings(useClang) progressBarWait(30000)
# open .cpp file in editor checkCodeModelSettings(useClang)
if not openDocument("property-animation.Sources.main\\.cpp"): # open .cpp file in editor
test.fatal("Could not open main.cpp") if not openDocument("property-animation.Sources.main\\.cpp"):
test.fatal("Could not open main.cpp")
invokeMenuItem("File", "Exit")
return
test.verify(checkIfObjectExists(":Qt Creator_CppEditor::Internal::CPPEditorWidget"),
"Verifying if: .cpp file is opened in Edit mode.")
# place cursor on line "QmlApplicationViewer viewer;"
editorWidget = findObject(":Qt Creator_CppEditor::Internal::CPPEditorWidget")
# invoke find usages from context menu on word "viewer"
if not invokeFindUsage(editorWidget, "QmlApplicationViewer viewer;", "<Left>", 10):
invokeMenuItem("File", "Exit")
return
# wait until search finished and verify search results
waitForSearchResults()
validateSearchResult(21)
result = re.search("QmlApplicationViewer", str(editorWidget.plainText))
test.verify(result, "Verifying if: The list of all usages of the selected text is displayed in Search Results. "
"File with used text is opened.")
# move cursor to the other word and test Find Usages function by pressing Ctrl+Shift+U.
openDocument("property-animation.Sources.main\\.cpp")
if not placeCursorToLine(editorWidget, "viewer.setOrientation(QmlApplicationViewer::ScreenOrientationAuto);"):
return
for i in range(4):
type(editorWidget, "<Left>")
type(editorWidget, "<Ctrl+Shift+u>")
# wait until search finished and verify search results
waitForSearchResults()
validateSearchResult(3)
invokeMenuItem("File", "Close All")
invokeMenuItem("File", "Exit") invokeMenuItem("File", "Exit")
return
test.verify(checkIfObjectExists(":Qt Creator_CppEditor::Internal::CPPEditorWidget"),
"Verifying if: .cpp file is opened in Edit mode.")
# place cursor on line "QmlApplicationViewer viewer;"
editorWidget = findObject(":Qt Creator_CppEditor::Internal::CPPEditorWidget")
# invoke find usages from context menu on word "viewer"
if not invokeFindUsage(editorWidget, "QmlApplicationViewer viewer;", "<Left>", 10):
invokeMenuItem("File", "Exit")
return
# wait until search finished and verify search results
waitForSearchResults()
validateSearchResult(21)
result = re.search("QmlApplicationViewer", str(editorWidget.plainText))
test.verify(result, "Verifying if: The list of all usages of the selected text is displayed in Search Results. "
"File with used text is opened.")
# move cursor to the other word and test Find Usages function by pressing Ctrl+Shift+U.
openDocument("property-animation.Sources.main\\.cpp")
if not placeCursorToLine(editorWidget, "viewer.setOrientation(QmlApplicationViewer::ScreenOrientationAuto);"):
return
for i in range(4):
type(editorWidget, "<Left>")
type(editorWidget, "<Ctrl+Shift+u>")
# wait until search finished and verify search results
waitForSearchResults()
validateSearchResult(3)
invokeMenuItem("File", "Close All")
invokeMenuItem("File", "Exit")

View File

@@ -36,59 +36,60 @@ def main():
templateDir = prepareTemplate(sourceExample) templateDir = prepareTemplate(sourceExample)
examplePath = os.path.join(templateDir, proFile) examplePath = os.path.join(templateDir, proFile)
for useClang in [False, True]: for useClang in [False, True]:
if not startCreator(useClang): with TestSection(getCodeModelString(useClang)):
continue if not startCreator(useClang):
# open example project continue
openQmakeProject(examplePath) # open example project
# wait for parsing to complete openQmakeProject(examplePath)
progressBarWait(30000) # wait for parsing to complete
checkCodeModelSettings(useClang) progressBarWait(30000)
# open .cpp file in editor checkCodeModelSettings(useClang)
if not openDocument("property-animation.Sources.main\\.cpp"): # open .cpp file in editor
test.fatal("Could not open main.cpp") if not openDocument("property-animation.Sources.main\\.cpp"):
invokeMenuItem("File", "Exit") test.fatal("Could not open main.cpp")
return invokeMenuItem("File", "Exit")
test.verify(checkIfObjectExists(":Qt Creator_CppEditor::Internal::CPPEditorWidget"), return
"Verifying if: .cpp file is opened in Edit mode.") test.verify(checkIfObjectExists(":Qt Creator_CppEditor::Internal::CPPEditorWidget"),
# select some word for example "viewer" and press Ctrl+F. "Verifying if: .cpp file is opened in Edit mode.")
editorWidget = findObject(":Qt Creator_CppEditor::Internal::CPPEditorWidget") # select some word for example "viewer" and press Ctrl+F.
if not placeCursorToLine(editorWidget, "QmlApplicationViewer viewer;"): editorWidget = findObject(":Qt Creator_CppEditor::Internal::CPPEditorWidget")
invokeMenuItem("File", "Exit") if not placeCursorToLine(editorWidget, "QmlApplicationViewer viewer;"):
return invokeMenuItem("File", "Exit")
type(editorWidget, "<Left>") return
markText(editorWidget, "Left", 6)
type(editorWidget, "<Ctrl+f>")
# verify if find toolbar exists and if search text contains selected word
test.verify(checkIfObjectExists(":*Qt Creator.Find_Find::Internal::FindToolBar"),
"Verifying if: Find/Replace pane is displayed at the bottom of the view.")
test.compare(waitForObject(":*Qt Creator.findEdit_Utils::FilterLineEdit").displayText, "viewer",
"Verifying if: Find line edit contains 'viewer' text.")
# insert some word to "Replace with:" field and select "Replace All".
replaceEditorContent(waitForObject(":Qt Creator.replaceEdit_Utils::FilterLineEdit"), "find")
oldCodeText = str(editorWidget.plainText)
clickButton(waitForObject(":Qt Creator.Replace All_QToolButton"))
mouseClick(waitForObject(":Qt Creator.replaceEdit_Utils::FilterLineEdit"), 5, 5, 0, Qt.LeftButton)
newCodeText = str(editorWidget.plainText)
test.compare(newCodeText, oldCodeText.replace("viewer", "find").replace("Viewer", "find"),
"Verifying if: Found text is replaced with new word properly.")
# select some other word in .cpp file and select "Edit" -> "Find/Replace".
clickButton(waitForObject(":Qt Creator.CloseFind_QToolButton"))
placeCursorToLine(editorWidget, "find.setOrientation(QmlApplicationfind::ScreenOrientationAuto);")
for i in range(25):
type(editorWidget, "<Left>") type(editorWidget, "<Left>")
markText(editorWidget, "Left", 18) markText(editorWidget, "Left", 6)
invokeMenuItem("Edit", "Find/Replace", "Find/Replace") type(editorWidget, "<Ctrl+f>")
replaceEditorContent(waitForObject(":Qt Creator.replaceEdit_Utils::FilterLineEdit"), "QmlApplicationViewer") # verify if find toolbar exists and if search text contains selected word
oldCodeText = str(editorWidget.plainText) test.verify(checkIfObjectExists(":*Qt Creator.Find_Find::Internal::FindToolBar"),
clickButton(waitForObject(":Qt Creator.Replace_QToolButton")) "Verifying if: Find/Replace pane is displayed at the bottom of the view.")
newCodeText = str(editorWidget.plainText) test.compare(waitForObject(":*Qt Creator.findEdit_Utils::FilterLineEdit").displayText, "viewer",
# "::" is used to replace only one occurrence by python "Verifying if: Find line edit contains 'viewer' text.")
test.compare(newCodeText, oldCodeText.replace("QmlApplicationfind::", "QmlApplicationViewer::"), # insert some word to "Replace with:" field and select "Replace All".
"Verifying if: Only selected word is replaced, the rest of found words are not replaced.") replaceEditorContent(waitForObject(":Qt Creator.replaceEdit_Utils::FilterLineEdit"), "find")
# close Find/Replace tab. oldCodeText = str(editorWidget.plainText)
clickButton(waitForObject(":Qt Creator.CloseFind_QToolButton")) clickButton(waitForObject(":Qt Creator.Replace All_QToolButton"))
test.verify(checkIfObjectExists(":*Qt Creator.Find_Find::Internal::FindToolBar", False), mouseClick(waitForObject(":Qt Creator.replaceEdit_Utils::FilterLineEdit"), 5, 5, 0, Qt.LeftButton)
"Verifying if: Find/Replace tab is closed.") newCodeText = str(editorWidget.plainText)
invokeMenuItem("File", "Close All") test.compare(newCodeText, oldCodeText.replace("viewer", "find").replace("Viewer", "find"),
clickButton(waitForObject(":Save Changes.Do not Save_QPushButton")) "Verifying if: Found text is replaced with new word properly.")
invokeMenuItem("File", "Exit") # select some other word in .cpp file and select "Edit" -> "Find/Replace".
clickButton(waitForObject(":Qt Creator.CloseFind_QToolButton"))
placeCursorToLine(editorWidget, "find.setOrientation(QmlApplicationfind::ScreenOrientationAuto);")
for i in range(25):
type(editorWidget, "<Left>")
markText(editorWidget, "Left", 18)
invokeMenuItem("Edit", "Find/Replace", "Find/Replace")
replaceEditorContent(waitForObject(":Qt Creator.replaceEdit_Utils::FilterLineEdit"), "QmlApplicationViewer")
oldCodeText = str(editorWidget.plainText)
clickButton(waitForObject(":Qt Creator.Replace_QToolButton"))
newCodeText = str(editorWidget.plainText)
# "::" is used to replace only one occurrence by python
test.compare(newCodeText, oldCodeText.replace("QmlApplicationfind::", "QmlApplicationViewer::"),
"Verifying if: Only selected word is replaced, the rest of found words are not replaced.")
# close Find/Replace tab.
clickButton(waitForObject(":Qt Creator.CloseFind_QToolButton"))
test.verify(checkIfObjectExists(":*Qt Creator.Find_Find::Internal::FindToolBar", False),
"Verifying if: Find/Replace tab is closed.")
invokeMenuItem("File", "Close All")
clickButton(waitForObject(":Save Changes.Do not Save_QPushButton"))
invokeMenuItem("File", "Exit")

View File

@@ -162,20 +162,21 @@ def main():
templateDir = prepareTemplate(examplePath) templateDir = prepareTemplate(examplePath)
examplePath = os.path.join(templateDir, "cplusplus-tools.pro") examplePath = os.path.join(templateDir, "cplusplus-tools.pro")
for useClang in [False, True]: for useClang in [False, True]:
if not startCreator(useClang): with TestSection(getCodeModelString(useClang)):
continue if not startCreator(useClang):
openQmakeProject(examplePath, [Targets.DESKTOP_531_DEFAULT]) continue
checkCodeModelSettings(useClang) openQmakeProject(examplePath, [Targets.DESKTOP_531_DEFAULT])
if not openDocument("cplusplus-tools.Sources.main\\.cpp"): checkCodeModelSettings(useClang)
earlyExit("Failed to open main.cpp.") if not openDocument("cplusplus-tools.Sources.main\\.cpp"):
return earlyExit("Failed to open main.cpp.")
editor = getEditorForFileSuffix("main.cpp") return
if editor: editor = getEditorForFileSuffix("main.cpp")
checkIncludeCompletion(editor, useClang) if editor:
checkSymbolCompletion(editor, useClang) checkIncludeCompletion(editor, useClang)
invokeMenuItem('File', 'Revert "main.cpp" to Saved') checkSymbolCompletion(editor, useClang)
clickButton(waitForObject(":Revert to Saved.Proceed_QPushButton")) invokeMenuItem('File', 'Revert "main.cpp" to Saved')
snooze(1) # 'Close "main.cpp"' might still be disabled clickButton(waitForObject(":Revert to Saved.Proceed_QPushButton"))
# editor must be closed to get the second code model applied on re-opening the file snooze(1) # 'Close "main.cpp"' might still be disabled
invokeMenuItem('File', 'Close "main.cpp"') # editor must be closed to get the second code model applied on re-opening the file
invokeMenuItem("File", "Exit") invokeMenuItem('File', 'Close "main.cpp"')
invokeMenuItem("File", "Exit")

View File

@@ -139,7 +139,7 @@ def main():
expect = (("QTableView", "unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'", expect = (("QTableView", "unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'",
"examples list"), "examples list"),
("QLineEdit", "placeholderText='Search in Examples...'", "examples search line edit"), ("QLineEdit", "placeholderText='Search in Examples...'", "examples search line edit"),
("QComboBox", "text~='.*Qt.*'", "Qt version combo box")) ("QComboBox", "currentText~='.*Qt.*'", "Qt version combo box"))
search = "{type='%s' %s}" search = "{type='%s' %s}"
for (qType, prop, info) in expect: for (qType, prop, info) in expect:
test.verify(checkIfObjectExists(search % (qType, prop)), test.verify(checkIfObjectExists(search % (qType, prop)),

View File

@@ -27,29 +27,30 @@ source("../../shared/qtcreator.py")
def main(): def main():
for useClang in [False, True]: for useClang in [False, True]:
if not startCreator(useClang): with TestSection(getCodeModelString(useClang)):
continue if not startCreator(useClang):
createProject_Qt_Console(tempDir(), "SquishProject") continue
checkCodeModelSettings(useClang) createProject_Qt_Console(tempDir(), "SquishProject")
selectFromLocator("main.cpp") checkCodeModelSettings(useClang)
cppwindow = waitForObject(":Qt Creator_CppEditor::Internal::CPPEditorWidget") selectFromLocator("main.cpp")
cppwindow = waitForObject(":Qt Creator_CppEditor::Internal::CPPEditorWidget")
for record in testData.dataset("usages.tsv"): for record in testData.dataset("usages.tsv"):
include = testData.field(record, "include") include = testData.field(record, "include")
if include: if include:
placeCursorToLine(cppwindow, "#include <QCoreApplication>") placeCursorToLine(cppwindow, "#include <QCoreApplication>")
typeLines(cppwindow, ("", "#include " + include)) typeLines(cppwindow, ("", "#include " + include))
placeCursorToLine(cppwindow, "return a.exec();") placeCursorToLine(cppwindow, "return a.exec();")
typeLines(cppwindow, ("<Up>", testData.field(record, "declaration"))) typeLines(cppwindow, ("<Up>", testData.field(record, "declaration")))
type(cppwindow, testData.field(record, "usage")) type(cppwindow, testData.field(record, "usage"))
snooze(1) # maybe find something better snooze(1) # maybe find something better
type(cppwindow, testData.field(record, "operator")) type(cppwindow, testData.field(record, "operator"))
waitFor("object.exists(':popupFrame_TextEditor::GenericProposalWidget')", 1500) waitFor("object.exists(':popupFrame_TextEditor::GenericProposalWidget')", 1500)
found = str(lineUnderCursor(cppwindow)).strip() found = str(lineUnderCursor(cppwindow)).strip()
exp = testData.field(record, "expected") exp = testData.field(record, "expected")
test.compare(found, exp) test.compare(found, exp)
invokeMenuItem("File", 'Revert "main.cpp" to Saved') invokeMenuItem("File", 'Revert "main.cpp" to Saved')
clickButton(waitForObject(":Revert to Saved.Proceed_QPushButton")) clickButton(waitForObject(":Revert to Saved.Proceed_QPushButton"))
snooze(1) snooze(1)
invokeMenuItem("File", "Close All") invokeMenuItem("File", "Close All")
invokeMenuItem("File", "Exit") invokeMenuItem("File", "Exit")

View File

@@ -207,5 +207,3 @@
"CMake Modules" "0" "CMake Modules" "0"
"cmake_uninstall.cmake.in" "1" "cmake_uninstall.cmake.in" "1"
"SourceFiles.cmake" "1" "SourceFiles.cmake" "1"
"resources" "1"
"speedcrunch.qrc" "2"
1 text nestinglevel
207 CMake Modules 0
208 cmake_uninstall.cmake.in 1
209 SourceFiles.cmake 1
resources 1
speedcrunch.qrc 2

View File

@@ -1,10 +1,12 @@
"language" "File" "Exit" "ISO" "language" "File" "Exit" "ISO"
"Czech (CzechRepublic)" "Soubor" "Ukončit" "cs_CZ" "Czech (CzechRepublic)" "Soubor" "Ukončit" "cs_CZ"
"Danish (Denmark)" "Fil" "Afslut" "da_DK"
"German (Germany)" "Datei" "Beenden" "de_DE" "German (Germany)" "Datei" "Beenden" "de_DE"
"French (France)" "Fichier" "Quitter" "fr_FR" "French (France)" "Fichier" "Quitter" "fr_FR"
"Japanese (Japan)" "ファイル(F)" "終了(X)" "ja_JP" "Japanese (Japan)" "ファイル(F)" "終了(X)" "ja_JP"
"Polish (Poland)" "Plik" "Zakończ" "pl_PL" "Polish (Poland)" "Plik" "Zakończ" "pl_PL"
"Russian (%1)" "Файл" "Выход" "ru_RU" "Russian (%1)" "Файл" "Выход" "ru_RU"
"Slovenian (Slovenia)" "Datoteka" "Končaj" "sl_SL" "Slovenian (Slovenia)" "Datoteka" "Končaj" "sl_SL"
"Ukrainian (Ukraine)" "Файл" "Вийти" "uk_UA"
"Chinese (China)" "文件(F)" "退出(X)" "zh_CN" "Chinese (China)" "文件(F)" "退出(X)" "zh_CN"
"Chinese (Taiwan)" "檔案(F)" "離開(X)" "zh_TW" "Chinese (Taiwan)" "檔案(F)" "離開(X)" "zh_TW"
1 language File Exit ISO
2 Czech (CzechRepublic) Soubor Ukončit cs_CZ
3 Danish (Denmark) Fil Afslut da_DK
4 German (Germany) Datei Beenden de_DE
5 French (France) Fichier Quitter fr_FR
6 Japanese (Japan) ファイル(F) 終了(X) ja_JP
7 Polish (Poland) Plik Zakończ pl_PL
8 Russian (%1) Файл Выход ru_RU
9 Slovenian (Slovenia) Datoteka Končaj sl_SL
10 Ukrainian (Ukraine) Файл Вийти uk_UA
11 Chinese (China) 文件(F) 退出(X) zh_CN
12 Chinese (Taiwan) 檔案(F) 離開(X) zh_TW

View File

@@ -118,6 +118,41 @@ TEST_F(JobQueue, DoNotAddDuplicateForWhichAJobIsAlreadyRunning)
ASSERT_FALSE(added); ASSERT_FALSE(added);
} }
TEST_F(JobQueue, DoNotAddForNotExistingDocument)
{
jobQueue.setCancelJobRequest([](const JobRequest &) {
return true;
});
const bool added = jobQueue.add(createJobRequest(Utf8StringLiteral("notExistingDocument.cpp"),
JobRequest::Type::UpdateDocumentAnnotations));
ASSERT_FALSE(added);
}
TEST_F(JobQueue, DoNotAddForNotIntactDocument)
{
document.setHasParseOrReparseFailed(true);
const bool added = jobQueue.add(createJobRequest(filePath1,
JobRequest::Type::UpdateDocumentAnnotations));
ASSERT_FALSE(added);
}
TEST_F(JobQueue, CancelDuringAddForNotIntactDocument)
{
document.setHasParseOrReparseFailed(true);
bool canceled = false;
jobQueue.setCancelJobRequest([&canceled](const JobRequest &) {
canceled = true;
});
jobQueue.add(createJobRequest(filePath1, JobRequest::Type::UpdateDocumentAnnotations));
ASSERT_TRUE(canceled);
}
TEST_F(JobQueue, ProcessEmpty) TEST_F(JobQueue, ProcessEmpty)
{ {
jobQueue.processQueue(); jobQueue.processQueue();
@@ -218,6 +253,20 @@ TEST_F(JobQueue, RemoveRequestsForNotIntactDocuments)
ASSERT_THAT(jobsToRun.size(), Eq(0)); ASSERT_THAT(jobsToRun.size(), Eq(0));
} }
TEST_F(JobQueue, CancelRequestsForNotIntactDocuments)
{
jobQueue.add(createJobRequest(filePath1, JobRequest::Type::UpdateDocumentAnnotations));
document.setHasParseOrReparseFailed(true);
bool canceled = false;
jobQueue.setCancelJobRequest([&canceled](const JobRequest &) {
canceled = true;
});
jobQueue.processQueue();
ASSERT_TRUE(canceled);
}
TEST_F(JobQueue, PrioritizeCurrentDocumentOverNotCurrent) TEST_F(JobQueue, PrioritizeCurrentDocumentOverNotCurrent)
{ {
resetVisibilityAndCurrentEditor(); resetVisibilityAndCurrentEditor();