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