forked from qt-creator/qt-creator
Merge remote-tracking branch 'origin/14.0'
Change-Id: I5cdfedcbdde6bb526ee02007a3dbc136c7d61353
This commit is contained in:
@@ -7,6 +7,7 @@ import sys
|
||||
import cdbext
|
||||
import re
|
||||
import threading
|
||||
import time
|
||||
from utils import TypeCode
|
||||
|
||||
sys.path.insert(1, os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))))
|
||||
@@ -421,6 +422,7 @@ class Dumper(DumperBase):
|
||||
return ptr
|
||||
|
||||
def fetchVariables(self, args):
|
||||
start_time = time.perf_counter()
|
||||
self.resetStats()
|
||||
(ok, res) = self.tryFetchInterpreterVariables(args)
|
||||
if ok:
|
||||
@@ -458,6 +460,8 @@ class Dumper(DumperBase):
|
||||
self.put(',qtnamespace="%s"' % self.qtNamespaceToReport)
|
||||
self.qtNamespaceToReport = None
|
||||
|
||||
runtime = time.perf_counter() - start_time
|
||||
self.put(',runtime="%s"' % runtime)
|
||||
self.reportResult(''.join(self.output), args)
|
||||
self.output = []
|
||||
|
||||
|
@@ -6,8 +6,6 @@
|
||||
#include <QString>
|
||||
#include <QCryptographicHash>
|
||||
|
||||
#include <limits>
|
||||
|
||||
namespace LanguageUtils {
|
||||
|
||||
// QTC_TEMP
|
||||
@@ -42,8 +40,8 @@ QString ComponentVersion::toString() const
|
||||
|
||||
void ComponentVersion::addToHash(QCryptographicHash &hash) const
|
||||
{
|
||||
hash.addData(reinterpret_cast<const char *>(&_major), sizeof(_major));
|
||||
hash.addData(reinterpret_cast<const char *>(&_minor), sizeof(_minor));
|
||||
hash.addData(QByteArrayView(reinterpret_cast<const char *>(&_major), sizeof(_major)));
|
||||
hash.addData(QByteArrayView(reinterpret_cast<const char *>(&_minor), sizeof(_minor)));
|
||||
}
|
||||
|
||||
} // namespace LanguageUtils
|
||||
|
@@ -6,6 +6,21 @@
|
||||
|
||||
using namespace LanguageUtils;
|
||||
|
||||
static QByteArrayView asData(const void *mem, size_t len)
|
||||
{
|
||||
return QByteArrayView(reinterpret_cast<const char *>(mem), len);
|
||||
}
|
||||
|
||||
static void addData(QCryptographicHash &hash, int x)
|
||||
{
|
||||
hash.addData(asData(&x, sizeof(int)));
|
||||
}
|
||||
|
||||
static void addData(QCryptographicHash &hash, const QString &x)
|
||||
{
|
||||
hash.addData(asData(x.constData(), x.size() * sizeof(QChar)));
|
||||
}
|
||||
|
||||
FakeMetaEnum::FakeMetaEnum()
|
||||
{}
|
||||
|
||||
@@ -39,15 +54,12 @@ bool FakeMetaEnum::hasKey(const QString &key) const
|
||||
|
||||
void FakeMetaEnum::addToHash(QCryptographicHash &hash) const
|
||||
{
|
||||
int len = m_name.size();
|
||||
hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
|
||||
hash.addData(reinterpret_cast<const char *>(m_name.constData()), len * sizeof(QChar));
|
||||
len = m_keys.size();
|
||||
hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
|
||||
addData(hash, m_name.size());
|
||||
addData(hash, m_name);
|
||||
addData(hash, m_keys.size());
|
||||
for (const QString &key : std::as_const(m_keys)) {
|
||||
len = key.size();
|
||||
hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
|
||||
hash.addData(reinterpret_cast<const char *>(key.constData()), len * sizeof(QChar));
|
||||
addData(hash, key.size());
|
||||
addData(hash, key);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -121,29 +133,23 @@ void FakeMetaMethod::setRevision(int r)
|
||||
|
||||
void FakeMetaMethod::addToHash(QCryptographicHash &hash) const
|
||||
{
|
||||
int len = m_name.size();
|
||||
hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
|
||||
hash.addData(reinterpret_cast<const char *>(m_name.constData()), len * sizeof(QChar));
|
||||
hash.addData(reinterpret_cast<const char *>(&m_methodAccess), sizeof(m_methodAccess));
|
||||
hash.addData(reinterpret_cast<const char *>(&m_methodTy), sizeof(m_methodTy));
|
||||
hash.addData(reinterpret_cast<const char *>(&m_revision), sizeof(m_revision));
|
||||
len = m_paramNames.size();
|
||||
hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
|
||||
addData(hash, m_name.size());
|
||||
addData(hash, m_name);
|
||||
addData(hash, m_methodAccess);
|
||||
addData(hash, m_methodTy);
|
||||
addData(hash, m_revision);
|
||||
addData(hash, m_paramNames.size());
|
||||
for (const QString &pName : std::as_const(m_paramNames)) {
|
||||
len = pName.size();
|
||||
hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
|
||||
hash.addData(reinterpret_cast<const char *>(pName.constData()), len * sizeof(QChar));
|
||||
addData(hash, pName.size());
|
||||
addData(hash, pName);
|
||||
}
|
||||
len = m_paramTypes.size();
|
||||
hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
|
||||
addData(hash, m_paramTypes.size());
|
||||
for (const QString &pType : std::as_const(m_paramTypes)) {
|
||||
len = pType.size();
|
||||
hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
|
||||
hash.addData(reinterpret_cast<const char *>(pType.constData()), len * sizeof(QChar));
|
||||
addData(hash, pType.size());
|
||||
addData(hash, pType);
|
||||
}
|
||||
len = m_returnType.size();
|
||||
hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
|
||||
hash.addData(reinterpret_cast<const char *>(m_returnType.constData()), len * sizeof(QChar));
|
||||
addData(hash, m_returnType.size());
|
||||
addData(hash, m_returnType);
|
||||
}
|
||||
|
||||
QString FakeMetaMethod::describe(int baseIndent) const
|
||||
@@ -213,17 +219,15 @@ int FakeMetaProperty::revision() const
|
||||
|
||||
void FakeMetaProperty::addToHash(QCryptographicHash &hash) const
|
||||
{
|
||||
int len = m_propertyName.size();
|
||||
hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
|
||||
hash.addData(reinterpret_cast<const char *>(m_propertyName.constData()), len * sizeof(QChar));
|
||||
hash.addData(reinterpret_cast<const char *>(&m_revision), sizeof(m_revision));
|
||||
addData(hash, m_propertyName.size());
|
||||
addData(hash, m_propertyName);
|
||||
addData(hash, m_revision);
|
||||
int flags = (m_isList ? (1 << 0) : 0)
|
||||
+ (m_isPointer ? (1 << 1) : 0)
|
||||
+ (m_isWritable ? (1 << 2) : 0);
|
||||
hash.addData(reinterpret_cast<const char *>(&flags), sizeof(flags));
|
||||
len = m_type.size();
|
||||
hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
|
||||
hash.addData(reinterpret_cast<const char *>(m_type.constData()), len * sizeof(QChar));
|
||||
addData(hash, flags);
|
||||
addData(hash, m_type.size());
|
||||
addData(hash, m_type);
|
||||
}
|
||||
|
||||
QString FakeMetaProperty::describe(int baseIndent) const
|
||||
@@ -361,34 +365,34 @@ QByteArray FakeMetaObject::calculateFingerprint() const
|
||||
{
|
||||
QCryptographicHash hash(QCryptographicHash::Sha1);
|
||||
int len = m_className.size();
|
||||
hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
|
||||
hash.addData(reinterpret_cast<const char *>(m_className.constData()), len * sizeof(QChar));
|
||||
addData(hash, len);
|
||||
addData(hash, m_className);
|
||||
len = m_attachedTypeName.size();
|
||||
hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
|
||||
hash.addData(reinterpret_cast<const char *>(m_attachedTypeName.constData()), len * sizeof(QChar));
|
||||
addData(hash, len);
|
||||
addData(hash, m_attachedTypeName);
|
||||
len = m_defaultPropertyName.size();
|
||||
hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
|
||||
hash.addData(reinterpret_cast<const char *>(m_defaultPropertyName.constData()), len * sizeof(QChar));
|
||||
addData(hash, len);
|
||||
addData(hash, m_defaultPropertyName);
|
||||
len = m_enumNameToIndex.size();
|
||||
hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
|
||||
addData(hash, len);
|
||||
{
|
||||
QStringList keys(m_enumNameToIndex.keys());
|
||||
keys.sort();
|
||||
for (const QString &key : std::as_const(keys)) {
|
||||
len = key.size();
|
||||
hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
|
||||
hash.addData(reinterpret_cast<const char *>(key.constData()), len * sizeof(QChar));
|
||||
addData(hash, len);
|
||||
addData(hash, key);
|
||||
int value = m_enumNameToIndex.value(key);
|
||||
hash.addData(reinterpret_cast<const char *>(&value), sizeof(value)); // avoid? this adds order dependency to fingerprint...
|
||||
addData(hash, value);
|
||||
m_enums.at(value).addToHash(hash);
|
||||
}
|
||||
}
|
||||
len = m_exports.size();
|
||||
hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
|
||||
addData(hash, len);
|
||||
for (const Export &e : std::as_const(m_exports))
|
||||
e.addToHash(hash); // normalize order?
|
||||
len = m_exports.size();
|
||||
hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
|
||||
addData(hash, len);
|
||||
for (const FakeMetaMethod &m : std::as_const(m_methods))
|
||||
m.addToHash(hash); // normalize order?
|
||||
{
|
||||
@@ -396,16 +400,16 @@ QByteArray FakeMetaObject::calculateFingerprint() const
|
||||
keys.sort();
|
||||
for (const QString &key : std::as_const(keys)) {
|
||||
len = key.size();
|
||||
hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
|
||||
hash.addData(reinterpret_cast<const char *>(key.constData()), len * sizeof(QChar));
|
||||
addData(hash, len);
|
||||
addData(hash, key);
|
||||
int value = m_propNameToIdx.value(key);
|
||||
hash.addData(reinterpret_cast<const char *>(&value), sizeof(value)); // avoid? this adds order dependency to fingerprint...
|
||||
addData(hash, value);
|
||||
m_props.at(value).addToHash(hash);
|
||||
}
|
||||
}
|
||||
len = m_superName.size();
|
||||
hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
|
||||
hash.addData(reinterpret_cast<const char *>(m_superName.constData()), len * sizeof(QChar));
|
||||
addData(hash, len);
|
||||
addData(hash, m_superName);
|
||||
|
||||
QByteArray res = hash.result();
|
||||
res.append('F');
|
||||
@@ -540,14 +544,12 @@ bool FakeMetaObject::Export::isValid() const
|
||||
|
||||
void FakeMetaObject::Export::addToHash(QCryptographicHash &hash) const
|
||||
{
|
||||
int len = package.size();
|
||||
hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
|
||||
hash.addData(reinterpret_cast<const char *>(package.constData()), len * sizeof(QChar));
|
||||
len = type.size();
|
||||
hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
|
||||
hash.addData(reinterpret_cast<const char *>(type.constData()), len * sizeof(QChar));
|
||||
addData(hash, package.size());
|
||||
addData(hash, package);
|
||||
addData(hash, type.size());
|
||||
addData(hash, type);
|
||||
version.addToHash(hash);
|
||||
hash.addData(reinterpret_cast<const char *>(&metaObjectRevision), sizeof(metaObjectRevision));
|
||||
addData(hash, metaObjectRevision);
|
||||
}
|
||||
|
||||
QString FakeMetaObject::Export::describe(int baseIndent) const
|
||||
|
@@ -185,14 +185,14 @@ ImportKey::ImportKey(ImportType::Enum type, const QString &path, int majorVersio
|
||||
|
||||
void ImportKey::addToHash(QCryptographicHash &hash) const
|
||||
{
|
||||
hash.addData(reinterpret_cast<const char *>(&type), sizeof(type));
|
||||
hash.addData(reinterpret_cast<const char *>(&majorVersion), sizeof(majorVersion));
|
||||
hash.addData(reinterpret_cast<const char *>(&minorVersion), sizeof(minorVersion));
|
||||
hash.addData(QByteArrayView(reinterpret_cast<const char *>(&type), sizeof(type)));
|
||||
hash.addData(QByteArrayView(reinterpret_cast<const char *>(&majorVersion), sizeof(majorVersion)));
|
||||
hash.addData(QByteArrayView(reinterpret_cast<const char *>(&minorVersion), sizeof(minorVersion)));
|
||||
for (const QString &s : splitPath) {
|
||||
hash.addData("/", 1);
|
||||
hash.addData(reinterpret_cast<const char *>(s.constData()), sizeof(QChar) * s.size());
|
||||
hash.addData("/");
|
||||
hash.addData(QByteArrayView(reinterpret_cast<const char *>(s.constData()), sizeof(QChar) * s.size()));
|
||||
}
|
||||
hash.addData("/", 1);
|
||||
hash.addData("/");
|
||||
}
|
||||
|
||||
ImportKey ImportKey::flatKey() const {
|
||||
@@ -547,11 +547,11 @@ QByteArray DependencyInfo::calculateFingerprint(const ImportDependencies &deps)
|
||||
QStringList coreImports = Utils::toList(allCoreImports);
|
||||
coreImports.sort();
|
||||
for (const QString &importId : std::as_const(coreImports)) {
|
||||
hash.addData(reinterpret_cast<const char*>(importId.constData()), importId.size() * sizeof(QChar));
|
||||
hash.addData(QByteArrayView(reinterpret_cast<const char*>(importId.constData()), importId.size() * sizeof(QChar)));
|
||||
QByteArray coreImportFingerprint = deps.coreImport(importId).fingerprint;
|
||||
hash.addData(coreImportFingerprint);
|
||||
}
|
||||
hash.addData("/", 1);
|
||||
hash.addData("/");
|
||||
QList<ImportKey> imports = Utils::toList(allImports);
|
||||
std::sort(imports.begin(), imports.end());
|
||||
for (const ImportKey &k : std::as_const(imports))
|
||||
|
@@ -2681,22 +2681,26 @@ void StringListAspect::addToLayout(Layout &parent)
|
||||
}
|
||||
};
|
||||
|
||||
connect(add, &QPushButton::clicked, this, [this, populate, editor] {
|
||||
d->undoable.setSilently(d->undoable.get() << "");
|
||||
populate();
|
||||
const QTreeWidgetItem *root = editor->invisibleRootItem();
|
||||
QTreeWidgetItem *lastChild = root->child(root->childCount() - 1);
|
||||
const QModelIndex index = editor->indexFromItem(lastChild, 0);
|
||||
editor->edit(index);
|
||||
});
|
||||
if (add) {
|
||||
connect(add, &QPushButton::clicked, this, [this, populate, editor] {
|
||||
d->undoable.setSilently(d->undoable.get() << "");
|
||||
populate();
|
||||
const QTreeWidgetItem *root = editor->invisibleRootItem();
|
||||
QTreeWidgetItem *lastChild = root->child(root->childCount() - 1);
|
||||
const QModelIndex index = editor->indexFromItem(lastChild, 0);
|
||||
editor->edit(index);
|
||||
});
|
||||
}
|
||||
|
||||
connect(remove, &QPushButton::clicked, this, [this, editor, itemsToStringList] {
|
||||
const QList<QTreeWidgetItem *> selected = editor->selectedItems();
|
||||
QTC_ASSERT(selected.size() == 1, return);
|
||||
editor->invisibleRootItem()->removeChild(selected.first());
|
||||
delete selected.first();
|
||||
d->undoable.set(undoStack(), itemsToStringList());
|
||||
});
|
||||
if (remove) {
|
||||
connect(remove, &QPushButton::clicked, this, [this, editor, itemsToStringList] {
|
||||
const QList<QTreeWidgetItem *> selected = editor->selectedItems();
|
||||
QTC_ASSERT(selected.size() == 1, return);
|
||||
editor->invisibleRootItem()->removeChild(selected.first());
|
||||
delete selected.first();
|
||||
d->undoable.set(undoStack(), itemsToStringList());
|
||||
});
|
||||
}
|
||||
|
||||
connect(
|
||||
&d->undoable.m_signal, &UndoSignaller::changed, editor, [this, populate, itemsToStringList] {
|
||||
|
@@ -763,6 +763,31 @@ void Label::setText(const QString &text)
|
||||
access(this)->setText(text);
|
||||
}
|
||||
|
||||
void Label::setTextFormat(Qt::TextFormat format)
|
||||
{
|
||||
access(this)->setTextFormat(format);
|
||||
}
|
||||
|
||||
void Label::setWordWrap(bool on)
|
||||
{
|
||||
access(this)->setWordWrap(on);
|
||||
}
|
||||
|
||||
void Label::setTextInteractionFlags(Qt::TextInteractionFlags flags)
|
||||
{
|
||||
access(this)->setTextInteractionFlags(flags);
|
||||
}
|
||||
|
||||
void Label::setOpenExternalLinks(bool on)
|
||||
{
|
||||
access(this)->setOpenExternalLinks(on);
|
||||
}
|
||||
|
||||
void Label::onLinkHovered(const std::function<void (const QString &)> &func, QObject *guard)
|
||||
{
|
||||
QObject::connect(access(this), &QLabel::linkHovered, guard, func);
|
||||
}
|
||||
|
||||
// Group
|
||||
|
||||
Group::Group(std::initializer_list<I> ps)
|
||||
|
@@ -279,6 +279,11 @@ public:
|
||||
Label(const QString &text);
|
||||
|
||||
void setText(const QString &);
|
||||
void setTextFormat(Qt::TextFormat);
|
||||
void setWordWrap(bool);
|
||||
void setTextInteractionFlags(Qt::TextInteractionFlags);
|
||||
void setOpenExternalLinks(bool);
|
||||
void onLinkHovered(const std::function<void(const QString &)> &, QObject *guard);
|
||||
};
|
||||
|
||||
class QTCREATOR_UTILS_EXPORT Group : public Widget
|
||||
@@ -446,6 +451,26 @@ class TitleId {};
|
||||
auto title(auto p) { return IdAndArg{TitleId{}, p}; }
|
||||
void doit(auto x, TitleId, auto p) { x->setTitle(p); }
|
||||
|
||||
class TextFormatId {};
|
||||
auto textFormat(auto p) { return IdAndArg{TextFormatId{}, p}; }
|
||||
void doit(auto x, TextFormatId, auto p) { x->setTextFormat(p); }
|
||||
|
||||
class WordWrapId {};
|
||||
auto wordWrap(auto p) { return IdAndArg{WordWrapId{}, p}; }
|
||||
void doit(auto x, WordWrapId, auto p) { x->setWordWrap(p); }
|
||||
|
||||
class TextInteractionFlagId {};
|
||||
auto textInteractionFlags(auto p) { return IdAndArg{TextInteractionFlagId{}, p}; }
|
||||
void doit(auto x, TextInteractionFlagId, auto p) { x->setTextInteractionFlags(p); }
|
||||
|
||||
class OpenExternalLinksId {};
|
||||
auto openExternalLinks(auto p) { return IdAndArg{OpenExternalLinksId{}, p}; }
|
||||
void doit(auto x, OpenExternalLinksId, auto p) { x->setOpenExternalLinks(p); }
|
||||
|
||||
class OnLinkHoveredId {};
|
||||
auto onLinkHovered(auto p, QObject *guard) { return IdAndArg{OnLinkHoveredId{}, std::pair{p, guard}}; }
|
||||
void doit(auto x, OnLinkHoveredId, auto p) { x->onLinkHovered(p.first, p.second); }
|
||||
|
||||
class GroupCheckerId {};
|
||||
auto groupChecker(auto p) { return IdAndArg{GroupCheckerId{}, p}; }
|
||||
void doit(auto x, GroupCheckerId, auto p) { x->setGroupChecker(p); }
|
||||
|
@@ -58,7 +58,7 @@ Link OutputLineParser::parseLinkTarget(const QString &target)
|
||||
return {};
|
||||
return Link(FilePath::fromString(parts.first()),
|
||||
parts.length() > 1 ? parts.at(1).toInt() : 0,
|
||||
parts.length() > 2 ? parts.at(2).toInt() : 0);
|
||||
parts.length() > 2 ? parts.at(2).toInt() - 1 : 0);
|
||||
}
|
||||
|
||||
// The redirection mechanism is needed for broken build tools (e.g. xcodebuild) that get invoked
|
||||
@@ -141,26 +141,39 @@ FilePath OutputLineParser::absoluteFilePath(const FilePath &filePath) const
|
||||
return filePath;
|
||||
}
|
||||
|
||||
void OutputLineParser::addLinkSpecForAbsoluteFilePath(OutputLineParser::LinkSpecs &linkSpecs,
|
||||
const FilePath &filePath, int lineNo, int pos, int len)
|
||||
void OutputLineParser::addLinkSpecForAbsoluteFilePath(
|
||||
OutputLineParser::LinkSpecs &linkSpecs,
|
||||
const FilePath &filePath,
|
||||
int lineNo,
|
||||
int column,
|
||||
int pos,
|
||||
int len)
|
||||
{
|
||||
if (filePath.toFileInfo().isAbsolute())
|
||||
linkSpecs.append({pos, len, createLinkTarget(filePath, lineNo)});
|
||||
linkSpecs.append({pos, len, createLinkTarget(filePath, lineNo, column)});
|
||||
}
|
||||
|
||||
void OutputLineParser::addLinkSpecForAbsoluteFilePath(OutputLineParser::LinkSpecs &linkSpecs,
|
||||
const FilePath &filePath, int lineNo, const QRegularExpressionMatch &match,
|
||||
int capIndex)
|
||||
void OutputLineParser::addLinkSpecForAbsoluteFilePath(
|
||||
OutputLineParser::LinkSpecs &linkSpecs,
|
||||
const FilePath &filePath,
|
||||
int lineNo,
|
||||
int column,
|
||||
const QRegularExpressionMatch &match,
|
||||
int capIndex)
|
||||
{
|
||||
addLinkSpecForAbsoluteFilePath(linkSpecs, filePath, lineNo, match.capturedStart(capIndex),
|
||||
match.capturedLength(capIndex));
|
||||
addLinkSpecForAbsoluteFilePath(linkSpecs, filePath, lineNo, column,
|
||||
match.capturedStart(capIndex), match.capturedLength(capIndex));
|
||||
}
|
||||
void OutputLineParser::addLinkSpecForAbsoluteFilePath(OutputLineParser::LinkSpecs &linkSpecs,
|
||||
const FilePath &filePath, int lineNo, const QRegularExpressionMatch &match,
|
||||
const QString &capName)
|
||||
void OutputLineParser::addLinkSpecForAbsoluteFilePath(
|
||||
OutputLineParser::LinkSpecs &linkSpecs,
|
||||
const FilePath &filePath,
|
||||
int lineNo,
|
||||
int column,
|
||||
const QRegularExpressionMatch &match,
|
||||
const QString &capName)
|
||||
{
|
||||
addLinkSpecForAbsoluteFilePath(linkSpecs, filePath, lineNo, match.capturedStart(capName),
|
||||
match.capturedLength(capName));
|
||||
addLinkSpecForAbsoluteFilePath(linkSpecs, filePath, lineNo, column,
|
||||
match.capturedStart(capName), match.capturedLength(capName));
|
||||
}
|
||||
|
||||
bool Utils::OutputLineParser::fileExists(const FilePath &fp) const
|
||||
|
@@ -93,12 +93,13 @@ protected:
|
||||
Utils::FilePath absoluteFilePath(const Utils::FilePath &filePath) const;
|
||||
static QString createLinkTarget(const FilePath &filePath, int line, int column);
|
||||
static void addLinkSpecForAbsoluteFilePath(LinkSpecs &linkSpecs, const FilePath &filePath,
|
||||
int lineNo, int pos, int len);
|
||||
int lineNo, int column, int pos, int len);
|
||||
static void addLinkSpecForAbsoluteFilePath(LinkSpecs &linkSpecs, const FilePath &filePath,
|
||||
int lineNo, const QRegularExpressionMatch &match,
|
||||
int capIndex);
|
||||
int lineNo, int column,
|
||||
const QRegularExpressionMatch &match, int capIndex);
|
||||
static void addLinkSpecForAbsoluteFilePath(LinkSpecs &linkSpecs, const FilePath &filePath,
|
||||
int lineNo, const QRegularExpressionMatch &match,
|
||||
int lineNo, int column,
|
||||
const QRegularExpressionMatch &match,
|
||||
const QString &capName);
|
||||
bool fileExists(const Utils::FilePath &fp) const;
|
||||
|
||||
|
@@ -43,6 +43,7 @@ static const QList<Tool> &sTools()
|
||||
{
|
||||
static QList<Tool> tools;
|
||||
if (tools.isEmpty()) {
|
||||
// clang-format off
|
||||
if (HostOsInfo::isWindowsHost()) {
|
||||
tools << Tool{{"powershell", "-command Expand-Archive -Force '%{src}' '%{dest}'", CommandLine::Raw},
|
||||
{"application/zip"},
|
||||
@@ -74,6 +75,10 @@ static const QList<Tool> &sTools()
|
||||
tools << Tool{{"cmake", {"-E", "tar", "xvjf", "%{src}"}},
|
||||
{"application/x-bzip-compressed-tar"},
|
||||
additionalCMakeDirs};
|
||||
// Keep this at the end so its only used as last resort. Otherwise it might be used for
|
||||
// .tar.gz files.
|
||||
tools << Tool{{"gzip", {"-d", "%{src}", "-c"}}, {"application/gzip"}, {}};
|
||||
// clang-format on
|
||||
}
|
||||
return tools;
|
||||
}
|
||||
@@ -147,6 +152,45 @@ void Unarchiver::start()
|
||||
m_sourceAndCommand->m_sourceFile, m_destDir);
|
||||
m_destDir.ensureWritableDir();
|
||||
|
||||
if (command.executable().fileName() == "gzip") {
|
||||
std::shared_ptr<QFile> outputFile = std::make_shared<QFile>(
|
||||
(m_destDir / m_gzipFileDestName).toFSPathString());
|
||||
|
||||
if (!outputFile->open(QIODevice::WriteOnly)) {
|
||||
emit outputReceived(Tr::tr("Failed to open output file."));
|
||||
emit done(DoneResult::Error);
|
||||
return;
|
||||
}
|
||||
|
||||
m_process.reset(new Process);
|
||||
QObject::connect(m_process.get(), &Process::readyReadStandardOutput, this, [this, outputFile] {
|
||||
const QByteArray data = m_process->readAllRawStandardOutput();
|
||||
if (outputFile->write(data) != data.size()) {
|
||||
emit outputReceived(Tr::tr("Failed to write output file."));
|
||||
emit done(DoneResult::Error);
|
||||
}
|
||||
});
|
||||
QObject::connect(m_process.get(), &Process::readyReadStandardError, this, [this] {
|
||||
emit outputReceived(m_process->readAllStandardError());
|
||||
});
|
||||
QObject::connect(m_process.get(), &Process::done, this, [outputFile, this] {
|
||||
outputFile->close();
|
||||
const bool success = m_process->result() == ProcessResult::FinishedWithSuccess;
|
||||
if (!success) {
|
||||
outputFile->remove();
|
||||
emit outputReceived(Tr::tr("Command failed."));
|
||||
}
|
||||
emit done(toDoneResult(success));
|
||||
});
|
||||
emit outputReceived(
|
||||
Tr::tr("Running %1\nin \"%2\".\n\n", "Running <cmd> in <workingdirectory>")
|
||||
.arg(command.toUserOutput(), m_destDir.toUserOutput()));
|
||||
m_process->setCommand(command);
|
||||
m_process->setWorkingDirectory(m_destDir);
|
||||
m_process->start();
|
||||
return;
|
||||
}
|
||||
|
||||
m_process.reset(new Process);
|
||||
m_process->setProcessChannelMode(QProcess::MergedChannels);
|
||||
QObject::connect(m_process.get(), &Process::readyReadStandardOutput, this, [this] {
|
||||
|
@@ -32,7 +32,10 @@ public:
|
||||
|
||||
void setSourceAndCommand(const SourceAndCommand &data) { m_sourceAndCommand = data; }
|
||||
void setDestDir(const FilePath &destDir) { m_destDir = destDir; }
|
||||
|
||||
void setGZipFileDestName(const QString &gzipFileDestName)
|
||||
{
|
||||
m_gzipFileDestName = gzipFileDestName;
|
||||
}
|
||||
void start();
|
||||
|
||||
signals:
|
||||
@@ -43,6 +46,7 @@ private:
|
||||
std::optional<SourceAndCommand> m_sourceAndCommand;
|
||||
FilePath m_destDir;
|
||||
std::unique_ptr<Process> m_process;
|
||||
QString m_gzipFileDestName;
|
||||
};
|
||||
|
||||
class QTCREATOR_UTILS_EXPORT UnarchiverTaskAdapter : public Tasking::TaskAdapter<Unarchiver>
|
||||
|
@@ -62,7 +62,7 @@ OutputLineParser::Result JavaParser::handleLine(const QString &line, OutputForma
|
||||
absoluteFilePath(file),
|
||||
lineno);
|
||||
LinkSpecs linkSpecs;
|
||||
addLinkSpecForAbsoluteFilePath(linkSpecs, task.file, task.line, match, 2);
|
||||
addLinkSpecForAbsoluteFilePath(linkSpecs, task.file, task.line, task.column, match, 2);
|
||||
scheduleTask(task, 1);
|
||||
return {Status::Done, linkSpecs};
|
||||
}
|
||||
|
@@ -15,7 +15,7 @@
|
||||
],
|
||||
"Description" : "Visualize CPU and Memory consumption for running applications",
|
||||
"LongDescription" : [
|
||||
"Select an application to monitor its performance in real-time.",
|
||||
"Select an application to monitor its performance in real-time."
|
||||
],
|
||||
"Url" : "https://www.qt.io",
|
||||
${IDE_PLUGIN_DEPENDENCIES}
|
||||
|
@@ -117,8 +117,8 @@ OutputLineParser::Result IarParser::parseWarningOrErrorOrFatalErrorDetailsMessag
|
||||
m_expectSnippet = false;
|
||||
m_expectFilePath = false;
|
||||
LinkSpecs linkSpecs;
|
||||
addLinkSpecForAbsoluteFilePath(linkSpecs, m_lastTask.file, m_lastTask.line, match,
|
||||
FilePathIndex);
|
||||
addLinkSpecForAbsoluteFilePath(
|
||||
linkSpecs, m_lastTask.file, m_lastTask.line, m_lastTask.column, match, FilePathIndex);
|
||||
return {Status::InProgress, linkSpecs};
|
||||
}
|
||||
|
||||
|
@@ -62,8 +62,8 @@ OutputLineParser::Result KeilParser::parseArmWarningOrErrorDetailsMessage(const
|
||||
const QString descr = match.captured(DescriptionIndex);
|
||||
newTask(CompileTask(type, descr, absoluteFilePath(fileName), lineno));
|
||||
LinkSpecs linkSpecs;
|
||||
addLinkSpecForAbsoluteFilePath(linkSpecs, m_lastTask.file, m_lastTask.line, match,
|
||||
FilePathIndex);
|
||||
addLinkSpecForAbsoluteFilePath(
|
||||
linkSpecs, m_lastTask.file, m_lastTask.line, m_lastTask.column, match, FilePathIndex);
|
||||
return {Status::InProgress, linkSpecs};
|
||||
}
|
||||
|
||||
@@ -98,8 +98,8 @@ OutputLineParser::Result KeilParser::parseMcs51WarningOrErrorDetailsMessage1(con
|
||||
match.captured(MessageTextIndex));
|
||||
newTask(CompileTask(type, descr, absoluteFilePath(fileName), lineno));
|
||||
LinkSpecs linkSpecs;
|
||||
addLinkSpecForAbsoluteFilePath(linkSpecs, m_lastTask.file, m_lastTask.line, match,
|
||||
FilePathIndex);
|
||||
addLinkSpecForAbsoluteFilePath(
|
||||
linkSpecs, m_lastTask.file, m_lastTask.line, m_lastTask.column, match, FilePathIndex);
|
||||
return {Status::InProgress, linkSpecs};
|
||||
}
|
||||
|
||||
@@ -119,8 +119,8 @@ OutputLineParser::Result KeilParser::parseMcs51WarningOrErrorDetailsMessage2(con
|
||||
match.captured(MessageTextIndex));
|
||||
newTask(CompileTask(type, descr, absoluteFilePath(fileName), lineno));
|
||||
LinkSpecs linkSpecs;
|
||||
addLinkSpecForAbsoluteFilePath(linkSpecs, m_lastTask.file, m_lastTask.line, match,
|
||||
FilePathIndex);
|
||||
addLinkSpecForAbsoluteFilePath(
|
||||
linkSpecs, m_lastTask.file, m_lastTask.line, m_lastTask.column, match, FilePathIndex);
|
||||
return {Status::InProgress, linkSpecs};
|
||||
}
|
||||
|
||||
|
@@ -73,8 +73,8 @@ OutputLineParser::Result SdccParser::handleLine(const QString &line, OutputForma
|
||||
const QString descr = match.captured(MessageTextIndex);
|
||||
newTask(CompileTask(type, descr, absoluteFilePath(fileName), lineno));
|
||||
LinkSpecs linkSpecs;
|
||||
addLinkSpecForAbsoluteFilePath(linkSpecs, m_lastTask.file, m_lastTask.line, match,
|
||||
FilePathIndex);
|
||||
addLinkSpecForAbsoluteFilePath(
|
||||
linkSpecs, m_lastTask.file, m_lastTask.line, m_lastTask.column, match, FilePathIndex);
|
||||
return {Status::InProgress, linkSpecs};
|
||||
}
|
||||
|
||||
@@ -90,8 +90,8 @@ OutputLineParser::Result SdccParser::handleLine(const QString &line, OutputForma
|
||||
const QString descr = match.captured(MessageTextIndex);
|
||||
newTask(CompileTask(type, descr, absoluteFilePath(fileName), lineno));
|
||||
LinkSpecs linkSpecs;
|
||||
addLinkSpecForAbsoluteFilePath(linkSpecs, m_lastTask.file, m_lastTask.line, match,
|
||||
FilePathIndex);
|
||||
addLinkSpecForAbsoluteFilePath(
|
||||
linkSpecs, m_lastTask.file, m_lastTask.line, m_lastTask.column, match, FilePathIndex);
|
||||
return {Status::InProgress, linkSpecs};
|
||||
}
|
||||
|
||||
|
@@ -349,7 +349,7 @@ public:
|
||||
|
||||
ClangdClient * const q;
|
||||
const CppEditor::ClangdSettings::Data settings;
|
||||
ClangdFollowSymbol *followSymbol = nullptr;
|
||||
QList<ClangdFollowSymbol *> followSymbolOps;
|
||||
ClangdSwitchDeclDef *switchDeclDef = nullptr;
|
||||
ClangdFindLocalReferences *findLocalRefs = nullptr;
|
||||
std::optional<QVersionNumber> versionNumber;
|
||||
@@ -501,8 +501,8 @@ ClangdClient::ClangdClient(Project *project, const Utils::FilePath &jsonDbDir, c
|
||||
|
||||
ClangdClient::~ClangdClient()
|
||||
{
|
||||
if (d->followSymbol)
|
||||
d->followSymbol->clear();
|
||||
for (ClangdFollowSymbol * const followSymbol : std::as_const(d->followSymbolOps))
|
||||
followSymbol->clear();
|
||||
delete d;
|
||||
}
|
||||
|
||||
@@ -990,7 +990,7 @@ MessageId ClangdClient::requestSymbolInfo(const Utils::FilePath &filePath, const
|
||||
#ifdef WITH_TESTS
|
||||
ClangdFollowSymbol *ClangdClient::currentFollowSymbolOperation()
|
||||
{
|
||||
return d->followSymbol;
|
||||
return d->followSymbolOps.isEmpty() ? nullptr : d->followSymbolOps.first();
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1005,8 +1005,20 @@ void ClangdClient::followSymbol(TextDocument *document,
|
||||
{
|
||||
QTC_ASSERT(documentOpen(document), openDocument(document));
|
||||
|
||||
if (d->followSymbol)
|
||||
d->followSymbol->cancel();
|
||||
const ClangdFollowSymbol::Origin origin
|
||||
= CppEditor::CppCodeModelSettings::isInteractiveFollowSymbol()
|
||||
? ClangdFollowSymbol::Origin::User
|
||||
: ClangdFollowSymbol::Origin::Code;
|
||||
if (origin == ClangdFollowSymbol::Origin::User) {
|
||||
for (auto it = d->followSymbolOps.begin(); it != d->followSymbolOps.end(); ) {
|
||||
if ((*it)->isInteractive()) {
|
||||
(*it)->cancel();
|
||||
it = d->followSymbolOps.erase(it);
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const QTextCursor adjustedCursor = d->adjustedCursor(cursor, document);
|
||||
if (followTo == FollowTo::SymbolDef && !resolveTarget) {
|
||||
@@ -1020,14 +1032,13 @@ void ClangdClient::followSymbol(TextDocument *document,
|
||||
|
||||
qCDebug(clangdLog) << "follow symbol requested" << document->filePath()
|
||||
<< adjustedCursor.blockNumber() << adjustedCursor.positionInBlock();
|
||||
auto clangdFollowSymbol = new ClangdFollowSymbol(this, adjustedCursor, editorWidget, document,
|
||||
callback, followTo, openInSplit);
|
||||
auto clangdFollowSymbol = new ClangdFollowSymbol(this, origin, adjustedCursor, editorWidget,
|
||||
document, callback, followTo, openInSplit);
|
||||
connect(clangdFollowSymbol, &ClangdFollowSymbol::done, this, [this, clangdFollowSymbol] {
|
||||
clangdFollowSymbol->deleteLater();
|
||||
if (clangdFollowSymbol == d->followSymbol)
|
||||
d->followSymbol = nullptr;
|
||||
d->followSymbolOps.removeOne(clangdFollowSymbol);
|
||||
});
|
||||
d->followSymbol = clangdFollowSymbol;
|
||||
d->followSymbolOps << clangdFollowSymbol;
|
||||
}
|
||||
|
||||
void ClangdClient::switchDeclDef(TextDocument *document, const QTextCursor &cursor,
|
||||
|
@@ -73,10 +73,10 @@ private:
|
||||
class ClangdFollowSymbol::Private
|
||||
{
|
||||
public:
|
||||
Private(ClangdFollowSymbol *q, ClangdClient *client, const QTextCursor &cursor,
|
||||
Private(ClangdFollowSymbol *q, ClangdClient *client, Origin origin, const QTextCursor &cursor,
|
||||
CppEditorWidget *editorWidget, const FilePath &filePath, const LinkHandler &callback,
|
||||
bool openInSplit)
|
||||
: q(q), client(client), cursor(cursor), editorWidget(editorWidget),
|
||||
: q(q), client(client), origin(origin), cursor(cursor), editorWidget(editorWidget),
|
||||
uri(client->hostPathToServerUri(filePath)), callback(callback),
|
||||
virtualFuncAssistProvider(q),
|
||||
docRevision(editorWidget ? editorWidget->textDocument()->document()->revision() : -1),
|
||||
@@ -94,6 +94,7 @@ public:
|
||||
|
||||
ClangdFollowSymbol * const q;
|
||||
ClangdClient * const client;
|
||||
const Origin origin;
|
||||
const QTextCursor cursor;
|
||||
const QPointer<CppEditor::CppEditorWidget> editorWidget;
|
||||
const DocumentUri uri;
|
||||
@@ -117,11 +118,11 @@ public:
|
||||
bool done = false;
|
||||
};
|
||||
|
||||
ClangdFollowSymbol::ClangdFollowSymbol(ClangdClient *client, const QTextCursor &cursor,
|
||||
CppEditorWidget *editorWidget, TextDocument *document, const LinkHandler &callback,
|
||||
FollowTo followTo, bool openInSplit)
|
||||
ClangdFollowSymbol::ClangdFollowSymbol(ClangdClient *client, Origin origin,
|
||||
const QTextCursor &cursor, CppEditorWidget *editorWidget, TextDocument *document,
|
||||
const LinkHandler &callback, FollowTo followTo, bool openInSplit)
|
||||
: QObject(client),
|
||||
d(new Private(this, client, cursor, editorWidget, document->filePath(), callback,
|
||||
d(new Private(this, client, origin, cursor, editorWidget, document->filePath(), callback,
|
||||
openInSplit))
|
||||
{
|
||||
// Abort if the user does something else with the document in the meantime.
|
||||
@@ -193,6 +194,11 @@ void ClangdFollowSymbol::clear()
|
||||
d->pendingGotoDefRequests.clear();
|
||||
}
|
||||
|
||||
bool ClangdFollowSymbol::isInteractive() const
|
||||
{
|
||||
return d->origin == Origin::User;
|
||||
}
|
||||
|
||||
void ClangdFollowSymbol::emitDone(const Link &link)
|
||||
{
|
||||
if (d->done)
|
||||
|
@@ -23,7 +23,9 @@ class ClangdFollowSymbol : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ClangdFollowSymbol(ClangdClient *client, const QTextCursor &cursor,
|
||||
enum class Origin { User, Code };
|
||||
|
||||
ClangdFollowSymbol(ClangdClient *client, Origin origin, const QTextCursor &cursor,
|
||||
CppEditor::CppEditorWidget *editorWidget,
|
||||
TextEditor::TextDocument *document, const Utils::LinkHandler &callback,
|
||||
FollowTo followTo, bool openInSplit);
|
||||
@@ -31,6 +33,8 @@ public:
|
||||
void cancel();
|
||||
void clear();
|
||||
|
||||
bool isInteractive() const;
|
||||
|
||||
signals:
|
||||
void done();
|
||||
|
||||
|
@@ -15,7 +15,7 @@
|
||||
"Category" : "Build Systems",
|
||||
"Description" : "Automate the configuration of build systems with CMake",
|
||||
"LongDescription" : [
|
||||
"CMake controls the software compilation process by using simple configuration files, called CMakeLists.txt files."
|
||||
"CMake controls the software compilation process by using simple configuration files, called CMakeLists.txt files.",
|
||||
"You also need:",
|
||||
"- CMake",
|
||||
"Qt Online Installer installs a CMake version that you can use."
|
||||
|
@@ -93,8 +93,8 @@ OutputLineParser::Result CMakeParser::handleLine(const QString &line, OutputForm
|
||||
match.captured(2).toInt());
|
||||
m_lines = 1;
|
||||
LinkSpecs linkSpecs;
|
||||
addLinkSpecForAbsoluteFilePath(linkSpecs, m_lastTask.file, m_lastTask.line,
|
||||
match, 1);
|
||||
addLinkSpecForAbsoluteFilePath(
|
||||
linkSpecs, m_lastTask.file, m_lastTask.line, m_lastTask.column, match, 1);
|
||||
|
||||
m_errorOrWarningLine.file = m_lastTask.file;
|
||||
m_errorOrWarningLine.line = m_lastTask.line;
|
||||
@@ -107,8 +107,8 @@ OutputLineParser::Result CMakeParser::handleLine(const QString &line, OutputForm
|
||||
m_lastTask = BuildSystemTask(Task::Error, QString(),
|
||||
absoluteFilePath(FilePath::fromUserInput(match.captured(1))));
|
||||
LinkSpecs linkSpecs;
|
||||
addLinkSpecForAbsoluteFilePath(linkSpecs, m_lastTask.file, m_lastTask.line,
|
||||
match, 1);
|
||||
addLinkSpecForAbsoluteFilePath(
|
||||
linkSpecs, m_lastTask.file, m_lastTask.line, m_lastTask.column, match, 1);
|
||||
m_lines = 1;
|
||||
return {Status::InProgress, linkSpecs};
|
||||
}
|
||||
@@ -121,8 +121,8 @@ OutputLineParser::Result CMakeParser::handleLine(const QString &line, OutputForm
|
||||
match.captured(3).toInt());
|
||||
m_lines = 1;
|
||||
LinkSpecs linkSpecs;
|
||||
addLinkSpecForAbsoluteFilePath(linkSpecs, m_lastTask.file, m_lastTask.line,
|
||||
match, 1);
|
||||
addLinkSpecForAbsoluteFilePath(
|
||||
linkSpecs, m_lastTask.file, m_lastTask.line, m_lastTask.column, match, 1);
|
||||
|
||||
m_errorOrWarningLine.file = m_lastTask.file;
|
||||
m_errorOrWarningLine.line = m_lastTask.line;
|
||||
@@ -174,8 +174,13 @@ OutputLineParser::Result CMakeParser::handleLine(const QString &line, OutputForm
|
||||
m_lastTask.line = match.captured(1).toInt();
|
||||
m_expectTripleLineErrorData = LINE_DESCRIPTION;
|
||||
LinkSpecs linkSpecs;
|
||||
addLinkSpecForAbsoluteFilePath(linkSpecs, m_lastTask.file, m_lastTask.line, 0,
|
||||
match.capturedStart());
|
||||
addLinkSpecForAbsoluteFilePath(
|
||||
linkSpecs,
|
||||
m_lastTask.file,
|
||||
m_lastTask.line,
|
||||
m_lastTask.column,
|
||||
0,
|
||||
match.capturedStart());
|
||||
return {Status::InProgress, linkSpecs};
|
||||
}
|
||||
case LINE_DESCRIPTION:
|
||||
|
@@ -210,9 +210,11 @@ static CMakeBuildTarget toBuildTarget(const TargetDetails &t,
|
||||
const FilePath &sourceDirectory,
|
||||
const FilePath &buildDirectory,
|
||||
bool relativeLibs,
|
||||
const QSet<FilePath> &artifacts)
|
||||
const QSet<FilePath> &sharedLibraryArtifacts)
|
||||
{
|
||||
const FilePath currentBuildDir = buildDirectory.resolvePath(t.buildDir);
|
||||
const QSet<FilePath> sharedLibraryArtifactsPaths
|
||||
= transform(sharedLibraryArtifacts, &FilePath::parentDir);
|
||||
|
||||
CMakeBuildTarget ct;
|
||||
ct.title = t.name;
|
||||
@@ -306,7 +308,6 @@ static CMakeBuildTarget toBuildTarget(const TargetDetails &t,
|
||||
if (f.role == "libraries")
|
||||
tmp = tmp.parentDir();
|
||||
|
||||
std::optional<QString> dllName;
|
||||
if (buildDir.osType() == OsTypeWindows && (f.role == "libraries")) {
|
||||
const auto partAsFilePath = FilePath::fromUserInput(part);
|
||||
part = partAsFilePath.fileName();
|
||||
@@ -314,24 +315,6 @@ static CMakeBuildTarget toBuildTarget(const TargetDetails &t,
|
||||
// Skip object libraries on Windows. This case can happen with static qml plugins
|
||||
if (part.endsWith(".obj") || part.endsWith(".o"))
|
||||
continue;
|
||||
|
||||
// Only consider dlls, not static libraries
|
||||
for (const QString &suffix :
|
||||
{QString(".lib"), QString(".dll.a"), QString(".a")}) {
|
||||
if (part.endsWith(suffix) && !dllName)
|
||||
dllName = part.chopped(suffix.length()).append(".dll");
|
||||
}
|
||||
|
||||
// MinGW has libQt6Core.a -> Qt6Core.dll
|
||||
// but libFoo.dll.a was already handled above
|
||||
const QString mingwPrefix("lib");
|
||||
const QString mingwSuffix("a");
|
||||
const QString completeSuffix = partAsFilePath.completeSuffix();
|
||||
if (part.startsWith(mingwPrefix) && completeSuffix == mingwSuffix) {
|
||||
dllName = part.chopped(mingwSuffix.length() + 1/*the '.'*/)
|
||||
.sliced(mingwPrefix.length())
|
||||
.append(".dll");
|
||||
}
|
||||
}
|
||||
|
||||
if (!tmp.isEmpty() && tmp.isDir()) {
|
||||
@@ -345,18 +328,15 @@ static CMakeBuildTarget toBuildTarget(const TargetDetails &t,
|
||||
{"/lib", "/lib64", "/usr/lib", "/usr/lib64", "/usr/local/lib"}))
|
||||
librarySeachPaths.append(tmp);
|
||||
|
||||
if (buildDir.osType() == OsTypeWindows && dllName) {
|
||||
const auto validPath = [&artifacts](const FilePath& path) {
|
||||
return path.exists() || artifacts.contains(path);
|
||||
};
|
||||
if (validPath(tmp.pathAppended(*dllName)))
|
||||
if (buildDir.osType() == OsTypeWindows) {
|
||||
if (sharedLibraryArtifactsPaths.contains(tmp))
|
||||
librarySeachPaths.append(tmp);
|
||||
|
||||
// Libraries often have their import libs in ../lib and the
|
||||
// actual dll files in ../bin on windows. Qt is one example of that.
|
||||
if (tmp.fileName() == "lib") {
|
||||
const FilePath path = tmp.parentDir().pathAppended("bin");
|
||||
if (path.isDir() && validPath(path.pathAppended(*dllName)))
|
||||
if (path.isDir())
|
||||
librarySeachPaths.append(path);
|
||||
}
|
||||
}
|
||||
@@ -375,17 +355,19 @@ static QList<CMakeBuildTarget> generateBuildTargets(const QFuture<void> &cancelF
|
||||
const FilePath &buildDirectory,
|
||||
bool relativeLibs)
|
||||
{
|
||||
QSet<FilePath> artifacts;
|
||||
QSet<FilePath> sharedLibraryArtifacts;
|
||||
for (const TargetDetails &t : input.targetDetails)
|
||||
for (const FilePath &p: t.artifacts)
|
||||
artifacts.insert(buildDirectory.resolvePath(p));
|
||||
if (t.type == "MODULE_LIBRARY" || t.type == "SHARED_LIBRARY")
|
||||
for (const FilePath &p : t.artifacts)
|
||||
sharedLibraryArtifacts.insert(buildDirectory.resolvePath(p));
|
||||
|
||||
QList<CMakeBuildTarget> result;
|
||||
result.reserve(input.targetDetails.size());
|
||||
for (const TargetDetails &t : input.targetDetails) {
|
||||
if (cancelFuture.isCanceled())
|
||||
return {};
|
||||
result.append(toBuildTarget(t, sourceDirectory, buildDirectory, relativeLibs, artifacts));
|
||||
result.append(
|
||||
toBuildTarget(t, sourceDirectory, buildDirectory, relativeLibs, sharedLibraryArtifacts));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@@ -168,41 +168,38 @@ CopilotSettings::CopilotSettings()
|
||||
setLayouter([this] {
|
||||
using namespace Layouting;
|
||||
|
||||
auto warningLabel = new QLabel;
|
||||
warningLabel->setWordWrap(true);
|
||||
warningLabel->setTextInteractionFlags(
|
||||
Qt::LinksAccessibleByMouse | Qt::LinksAccessibleByKeyboard | Qt::TextSelectableByMouse);
|
||||
warningLabel->setText(
|
||||
Tr::tr("Enabling %1 is subject to your agreement and abidance with your applicable "
|
||||
"%1 terms. It is your responsibility to know and accept the requirements and "
|
||||
"parameters of using tools like %1. This may include, but is not limited to, "
|
||||
"ensuring you have the rights to allow %1 access to your code, as well as "
|
||||
"understanding any implications of your use of %1 and suggestions produced "
|
||||
"(like copyright, accuracy, etc.).")
|
||||
.arg("Copilot"));
|
||||
|
||||
auto authWidget = new AuthWidget();
|
||||
|
||||
auto helpLabel = new QLabel();
|
||||
helpLabel->setTextFormat(Qt::MarkdownText);
|
||||
helpLabel->setWordWrap(true);
|
||||
helpLabel->setTextInteractionFlags(
|
||||
Qt::LinksAccessibleByMouse | Qt::LinksAccessibleByKeyboard | Qt::TextSelectableByMouse);
|
||||
helpLabel->setOpenExternalLinks(true);
|
||||
connect(helpLabel, &QLabel::linkHovered, [](const QString &link) {
|
||||
QToolTip::showText(QCursor::pos(), link);
|
||||
});
|
||||
|
||||
// clang-format off
|
||||
helpLabel->setText(Tr::tr(
|
||||
"The Copilot plugin requires node.js and the Copilot neovim plugin. "
|
||||
"If you install the neovim plugin as described in %1, "
|
||||
"the plugin will find the agent.js file automatically.\n\n"
|
||||
"Otherwise you need to specify the path to the %2 "
|
||||
"file from the Copilot neovim plugin.",
|
||||
"Markdown text for the copilot instruction label")
|
||||
.arg("[README.md](https://github.com/github/copilot.vim)")
|
||||
.arg("[agent.js](https://github.com/github/copilot.vim/tree/release/dist)"));
|
||||
|
||||
Label warningLabel {
|
||||
wordWrap(true),
|
||||
textInteractionFlags(
|
||||
Qt::LinksAccessibleByMouse | Qt::LinksAccessibleByKeyboard | Qt::TextSelectableByMouse),
|
||||
text(Tr::tr("Enabling %1 is subject to your agreement and abidance with your applicable "
|
||||
"%1 terms. It is your responsibility to know and accept the requirements and "
|
||||
"parameters of using tools like %1. This may include, but is not limited to, "
|
||||
"ensuring you have the rights to allow %1 access to your code, as well as "
|
||||
"understanding any implications of your use of %1 and suggestions produced "
|
||||
"(like copyright, accuracy, etc.).")
|
||||
.arg("Copilot")),
|
||||
};
|
||||
|
||||
Label helpLabel {
|
||||
textFormat(Qt::MarkdownText),
|
||||
wordWrap(true),
|
||||
textInteractionFlags(
|
||||
Qt::LinksAccessibleByMouse | Qt::LinksAccessibleByKeyboard | Qt::TextSelectableByMouse),
|
||||
openExternalLinks(true),
|
||||
onLinkHovered([](const QString &link) { QToolTip::showText(QCursor::pos(), link); }, this),
|
||||
text(Tr::tr(
|
||||
"The Copilot plugin requires node.js and the Copilot neovim plugin. "
|
||||
"If you install the neovim plugin as described in %1, "
|
||||
"the plugin will find the agent.js file automatically.\n\n"
|
||||
"Otherwise you need to specify the path to the %2 "
|
||||
"file from the Copilot neovim plugin.",
|
||||
"Markdown text for the copilot instruction label")
|
||||
.arg("[README.md](https://github.com/github/copilot.vim)")
|
||||
.arg("[agent.js](https://github.com/github/copilot.vim/tree/release/dist)"))
|
||||
};
|
||||
|
||||
return Column {
|
||||
Group {
|
||||
@@ -213,7 +210,7 @@ CopilotSettings::CopilotSettings()
|
||||
}
|
||||
},
|
||||
Form {
|
||||
authWidget, br,
|
||||
new AuthWidget, br,
|
||||
enableCopilot, br,
|
||||
nodeJsPath, br,
|
||||
distPath, br,
|
||||
|
@@ -251,6 +251,9 @@ bool CorePlugin::initialize(const QStringList &arguments, QString *errorMessage)
|
||||
expander->registerVariable("HostOs:ExecutableSuffix",
|
||||
Tr::tr("The platform executable suffix."),
|
||||
[] { return QString(Utils::HostOsInfo::withExecutableSuffix("")); });
|
||||
expander->registerFileVariables("IDE:Executable",
|
||||
Tr::tr("The path to the running %1 itself.").arg(QGuiApplication::applicationDisplayName()),
|
||||
[]() { return FilePath::fromUserInput(QCoreApplication::applicationFilePath()); });
|
||||
expander->registerVariable("IDE:ResourcePath",
|
||||
Tr::tr("The directory where %1 finds its pre-installed resources.")
|
||||
.arg(QGuiApplication::applicationDisplayName()),
|
||||
|
@@ -301,7 +301,6 @@ public:
|
||||
WindowSupport *m_windowSupport = nullptr;
|
||||
EditorManager *m_editorManager = nullptr;
|
||||
ExternalToolManager *m_externalToolManager = nullptr;
|
||||
MessageManager *m_messageManager = nullptr;
|
||||
ProgressManagerPrivate *m_progressManager = nullptr;
|
||||
JsExpander *m_jsExpander = nullptr;
|
||||
VcsManager *m_vcsManager = nullptr;
|
||||
@@ -1395,7 +1394,6 @@ void ICorePrivate::init()
|
||||
m_rightNavigationWidget = new NavigationWidget(m_toggleRightSideBarAction, Side::Right);
|
||||
m_rightPaneWidget = new RightPaneWidget();
|
||||
|
||||
m_messageManager = new MessageManager;
|
||||
m_editorManager = new EditorManager(this);
|
||||
m_externalToolManager = new ExternalToolManager();
|
||||
|
||||
@@ -1454,8 +1452,7 @@ ICorePrivate::~ICorePrivate()
|
||||
|
||||
delete m_externalToolManager;
|
||||
m_externalToolManager = nullptr;
|
||||
delete m_messageManager;
|
||||
m_messageManager = nullptr;
|
||||
MessageManager::destroy();
|
||||
delete m_shortcutSettings;
|
||||
m_shortcutSettings = nullptr;
|
||||
delete m_toolSettings;
|
||||
|
@@ -237,98 +237,6 @@ private:
|
||||
QList<std::optional<LocatorFilterEntries>> m_outputData;
|
||||
};
|
||||
|
||||
// This instance of this object is created by LocatorMatcher tree.
|
||||
// It starts a separate thread which collects and deduplicates the results reported
|
||||
// by LocatorStorage instances. The ResultsCollector is started as a first task in
|
||||
// LocatorMatcher and runs in parallel to all the filters started by LocatorMatcher.
|
||||
// When all the results are reported (the expected number of reports is set with setFilterCount()),
|
||||
// the ResultsCollector finishes. The intermediate results are reported with
|
||||
// serialOutputDataReady() signal.
|
||||
// The object of ResultsCollector is registered in Tasking namespace under the
|
||||
// ResultsCollectorTask name.
|
||||
class ResultsCollector : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
~ResultsCollector();
|
||||
void setFilterCount(int count);
|
||||
void start();
|
||||
|
||||
bool isRunning() const { return m_watcher.get(); }
|
||||
|
||||
std::shared_ptr<ResultsDeduplicator> deduplicator() const { return m_deduplicator; }
|
||||
|
||||
signals:
|
||||
void serialOutputDataReady(const LocatorFilterEntries &serialOutputData);
|
||||
void done();
|
||||
|
||||
private:
|
||||
int m_filterCount = 0;
|
||||
std::unique_ptr<QFutureWatcher<LocatorFilterEntries>> m_watcher;
|
||||
std::shared_ptr<ResultsDeduplicator> m_deduplicator;
|
||||
};
|
||||
|
||||
ResultsCollector::~ResultsCollector()
|
||||
{
|
||||
if (!isRunning())
|
||||
return;
|
||||
|
||||
m_deduplicator->cancel();
|
||||
if (Utils::futureSynchronizer()) {
|
||||
Utils::futureSynchronizer()->addFuture(m_watcher->future());
|
||||
return;
|
||||
}
|
||||
m_watcher->future().waitForFinished();
|
||||
}
|
||||
|
||||
void ResultsCollector::setFilterCount(int count)
|
||||
{
|
||||
QTC_ASSERT(!isRunning(), return);
|
||||
QTC_ASSERT(count >= 0, return);
|
||||
|
||||
m_filterCount = count;
|
||||
}
|
||||
|
||||
void ResultsCollector::start()
|
||||
{
|
||||
QTC_ASSERT(!m_watcher, return);
|
||||
QTC_ASSERT(!isRunning(), return);
|
||||
if (m_filterCount == 0) {
|
||||
emit done();
|
||||
return;
|
||||
}
|
||||
|
||||
m_deduplicator.reset(new ResultsDeduplicator(m_filterCount));
|
||||
m_watcher.reset(new QFutureWatcher<LocatorFilterEntries>);
|
||||
connect(m_watcher.get(), &QFutureWatcherBase::resultReadyAt, this, [this](int index) {
|
||||
emit serialOutputDataReady(m_watcher->resultAt(index));
|
||||
});
|
||||
connect(m_watcher.get(), &QFutureWatcherBase::finished, this, [this] {
|
||||
emit done();
|
||||
m_watcher.release()->deleteLater();
|
||||
m_deduplicator.reset();
|
||||
});
|
||||
|
||||
// TODO: When filterCount == 1, deliver results directly and finish?
|
||||
auto deduplicate = [](QPromise<LocatorFilterEntries> &promise,
|
||||
const std::shared_ptr<ResultsDeduplicator> &deduplicator) {
|
||||
deduplicator->run(promise);
|
||||
};
|
||||
m_watcher->setFuture(Utils::asyncRun(deduplicate, m_deduplicator));
|
||||
}
|
||||
|
||||
class ResultsCollectorTaskAdapter : public TaskAdapter<ResultsCollector>
|
||||
{
|
||||
public:
|
||||
ResultsCollectorTaskAdapter() {
|
||||
connect(task(), &ResultsCollector::done, this, [this] { emit done(DoneResult::Success); });
|
||||
}
|
||||
void start() final { task()->start(); }
|
||||
};
|
||||
|
||||
using ResultsCollectorTask = CustomTask<ResultsCollectorTaskAdapter>;
|
||||
|
||||
class LocatorStoragePrivate
|
||||
{
|
||||
public:
|
||||
@@ -425,23 +333,39 @@ void LocatorMatcher::start()
|
||||
QTC_ASSERT(!isRunning(), return);
|
||||
d->m_output = {};
|
||||
|
||||
const Storage<ResultsCollector *> collectorStorage;
|
||||
const int filterCount = d->m_tasks.size();
|
||||
if (filterCount <= 0)
|
||||
return;
|
||||
|
||||
struct ResultsCollector
|
||||
{
|
||||
~ResultsCollector() {
|
||||
if (m_deduplicator)
|
||||
m_deduplicator->cancel();
|
||||
}
|
||||
std::shared_ptr<ResultsDeduplicator> m_deduplicator;
|
||||
};
|
||||
|
||||
const Storage<ResultsCollector> collectorStorage;
|
||||
const LoopList iterator(d->m_tasks);
|
||||
|
||||
const auto onCollectorSetup = [this, filterCount = d->m_tasks.size(), collectorStorage](
|
||||
ResultsCollector &collector) {
|
||||
*collectorStorage = &collector;
|
||||
collector.setFilterCount(filterCount);
|
||||
connect(&collector, &ResultsCollector::serialOutputDataReady,
|
||||
this, [this](const LocatorFilterEntries &serialOutputData) {
|
||||
const auto onCollectorSetup = [this, filterCount, collectorStorage](
|
||||
Async<LocatorFilterEntries> &async) {
|
||||
const std::shared_ptr<ResultsDeduplicator> deduplicator(new ResultsDeduplicator(filterCount));
|
||||
collectorStorage->m_deduplicator = deduplicator;
|
||||
Async<LocatorFilterEntries> *asyncPtr = &async;
|
||||
connect(asyncPtr, &AsyncBase::resultReadyAt, this, [this, asyncPtr](int index) {
|
||||
const LocatorFilterEntries serialOutputData = asyncPtr->resultAt(index);
|
||||
d->m_output += serialOutputData;
|
||||
emit serialOutputDataReady(serialOutputData);
|
||||
});
|
||||
// TODO: When filterCount == 1, deliver results directly and finish?
|
||||
async.setConcurrentCallData(&ResultsDeduplicator::run, deduplicator);
|
||||
};
|
||||
const auto onCollectorDone = [collectorStorage] { *collectorStorage = nullptr; };
|
||||
const auto onCollectorDone = [collectorStorage] { collectorStorage->m_deduplicator->cancel(); };
|
||||
|
||||
const auto onTaskTreeSetup = [iterator, input = d->m_input, collectorStorage](TaskTree &taskTree) {
|
||||
const std::shared_ptr<ResultsDeduplicator> deduplicator = (*collectorStorage)->deduplicator();
|
||||
const std::shared_ptr<ResultsDeduplicator> deduplicator = collectorStorage->m_deduplicator;
|
||||
const Storage<LocatorStorage> storage = iterator->storage;
|
||||
const auto onSetup = [storage, input, index = iterator.iteration(), deduplicator] {
|
||||
*storage = std::make_shared<LocatorStoragePrivate>(input, index, deduplicator);
|
||||
@@ -458,7 +382,7 @@ void LocatorMatcher::start()
|
||||
const Group root {
|
||||
parallel,
|
||||
collectorStorage,
|
||||
ResultsCollectorTask(onCollectorSetup, onCollectorDone),
|
||||
AsyncTask<LocatorFilterEntries>(onCollectorSetup, onCollectorDone),
|
||||
Group {
|
||||
parallelLimit(d->m_parallelLimit),
|
||||
iterator,
|
||||
@@ -1472,5 +1396,3 @@ LocatorMatcherTask LocatorFileCache::matcher() const
|
||||
}
|
||||
|
||||
} // Core
|
||||
|
||||
#include "ilocatorfilter.moc"
|
||||
|
@@ -5,113 +5,88 @@
|
||||
|
||||
#include "messageoutputwindow.h"
|
||||
|
||||
#include <extensionsystem/pluginmanager.h>
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
#include <QFont>
|
||||
#include <QThread>
|
||||
#include <QTime>
|
||||
|
||||
#include <memory>
|
||||
|
||||
/*!
|
||||
\class Core::MessageManager
|
||||
\namespace Core::MessageManager
|
||||
\inheaderfile coreplugin/messagemanager.h
|
||||
\ingroup mainclasses
|
||||
\inmodule QtCreator
|
||||
|
||||
\brief The MessageManager class is used to post messages in the
|
||||
\brief The MessageManager namespace is used to post messages in the
|
||||
\uicontrol{General Messages} pane.
|
||||
*/
|
||||
|
||||
namespace Core {
|
||||
namespace Core::MessageManager {
|
||||
|
||||
static MessageManager *m_instance = nullptr;
|
||||
static Internal::MessageOutputWindow *m_messageOutputWindow = nullptr;
|
||||
static std::unique_ptr<Internal::MessageOutputWindow> s_messageOutputWindow;
|
||||
|
||||
enum class Flag { Silent, Flash, Disrupt };
|
||||
|
||||
static void showOutputPane(Flag flags)
|
||||
{
|
||||
QTC_ASSERT(m_messageOutputWindow, return);
|
||||
|
||||
QTC_ASSERT(s_messageOutputWindow, return);
|
||||
switch (flags) {
|
||||
case Core::Flag::Silent:
|
||||
case Flag::Silent:
|
||||
break;
|
||||
case Core::Flag::Flash:
|
||||
m_messageOutputWindow->flash();
|
||||
case Flag::Flash:
|
||||
s_messageOutputWindow->flash();
|
||||
break;
|
||||
case Core::Flag::Disrupt:
|
||||
m_messageOutputWindow->popup(IOutputPane::ModeSwitch | IOutputPane::WithFocus);
|
||||
case Flag::Disrupt:
|
||||
s_messageOutputWindow->popup(IOutputPane::ModeSwitch | IOutputPane::WithFocus);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void doWrite(const QString &text, Flag flags)
|
||||
{
|
||||
QTC_ASSERT(m_messageOutputWindow, return);
|
||||
|
||||
QTC_ASSERT(s_messageOutputWindow, return);
|
||||
showOutputPane(flags);
|
||||
m_messageOutputWindow->append(text + '\n');
|
||||
s_messageOutputWindow->append(text + '\n');
|
||||
}
|
||||
|
||||
static void write(const QString &text, Flag flags)
|
||||
static void writeImpl(const QString &text, Flag flags)
|
||||
{
|
||||
QTC_ASSERT(m_instance, return);
|
||||
if (QThread::currentThread() == m_instance->thread())
|
||||
doWrite(text, flags);
|
||||
else
|
||||
QMetaObject::invokeMethod(m_instance, [text, flags] {
|
||||
doWrite(text, flags);
|
||||
}, Qt::QueuedConnection);
|
||||
QTC_ASSERT(s_messageOutputWindow, return);
|
||||
QMetaObject::invokeMethod(s_messageOutputWindow.get(), [text, flags] { doWrite(text, flags); });
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
*/
|
||||
MessageManager::MessageManager()
|
||||
void init()
|
||||
{
|
||||
m_instance = this;
|
||||
m_messageOutputWindow = nullptr;
|
||||
s_messageOutputWindow.reset(new Internal::MessageOutputWindow);
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
*/
|
||||
MessageManager::~MessageManager()
|
||||
void destroy()
|
||||
{
|
||||
if (m_messageOutputWindow) {
|
||||
ExtensionSystem::PluginManager::removeObject(m_messageOutputWindow);
|
||||
delete m_messageOutputWindow;
|
||||
}
|
||||
m_instance = nullptr;
|
||||
s_messageOutputWindow.reset();
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
*/
|
||||
void MessageManager::init()
|
||||
void setFont(const QFont &font)
|
||||
{
|
||||
m_messageOutputWindow = new Internal::MessageOutputWindow;
|
||||
ExtensionSystem::PluginManager::addObject(m_messageOutputWindow);
|
||||
QTC_ASSERT(s_messageOutputWindow, return);
|
||||
s_messageOutputWindow->setFont(font);
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
*/
|
||||
void MessageManager::setFont(const QFont &font)
|
||||
void setWheelZoomEnabled(bool enabled)
|
||||
{
|
||||
QTC_ASSERT(m_messageOutputWindow, return);
|
||||
|
||||
m_messageOutputWindow->setFont(font);
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
*/
|
||||
void MessageManager::setWheelZoomEnabled(bool enabled)
|
||||
{
|
||||
QTC_ASSERT(m_messageOutputWindow, return);
|
||||
|
||||
m_messageOutputWindow->setWheelZoomEnabled(enabled);
|
||||
QTC_ASSERT(s_messageOutputWindow, return);
|
||||
s_messageOutputWindow->setWheelZoomEnabled(enabled);
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -124,9 +99,9 @@ void MessageManager::setWheelZoomEnabled(bool enabled)
|
||||
\sa writeFlashing()
|
||||
\sa writeDisrupting()
|
||||
*/
|
||||
void MessageManager::writeSilently(const QString &message)
|
||||
void writeSilently(const QString &message)
|
||||
{
|
||||
Core::write(message, Flag::Silent);
|
||||
writeImpl(message, Flag::Silent);
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -141,9 +116,9 @@ void MessageManager::writeSilently(const QString &message)
|
||||
\sa writeSilently()
|
||||
\sa writeDisrupting()
|
||||
*/
|
||||
void MessageManager::writeFlashing(const QString &message)
|
||||
void writeFlashing(const QString &message)
|
||||
{
|
||||
Core::write(message, Flag::Flash);
|
||||
writeImpl(message, Flag::Flash);
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -156,15 +131,15 @@ void MessageManager::writeFlashing(const QString &message)
|
||||
\sa writeSilently()
|
||||
\sa writeFlashing()
|
||||
*/
|
||||
void MessageManager::writeDisrupting(const QString &message)
|
||||
void writeDisrupting(const QString &message)
|
||||
{
|
||||
Core::write(message, Flag::Disrupt);
|
||||
writeImpl(message, Flag::Disrupt);
|
||||
}
|
||||
|
||||
/*!
|
||||
\overload writeSilently()
|
||||
*/
|
||||
void MessageManager::writeSilently(const QStringList &messages)
|
||||
void writeSilently(const QStringList &messages)
|
||||
{
|
||||
writeSilently(messages.join('\n'));
|
||||
}
|
||||
@@ -172,7 +147,7 @@ void MessageManager::writeSilently(const QStringList &messages)
|
||||
/*!
|
||||
\overload writeFlashing()
|
||||
*/
|
||||
void MessageManager::writeFlashing(const QStringList &messages)
|
||||
void writeFlashing(const QStringList &messages)
|
||||
{
|
||||
writeFlashing(messages.join('\n'));
|
||||
}
|
||||
@@ -180,9 +155,9 @@ void MessageManager::writeFlashing(const QStringList &messages)
|
||||
/*!
|
||||
\overload writeDisrupting()
|
||||
*/
|
||||
void MessageManager::writeDisrupting(const QStringList &messages)
|
||||
void writeDisrupting(const QStringList &messages)
|
||||
{
|
||||
writeDisrupting(messages.join('\n'));
|
||||
}
|
||||
|
||||
} // namespace Core
|
||||
} // namespace Core::MessageManager
|
||||
|
@@ -5,47 +5,26 @@
|
||||
|
||||
#include "core_global.h"
|
||||
|
||||
#include <QMetaType>
|
||||
#include <QObject>
|
||||
#include <QStringList>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QFont;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
namespace Core {
|
||||
namespace Core::MessageManager {
|
||||
|
||||
class ICore;
|
||||
CORE_EXPORT void setFont(const QFont &font);
|
||||
CORE_EXPORT void setWheelZoomEnabled(bool enabled);
|
||||
|
||||
namespace Internal {
|
||||
class ICorePrivate;
|
||||
class MainWindow;
|
||||
}
|
||||
CORE_EXPORT void writeSilently(const QString &message);
|
||||
CORE_EXPORT void writeFlashing(const QString &message);
|
||||
CORE_EXPORT void writeDisrupting(const QString &message);
|
||||
|
||||
class CORE_EXPORT MessageManager : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
CORE_EXPORT void writeSilently(const QStringList &messages);
|
||||
CORE_EXPORT void writeFlashing(const QStringList &messages);
|
||||
CORE_EXPORT void writeDisrupting(const QStringList &messages);
|
||||
|
||||
public:
|
||||
static void setFont(const QFont &font);
|
||||
static void setWheelZoomEnabled(bool enabled);
|
||||
void init();
|
||||
void destroy();
|
||||
|
||||
static void writeSilently(const QString &message);
|
||||
static void writeFlashing(const QString &message);
|
||||
static void writeDisrupting(const QString &message);
|
||||
|
||||
static void writeSilently(const QStringList &messages);
|
||||
static void writeFlashing(const QStringList &messages);
|
||||
static void writeDisrupting(const QStringList &messages);
|
||||
|
||||
private:
|
||||
MessageManager();
|
||||
~MessageManager() override;
|
||||
|
||||
static void init();
|
||||
|
||||
friend class ICore;
|
||||
friend class Internal::ICorePrivate;
|
||||
friend class Internal::MainWindow;
|
||||
};
|
||||
|
||||
} // namespace Core
|
||||
} // namespace Core::MessageManager
|
||||
|
@@ -83,6 +83,7 @@ bool operator==(const CppEditor::CppCodeModelSettings &s1,
|
||||
&& s1.useBuiltinPreprocessor == s2.useBuiltinPreprocessor
|
||||
&& s1.indexerFileSizeLimitInMb == s2.indexerFileSizeLimitInMb
|
||||
&& s1.m_categorizeFindReferences == s2.m_categorizeFindReferences
|
||||
&& s1.interactiveFollowSymbol == s2.interactiveFollowSymbol
|
||||
&& s1.ignoreFiles == s2.ignoreFiles && s1.ignorePattern == s2.ignorePattern;
|
||||
}
|
||||
|
||||
@@ -204,6 +205,16 @@ void CppCodeModelSettings::setCategorizeFindReferences(bool categorize)
|
||||
globalInstance().m_categorizeFindReferences = categorize;
|
||||
}
|
||||
|
||||
bool CppCodeModelSettings::isInteractiveFollowSymbol()
|
||||
{
|
||||
return globalInstance().interactiveFollowSymbol;
|
||||
}
|
||||
|
||||
void CppCodeModelSettings::setInteractiveFollowSymbol(bool interactive)
|
||||
{
|
||||
globalInstance().interactiveFollowSymbol = interactive;
|
||||
}
|
||||
|
||||
CppCodeModelProjectSettings::CppCodeModelProjectSettings(ProjectExplorer::Project *project)
|
||||
: m_project(project)
|
||||
{
|
||||
|
@@ -55,6 +55,9 @@ public:
|
||||
static bool categorizeFindReferences();
|
||||
static void setCategorizeFindReferences(bool categorize);
|
||||
|
||||
static bool isInteractiveFollowSymbol();
|
||||
static void setInteractiveFollowSymbol(bool interactive);
|
||||
|
||||
QString ignorePattern;
|
||||
PCHUsage pchUsage = PchUse_BuildSystem;
|
||||
int indexerFileSizeLimitInMb = 5;
|
||||
@@ -63,7 +66,10 @@ public:
|
||||
bool useBuiltinPreprocessor = true;
|
||||
bool ignoreFiles = false;
|
||||
bool enableIndexing = true;
|
||||
bool m_categorizeFindReferences = false; // Ephemeral!
|
||||
|
||||
// Ephemeral!
|
||||
bool m_categorizeFindReferences = false;
|
||||
bool interactiveFollowSymbol = true;
|
||||
|
||||
private:
|
||||
CppCodeModelSettings(Utils::QtcSettings *s) { fromSettings(s); }
|
||||
@@ -76,6 +82,14 @@ private:
|
||||
namespace Internal {
|
||||
void setupCppCodeModelSettingsPage();
|
||||
void setupCppCodeModelProjectSettingsPanel();
|
||||
|
||||
class NonInteractiveFollowSymbolMarker
|
||||
{
|
||||
public:
|
||||
NonInteractiveFollowSymbolMarker() { CppCodeModelSettings::setInteractiveFollowSymbol(false); }
|
||||
~NonInteractiveFollowSymbolMarker() { CppCodeModelSettings::setInteractiveFollowSymbol(true); }
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
|
||||
} // namespace CppEditor
|
||||
|
@@ -623,6 +623,7 @@ void CppEditorWidget::renameUsages(const QString &replacement, QTextCursor curso
|
||||
const CursorInEditor cursorInEditor{cursor, textDocument()->filePath(), this, textDocument()};
|
||||
CppModelManager::globalRename(cursorInEditor, replacement);
|
||||
};
|
||||
NonInteractiveFollowSymbolMarker niMarker;
|
||||
CppModelManager::followSymbol(CursorInEditor{cursor,
|
||||
textDocument()->filePath(),
|
||||
this,
|
||||
|
@@ -260,15 +260,14 @@ static void extractNames(const CppRefactoringFilePtr &file,
|
||||
class GetterSetterRefactoringHelper
|
||||
{
|
||||
public:
|
||||
GetterSetterRefactoringHelper(CppQuickFixOperation *operation,
|
||||
const FilePath &filePath,
|
||||
Class *clazz)
|
||||
GetterSetterRefactoringHelper(CppQuickFixOperation *operation, Class *clazz)
|
||||
: m_operation(operation)
|
||||
, m_changes(m_operation->snapshot())
|
||||
, m_locator(m_changes)
|
||||
, m_headerFile(m_changes.cppFile(filePath))
|
||||
, m_headerFile(operation->currentFile())
|
||||
, m_sourceFile([&] {
|
||||
FilePath cppFilePath = correspondingHeaderOrSource(filePath, &m_isHeaderHeaderFile);
|
||||
FilePath cppFilePath = correspondingHeaderOrSource(m_headerFile->filePath(),
|
||||
&m_isHeaderHeaderFile);
|
||||
if (!m_isHeaderHeaderFile || !cppFilePath.exists()) {
|
||||
// there is no "source" file
|
||||
return m_headerFile;
|
||||
@@ -1271,11 +1270,10 @@ private:
|
||||
const ClassSpecifierAST *m_classAST;
|
||||
InsertionPointLocator::AccessSpec m_accessSpec;
|
||||
GenerateConstructorRefactoringHelper(CppQuickFixOperation *operation,
|
||||
const FilePath &filePath,
|
||||
Class *clazz,
|
||||
const ClassSpecifierAST *classAST,
|
||||
InsertionPointLocator::AccessSpec accessSpec)
|
||||
: GetterSetterRefactoringHelper(operation, filePath, clazz)
|
||||
: GetterSetterRefactoringHelper(operation, clazz)
|
||||
, m_classAST(classAST)
|
||||
, m_accessSpec(accessSpec)
|
||||
{}
|
||||
@@ -1416,7 +1414,6 @@ private:
|
||||
}
|
||||
};
|
||||
GenerateConstructorRefactoringHelper helper(this,
|
||||
currentFile()->filePath(),
|
||||
m_classAST->symbol,
|
||||
m_classAST,
|
||||
accessSpec);
|
||||
@@ -1509,7 +1506,7 @@ public:
|
||||
|
||||
void perform() override
|
||||
{
|
||||
GetterSetterRefactoringHelper helper(this, currentFile()->filePath(), m_data.clazz);
|
||||
GetterSetterRefactoringHelper helper(this, m_data.clazz);
|
||||
helper.performGeneration(m_data, m_generateFlags);
|
||||
helper.applyChanges();
|
||||
}
|
||||
@@ -1829,9 +1826,7 @@ private:
|
||||
}
|
||||
if (m_candidates.empty())
|
||||
return;
|
||||
GetterSetterRefactoringHelper helper(this,
|
||||
currentFile()->filePath(),
|
||||
m_candidates.front().data.clazz);
|
||||
GetterSetterRefactoringHelper helper(this, m_candidates.front().data.clazz);
|
||||
for (MemberInfo &mi : m_candidates) {
|
||||
if (mi.requestedFlags != 0) {
|
||||
helper.performGeneration(mi.data, mi.requestedFlags);
|
||||
|
@@ -767,8 +767,7 @@ public:
|
||||
printer.showTemplateParameters = true;
|
||||
Utils::ChangeSet headerChangeSet;
|
||||
const CppRefactoringChanges refactoring(snapshot());
|
||||
const Utils::FilePath filePath = currentFile()->filePath();
|
||||
const CppRefactoringFilePtr headerFile = refactoring.cppFile(filePath);
|
||||
const CppRefactoringFilePtr headerFile = currentFile();
|
||||
const LookupContext targetContext(headerFile->cppDocument(), snapshot());
|
||||
|
||||
const Class *targetClass = m_classAST->symbol;
|
||||
|
@@ -370,6 +370,7 @@ private:
|
||||
if (!link.hasValidTarget())
|
||||
collectOperations(interface, result);
|
||||
};
|
||||
NonInteractiveFollowSymbolMarker niMarker;
|
||||
CppModelManager::followSymbol(cursorInEditor, followSymbolFallback, false, false,
|
||||
FollowSymbolMode::Exact,
|
||||
CppModelManager::Backend::Builtin);
|
||||
|
@@ -155,8 +155,7 @@ public:
|
||||
|
||||
// rewrite the function name
|
||||
if (nameIncludesOperatorName(decl->name())) {
|
||||
CppRefactoringFilePtr file = refactoring.cppFile(op->filePath());
|
||||
const QString operatorNameText = file->textOf(declAST->core_declarator);
|
||||
const QString operatorNameText = op->currentFile()->textOf(declAST->core_declarator);
|
||||
oo.includeWhiteSpaceInOperatorName = operatorNameText.contains(QLatin1Char(' '));
|
||||
}
|
||||
const QString name = oo.prettyName(LookupContext::minimalName(decl, targetCoN,
|
||||
|
@@ -294,6 +294,7 @@ private:
|
||||
|
||||
// Force queued execution, as the built-in editor can run the callback synchronously.
|
||||
const auto followSymbol = [cursorInEditor, callback] {
|
||||
NonInteractiveFollowSymbolMarker niMarker;
|
||||
CppModelManager::followSymbol(
|
||||
cursorInEditor, callback, true, false, FollowSymbolMode::Exact);
|
||||
};
|
||||
|
@@ -86,10 +86,10 @@ public:
|
||||
};
|
||||
|
||||
MoveFuncDefRefactoringHelper(CppQuickFixOperation *operation, MoveType type,
|
||||
const FilePath &fromFile, const FilePath &toFile)
|
||||
const FilePath &toFile)
|
||||
: m_operation(operation), m_type(type), m_changes(m_operation->snapshot())
|
||||
{
|
||||
m_fromFile = m_changes.cppFile(fromFile);
|
||||
m_fromFile = operation->currentFile();
|
||||
m_toFile = (m_type == MoveOutside) ? m_fromFile : m_changes.cppFile(toFile);
|
||||
}
|
||||
|
||||
@@ -159,19 +159,18 @@ public:
|
||||
, m_funcDef(funcDef)
|
||||
, m_type(type)
|
||||
, m_cppFilePath(cppFilePath)
|
||||
, m_headerFilePath(funcDef->symbol->filePath())
|
||||
{
|
||||
if (m_type == MoveFuncDefRefactoringHelper::MoveOutside) {
|
||||
setDescription(Tr::tr("Move Definition Outside Class"));
|
||||
} else {
|
||||
const FilePath resolved = m_cppFilePath.relativePathFrom(m_headerFilePath.parentDir());
|
||||
const FilePath resolved = m_cppFilePath.relativePathFrom(filePath().parentDir());
|
||||
setDescription(Tr::tr("Move Definition to %1").arg(resolved.displayName()));
|
||||
}
|
||||
}
|
||||
|
||||
void perform() override
|
||||
{
|
||||
MoveFuncDefRefactoringHelper helper(this, m_type, m_headerFilePath, m_cppFilePath);
|
||||
MoveFuncDefRefactoringHelper helper(this, m_type, m_cppFilePath);
|
||||
helper.performMove(m_funcDef);
|
||||
helper.applyChanges();
|
||||
}
|
||||
@@ -180,7 +179,6 @@ private:
|
||||
FunctionDefinitionAST *m_funcDef;
|
||||
MoveFuncDefRefactoringHelper::MoveType m_type;
|
||||
const FilePath m_cppFilePath;
|
||||
const FilePath m_headerFilePath;
|
||||
};
|
||||
|
||||
class MoveAllFuncDefOutsideOp : public CppQuickFixOperation
|
||||
@@ -193,12 +191,11 @@ public:
|
||||
, m_type(type)
|
||||
, m_classDef(classDef)
|
||||
, m_cppFilePath(cppFileName)
|
||||
, m_headerFilePath(classDef->symbol->filePath())
|
||||
{
|
||||
if (m_type == MoveFuncDefRefactoringHelper::MoveOutside) {
|
||||
setDescription(Tr::tr("Definitions Outside Class"));
|
||||
} else {
|
||||
const FilePath resolved = m_cppFilePath.relativePathFrom(m_headerFilePath.parentDir());
|
||||
const FilePath resolved = m_cppFilePath.relativePathFrom(filePath().parentDir());
|
||||
setDescription(Tr::tr("Move All Function Definitions to %1")
|
||||
.arg(resolved.displayName()));
|
||||
}
|
||||
@@ -206,7 +203,7 @@ public:
|
||||
|
||||
void perform() override
|
||||
{
|
||||
MoveFuncDefRefactoringHelper helper(this, m_type, m_headerFilePath, m_cppFilePath);
|
||||
MoveFuncDefRefactoringHelper helper(this, m_type, m_cppFilePath);
|
||||
for (DeclarationListAST *it = m_classDef->member_specifier_list; it; it = it->next) {
|
||||
if (FunctionDefinitionAST *funcAST = it->value->asFunctionDefinition()) {
|
||||
if (funcAST->symbol && !funcAST->symbol->isGenerated())
|
||||
@@ -220,7 +217,6 @@ private:
|
||||
MoveFuncDefRefactoringHelper::MoveType m_type;
|
||||
ClassSpecifierAST *m_classDef;
|
||||
const FilePath m_cppFilePath;
|
||||
const FilePath m_headerFilePath;
|
||||
};
|
||||
|
||||
class MoveFuncDefToDeclOp : public CppQuickFixOperation
|
||||
|
@@ -235,29 +235,34 @@ public:
|
||||
private:
|
||||
void perform() override
|
||||
{
|
||||
const auto textDoc = const_cast<QTextDocument *>(currentFile()->document());
|
||||
const int pos = currentFile()->cppDocument()->translationUnit()->getTokenPositionInDocument(
|
||||
const CppRefactoringFilePtr file = currentFile();
|
||||
const auto textDoc = const_cast<QTextDocument *>(file->document());
|
||||
const int pos = file->cppDocument()->translationUnit()->getTokenPositionInDocument(
|
||||
m_symbol->sourceLocation(), textDoc);
|
||||
QTextCursor cursor(textDoc);
|
||||
cursor.setPosition(pos);
|
||||
const CursorInEditor cursorInEditor(cursor, currentFile()->filePath(), editor(),
|
||||
const CursorInEditor cursorInEditor(cursor, file->filePath(), editor(),
|
||||
editor()->textDocument());
|
||||
const auto callback = [symbolLoc = m_symbol->toLink(), comments = m_commentTokens]
|
||||
const auto callback = [symbolLoc = m_symbol->toLink(), comments = m_commentTokens, file]
|
||||
(const Link &link) {
|
||||
moveComments(link, symbolLoc, comments);
|
||||
moveComments(file, link, symbolLoc, comments);
|
||||
};
|
||||
NonInteractiveFollowSymbolMarker niMarker;
|
||||
CppCodeModelSettings::setInteractiveFollowSymbol(false);
|
||||
CppModelManager::followSymbol(cursorInEditor, callback, true, false,
|
||||
FollowSymbolMode::Exact);
|
||||
}
|
||||
|
||||
static void moveComments(const Link &targetLoc, const Link &symbolLoc,
|
||||
const QList<Token> &comments)
|
||||
static void moveComments(
|
||||
const CppRefactoringFilePtr &sourceFile,
|
||||
const Link &targetLoc,
|
||||
const Link &symbolLoc,
|
||||
const QList<Token> &comments)
|
||||
{
|
||||
if (!targetLoc.hasValidTarget() || targetLoc.hasSameLocation(symbolLoc))
|
||||
return;
|
||||
|
||||
CppRefactoringChanges changes(CppModelManager::snapshot());
|
||||
const CppRefactoringFilePtr sourceFile = changes.cppFile(symbolLoc.targetFilePath);
|
||||
const CppRefactoringFilePtr targetFile
|
||||
= targetLoc.targetFilePath == symbolLoc.targetFilePath
|
||||
? sourceFile
|
||||
|
@@ -41,6 +41,7 @@ public:
|
||||
setDescription(
|
||||
Tr::tr("Re-order Member Function Definitions According to Declaration Order"));
|
||||
m_state->decls = decls;
|
||||
m_state->currentFile = currentFile();
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -71,6 +72,7 @@ private:
|
||||
|
||||
QList<Symbol *> decls;
|
||||
QHash<FilePath, DefLocations> defLocations;
|
||||
CppRefactoringFilePtr currentFile;
|
||||
int remainingFollowSymbolOps = 0;
|
||||
};
|
||||
|
||||
@@ -120,6 +122,7 @@ private:
|
||||
|
||||
// Force queued execution, as the built-in editor can run the callback synchronously.
|
||||
const auto followSymbol = [cursorInEditor, callback] {
|
||||
NonInteractiveFollowSymbolMarker niMarker;
|
||||
CppModelManager::followSymbol(
|
||||
cursorInEditor, callback, true, false, FollowSymbolMode::Exact);
|
||||
};
|
||||
@@ -157,7 +160,9 @@ private:
|
||||
if (defLocsExpectedOrder == defLocsActualOrder)
|
||||
continue;
|
||||
|
||||
CppRefactoringFilePtr file = factory.cppFile(it.key());
|
||||
CppRefactoringFilePtr file = it.key() == state->currentFile->filePath()
|
||||
? state->currentFile
|
||||
: factory.cppFile(it.key());
|
||||
ChangeSet changes;
|
||||
for (int i = 0; i < defLocsActualOrder.size(); ++i) {
|
||||
const DefLocation &actualLoc = defLocsActualOrder[i];
|
||||
|
@@ -15,7 +15,7 @@
|
||||
"Category" : "Qt Creator",
|
||||
"Description" : "Design Qt-widgets based UIs",
|
||||
"LongDescription" : [
|
||||
"Create widgets and forms that are integrated with Qt C++ code.",
|
||||
"Create widgets and forms that are integrated with Qt C++ code."
|
||||
],
|
||||
"Url" : "https://www.qt.io",
|
||||
${DESIGNER_PLUGIN_ARGUMENTS}
|
||||
|
@@ -26,7 +26,6 @@
|
||||
#include <QAction>
|
||||
#include <QMainWindow>
|
||||
|
||||
using namespace ExtensionSystem;
|
||||
using namespace Core;
|
||||
using namespace Utils;
|
||||
|
||||
@@ -45,7 +44,7 @@ public:
|
||||
Theme::IconsBaseColor}});
|
||||
const Icon FLAT_ACTIVE({{":/extensionmanager/images/mode_extensionmanager_mask.png",
|
||||
Theme::IconsModeWelcomeActiveColor}});
|
||||
setIcon(Utils::Icon::modeIcon(FLAT, FLAT, FLAT_ACTIVE));
|
||||
setIcon(Icon::modeIcon(FLAT, FLAT, FLAT_ACTIVE));
|
||||
setPriority(72);
|
||||
|
||||
using namespace Layouting;
|
||||
|
@@ -280,7 +280,7 @@ void ExtensionManagerWidget::updateView(const QModelIndex ¤t)
|
||||
const LinksData linksData = current.data(RoleDescriptionLinks).value<LinksData>();
|
||||
if (!linksData.isEmpty()) {
|
||||
QString linksHtml;
|
||||
const QStringList links = Utils::transform(linksData, [](const LinksData::Type &link) {
|
||||
const QStringList links = transform(linksData, [](const LinksData::Type &link) {
|
||||
const QString anchor = link.first.isEmpty() ? link.second : link.first;
|
||||
return QString::fromLatin1("<a href=\"%1\">%2 ></a>")
|
||||
.arg(link.second).arg(anchor);
|
||||
@@ -293,7 +293,7 @@ void ExtensionManagerWidget::updateView(const QModelIndex ¤t)
|
||||
if (!imagesData.isEmpty()) {
|
||||
const QString examplesBoxCss =
|
||||
QString::fromLatin1("height: 168px; background-color: %1; ")
|
||||
.arg(creatorTheme()->color(Theme::Token_Background_Default).name());
|
||||
.arg(creatorColor(Theme::Token_Background_Default).name());
|
||||
description.append(QString(R"(
|
||||
<br/>
|
||||
<div style="%1">%2</div>
|
||||
@@ -362,8 +362,8 @@ void ExtensionManagerWidget::updateView(const QModelIndex ¤t)
|
||||
if (!tags.isEmpty()) {
|
||||
const QString tagTemplate = QString(R"(
|
||||
<td style="border: 1px solid %1; padding: 3px; ">%2</td>
|
||||
)").arg(creatorTheme()->color(Theme::Token_Stroke_Subtle).name());
|
||||
const QStringList tagsFmt = Utils::transform(tags, [&tagTemplate](const QString &tag) {
|
||||
)").arg(creatorColor(Theme::Token_Stroke_Subtle).name());
|
||||
const QStringList tagsFmt = transform(tags, [&tagTemplate](const QString &tag) {
|
||||
return tagTemplate.arg(tag);
|
||||
});
|
||||
description.append(QString(R"(
|
||||
@@ -397,8 +397,7 @@ void ExtensionManagerWidget::updateView(const QModelIndex ¤t)
|
||||
|
||||
if (isPack) {
|
||||
const PluginsData plugins = current.data(RolePlugins).value<PluginsData>();
|
||||
const QStringList extensions = Utils::transform(plugins,
|
||||
&QPair<QString, QString>::first);
|
||||
const QStringList extensions = transform(plugins, &QPair<QString, QString>::first);
|
||||
const QString extensionsFmt = extensions.join("<br/>");
|
||||
description.append(QString(R"(
|
||||
<div style="%1">%2</div>
|
||||
@@ -422,7 +421,7 @@ void ExtensionManagerWidget::fetchAndInstallPlugin(const QUrl &url)
|
||||
StorageStruct() {
|
||||
progressDialog.reset(new QProgressDialog(Tr::tr("Downloading Plugin..."),
|
||||
Tr::tr("Cancel"), 0, 0,
|
||||
Core::ICore::dialogParent()));
|
||||
ICore::dialogParent()));
|
||||
progressDialog->setWindowModality(Qt::ApplicationModal);
|
||||
progressDialog->setFixedSize(progressDialog->sizeHint());
|
||||
progressDialog->setAutoClose(false);
|
||||
|
@@ -198,7 +198,7 @@ ExtensionsBrowser::ExtensionsBrowser(QWidget *parent)
|
||||
auto manageLabel = new QLabel(Tr::tr("Manage Extensions"));
|
||||
manageLabel->setFont(StyleHelper::uiFont(StyleHelper::UiElementH1));
|
||||
|
||||
d->searchBox = new Core::SearchBox;
|
||||
d->searchBox = new SearchBox;
|
||||
d->searchBox->setFixedWidth(itemSize.width());
|
||||
|
||||
d->updateButton = new Button(Tr::tr("Install..."), Button::MediumPrimary);
|
||||
@@ -252,10 +252,8 @@ ExtensionsBrowser::ExtensionsBrowser(QWidget *parent)
|
||||
connect(d->updateButton, &QAbstractButton::pressed, this, []() {
|
||||
executePluginInstallWizard();
|
||||
});
|
||||
connect(ExtensionSystem::PluginManager::instance(),
|
||||
&ExtensionSystem::PluginManager::pluginsChanged, this, updateModel);
|
||||
connect(ExtensionSystem::PluginManager::instance(),
|
||||
&ExtensionSystem::PluginManager::initializationDone,
|
||||
connect(PluginManager::instance(), &PluginManager::pluginsChanged, this, updateModel);
|
||||
connect(PluginManager::instance(), &PluginManager::initializationDone,
|
||||
this, &ExtensionsBrowser::fetchExtensions);
|
||||
connect(d->searchBox, &QLineEdit::textChanged,
|
||||
d->filterProxyModel, &QSortFilterProxyModel::setFilterWildcard);
|
||||
|
@@ -3,9 +3,6 @@
|
||||
|
||||
#include "extensionsmodel.h"
|
||||
|
||||
#include "extensionsbrowser.h"
|
||||
|
||||
#include "extensionmanagertr.h"
|
||||
#include "utils/algorithm.h"
|
||||
|
||||
#include <coreplugin/coreconstants.h>
|
||||
@@ -30,16 +27,16 @@ namespace ExtensionManager::Internal {
|
||||
|
||||
Q_LOGGING_CATEGORY(modelLog, "qtc.extensionmanager.model", QtWarningMsg)
|
||||
|
||||
struct PluginDependency
|
||||
struct Dependency
|
||||
{
|
||||
QString name;
|
||||
QString version;
|
||||
};
|
||||
using PluginDependencies = QList<PluginDependency>;
|
||||
using Dependencies = QList<Dependency>;
|
||||
|
||||
struct Plugin
|
||||
{
|
||||
PluginDependencies dependencies;
|
||||
Dependencies dependencies;
|
||||
QString copyright;
|
||||
QString name;
|
||||
QString packageUrl;
|
||||
@@ -74,10 +71,10 @@ static Plugin pluginFromJson(const QJsonObject &obj)
|
||||
const QJsonObject metaDataObj = obj.value("meta_data").toObject();
|
||||
|
||||
const QJsonArray dependenciesArray = metaDataObj.value("Dependencies").toArray();
|
||||
PluginDependencies dependencies;
|
||||
Dependencies dependencies;
|
||||
for (const QJsonValueConstRef &dependencyVal : dependenciesArray) {
|
||||
const QJsonObject dependencyObj = dependencyVal.toObject();
|
||||
dependencies.append(PluginDependency{
|
||||
dependencies.append(Dependency{
|
||||
.name = dependencyObj.value("Name").toString(),
|
||||
.version = dependencyObj.value("Version").toString(),
|
||||
});
|
||||
@@ -189,19 +186,12 @@ static Extensions parseExtensionsRepoReply(const QByteArray &jsonData)
|
||||
return parsedExtensions;
|
||||
}
|
||||
|
||||
class ExtensionsModelPrivate : public QObject
|
||||
class ExtensionsModelPrivate
|
||||
{
|
||||
public:
|
||||
ExtensionsModelPrivate(ExtensionsModel *parent)
|
||||
: q(parent)
|
||||
{
|
||||
}
|
||||
|
||||
void setExtensions(const Extensions &extensions);
|
||||
void removeLocalExtensions();
|
||||
|
||||
ExtensionsModel *q;
|
||||
|
||||
Extensions allExtensions; // Original, complete extensions entries
|
||||
Extensions absentExtensions; // All packs + plugin extensions that are not (yet) installed
|
||||
};
|
||||
@@ -224,7 +214,7 @@ void ExtensionsModelPrivate::removeLocalExtensions()
|
||||
|
||||
ExtensionsModel::ExtensionsModel(QObject *parent)
|
||||
: QAbstractListModel(parent)
|
||||
, d(new ExtensionsModelPrivate(this))
|
||||
, d(new ExtensionsModelPrivate)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -250,7 +240,7 @@ static QVariant dataFromPluginSpec(const PluginSpec *pluginSpec, int role)
|
||||
return pluginSpec->copyright();
|
||||
case RoleDependencies: {
|
||||
QStringList dependencies = transform(pluginSpec->dependencies(),
|
||||
&ExtensionSystem::PluginDependency::toString);
|
||||
&PluginDependency::toString);
|
||||
dependencies.sort();
|
||||
return dependencies;
|
||||
}
|
||||
@@ -301,7 +291,7 @@ static QStringList dependenciesFromExtension(const Extension &extension)
|
||||
{
|
||||
QStringList dependencies;
|
||||
for (const Plugin &plugin : extension.plugins) {
|
||||
for (const PluginDependency &dependency : plugin.dependencies) {
|
||||
for (const Dependency &dependency : plugin.dependencies) {
|
||||
const QString withVersion = QString::fromLatin1("%1 (%2)").arg(dependency.name)
|
||||
.arg(dependency.version);
|
||||
dependencies.append(withVersion);
|
||||
@@ -404,8 +394,7 @@ void ExtensionsModel::setExtensionsJson(const QByteArray &json)
|
||||
|
||||
PluginSpec *ExtensionsModel::pluginSpecForName(const QString &pluginName)
|
||||
{
|
||||
return Utils::findOrDefault(PluginManager::plugins(),
|
||||
Utils::equal(&PluginSpec::name, pluginName));
|
||||
return findOrDefault(PluginManager::plugins(), equal(&PluginSpec::name, pluginName));
|
||||
}
|
||||
|
||||
} // ExtensionManager::Internal
|
||||
|
@@ -39,10 +39,15 @@ add_qtc_plugin(Lua
|
||||
meta/simpletypes.lua
|
||||
meta/utils.lua
|
||||
meta/widgets.lua
|
||||
meta/wizard.lua
|
||||
# generateqtbindings.cpp # Use this if you need to generate some code.
|
||||
)
|
||||
|
||||
qt_add_resources(Lua lua_images_rcc
|
||||
PREFIX "/lua"
|
||||
FILES
|
||||
images/settingscategory_lua.png
|
||||
images/settingscategory_lua@2x.png
|
||||
)
|
||||
|
||||
set_source_files_properties(luauibindings.cpp PROPERTY SKIP_AUTOMOC ON PROPERTY SKIP_AUTOGEN ON)
|
||||
|
||||
@@ -66,7 +71,6 @@ set(META_FILES
|
||||
meta/simpletypes.lua
|
||||
meta/utils.lua
|
||||
meta/widgets.lua
|
||||
meta/wizard.lua
|
||||
)
|
||||
|
||||
qtc_copy_to_builddir(copy_lua_meta_files
|
||||
|
@@ -3,11 +3,22 @@
|
||||
|
||||
#include "../luaengine.h"
|
||||
#include "../luaqttypes.h"
|
||||
#include "../luatr.h"
|
||||
|
||||
#include <coreplugin/dialogs/ioptionspage.h>
|
||||
#include <coreplugin/icore.h>
|
||||
|
||||
#include <utils/aspects.h>
|
||||
#include <utils/infobar.h>
|
||||
#include <utils/layoutbuilder.h>
|
||||
#include <utils/networkaccessmanager.h>
|
||||
#include <utils/stylehelper.h>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QCheckBox>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonDocument>
|
||||
#include <QMessageBox>
|
||||
#include <QMetaEnum>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QNetworkReply>
|
||||
@@ -37,35 +48,205 @@ static QString opToString(QNetworkAccessManager::Operation op)
|
||||
|
||||
void addFetchModule()
|
||||
{
|
||||
LuaEngine::registerProvider(
|
||||
"Fetch", [](sol::state_view lua) -> sol::object {
|
||||
const ScriptPluginSpec *pluginSpec = lua.get<ScriptPluginSpec *>("PluginSpec");
|
||||
class Module : Utils::AspectContainer
|
||||
{
|
||||
Utils::StringListAspect pluginsAllowedToFetch{this};
|
||||
Utils::StringListAspect pluginsNotAllowedToFetch{this};
|
||||
|
||||
sol::table async = lua.script("return require('async')", "_fetch_").get<sol::table>();
|
||||
sol::function wrap = async["wrap"];
|
||||
class LuaOptionsPage : public Core::IOptionsPage
|
||||
{
|
||||
public:
|
||||
LuaOptionsPage(Module *module)
|
||||
{
|
||||
setId("BB.Lua.Fetch");
|
||||
setDisplayName(Tr::tr("Network access"));
|
||||
setCategory("ZY.Lua");
|
||||
setDisplayCategory("Lua");
|
||||
setCategoryIconPath(":/lua/images/settingscategory_lua.png");
|
||||
setSettingsProvider(
|
||||
[module] { return static_cast<Utils::AspectContainer *>(module); });
|
||||
}
|
||||
};
|
||||
|
||||
sol::table fetch = lua.create_table();
|
||||
LuaOptionsPage settingsPage{this};
|
||||
|
||||
auto networkReplyType = lua.new_usertype<QNetworkReply>(
|
||||
"QNetworkReply",
|
||||
"error",
|
||||
sol::property([](QNetworkReply *self) -> int { return self->error(); }),
|
||||
"readAll",
|
||||
[](QNetworkReply *r) { return r->readAll().toStdString(); },
|
||||
"__tostring",
|
||||
[](QNetworkReply *r) {
|
||||
return QString("QNetworkReply(%1 \"%2\") => %3")
|
||||
.arg(opToString(r->operation()))
|
||||
.arg(r->url().toString())
|
||||
.arg(r->error());
|
||||
});
|
||||
public:
|
||||
Module()
|
||||
{
|
||||
setSettingsGroup("Lua.Fetch");
|
||||
|
||||
fetch["fetch_cb"] = [guard = pluginSpec->connectionGuard.get()](
|
||||
const sol::table &options,
|
||||
const sol::function &callback,
|
||||
const sol::this_state &thisState) {
|
||||
auto url = options.get<QString>("url");
|
||||
pluginsAllowedToFetch.setSettingsKey("pluginsAllowedToFetch");
|
||||
pluginsAllowedToFetch.setLabelText("Plugins allowed to fetch data from the internet");
|
||||
pluginsAllowedToFetch.setToolTip(
|
||||
"List of plugins that are allowed to fetch data from the internet");
|
||||
pluginsAllowedToFetch.setUiAllowAdding(false);
|
||||
pluginsAllowedToFetch.setUiAllowEditing(false);
|
||||
|
||||
pluginsNotAllowedToFetch.setSettingsKey("pluginsNotAllowedToFetch");
|
||||
pluginsNotAllowedToFetch.setLabelText(
|
||||
"Plugins not allowed to fetch data from the internet");
|
||||
pluginsNotAllowedToFetch.setToolTip(
|
||||
"List of plugins that are not allowed to fetch data from the internet");
|
||||
pluginsNotAllowedToFetch.setUiAllowAdding(false);
|
||||
pluginsNotAllowedToFetch.setUiAllowEditing(false);
|
||||
|
||||
setLayouter([this] {
|
||||
using namespace Layouting;
|
||||
// clang-format off
|
||||
return Form {
|
||||
pluginsAllowedToFetch, br,
|
||||
pluginsNotAllowedToFetch, br,
|
||||
};
|
||||
// clang-format on
|
||||
});
|
||||
|
||||
readSettings();
|
||||
}
|
||||
|
||||
~Module() { writeSettings(); }
|
||||
|
||||
enum class IsAllowed { Yes, No, NeedsToAsk };
|
||||
|
||||
IsAllowed isAllowedToFetch(const QString &pluginName) const
|
||||
{
|
||||
if (pluginsAllowedToFetch().contains(pluginName))
|
||||
return IsAllowed::Yes;
|
||||
if (pluginsNotAllowedToFetch().contains(pluginName))
|
||||
return IsAllowed::No;
|
||||
return IsAllowed::NeedsToAsk;
|
||||
}
|
||||
|
||||
void setAllowedToFetch(const QString &pluginName, IsAllowed allowed)
|
||||
{
|
||||
if (allowed == IsAllowed::Yes)
|
||||
pluginsAllowedToFetch.appendValue(pluginName);
|
||||
else if (allowed == IsAllowed::No)
|
||||
pluginsNotAllowedToFetch.appendValue(pluginName);
|
||||
|
||||
if (allowed == IsAllowed::Yes)
|
||||
pluginsNotAllowedToFetch.removeValue(pluginName);
|
||||
else if (allowed == IsAllowed::No)
|
||||
pluginsAllowedToFetch.removeValue(pluginName);
|
||||
}
|
||||
};
|
||||
|
||||
std::shared_ptr<Module> module = std::make_shared<Module>();
|
||||
|
||||
LuaEngine::registerProvider("Fetch", [mod = std::move(module)](sol::state_view lua) -> sol::object {
|
||||
const ScriptPluginSpec *pluginSpec = lua.get<ScriptPluginSpec *>("PluginSpec");
|
||||
|
||||
sol::table async = lua.script("return require('async')", "_fetch_").get<sol::table>();
|
||||
sol::function wrap = async["wrap"];
|
||||
|
||||
sol::table fetch = lua.create_table();
|
||||
|
||||
auto networkReplyType = lua.new_usertype<QNetworkReply>(
|
||||
"QNetworkReply",
|
||||
"error",
|
||||
sol::property([](QNetworkReply *self) -> int { return self->error(); }),
|
||||
"readAll",
|
||||
[](QNetworkReply *r) { return r->readAll().toStdString(); },
|
||||
"__tostring",
|
||||
[](QNetworkReply *r) {
|
||||
return QString("QNetworkReply(%1 \"%2\") => %3")
|
||||
.arg(opToString(r->operation()))
|
||||
.arg(r->url().toString())
|
||||
.arg(r->error());
|
||||
});
|
||||
|
||||
auto checkPermission = [mod,
|
||||
pluginName = pluginSpec->name,
|
||||
guard = pluginSpec->connectionGuard.get()](
|
||||
QString url,
|
||||
std::function<void()> fetch,
|
||||
std::function<void()> notAllowed) {
|
||||
auto isAllowed = mod->isAllowedToFetch(pluginName);
|
||||
if (isAllowed == Module::IsAllowed::Yes) {
|
||||
fetch();
|
||||
return;
|
||||
}
|
||||
|
||||
if (isAllowed == Module::IsAllowed::No) {
|
||||
notAllowed();
|
||||
return;
|
||||
}
|
||||
|
||||
if (QApplication::activeModalWidget()) {
|
||||
// We are already showing a modal dialog,
|
||||
// so we have to use a QMessageBox instead of the info bar
|
||||
auto msgBox = new QMessageBox(
|
||||
QMessageBox::Question,
|
||||
Tr::tr("Allow Internet access"),
|
||||
Tr::tr("The plugin \"%1\" would like to fetch from the following url:\n%2")
|
||||
.arg(pluginName)
|
||||
.arg(url),
|
||||
QMessageBox::Yes | QMessageBox::No,
|
||||
Core::ICore::dialogParent());
|
||||
msgBox->setCheckBox(new QCheckBox(Tr::tr("Remember choice")));
|
||||
|
||||
QObject::connect(
|
||||
msgBox, &QMessageBox::accepted, guard, [mod, fetch, pluginName, msgBox]() {
|
||||
if (msgBox->checkBox()->isChecked())
|
||||
mod->setAllowedToFetch(pluginName, Module::IsAllowed::Yes);
|
||||
fetch();
|
||||
});
|
||||
|
||||
QObject::connect(
|
||||
msgBox, &QMessageBox::rejected, guard, [mod, notAllowed, pluginName, msgBox]() {
|
||||
if (msgBox->checkBox()->isChecked())
|
||||
mod->setAllowedToFetch(pluginName, Module::IsAllowed::No);
|
||||
notAllowed();
|
||||
});
|
||||
|
||||
msgBox->show();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Utils::InfoBarEntry entry{
|
||||
Utils::Id::fromString("Fetch" + pluginName),
|
||||
Tr::tr("The plugin \"%1\" would like to fetch data from the internet. Do "
|
||||
"you want to allow this?")
|
||||
.arg(pluginName)};
|
||||
entry.setDetailsWidgetCreator([pluginName, url] {
|
||||
const QString markdown = Tr::tr("The plugin \"**%1**\" would like to fetch "
|
||||
"from the following url:\n\n")
|
||||
.arg(pluginName)
|
||||
+ QString("* [%3](%3)").arg(url);
|
||||
|
||||
QLabel *list = new QLabel();
|
||||
list->setTextFormat(Qt::TextFormat::MarkdownText);
|
||||
list->setText(markdown);
|
||||
list->setMargin(Utils::StyleHelper::SpacingTokens::ExPaddingGapS);
|
||||
return list;
|
||||
});
|
||||
entry.addCustomButton(Tr::tr("Always Allow"), [mod, pluginName, fetch]() {
|
||||
mod->setAllowedToFetch(pluginName, Module::IsAllowed::Yes);
|
||||
Core::ICore::infoBar()->removeInfo(Utils::Id::fromString("Fetch" + pluginName));
|
||||
fetch();
|
||||
});
|
||||
entry.addCustomButton(Tr::tr("Allow once"), [pluginName, fetch]() {
|
||||
Core::ICore::infoBar()->removeInfo(Utils::Id::fromString("Fetch" + pluginName));
|
||||
fetch();
|
||||
});
|
||||
|
||||
entry.setCancelButtonInfo(Tr::tr("Deny"), [mod, notAllowed, pluginName]() {
|
||||
Core::ICore::infoBar()->removeInfo(Utils::Id::fromString("Fetch" + pluginName));
|
||||
mod->setAllowedToFetch(pluginName, Module::IsAllowed::No);
|
||||
notAllowed();
|
||||
});
|
||||
Core::ICore::infoBar()->addInfo(entry);
|
||||
};
|
||||
|
||||
fetch["fetch_cb"] = [checkPermission,
|
||||
pluginName = pluginSpec->name,
|
||||
guard = pluginSpec->connectionGuard.get(),
|
||||
mod](
|
||||
const sol::table &options,
|
||||
const sol::function &callback,
|
||||
const sol::this_state &thisState) {
|
||||
auto url = options.get<QString>("url");
|
||||
auto actualFetch = [guard, url, options, callback, thisState]() {
|
||||
auto method = (options.get_or<QString>("method", "GET")).toLower();
|
||||
auto headers = options.get_or<sol::table>("headers", {});
|
||||
auto data = options.get_or<QString>("body", {});
|
||||
@@ -129,10 +310,17 @@ void addFetchModule()
|
||||
}
|
||||
};
|
||||
|
||||
fetch["fetch"] = wrap(fetch["fetch_cb"]);
|
||||
checkPermission(url, actualFetch, [callback, pluginName]() {
|
||||
callback(Tr::tr("Fetching is not allowed for the plugin \"%1\" (You can edit "
|
||||
"permissions in Preferences => Lua)")
|
||||
.arg(pluginName));
|
||||
});
|
||||
};
|
||||
|
||||
return fetch;
|
||||
});
|
||||
fetch["fetch"] = wrap(fetch["fetch_cb"]);
|
||||
|
||||
return fetch;
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace Lua::Internal
|
||||
|
@@ -17,8 +17,10 @@
|
||||
#include <utils/stylehelper.h>
|
||||
#include <utils/unarchiver.h>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QJsonDocument>
|
||||
#include <QLabel>
|
||||
#include <QMessageBox>
|
||||
#include <QTemporaryFile>
|
||||
#include <QtConcurrent>
|
||||
|
||||
@@ -159,6 +161,7 @@ static Group installRecipe(
|
||||
emitResult(sourceAndCommand.error());
|
||||
return SetupResult::StopWithError;
|
||||
}
|
||||
unarchiver.setGZipFileDestName(installOptionsIt->name);
|
||||
unarchiver.setSourceAndCommand(*sourceAndCommand);
|
||||
unarchiver.setDestDir(destination(appDataPath, *installOptionsIt));
|
||||
return SetupResult::Continue;
|
||||
@@ -170,6 +173,12 @@ static Group installRecipe(
|
||||
if (result == DoneWith::Cancel)
|
||||
return DoneResult::Error;
|
||||
|
||||
const FilePath destDir = destination(appDataPath, *installOptionsIt);
|
||||
const FilePath binary = destDir / installOptionsIt->name;
|
||||
|
||||
if (binary.isFile())
|
||||
binary.setPermissions(QFile::ExeUser | QFile::ExeGroup | QFile::ExeOther);
|
||||
|
||||
expected_str<QJsonDocument> doc = getOrCreatePackageInfo(appDataPath);
|
||||
if (!doc)
|
||||
return emitResult(doc.error());
|
||||
@@ -178,7 +187,7 @@ static Group installRecipe(
|
||||
QJsonObject installedPackage;
|
||||
installedPackage["version"] = installOptionsIt->version;
|
||||
installedPackage["name"] = installOptionsIt->name;
|
||||
installedPackage["path"] = destination(appDataPath, *installOptionsIt).toFSPathString();
|
||||
installedPackage["path"] = destDir.toFSPathString();
|
||||
obj[installOptionsIt->name] = installedPackage;
|
||||
|
||||
expected_str<void> res = savePackageInfo(appDataPath, QJsonDocument(obj));
|
||||
@@ -301,41 +310,71 @@ void addInstallModule()
|
||||
installOptionsList.append({url, name, version});
|
||||
}
|
||||
|
||||
auto install = [&state, pluginSpec, installOptionsList, callback]() {
|
||||
auto tree = state.createTree();
|
||||
|
||||
auto progress = new TaskProgress(tree);
|
||||
progress->setDisplayName(Tr::tr("Installing package(s) %1").arg("..."));
|
||||
|
||||
tree->setRecipe(
|
||||
installRecipe(pluginSpec->appDataPath, installOptionsList, callback));
|
||||
tree->start();
|
||||
};
|
||||
|
||||
auto denied = [callback]() { callback(false, "User denied installation"); };
|
||||
|
||||
if (QApplication::activeModalWidget()) {
|
||||
auto msgBox = new QMessageBox(
|
||||
QMessageBox::Question,
|
||||
Tr::tr("Install package"),
|
||||
msg,
|
||||
QMessageBox::Yes | QMessageBox::No,
|
||||
Core::ICore::dialogParent());
|
||||
|
||||
const QString details
|
||||
= Tr::tr("The plugin \"%1\" would like to install the following "
|
||||
"package(s):\n\n")
|
||||
.arg(pluginSpec->name)
|
||||
+ Utils::transform(installOptionsList, [](const InstallOptions &options) {
|
||||
return QString("* %1 - %2 (from: %3)")
|
||||
.arg(options.name, options.version, options.url.toString());
|
||||
}).join("\n");
|
||||
|
||||
msgBox->setDetailedText(details);
|
||||
|
||||
auto guard = pluginSpec->connectionGuard.get();
|
||||
QObject::connect(msgBox, &QMessageBox::accepted, guard, install);
|
||||
QObject::connect(msgBox, &QMessageBox::rejected, guard, denied);
|
||||
|
||||
msgBox->show();
|
||||
return;
|
||||
}
|
||||
|
||||
const Utils::Id infoBarId = Utils::Id::fromString(
|
||||
"Install" + pluginSpec->name + QString::number(qHash(installOptionsList)));
|
||||
|
||||
InfoBarEntry entry(infoBarId, msg, InfoBarEntry::GlobalSuppression::Enabled);
|
||||
|
||||
entry.addCustomButton(
|
||||
Tr::tr("Install"),
|
||||
[infoBarId, &state, pluginSpec, installOptionsList, callback]() {
|
||||
auto tree = state.createTree();
|
||||
entry.addCustomButton(Tr::tr("Install"), [install, infoBarId]() {
|
||||
install();
|
||||
Core::ICore::infoBar()->removeInfo(infoBarId);
|
||||
});
|
||||
|
||||
auto progress = new TaskProgress(tree);
|
||||
progress->setDisplayName(Tr::tr("Installing package(s) %1").arg("..."));
|
||||
entry.setCancelButtonInfo(denied);
|
||||
|
||||
tree->setRecipe(
|
||||
installRecipe(pluginSpec->appDataPath, installOptionsList, callback));
|
||||
tree->start();
|
||||
|
||||
Core::ICore::infoBar()->removeInfo(infoBarId);
|
||||
});
|
||||
entry.setCancelButtonInfo(
|
||||
[callback]() { callback(false, "User denied installation"); });
|
||||
|
||||
entry.setDetailsWidgetCreator([pluginSpec, installOptionsList]() -> QWidget * {
|
||||
const QString markdown
|
||||
= Tr::tr("The plugin \"**%1**\" would like to install the following "
|
||||
"package(s):\n\n")
|
||||
.arg(pluginSpec->name)
|
||||
+ Utils::transform(installOptionsList, [](const InstallOptions &options) {
|
||||
return QString("* %1 - %2 (from: [%3](%3))")
|
||||
.arg(options.name, options.version, options.url.toString());
|
||||
}).join("\n");
|
||||
const QString details
|
||||
= Tr::tr("The plugin \"**%1**\" would like to install the following "
|
||||
"package(s):\n\n")
|
||||
.arg(pluginSpec->name)
|
||||
+ Utils::transform(installOptionsList, [](const InstallOptions &options) {
|
||||
return QString("* %1 - %2 (from: [%3](%3))")
|
||||
.arg(options.name, options.version, options.url.toString());
|
||||
}).join("\n");
|
||||
|
||||
entry.setDetailsWidgetCreator([details]() -> QWidget * {
|
||||
QLabel *list = new QLabel();
|
||||
list->setTextFormat(Qt::TextFormat::MarkdownText);
|
||||
list->setText(markdown);
|
||||
list->setText(details);
|
||||
list->setMargin(StyleHelper::SpacingTokens::ExPaddingGapS);
|
||||
return list;
|
||||
});
|
||||
|
@@ -29,11 +29,22 @@ void addProcessModule()
|
||||
p->setEnvironment(Environment::systemEnvironment());
|
||||
|
||||
QObject::connect(p, &Process::done, guard, [p, cb]() { cb(p->exitCode()); });
|
||||
};
|
||||
|
||||
process["commandOutput_cb"] =
|
||||
[guard
|
||||
= pluginSpec->connectionGuard.get()](const QString &cmdline, const sol::function &cb) {
|
||||
Process *p = new Process;
|
||||
p->setCommand(CommandLine::fromUserInput((cmdline)));
|
||||
p->setEnvironment(Environment::systemEnvironment());
|
||||
|
||||
QObject::connect(p, &Process::done, guard, [p, cb]() { cb(p->allOutput()); });
|
||||
|
||||
p->start();
|
||||
};
|
||||
|
||||
process["runInTerminal"] = wrap(process["runInTerminal_cb"]);
|
||||
process["commandOutput"] = wrap(process["commandOutput_cb"]);
|
||||
|
||||
return process;
|
||||
});
|
||||
|
BIN
src/plugins/lua/images/settingscategory_lua.png
Normal file
BIN
src/plugins/lua/images/settingscategory_lua.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 513 B |
BIN
src/plugins/lua/images/settingscategory_lua@2x.png
Normal file
BIN
src/plugins/lua/images/settingscategory_lua@2x.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.1 KiB |
@@ -68,7 +68,6 @@ QtcPlugin {
|
||||
"simpletypes.lua",
|
||||
"utils.lua",
|
||||
"widgets.lua",
|
||||
"wizard.lua",
|
||||
]
|
||||
qbs.install: true
|
||||
qbs.installDir: qtc.ide_data_path + "/lua/meta/"
|
||||
|
@@ -4,6 +4,7 @@
|
||||
#include "luaengine.h"
|
||||
|
||||
#include "luapluginspec.h"
|
||||
#include "luatr.h"
|
||||
|
||||
#include <coreplugin/icore.h>
|
||||
#include <coreplugin/messagemanager.h>
|
||||
@@ -172,14 +173,6 @@ expected_str<void> LuaEngine::connectHooks(
|
||||
return {};
|
||||
}
|
||||
|
||||
expected_str<void> LuaEngine::connectHooks(sol::state_view lua, const sol::table &hookTable)
|
||||
{
|
||||
if (!hookTable)
|
||||
return {};
|
||||
|
||||
return instance().connectHooks(lua, hookTable, "");
|
||||
}
|
||||
|
||||
expected_str<LuaPluginSpec *> LuaEngine::loadPlugin(const Utils::FilePath &path)
|
||||
{
|
||||
auto contents = path.fileContents();
|
||||
@@ -204,12 +197,16 @@ expected_str<LuaPluginSpec *> LuaEngine::loadPlugin(const Utils::FilePath &path)
|
||||
sol::table pluginInfo = result.get<sol::table>();
|
||||
if (!pluginInfo.valid())
|
||||
return make_unexpected(QString("Script did not return a table with plugin info"));
|
||||
return LuaPluginSpec::create(path, std::move(lua), pluginInfo);
|
||||
return LuaPluginSpec::create(path, pluginInfo);
|
||||
}
|
||||
|
||||
expected_str<void> LuaEngine::prepareSetup(
|
||||
sol::state_view &lua, const LuaPluginSpec &pluginSpec, sol::optional<sol::table> hookTable)
|
||||
expected_str<sol::protected_function> LuaEngine::prepareSetup(
|
||||
sol::state_view lua, const LuaPluginSpec &pluginSpec)
|
||||
{
|
||||
auto contents = pluginSpec.filePath().fileContents();
|
||||
if (!contents)
|
||||
return make_unexpected(contents.error());
|
||||
|
||||
// TODO: Only open libraries requested by the plugin
|
||||
lua.open_libraries(
|
||||
sol::lib::base,
|
||||
@@ -261,10 +258,29 @@ expected_str<void> LuaEngine::prepareSetup(
|
||||
for (const auto &func : d->m_autoProviders)
|
||||
func(lua);
|
||||
|
||||
if (hookTable)
|
||||
return LuaEngine::connectHooks(lua, *hookTable);
|
||||
sol::protected_function_result result = lua.safe_script(
|
||||
std::string_view(contents->data(), contents->size()),
|
||||
sol::script_pass_on_error,
|
||||
pluginSpec.filePath().fileName().toUtf8().constData());
|
||||
|
||||
return {};
|
||||
auto pluginTable = result.get<sol::optional<sol::table>>();
|
||||
if (!pluginTable)
|
||||
return make_unexpected(Tr::tr("Script did not return a table"));
|
||||
|
||||
auto hookTable = pluginTable->get<sol::optional<sol::table>>("hooks");
|
||||
|
||||
if (hookTable) {
|
||||
auto connectResult = connectHooks(lua, *hookTable, {});
|
||||
if (!connectResult)
|
||||
return make_unexpected(connectResult.error());
|
||||
}
|
||||
|
||||
auto setupFunction = pluginTable->get_or<sol::function>("setup", {});
|
||||
|
||||
if (!setupFunction)
|
||||
return make_unexpected(Tr::tr("Plugin info table did not contain a setup function"));
|
||||
|
||||
return setupFunction;
|
||||
}
|
||||
|
||||
bool LuaEngine::isCoroutine(lua_State *state)
|
||||
|
@@ -55,15 +55,13 @@ public:
|
||||
static LuaEngine &instance();
|
||||
|
||||
Utils::expected_str<LuaPluginSpec *> loadPlugin(const Utils::FilePath &path);
|
||||
Utils::expected_str<void> prepareSetup(
|
||||
sol::state_view &lua, const LuaPluginSpec &pluginSpec, sol::optional<sol::table> hookTable);
|
||||
Utils::expected_str<sol::protected_function> prepareSetup(
|
||||
sol::state_view lua, const LuaPluginSpec &pluginSpec);
|
||||
|
||||
static void registerProvider(const QString &packageName, const PackageProvider &provider);
|
||||
static void autoRegister(const std::function<void(sol::state_view)> ®isterFunction);
|
||||
static void registerHook(QString name, const std::function<void(sol::function)> &hookProvider);
|
||||
|
||||
static Utils::expected_str<void> connectHooks(sol::state_view lua, const sol::table &hookTable);
|
||||
|
||||
static bool isCoroutine(lua_State *state);
|
||||
|
||||
static sol::table toTable(const sol::state_view &lua, const QJsonValue &v);
|
||||
|
@@ -34,28 +34,19 @@ class LuaPluginSpecPrivate
|
||||
{
|
||||
public:
|
||||
FilePath pluginScriptPath;
|
||||
|
||||
sol::state lua;
|
||||
sol::table pluginTable;
|
||||
|
||||
sol::function setupFunction;
|
||||
bool printToOutputPane = false;
|
||||
std::unique_ptr<sol::state> activeLuaState;
|
||||
};
|
||||
|
||||
LuaPluginSpec::LuaPluginSpec()
|
||||
: d(new LuaPluginSpecPrivate())
|
||||
{}
|
||||
|
||||
expected_str<LuaPluginSpec *> LuaPluginSpec::create(const FilePath &filePath,
|
||||
sol::state lua,
|
||||
sol::table pluginTable)
|
||||
expected_str<LuaPluginSpec *> LuaPluginSpec::create(const FilePath &filePath, sol::table pluginTable)
|
||||
{
|
||||
std::unique_ptr<LuaPluginSpec> pluginSpec(new LuaPluginSpec());
|
||||
|
||||
pluginSpec->d->lua = std::move(lua);
|
||||
pluginSpec->d->pluginTable = pluginTable;
|
||||
|
||||
pluginSpec->d->setupFunction = pluginTable.get_or<sol::function>("setup", {});
|
||||
if (!pluginSpec->d->setupFunction)
|
||||
if (!pluginTable.get_or<sol::function>("setup", {}))
|
||||
return make_unexpected(QString("Plugin info table did not contain a setup function"));
|
||||
|
||||
QJsonValue v = LuaEngine::toJson(pluginTable);
|
||||
@@ -75,6 +66,7 @@ expected_str<LuaPluginSpec *> LuaPluginSpec::create(const FilePath &filePath,
|
||||
pluginSpec->setLocation(filePath.parentDir());
|
||||
|
||||
pluginSpec->d->pluginScriptPath = filePath;
|
||||
pluginSpec->d->printToOutputPane = pluginTable.get_or("printToOutputPane", false);
|
||||
|
||||
return pluginSpec.release();
|
||||
}
|
||||
@@ -94,16 +86,19 @@ bool LuaPluginSpec::loadLibrary()
|
||||
}
|
||||
bool LuaPluginSpec::initializePlugin()
|
||||
{
|
||||
expected_str<void> setupResult
|
||||
= LuaEngine::instance()
|
||||
.prepareSetup(d->lua, *this, d->pluginTable.get<sol::optional<sol::table>>("hooks"));
|
||||
QTC_ASSERT(!d->activeLuaState, return false);
|
||||
|
||||
std::unique_ptr<sol::state> activeLuaState = std::make_unique<sol::state>();
|
||||
|
||||
expected_str<sol::protected_function> setupResult
|
||||
= LuaEngine::instance().prepareSetup(*activeLuaState, *this);
|
||||
|
||||
if (!setupResult) {
|
||||
setError(Lua::Tr::tr("Failed to prepare plugin setup: %1").arg(setupResult.error()));
|
||||
return false;
|
||||
}
|
||||
|
||||
auto result = d->setupFunction.call();
|
||||
auto result = setupResult->call();
|
||||
|
||||
if (result.get_type() == sol::type::boolean && result.get<bool>() == false) {
|
||||
setError(Lua::Tr::tr("Plugin setup function returned false"));
|
||||
@@ -117,6 +112,8 @@ bool LuaPluginSpec::initializePlugin()
|
||||
}
|
||||
}
|
||||
|
||||
d->activeLuaState = std::move(activeLuaState);
|
||||
|
||||
setState(PluginSpec::State::Initialized);
|
||||
return true;
|
||||
}
|
||||
@@ -133,14 +130,18 @@ bool LuaPluginSpec::delayedInitialize()
|
||||
}
|
||||
ExtensionSystem::IPlugin::ShutdownFlag LuaPluginSpec::stop()
|
||||
{
|
||||
d->activeLuaState.reset();
|
||||
return ExtensionSystem::IPlugin::ShutdownFlag::SynchronousShutdown;
|
||||
}
|
||||
|
||||
void LuaPluginSpec::kill() {}
|
||||
void LuaPluginSpec::kill()
|
||||
{
|
||||
d->activeLuaState.reset();
|
||||
}
|
||||
|
||||
bool LuaPluginSpec::printToOutputPane() const
|
||||
{
|
||||
return d->pluginTable.get_or("printToOutputPane", false);
|
||||
return d->printToOutputPane;
|
||||
}
|
||||
|
||||
} // namespace Lua
|
||||
|
@@ -39,9 +39,8 @@ class LuaPluginSpec : public ExtensionSystem::PluginSpec
|
||||
LuaPluginSpec();
|
||||
|
||||
public:
|
||||
static Utils::expected_str<LuaPluginSpec *> create(const Utils::FilePath &filePath,
|
||||
sol::state lua,
|
||||
sol::table pluginTable);
|
||||
static Utils::expected_str<LuaPluginSpec *> create(
|
||||
const Utils::FilePath &filePath, sol::table pluginTable);
|
||||
|
||||
ExtensionSystem::IPlugin *plugin() const override;
|
||||
|
||||
|
@@ -8,4 +8,10 @@ local process = {}
|
||||
---@return number The exit code of the command
|
||||
function process.runInTerminal(cmd) end
|
||||
|
||||
---@async
|
||||
---Runs a command and returns the output!
|
||||
---@param cmd string The command to run
|
||||
---@return string The output of the command
|
||||
function process.commandOutput(cmd) end
|
||||
|
||||
return process
|
||||
|
@@ -1,61 +0,0 @@
|
||||
---@meta Wizard
|
||||
|
||||
---@module "Layout"
|
||||
local Layout = require("Layout")
|
||||
|
||||
---@module "Core"
|
||||
local Core = require("Core")
|
||||
|
||||
local wizard = {}
|
||||
|
||||
---@class (exact) WizardFactoryOptions
|
||||
---@field id string
|
||||
---@field displayName string
|
||||
---@field description string
|
||||
---@field category string
|
||||
---@field displayCategory string
|
||||
---@field icon? string
|
||||
---@field iconText? string
|
||||
---@field factory function A function returning a Wizard
|
||||
|
||||
--- Registers a wizard factory.
|
||||
---@param options WizardFactoryOptions
|
||||
function wizard.registerFactory(options) end
|
||||
|
||||
---@class Wizard
|
||||
Wizard = {}
|
||||
|
||||
---@class (exact) WizardPageOptions
|
||||
---@field title string
|
||||
---@field layout LayoutItem
|
||||
---@field initializePage? function The function called before showing the page
|
||||
|
||||
---Add a page to the wizard
|
||||
---@param options WizardPageOptions
|
||||
function Wizard:addPage(options) end
|
||||
|
||||
---@class SummaryPage
|
||||
Wizard.SummaryPage = {}
|
||||
|
||||
---Set the files to be shown on the summary page
|
||||
---@param generatedFiles Core.GeneratedFile[]
|
||||
function Wizard.SummaryPage:setFiles(generatedFiles) end
|
||||
|
||||
---@class SummaryPageOptions
|
||||
---@field title? string
|
||||
---@field initializePage? function The function called before showing the page
|
||||
|
||||
---Add a summary page to the wizard
|
||||
---@param options SummaryPageOptions
|
||||
---@return SummaryPage
|
||||
function Wizard:addSummaryPage(options) end
|
||||
|
||||
---@class WizardOptions
|
||||
---@field fileFactory function A function returning a GeneratedFile[]
|
||||
|
||||
---Create a wizard
|
||||
---@param options WizardOptions
|
||||
---@return Wizard
|
||||
function wizard.create(options) end
|
||||
|
||||
return wizard
|
@@ -7,6 +7,7 @@ local S = require('Settings')
|
||||
local Gui = require('Gui')
|
||||
local a = require('async')
|
||||
local fetch = require('Fetch').fetch
|
||||
local Install = require('Install')
|
||||
|
||||
Settings = {}
|
||||
|
||||
@@ -34,17 +35,12 @@ end
|
||||
|
||||
local function installOrUpdateServer()
|
||||
local data = a.wait(fetch({
|
||||
url = "https://api.github.com/repos/LuaLS/lua-language-server/releases?per_page=1",
|
||||
convertToTable = true,
|
||||
headers = {
|
||||
Accept = "application/vnd.github.v3+json",
|
||||
["X-GitHub-Api-Version"] = "2022-11-28"
|
||||
}
|
||||
url = "https://qtccache.qt.io/LuaLanguageServer/LatestRelease",
|
||||
convertToTable = true
|
||||
}))
|
||||
|
||||
if type(data) == "table" and #data > 0 then
|
||||
local r = data[1]
|
||||
Install = require('Install')
|
||||
local lspPkgInfo = Install.packageInfo("lua-language-server")
|
||||
if not lspPkgInfo or lspPkgInfo.version ~= r.tag_name then
|
||||
local osTr = { mac = "darwin", windows = "win32", linux = "linux" }
|
||||
@@ -83,7 +79,7 @@ local function installOrUpdateServer()
|
||||
binary = "bin/lua-language-server.exe"
|
||||
end
|
||||
|
||||
Settings.binary.defaultPath = lspPkgInfo.path:resolvePath(binary)
|
||||
Settings.binary:setValue(lspPkgInfo.path:resolvePath(binary))
|
||||
Settings:apply()
|
||||
return
|
||||
end
|
||||
@@ -138,31 +134,53 @@ local function layoutSettings()
|
||||
--- "using namespace Gui"
|
||||
local _ENV = using(Gui)
|
||||
|
||||
local installButton = {}
|
||||
|
||||
if Settings.binary.expandedValue:isExecutableFile() == false then
|
||||
installButton = {
|
||||
"Language server not found:",
|
||||
Row {
|
||||
PushButton {
|
||||
text = "Try to install lua language server",
|
||||
onClicked = function() a.sync(installServer)() end,
|
||||
},
|
||||
st
|
||||
}
|
||||
}
|
||||
end
|
||||
local layout = Form {
|
||||
Settings.binary, br,
|
||||
Settings.developMode, br,
|
||||
Settings.showSource, br,
|
||||
Settings.showNode, br,
|
||||
table.unpack(installButton)
|
||||
Row {
|
||||
PushButton {
|
||||
text = "Update Lua Language Server",
|
||||
onClicked = function() a.sync(installOrUpdateServer)() end,
|
||||
},
|
||||
st
|
||||
}
|
||||
}
|
||||
|
||||
return layout
|
||||
end
|
||||
|
||||
local function binaryFromPkg()
|
||||
local lspPkgInfo = Install.packageInfo("lua-language-server")
|
||||
if lspPkgInfo then
|
||||
local binary = "bin/lua-language-server"
|
||||
if Utils.HostOsInfo.isWindowsHost() then
|
||||
binary = "bin/lua-language-server.exe"
|
||||
end
|
||||
local binaryPath = lspPkgInfo.path:resolvePath(binary)
|
||||
if binaryPath:isExecutableFile() == true then
|
||||
return binaryPath
|
||||
end
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
local function findBinary()
|
||||
local binary = binaryFromPkg()
|
||||
if binary then
|
||||
return binary
|
||||
end
|
||||
|
||||
-- Search for the binary in the PATH
|
||||
local serverPath = Utils.FilePath.fromUserInput("lua-language-server")
|
||||
local absolute = a.wait(serverPath:searchInPath()):resolveSymlinks()
|
||||
if absolute:isExecutableFile() == true then
|
||||
return absolute
|
||||
end
|
||||
return serverPath
|
||||
end
|
||||
|
||||
local function setupAspect()
|
||||
---@class Settings: AspectContainer
|
||||
Settings = S.AspectContainer.create({
|
||||
@@ -176,14 +194,9 @@ local function setupAspect()
|
||||
labelText = "Binary:",
|
||||
toolTip = "The path to the lua-language-server binary.",
|
||||
expectedKind = S.Kind.ExistingCommand,
|
||||
defaultPath = Utils.FilePath.fromUserInput("lua-language-server"),
|
||||
defaultPath = findBinary(),
|
||||
})
|
||||
-- Search for the binary in the PATH
|
||||
local serverPath = Settings.binary.defaultPath
|
||||
local absolute = a.wait(serverPath:searchInPath()):resolveSymlinks()
|
||||
if absolute:isExecutableFile() == true then
|
||||
Settings.binary.defaultPath = absolute
|
||||
end
|
||||
|
||||
Settings.developMode = S.BoolAspect.create({
|
||||
settingsKey = "LuaCopilot.DevelopMode",
|
||||
displayName = "Enable Develop Mode",
|
||||
|
@@ -30,7 +30,7 @@ MercurialSettings::MercurialSettings()
|
||||
binaryPath.setExpectedKind(PathChooser::ExistingCommand);
|
||||
binaryPath.setDefaultValue(Constants::MERCURIALDEFAULT);
|
||||
binaryPath.setDisplayName(Tr::tr("Mercurial Command"));
|
||||
binaryPath.setHistoryCompleter("Bazaar.Command.History");
|
||||
binaryPath.setHistoryCompleter("Mercurial.Command.History");
|
||||
binaryPath.setLabelText(Tr::tr("Command:"));
|
||||
|
||||
userName.setDisplayStyle(StringAspect::LineEditDisplay);
|
||||
|
@@ -56,7 +56,7 @@ inline Utils::OutputLineParser::LinkSpecs MesonOutputParser::addTask(
|
||||
fileName,
|
||||
match.captured(lineNumberCapIndex).toInt());
|
||||
addTask(task);
|
||||
addLinkSpecForAbsoluteFilePath(linkSpecs, task.file, task.line, match, 1);
|
||||
addLinkSpecForAbsoluteFilePath(linkSpecs, task.file, task.line, task.column, match, 1);
|
||||
#else
|
||||
Q_UNUSED(type);
|
||||
Q_UNUSED(line);
|
||||
|
@@ -39,7 +39,7 @@ NimParser::Result NimParser::handleLine(const QString &lne, OutputFormat)
|
||||
const CompileTask t(type, message, absoluteFilePath(FilePath::fromUserInput(filename)),
|
||||
lineNumber);
|
||||
LinkSpecs linkSpecs;
|
||||
addLinkSpecForAbsoluteFilePath(linkSpecs, t.file, t.line, match, 1);
|
||||
addLinkSpecForAbsoluteFilePath(linkSpecs, t.file, t.line, t.column, match, 1);
|
||||
scheduleTask(t, 1);
|
||||
return {Status::Done, linkSpecs};
|
||||
}
|
||||
|
@@ -65,7 +65,7 @@ OutputLineParser::Result ClangParser::handleLine(const QString &line, OutputForm
|
||||
const int lineNo = match.captured(3).toInt();
|
||||
const int column = 0;
|
||||
LinkSpecs linkSpecs;
|
||||
addLinkSpecForAbsoluteFilePath(linkSpecs, filePath, lineNo, match, 2);
|
||||
addLinkSpecForAbsoluteFilePath(linkSpecs, filePath, lineNo, column, match, 2);
|
||||
createOrAmendTask(Task::Unknown, lne.trimmed(), lne, false,
|
||||
filePath, lineNo, column, linkSpecs);
|
||||
return {Status::InProgress, linkSpecs};
|
||||
@@ -84,7 +84,7 @@ OutputLineParser::Result ClangParser::handleLine(const QString &line, OutputForm
|
||||
|
||||
const FilePath filePath = absoluteFilePath(FilePath::fromUserInput(match.captured(1)));
|
||||
LinkSpecs linkSpecs;
|
||||
addLinkSpecForAbsoluteFilePath(linkSpecs, filePath, lineNo, match, 1);
|
||||
addLinkSpecForAbsoluteFilePath(linkSpecs, filePath, lineNo, column, match, 1);
|
||||
createOrAmendTask(taskType(match.captured(8)), match.captured(9), lne, false,
|
||||
filePath, lineNo, column, linkSpecs);
|
||||
return {Status::InProgress, linkSpecs};
|
||||
@@ -235,7 +235,7 @@ void ProjectExplorerTest::testClangOutputParser_data()
|
||||
68, 10,
|
||||
QVector<QTextLayout::FormatRange>()
|
||||
<< formatRange(34, 0)
|
||||
<< formatRange(34, 28, "olpfile:///usr/include/c++/4.6/utility::68::-1")
|
||||
<< formatRange(34, 28, "olpfile:///usr/include/c++/4.6/utility::68::10")
|
||||
<< formatRange(62, 93)))
|
||||
<< QString();
|
||||
|
||||
@@ -255,7 +255,7 @@ void ProjectExplorerTest::testClangOutputParser_data()
|
||||
567, 51,
|
||||
QVector<QTextLayout::FormatRange>()
|
||||
<< formatRange(74, 0)
|
||||
<< formatRange(74, 64, "olpfile:///home/code/src/creator/src/plugins/coreplugin/manhattanstyle.cpp::567::-1")
|
||||
<< formatRange(74, 64, "olpfile:///home/code/src/creator/src/plugins/coreplugin/manhattanstyle.cpp::567::51")
|
||||
<< formatRange(138, 202)))
|
||||
<< QString();
|
||||
|
||||
|
@@ -237,7 +237,7 @@ OutputLineParser::Result CustomParser::hasMatch(
|
||||
const int lineNumber = match.captured(expression.lineNumberCap()).toInt();
|
||||
const QString message = match.captured(expression.messageCap());
|
||||
LinkSpecs linkSpecs;
|
||||
addLinkSpecForAbsoluteFilePath(linkSpecs, fileName, lineNumber, match,
|
||||
addLinkSpecForAbsoluteFilePath(linkSpecs, fileName, lineNumber, -1, match,
|
||||
expression.fileNameCap());
|
||||
scheduleTask(CompileTask(taskType, message, fileName, lineNumber), 1);
|
||||
return {Status::Done, linkSpecs};
|
||||
|
@@ -221,7 +221,7 @@ OutputLineParser::Result GccParser::handleLine(const QString &line, OutputFormat
|
||||
const int lineNo = match.captured(2).toInt();
|
||||
const int column = match.captured(3).toInt();
|
||||
LinkSpecs linkSpecs;
|
||||
addLinkSpecForAbsoluteFilePath(linkSpecs, filePath, lineNo, match, "file");
|
||||
addLinkSpecForAbsoluteFilePath(linkSpecs, filePath, lineNo, column, match, "file");
|
||||
gccCreateOrAmendTask(
|
||||
Task::Unknown, lne.trimmed(), lne, false, filePath, lineNo, column, linkSpecs);
|
||||
return {Status::InProgress, linkSpecs};
|
||||
@@ -234,7 +234,7 @@ OutputLineParser::Result GccParser::handleLine(const QString &line, OutputFormat
|
||||
const FilePath filePath = absoluteFilePath(FilePath::fromUserInput(match.captured(3)));
|
||||
LinkSpecs linkSpecs;
|
||||
if (!filePath.isEmpty())
|
||||
addLinkSpecForAbsoluteFilePath(linkSpecs, filePath, -1, match, 3);
|
||||
addLinkSpecForAbsoluteFilePath(linkSpecs, filePath, -1, -1, match, 3);
|
||||
gccCreateOrAmendTask(type, match.captured(2), lne, false, filePath, -1, 0, linkSpecs);
|
||||
return {Status::Done, linkSpecs};
|
||||
}
|
||||
@@ -243,7 +243,12 @@ OutputLineParser::Result GccParser::handleLine(const QString &line, OutputFormat
|
||||
const FilePath filePath = absoluteFilePath(FilePath::fromUserInput(data->rawFilePath));
|
||||
LinkSpecs linkSpecs;
|
||||
addLinkSpecForAbsoluteFilePath(
|
||||
linkSpecs, filePath, data->line, data->fileOffset, data->rawFilePath.size());
|
||||
linkSpecs,
|
||||
filePath,
|
||||
data->line,
|
||||
data->column,
|
||||
data->fileOffset,
|
||||
data->rawFilePath.size());
|
||||
gccCreateOrAmendTask(
|
||||
data->type, data->description, lne, false, filePath, data->line, data->column, linkSpecs);
|
||||
return {Status::InProgress, linkSpecs};
|
||||
@@ -343,9 +348,9 @@ void ProjectExplorerTest::testGccOutputParsers_data()
|
||||
9, 0,
|
||||
QVector<QTextLayout::FormatRange>()
|
||||
<< formatRange(46, 0)
|
||||
<< formatRange(46, 29, "olpfile:///temp/test/untitled8/main.cpp::0::-1")
|
||||
<< formatRange(46, 29, "olpfile:///temp/test/untitled8/main.cpp::0::0")
|
||||
<< formatRange(75, 39)
|
||||
<< formatRange(114, 29, "olpfile:///temp/test/untitled8/main.cpp::9::-1")
|
||||
<< formatRange(114, 29, "olpfile:///temp/test/untitled8/main.cpp::9::0")
|
||||
<< formatRange(143, 56))
|
||||
<< CompileTask(Task::Error,
|
||||
"(Each undeclared identifier is reported only once for each function it appears in.)",
|
||||
@@ -514,9 +519,9 @@ void ProjectExplorerTest::testGccOutputParsers_data()
|
||||
264, 0,
|
||||
QVector<QTextLayout::FormatRange>()
|
||||
<< formatRange(45, 0)
|
||||
<< formatRange(45, 68, "olpfile:///home/code/src/creator/src/plugins/projectexplorer/gnumakeparser.cpp::0::-1")
|
||||
<< formatRange(45, 68, "olpfile:///home/code/src/creator/src/plugins/projectexplorer/gnumakeparser.cpp::0::0")
|
||||
<< formatRange(113, 106)
|
||||
<< formatRange(219, 68, "olpfile:///home/code/src/creator/src/plugins/projectexplorer/gnumakeparser.cpp::264::-1")
|
||||
<< formatRange(219, 68, "olpfile:///home/code/src/creator/src/plugins/projectexplorer/gnumakeparser.cpp::264::0")
|
||||
<< formatRange(287, 57))
|
||||
<< CompileTask(Task::Error,
|
||||
"expected ';' before ':' token",
|
||||
@@ -583,9 +588,9 @@ void ProjectExplorerTest::testGccOutputParsers_data()
|
||||
194, 0,
|
||||
QVector<QTextLayout::FormatRange>()
|
||||
<< formatRange(50, 0)
|
||||
<< formatRange(50, 67, "olpfile:///Qt/4.6.2-Symbian/s60sdk/epoc32/include/stdapis/stlport/stl/_tree.c::0::-1")
|
||||
<< formatRange(50, 67, "olpfile:///Qt/4.6.2-Symbian/s60sdk/epoc32/include/stdapis/stlport/stl/_tree.c::0::0")
|
||||
<< formatRange(117, 216)
|
||||
<< formatRange(333, 67, "olpfile:///Qt/4.6.2-Symbian/s60sdk/epoc32/include/stdapis/stlport/stl/_tree.c::194::-1")
|
||||
<< formatRange(333, 67, "olpfile:///Qt/4.6.2-Symbian/s60sdk/epoc32/include/stdapis/stlport/stl/_tree.c::194::0")
|
||||
<< formatRange(400, 64)))
|
||||
<< QString();
|
||||
|
||||
@@ -822,9 +827,9 @@ void ProjectExplorerTest::testGccOutputParsers_data()
|
||||
1134, 26,
|
||||
QVector<QTextLayout::FormatRange>()
|
||||
<< formatRange(26, 22)
|
||||
<< formatRange(48, 39, "olpfile:///Symbian/SDK/EPOC32/INCLUDE/GCCE/GCCE.h::15::-1")
|
||||
<< formatRange(48, 39, "olpfile:///Symbian/SDK/EPOC32/INCLUDE/GCCE/GCCE.h::15::0")
|
||||
<< formatRange(87, 46)
|
||||
<< formatRange(133, 50, "olpfile:///Symbian/SDK/epoc32/include/variant/Symbian_OS.hrh::1134::-1")
|
||||
<< formatRange(133, 50, "olpfile:///Symbian/SDK/epoc32/include/variant/Symbian_OS.hrh::1134::26")
|
||||
<< formatRange(183, 44))}
|
||||
<< QString();
|
||||
|
||||
@@ -929,7 +934,7 @@ void ProjectExplorerTest::testGccOutputParsers_data()
|
||||
14, 25,
|
||||
QVector<QTextLayout::FormatRange>()
|
||||
<< formatRange(41, 22)
|
||||
<< formatRange(63, 67, "olpfile:///home/code/src/creator/src/libs/extensionsystem/pluginerrorview.cpp::31::-1")
|
||||
<< formatRange(63, 67, "olpfile:///home/code/src/creator/src/libs/extensionsystem/pluginerrorview.cpp::31::0")
|
||||
<< formatRange(130, 146))}
|
||||
<< QString();
|
||||
|
||||
@@ -953,11 +958,11 @@ void ProjectExplorerTest::testGccOutputParsers_data()
|
||||
597, 5,
|
||||
QVector<QTextLayout::FormatRange>()
|
||||
<< formatRange(43, 22)
|
||||
<< formatRange(65, 31, "olpfile:///usr/include/qt4/QtCore/QString::1::-1")
|
||||
<< formatRange(65, 31, "olpfile:///usr/include/qt4/QtCore/QString::1::0")
|
||||
<< formatRange(96, 40)
|
||||
<< formatRange(136, 33, "olpfile:///usr/include/qt4/QtCore/qstring.h::0::-1")
|
||||
<< formatRange(136, 33, "olpfile:///usr/include/qt4/QtCore/qstring.h::0::0")
|
||||
<< formatRange(169, 28)
|
||||
<< formatRange(197, 33, "olpfile:///usr/include/qt4/QtCore/qstring.h::597::-1")
|
||||
<< formatRange(197, 33, "olpfile:///usr/include/qt4/QtCore/qstring.h::597::5")
|
||||
<< formatRange(230, 99))}
|
||||
<< QString();
|
||||
|
||||
@@ -1233,17 +1238,17 @@ void ProjectExplorerTest::testGccOutputParsers_data()
|
||||
273, 25,
|
||||
QVector<QTextLayout::FormatRange>()
|
||||
<< formatRange(140, 22)
|
||||
<< formatRange(162, 32, "olpfile:///usr/include/qt/QtCore/qlocale.h::43::-1")
|
||||
<< formatRange(162, 32, "olpfile:///usr/include/qt/QtCore/qlocale.h::43::0")
|
||||
<< formatRange(194, 27)
|
||||
<< formatRange(221, 36, "olpfile:///usr/include/qt/QtCore/qtextstream.h::46::-1")
|
||||
<< formatRange(221, 36, "olpfile:///usr/include/qt/QtCore/qtextstream.h::46::0")
|
||||
<< formatRange(257, 27)
|
||||
<< formatRange(284, 38, "olpfile:///qtc/src/shared/proparser/proitems.cpp::31::-1")
|
||||
<< formatRange(284, 38, "olpfile:///qtc/src/shared/proparser/proitems.cpp::31::0")
|
||||
<< formatRange(322, 5)
|
||||
<< formatRange(327, 33, "olpfile:///usr/include/qt/QtCore/qvariant.h::0::-1")
|
||||
<< formatRange(327, 33, "olpfile:///usr/include/qt/QtCore/qvariant.h::0::0")
|
||||
<< formatRange(360, 51)
|
||||
<< formatRange(411, 33, "olpfile:///usr/include/qt/QtCore/qvariant.h::273::-1")
|
||||
<< formatRange(411, 33, "olpfile:///usr/include/qt/QtCore/qvariant.h::273::25")
|
||||
<< formatRange(444, 229)
|
||||
<< formatRange(673, 33, "olpfile:///usr/include/qt/QtCore/qvariant.h::399::-1")
|
||||
<< formatRange(673, 33, "olpfile:///usr/include/qt/QtCore/qvariant.h::399::16")
|
||||
<< formatRange(706, 221)),
|
||||
compileTask(Task::Error,
|
||||
"no match for ‘operator+’ (operand types are ‘boxed_value<double>’ and ‘boxed_value<double>’)\n"
|
||||
@@ -1477,13 +1482,13 @@ void ProjectExplorerTest::testGccOutputParsers_data()
|
||||
FilePath::fromUserInput("/data/dev/creator/src/libs/utils/aspects.cpp"), 3454, 13,
|
||||
QVector<QTextLayout::FormatRange>{
|
||||
formatRange(82, 22),
|
||||
formatRange(104, 44, "olpfile:///data/dev/creator/src/libs/utils/aspects.cpp::12::-1"),
|
||||
formatRange(104, 44, "olpfile:///data/dev/creator/src/libs/utils/aspects.cpp::12::0"),
|
||||
formatRange(148, 5),
|
||||
formatRange(153, 48, "olpfile:///data/dev/creator/src/libs/utils/layoutbuilder.h::0::-1"),
|
||||
formatRange(153, 48, "olpfile:///data/dev/creator/src/libs/utils/layoutbuilder.h::0::0"),
|
||||
formatRange(201, 177),
|
||||
formatRange(378, 44, "olpfile:///data/dev/creator/src/libs/utils/aspects.cpp::3454::-1"),
|
||||
formatRange(378, 44, "olpfile:///data/dev/creator/src/libs/utils/aspects.cpp::3454::13"),
|
||||
formatRange(422, 31),
|
||||
formatRange(453, 48, "olpfile:///data/dev/creator/src/libs/utils/layoutbuilder.h::79::-1"),
|
||||
formatRange(453, 48, "olpfile:///data/dev/creator/src/libs/utils/layoutbuilder.h::79::51"),
|
||||
formatRange(501, 228)})})
|
||||
<< QString();
|
||||
}
|
||||
|
@@ -103,7 +103,7 @@ OutputLineParser::Result GnuMakeParser::handleLine(const QString &line, OutputFo
|
||||
if (!m_suppressIssues) {
|
||||
const FilePath file = absoluteFilePath(FilePath::fromUserInput(match.captured(1)));
|
||||
const int lineNo = match.captured(4).toInt();
|
||||
addLinkSpecForAbsoluteFilePath(linkSpecs, file, lineNo, match, 1);
|
||||
addLinkSpecForAbsoluteFilePath(linkSpecs, file, lineNo, -1, match, 1);
|
||||
emitTask(BuildSystemTask(res.type, res.description, file, lineNo));
|
||||
}
|
||||
return {Status::Done, linkSpecs};
|
||||
|
@@ -62,7 +62,7 @@ Utils::OutputLineParser::Result LdParser::handleLine(const QString &line, Utils:
|
||||
if (match.hasMatch()) {
|
||||
handle = true;
|
||||
filePath = absoluteFilePath(Utils::FilePath::fromString(match.captured("file")));
|
||||
addLinkSpecForAbsoluteFilePath(linkSpecs, filePath, 0, match, "file");
|
||||
addLinkSpecForAbsoluteFilePath(linkSpecs, filePath, -1, -1, match, "file");
|
||||
currentTask().setFile(filePath);
|
||||
} else {
|
||||
handle = !lne.isEmpty() && lne.at(0).isSpace();
|
||||
@@ -135,7 +135,7 @@ Utils::OutputLineParser::Result LdParser::handleLine(const QString &line, Utils:
|
||||
}
|
||||
if (hasKeyword || filePath.fileName().endsWith(".o")) {
|
||||
LinkSpecs linkSpecs;
|
||||
addLinkSpecForAbsoluteFilePath(linkSpecs, filePath, lineno, match, capIndex);
|
||||
addLinkSpecForAbsoluteFilePath(linkSpecs, filePath, lineno, -1, match, capIndex);
|
||||
createOrAmendTask(type, description, line, false, filePath, lineno, 0, linkSpecs);
|
||||
return {getStatus(), linkSpecs};
|
||||
}
|
||||
|
@@ -59,7 +59,7 @@ OutputLineParser::Result LinuxIccParser::handleLine(const QString &line, OutputF
|
||||
const FilePath filePath = absoluteFilePath(FilePath::fromUserInput(match.captured(1)));
|
||||
const int lineNo = match.captured(2).toInt();
|
||||
LinkSpecs linkSpecs;
|
||||
addLinkSpecForAbsoluteFilePath(linkSpecs, filePath, lineNo, match, 1);
|
||||
addLinkSpecForAbsoluteFilePath(linkSpecs, filePath, lineNo, -1, match, 1);
|
||||
createOrAmendTask(type, match.captured(6).trimmed(), line, false, filePath, lineNo);
|
||||
m_expectFirstLine = false;
|
||||
return Status::InProgress;
|
||||
|
@@ -46,7 +46,7 @@ Utils::OutputLineParser::Result LldParser::handleLine(const QString &line, Utils
|
||||
const auto file = absoluteFilePath(Utils::FilePath::fromUserInput(
|
||||
trimmedLine.mid(filePathOffset, filePathLen).trimmed()));
|
||||
LinkSpecs linkSpecs;
|
||||
addLinkSpecForAbsoluteFilePath(linkSpecs, file, lineNo, filePathOffset, filePathLen);
|
||||
addLinkSpecForAbsoluteFilePath(linkSpecs, file, lineNo, -1, filePathOffset, filePathLen);
|
||||
scheduleTask(CompileTask(Task::Unknown, trimmedLine.mid(4).trimmed(),
|
||||
file, lineNo), 1);
|
||||
return {Status::Done, linkSpecs};
|
||||
|
@@ -114,7 +114,7 @@ OutputLineParser::Result MsvcParser::handleLine(const QString &line, OutputForma
|
||||
const FilePath filePath = absoluteFilePath(FilePath::fromUserInput(match.captured(2)));
|
||||
const int lineNo = match.captured(3).toInt();
|
||||
LinkSpecs linkSpecs;
|
||||
addLinkSpecForAbsoluteFilePath(linkSpecs, filePath, lineNo, match, 2);
|
||||
addLinkSpecForAbsoluteFilePath(linkSpecs, filePath, lineNo, -1, match, 2);
|
||||
createOrAmendTask(Task::Unknown, description, line, false, filePath, lineNo, 0, linkSpecs);
|
||||
return {Status::InProgress, linkSpecs};
|
||||
}
|
||||
@@ -146,7 +146,7 @@ MsvcParser::Result MsvcParser::processCompileLine(const QString &line)
|
||||
QPair<FilePath, int> position = parseFileName(match.captured(1));
|
||||
const FilePath filePath = absoluteFilePath(position.first);
|
||||
LinkSpecs linkSpecs;
|
||||
addLinkSpecForAbsoluteFilePath(linkSpecs, filePath, position.second, match, 1);
|
||||
addLinkSpecForAbsoluteFilePath(linkSpecs, filePath, position.second, -1, match, 1);
|
||||
const QString &description = match.captured(3) + match.captured(4).trimmed();
|
||||
createOrAmendTask(
|
||||
taskType(match.captured(2)),
|
||||
@@ -228,7 +228,7 @@ OutputLineParser::Result ClangClParser::handleLine(const QString &line, OutputFo
|
||||
const FilePath file = absoluteFilePath(position.first);
|
||||
const int lineNo = position.second;
|
||||
LinkSpecs linkSpecs;
|
||||
addLinkSpecForAbsoluteFilePath(linkSpecs, file, lineNo, match, 1);
|
||||
addLinkSpecForAbsoluteFilePath(linkSpecs, file, lineNo, -1, match, 1);
|
||||
createOrAmendTask(
|
||||
taskType(match.captured(2)), match.captured(3).trimmed(), line, false, file, lineNo);
|
||||
return {Status::InProgress, linkSpecs};
|
||||
|
@@ -93,7 +93,8 @@ OutputLineParser::Result SanitizerParser::handleContinuation(const QString &line
|
||||
m_task.file = file;
|
||||
m_task.line = summaryMatch.captured("line").toInt();
|
||||
m_task.column = summaryMatch.captured("column").toInt();
|
||||
addLinkSpecForAbsoluteFilePath(linkSpecs, file, m_task.line, summaryMatch, "file");
|
||||
addLinkSpecForAbsoluteFilePath(
|
||||
linkSpecs, file, m_task.line, m_task.column, summaryMatch, "file");
|
||||
addLinkSpecs(linkSpecs);
|
||||
}
|
||||
} else {
|
||||
@@ -107,7 +108,7 @@ OutputLineParser::Result SanitizerParser::handleContinuation(const QString &line
|
||||
const FilePath file = absoluteFilePath(FilePath::fromUserInput(fileMatch.captured("file")));
|
||||
if (fileExists(file)) {
|
||||
addLinkSpecForAbsoluteFilePath(linkSpecs, file, fileMatch.captured("line").toInt(),
|
||||
fileMatch, "file");
|
||||
fileMatch.captured("column").toInt(), fileMatch, "file");
|
||||
addLinkSpecs(linkSpecs);
|
||||
}
|
||||
}
|
||||
|
@@ -57,7 +57,8 @@ OutputLineParser::Result XcodebuildParser::handleLine(const QString &line, Outpu
|
||||
absoluteFilePath(FilePath::fromString(
|
||||
lne.left(filePathEndPos))));
|
||||
LinkSpecs linkSpecs;
|
||||
addLinkSpecForAbsoluteFilePath(linkSpecs, task.file, task.line, 0, filePathEndPos);
|
||||
addLinkSpecForAbsoluteFilePath(linkSpecs, task.file, task.line, task.column, 0,
|
||||
filePathEndPos);
|
||||
scheduleTask(task, 1);
|
||||
return {Status::Done, linkSpecs};
|
||||
}
|
||||
|
@@ -46,7 +46,7 @@ OutputLineParser::Result QMakeParser::handleLine(const QString &line, OutputForm
|
||||
BuildSystemTask t(type, description, absoluteFilePath(FilePath::fromUserInput(fileName)),
|
||||
match.captured(2).toInt() /* line */);
|
||||
LinkSpecs linkSpecs;
|
||||
addLinkSpecForAbsoluteFilePath(linkSpecs, t.file, t.line, fileNameOffset,
|
||||
addLinkSpecForAbsoluteFilePath(linkSpecs, t.file, t.line, t.column, fileNameOffset,
|
||||
fileName.length());
|
||||
scheduleTask(t, 1);
|
||||
return {Status::Done, linkSpecs};
|
||||
|
@@ -45,7 +45,7 @@ Utils::OutputLineParser::Result QtParser::handleLine(const QString &line, Utils:
|
||||
LinkSpecs linkSpecs;
|
||||
const Utils::FilePath file
|
||||
= absoluteFilePath(Utils::FilePath::fromUserInput(match.captured("file")));
|
||||
addLinkSpecForAbsoluteFilePath(linkSpecs, file, lineno, match, "file");
|
||||
addLinkSpecForAbsoluteFilePath(linkSpecs, file, lineno, -1, match, "file");
|
||||
CompileTask task(type, match.captured("description").trimmed(), file, lineno);
|
||||
task.column = match.captured("column").toInt();
|
||||
scheduleTask(task, 1);
|
||||
@@ -62,7 +62,7 @@ Utils::OutputLineParser::Result QtParser::handleLine(const QString &line, Utils:
|
||||
message.prepend(": ").prepend(fileName);
|
||||
} else if (fileName.endsWith(".ui")) {
|
||||
filePath = absoluteFilePath(Utils::FilePath::fromUserInput(fileName));
|
||||
addLinkSpecForAbsoluteFilePath(linkSpecs, filePath, -1, match, "file");
|
||||
addLinkSpecForAbsoluteFilePath(linkSpecs, filePath, -1, -1, match, "file");
|
||||
} else {
|
||||
isUicMessage = false;
|
||||
}
|
||||
@@ -79,7 +79,7 @@ Utils::OutputLineParser::Result QtParser::handleLine(const QString &line, Utils:
|
||||
LinkSpecs linkSpecs;
|
||||
const Utils::FilePath file
|
||||
= absoluteFilePath(Utils::FilePath::fromUserInput(match.captured("file")));
|
||||
addLinkSpecForAbsoluteFilePath(linkSpecs, file, 0, match, "file");
|
||||
addLinkSpecForAbsoluteFilePath(linkSpecs, file, -1, -1, match, "file");
|
||||
CompileTask task(type, match.captured("description"), file);
|
||||
scheduleTask(task, 1);
|
||||
return {Status::Done, linkSpecs};
|
||||
@@ -95,7 +95,7 @@ Utils::OutputLineParser::Result QtParser::handleLine(const QString &line, Utils:
|
||||
if (!ok)
|
||||
lineno = -1;
|
||||
LinkSpecs linkSpecs;
|
||||
addLinkSpecForAbsoluteFilePath(linkSpecs, file, lineno, match, "file");
|
||||
addLinkSpecForAbsoluteFilePath(linkSpecs, file, lineno, -1, match, "file");
|
||||
CompileTask task(type, match.captured("description"), file, lineno,
|
||||
match.captured("column").toInt());
|
||||
scheduleTask(task, 1);
|
||||
|
@@ -44,8 +44,8 @@ OutputLineParser::Result QtTestParser::handleLine(const QString &line, OutputFor
|
||||
m_currentTask.file = absoluteFilePath(FilePath::fromString(
|
||||
QDir::fromNativeSeparators(match.captured("file"))));
|
||||
m_currentTask.line = match.captured("line").toInt();
|
||||
addLinkSpecForAbsoluteFilePath(linkSpecs, m_currentTask.file, m_currentTask.line, match,
|
||||
"file");
|
||||
addLinkSpecForAbsoluteFilePath(
|
||||
linkSpecs, m_currentTask.file, m_currentTask.line, m_currentTask.column, match, "file");
|
||||
emitCurrentTask();
|
||||
return {Status::Done, linkSpecs};
|
||||
}
|
||||
|
@@ -8,6 +8,7 @@ local S = require('Settings')
|
||||
local Gui = require('Gui')
|
||||
local a = require('async')
|
||||
local fetch = require('Fetch').fetch
|
||||
local Install = require('Install')
|
||||
|
||||
Settings = {}
|
||||
|
||||
@@ -39,7 +40,6 @@ local function installOrUpdateServer()
|
||||
if r.prerelease then
|
||||
r = data[2]
|
||||
end
|
||||
Install = require('Install')
|
||||
local lspPkgInfo = Install.packageInfo("rust-analyzer")
|
||||
if not lspPkgInfo or lspPkgInfo.version ~= r.tag_name then
|
||||
local osTr = { mac = "apple-darwin", windows = "pc-windows-msvc", linux = "unknown-linux-gnu" }
|
||||
@@ -80,7 +80,7 @@ local function installOrUpdateServer()
|
||||
binary = "rust-analyzer.exe"
|
||||
end
|
||||
|
||||
Settings.binary.defaultPath = lspPkgInfo.path:resolvePath(binary)
|
||||
Settings.binary:setValue(lspPkgInfo.path:resolvePath(binary))
|
||||
Settings:apply()
|
||||
return
|
||||
end
|
||||
@@ -130,8 +130,8 @@ local function layoutSettings()
|
||||
Settings.binary, br,
|
||||
Row {
|
||||
PushButton {
|
||||
text("Try to install Rust language server"),
|
||||
onClicked(function() a.sync(installOrUpdateServer)() end),
|
||||
text = "Try to install Rust language server",
|
||||
onClicked = function() a.sync(installOrUpdateServer)() end,
|
||||
br,
|
||||
},
|
||||
st
|
||||
@@ -141,6 +141,36 @@ local function layoutSettings()
|
||||
return layout
|
||||
end
|
||||
|
||||
local function binaryFromPkg()
|
||||
local lspPkgInfo = Install.packageInfo("rust-analyzer")
|
||||
if lspPkgInfo then
|
||||
local binary = "rust-analyzer"
|
||||
if Utils.HostOsInfo.isWindowsHost() then
|
||||
binary = "rust-analyzer.exe"
|
||||
end
|
||||
local binaryPath = lspPkgInfo.path:resolvePath(binary)
|
||||
if binaryPath:isExecutableFile() == true then
|
||||
return binaryPath
|
||||
end
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
local function findBinary()
|
||||
local binary = binaryFromPkg()
|
||||
if binary then
|
||||
return binary
|
||||
end
|
||||
|
||||
-- Search for the binary in the PATH
|
||||
local serverPath = Utils.FilePath.fromUserInput("rust-analyzer")
|
||||
local absolute = a.wait(serverPath:searchInPath()):resolveSymlinks()
|
||||
if absolute:isExecutableFile() == true then
|
||||
return absolute
|
||||
end
|
||||
return serverPath
|
||||
end
|
||||
local function setupAspect()
|
||||
---@class Settings: AspectContainer
|
||||
Settings = S.AspectContainer.create({
|
||||
@@ -154,14 +184,8 @@ local function setupAspect()
|
||||
labelText = "Binary:",
|
||||
toolTip = "The path to the rust analyzer binary.",
|
||||
expectedKind = S.Kind.ExistingCommand,
|
||||
defaultPath = Utils.FilePath.fromUserInput("rust-analyzer"),
|
||||
defaultPath = findBinary(),
|
||||
})
|
||||
-- Search for the binary in the PATH
|
||||
local serverPath = Settings.binary.defaultPath
|
||||
local absolute = a.wait(serverPath:searchInPath()):resolveSymlinks()
|
||||
if absolute:isExecutableFile() == true then
|
||||
Settings.binary.defaultPath = absolute
|
||||
end
|
||||
|
||||
return Settings
|
||||
end
|
||||
|
@@ -16,7 +16,7 @@
|
||||
"Description" : "Provides the technical basis for version control system (VCS) extensions",
|
||||
"LongDescription" : [
|
||||
"You also need:",
|
||||
"- An extension for a VCS tool, such as Git, and the tool
|
||||
"- An extension for a VCS tool, such as Git, and the tool"
|
||||
],
|
||||
"Url" : "https://www.qt.io",
|
||||
${IDE_PLUGIN_DEPENDENCIES}
|
||||
|
@@ -1949,6 +1949,9 @@ void tst_Dumpers::dumper()
|
||||
} while (localsBeginPos != -1);
|
||||
actual.fromString(QString::fromLocal8Bit(contents));
|
||||
context.nameSpace = actual["result"]["qtnamespace"].data();
|
||||
int runtime = actual["result"]["runtime"].data().toFloat() * 1000;
|
||||
qCDebug(lcDumpers, "CaseInner: %5d", runtime);
|
||||
m_totalInnerTime += runtime;
|
||||
actual = actual["result"]["data"];
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user