Merge remote-tracking branch 'origin/14.0'

Change-Id: I5cdfedcbdde6bb526ee02007a3dbc136c7d61353
This commit is contained in:
Eike Ziller
2024-06-03 12:35:34 +02:00
77 changed files with 998 additions and 738 deletions

View File

@@ -7,6 +7,7 @@ import sys
import cdbext
import re
import threading
import time
from utils import TypeCode
sys.path.insert(1, os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))))
@@ -421,6 +422,7 @@ class Dumper(DumperBase):
return ptr
def fetchVariables(self, args):
start_time = time.perf_counter()
self.resetStats()
(ok, res) = self.tryFetchInterpreterVariables(args)
if ok:
@@ -458,6 +460,8 @@ class Dumper(DumperBase):
self.put(',qtnamespace="%s"' % self.qtNamespaceToReport)
self.qtNamespaceToReport = None
runtime = time.perf_counter() - start_time
self.put(',runtime="%s"' % runtime)
self.reportResult(''.join(self.output), args)
self.output = []

View File

@@ -6,8 +6,6 @@
#include <QString>
#include <QCryptographicHash>
#include <limits>
namespace LanguageUtils {
// QTC_TEMP
@@ -42,8 +40,8 @@ QString ComponentVersion::toString() const
void ComponentVersion::addToHash(QCryptographicHash &hash) const
{
hash.addData(reinterpret_cast<const char *>(&_major), sizeof(_major));
hash.addData(reinterpret_cast<const char *>(&_minor), sizeof(_minor));
hash.addData(QByteArrayView(reinterpret_cast<const char *>(&_major), sizeof(_major)));
hash.addData(QByteArrayView(reinterpret_cast<const char *>(&_minor), sizeof(_minor)));
}
} // namespace LanguageUtils

View File

@@ -6,6 +6,21 @@
using namespace LanguageUtils;
static QByteArrayView asData(const void *mem, size_t len)
{
return QByteArrayView(reinterpret_cast<const char *>(mem), len);
}
static void addData(QCryptographicHash &hash, int x)
{
hash.addData(asData(&x, sizeof(int)));
}
static void addData(QCryptographicHash &hash, const QString &x)
{
hash.addData(asData(x.constData(), x.size() * sizeof(QChar)));
}
FakeMetaEnum::FakeMetaEnum()
{}
@@ -39,15 +54,12 @@ bool FakeMetaEnum::hasKey(const QString &key) const
void FakeMetaEnum::addToHash(QCryptographicHash &hash) const
{
int len = m_name.size();
hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
hash.addData(reinterpret_cast<const char *>(m_name.constData()), len * sizeof(QChar));
len = m_keys.size();
hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
addData(hash, m_name.size());
addData(hash, m_name);
addData(hash, m_keys.size());
for (const QString &key : std::as_const(m_keys)) {
len = key.size();
hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
hash.addData(reinterpret_cast<const char *>(key.constData()), len * sizeof(QChar));
addData(hash, key.size());
addData(hash, key);
}
}
@@ -121,29 +133,23 @@ void FakeMetaMethod::setRevision(int r)
void FakeMetaMethod::addToHash(QCryptographicHash &hash) const
{
int len = m_name.size();
hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
hash.addData(reinterpret_cast<const char *>(m_name.constData()), len * sizeof(QChar));
hash.addData(reinterpret_cast<const char *>(&m_methodAccess), sizeof(m_methodAccess));
hash.addData(reinterpret_cast<const char *>(&m_methodTy), sizeof(m_methodTy));
hash.addData(reinterpret_cast<const char *>(&m_revision), sizeof(m_revision));
len = m_paramNames.size();
hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
addData(hash, m_name.size());
addData(hash, m_name);
addData(hash, m_methodAccess);
addData(hash, m_methodTy);
addData(hash, m_revision);
addData(hash, m_paramNames.size());
for (const QString &pName : std::as_const(m_paramNames)) {
len = pName.size();
hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
hash.addData(reinterpret_cast<const char *>(pName.constData()), len * sizeof(QChar));
addData(hash, pName.size());
addData(hash, pName);
}
len = m_paramTypes.size();
hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
addData(hash, m_paramTypes.size());
for (const QString &pType : std::as_const(m_paramTypes)) {
len = pType.size();
hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
hash.addData(reinterpret_cast<const char *>(pType.constData()), len * sizeof(QChar));
addData(hash, pType.size());
addData(hash, pType);
}
len = m_returnType.size();
hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
hash.addData(reinterpret_cast<const char *>(m_returnType.constData()), len * sizeof(QChar));
addData(hash, m_returnType.size());
addData(hash, m_returnType);
}
QString FakeMetaMethod::describe(int baseIndent) const
@@ -213,17 +219,15 @@ int FakeMetaProperty::revision() const
void FakeMetaProperty::addToHash(QCryptographicHash &hash) const
{
int len = m_propertyName.size();
hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
hash.addData(reinterpret_cast<const char *>(m_propertyName.constData()), len * sizeof(QChar));
hash.addData(reinterpret_cast<const char *>(&m_revision), sizeof(m_revision));
addData(hash, m_propertyName.size());
addData(hash, m_propertyName);
addData(hash, m_revision);
int flags = (m_isList ? (1 << 0) : 0)
+ (m_isPointer ? (1 << 1) : 0)
+ (m_isWritable ? (1 << 2) : 0);
hash.addData(reinterpret_cast<const char *>(&flags), sizeof(flags));
len = m_type.size();
hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
hash.addData(reinterpret_cast<const char *>(m_type.constData()), len * sizeof(QChar));
addData(hash, flags);
addData(hash, m_type.size());
addData(hash, m_type);
}
QString FakeMetaProperty::describe(int baseIndent) const
@@ -361,34 +365,34 @@ QByteArray FakeMetaObject::calculateFingerprint() const
{
QCryptographicHash hash(QCryptographicHash::Sha1);
int len = m_className.size();
hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
hash.addData(reinterpret_cast<const char *>(m_className.constData()), len * sizeof(QChar));
addData(hash, len);
addData(hash, m_className);
len = m_attachedTypeName.size();
hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
hash.addData(reinterpret_cast<const char *>(m_attachedTypeName.constData()), len * sizeof(QChar));
addData(hash, len);
addData(hash, m_attachedTypeName);
len = m_defaultPropertyName.size();
hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
hash.addData(reinterpret_cast<const char *>(m_defaultPropertyName.constData()), len * sizeof(QChar));
addData(hash, len);
addData(hash, m_defaultPropertyName);
len = m_enumNameToIndex.size();
hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
addData(hash, len);
{
QStringList keys(m_enumNameToIndex.keys());
keys.sort();
for (const QString &key : std::as_const(keys)) {
len = key.size();
hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
hash.addData(reinterpret_cast<const char *>(key.constData()), len * sizeof(QChar));
addData(hash, len);
addData(hash, key);
int value = m_enumNameToIndex.value(key);
hash.addData(reinterpret_cast<const char *>(&value), sizeof(value)); // avoid? this adds order dependency to fingerprint...
addData(hash, value);
m_enums.at(value).addToHash(hash);
}
}
len = m_exports.size();
hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
addData(hash, len);
for (const Export &e : std::as_const(m_exports))
e.addToHash(hash); // normalize order?
len = m_exports.size();
hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
addData(hash, len);
for (const FakeMetaMethod &m : std::as_const(m_methods))
m.addToHash(hash); // normalize order?
{
@@ -396,16 +400,16 @@ QByteArray FakeMetaObject::calculateFingerprint() const
keys.sort();
for (const QString &key : std::as_const(keys)) {
len = key.size();
hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
hash.addData(reinterpret_cast<const char *>(key.constData()), len * sizeof(QChar));
addData(hash, len);
addData(hash, key);
int value = m_propNameToIdx.value(key);
hash.addData(reinterpret_cast<const char *>(&value), sizeof(value)); // avoid? this adds order dependency to fingerprint...
addData(hash, value);
m_props.at(value).addToHash(hash);
}
}
len = m_superName.size();
hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
hash.addData(reinterpret_cast<const char *>(m_superName.constData()), len * sizeof(QChar));
addData(hash, len);
addData(hash, m_superName);
QByteArray res = hash.result();
res.append('F');
@@ -540,14 +544,12 @@ bool FakeMetaObject::Export::isValid() const
void FakeMetaObject::Export::addToHash(QCryptographicHash &hash) const
{
int len = package.size();
hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
hash.addData(reinterpret_cast<const char *>(package.constData()), len * sizeof(QChar));
len = type.size();
hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
hash.addData(reinterpret_cast<const char *>(type.constData()), len * sizeof(QChar));
addData(hash, package.size());
addData(hash, package);
addData(hash, type.size());
addData(hash, type);
version.addToHash(hash);
hash.addData(reinterpret_cast<const char *>(&metaObjectRevision), sizeof(metaObjectRevision));
addData(hash, metaObjectRevision);
}
QString FakeMetaObject::Export::describe(int baseIndent) const

View File

@@ -185,14 +185,14 @@ ImportKey::ImportKey(ImportType::Enum type, const QString &path, int majorVersio
void ImportKey::addToHash(QCryptographicHash &hash) const
{
hash.addData(reinterpret_cast<const char *>(&type), sizeof(type));
hash.addData(reinterpret_cast<const char *>(&majorVersion), sizeof(majorVersion));
hash.addData(reinterpret_cast<const char *>(&minorVersion), sizeof(minorVersion));
hash.addData(QByteArrayView(reinterpret_cast<const char *>(&type), sizeof(type)));
hash.addData(QByteArrayView(reinterpret_cast<const char *>(&majorVersion), sizeof(majorVersion)));
hash.addData(QByteArrayView(reinterpret_cast<const char *>(&minorVersion), sizeof(minorVersion)));
for (const QString &s : splitPath) {
hash.addData("/", 1);
hash.addData(reinterpret_cast<const char *>(s.constData()), sizeof(QChar) * s.size());
hash.addData("/");
hash.addData(QByteArrayView(reinterpret_cast<const char *>(s.constData()), sizeof(QChar) * s.size()));
}
hash.addData("/", 1);
hash.addData("/");
}
ImportKey ImportKey::flatKey() const {
@@ -547,11 +547,11 @@ QByteArray DependencyInfo::calculateFingerprint(const ImportDependencies &deps)
QStringList coreImports = Utils::toList(allCoreImports);
coreImports.sort();
for (const QString &importId : std::as_const(coreImports)) {
hash.addData(reinterpret_cast<const char*>(importId.constData()), importId.size() * sizeof(QChar));
hash.addData(QByteArrayView(reinterpret_cast<const char*>(importId.constData()), importId.size() * sizeof(QChar)));
QByteArray coreImportFingerprint = deps.coreImport(importId).fingerprint;
hash.addData(coreImportFingerprint);
}
hash.addData("/", 1);
hash.addData("/");
QList<ImportKey> imports = Utils::toList(allImports);
std::sort(imports.begin(), imports.end());
for (const ImportKey &k : std::as_const(imports))

View File

@@ -2681,22 +2681,26 @@ void StringListAspect::addToLayout(Layout &parent)
}
};
connect(add, &QPushButton::clicked, this, [this, populate, editor] {
d->undoable.setSilently(d->undoable.get() << "");
populate();
const QTreeWidgetItem *root = editor->invisibleRootItem();
QTreeWidgetItem *lastChild = root->child(root->childCount() - 1);
const QModelIndex index = editor->indexFromItem(lastChild, 0);
editor->edit(index);
});
if (add) {
connect(add, &QPushButton::clicked, this, [this, populate, editor] {
d->undoable.setSilently(d->undoable.get() << "");
populate();
const QTreeWidgetItem *root = editor->invisibleRootItem();
QTreeWidgetItem *lastChild = root->child(root->childCount() - 1);
const QModelIndex index = editor->indexFromItem(lastChild, 0);
editor->edit(index);
});
}
connect(remove, &QPushButton::clicked, this, [this, editor, itemsToStringList] {
const QList<QTreeWidgetItem *> selected = editor->selectedItems();
QTC_ASSERT(selected.size() == 1, return);
editor->invisibleRootItem()->removeChild(selected.first());
delete selected.first();
d->undoable.set(undoStack(), itemsToStringList());
});
if (remove) {
connect(remove, &QPushButton::clicked, this, [this, editor, itemsToStringList] {
const QList<QTreeWidgetItem *> selected = editor->selectedItems();
QTC_ASSERT(selected.size() == 1, return);
editor->invisibleRootItem()->removeChild(selected.first());
delete selected.first();
d->undoable.set(undoStack(), itemsToStringList());
});
}
connect(
&d->undoable.m_signal, &UndoSignaller::changed, editor, [this, populate, itemsToStringList] {

View File

@@ -763,6 +763,31 @@ void Label::setText(const QString &text)
access(this)->setText(text);
}
void Label::setTextFormat(Qt::TextFormat format)
{
access(this)->setTextFormat(format);
}
void Label::setWordWrap(bool on)
{
access(this)->setWordWrap(on);
}
void Label::setTextInteractionFlags(Qt::TextInteractionFlags flags)
{
access(this)->setTextInteractionFlags(flags);
}
void Label::setOpenExternalLinks(bool on)
{
access(this)->setOpenExternalLinks(on);
}
void Label::onLinkHovered(const std::function<void (const QString &)> &func, QObject *guard)
{
QObject::connect(access(this), &QLabel::linkHovered, guard, func);
}
// Group
Group::Group(std::initializer_list<I> ps)

View File

@@ -279,6 +279,11 @@ public:
Label(const QString &text);
void setText(const QString &);
void setTextFormat(Qt::TextFormat);
void setWordWrap(bool);
void setTextInteractionFlags(Qt::TextInteractionFlags);
void setOpenExternalLinks(bool);
void onLinkHovered(const std::function<void(const QString &)> &, QObject *guard);
};
class QTCREATOR_UTILS_EXPORT Group : public Widget
@@ -446,6 +451,26 @@ class TitleId {};
auto title(auto p) { return IdAndArg{TitleId{}, p}; }
void doit(auto x, TitleId, auto p) { x->setTitle(p); }
class TextFormatId {};
auto textFormat(auto p) { return IdAndArg{TextFormatId{}, p}; }
void doit(auto x, TextFormatId, auto p) { x->setTextFormat(p); }
class WordWrapId {};
auto wordWrap(auto p) { return IdAndArg{WordWrapId{}, p}; }
void doit(auto x, WordWrapId, auto p) { x->setWordWrap(p); }
class TextInteractionFlagId {};
auto textInteractionFlags(auto p) { return IdAndArg{TextInteractionFlagId{}, p}; }
void doit(auto x, TextInteractionFlagId, auto p) { x->setTextInteractionFlags(p); }
class OpenExternalLinksId {};
auto openExternalLinks(auto p) { return IdAndArg{OpenExternalLinksId{}, p}; }
void doit(auto x, OpenExternalLinksId, auto p) { x->setOpenExternalLinks(p); }
class OnLinkHoveredId {};
auto onLinkHovered(auto p, QObject *guard) { return IdAndArg{OnLinkHoveredId{}, std::pair{p, guard}}; }
void doit(auto x, OnLinkHoveredId, auto p) { x->onLinkHovered(p.first, p.second); }
class GroupCheckerId {};
auto groupChecker(auto p) { return IdAndArg{GroupCheckerId{}, p}; }
void doit(auto x, GroupCheckerId, auto p) { x->setGroupChecker(p); }

View File

@@ -58,7 +58,7 @@ Link OutputLineParser::parseLinkTarget(const QString &target)
return {};
return Link(FilePath::fromString(parts.first()),
parts.length() > 1 ? parts.at(1).toInt() : 0,
parts.length() > 2 ? parts.at(2).toInt() : 0);
parts.length() > 2 ? parts.at(2).toInt() - 1 : 0);
}
// The redirection mechanism is needed for broken build tools (e.g. xcodebuild) that get invoked
@@ -141,26 +141,39 @@ FilePath OutputLineParser::absoluteFilePath(const FilePath &filePath) const
return filePath;
}
void OutputLineParser::addLinkSpecForAbsoluteFilePath(OutputLineParser::LinkSpecs &linkSpecs,
const FilePath &filePath, int lineNo, int pos, int len)
void OutputLineParser::addLinkSpecForAbsoluteFilePath(
OutputLineParser::LinkSpecs &linkSpecs,
const FilePath &filePath,
int lineNo,
int column,
int pos,
int len)
{
if (filePath.toFileInfo().isAbsolute())
linkSpecs.append({pos, len, createLinkTarget(filePath, lineNo)});
linkSpecs.append({pos, len, createLinkTarget(filePath, lineNo, column)});
}
void OutputLineParser::addLinkSpecForAbsoluteFilePath(OutputLineParser::LinkSpecs &linkSpecs,
const FilePath &filePath, int lineNo, const QRegularExpressionMatch &match,
int capIndex)
void OutputLineParser::addLinkSpecForAbsoluteFilePath(
OutputLineParser::LinkSpecs &linkSpecs,
const FilePath &filePath,
int lineNo,
int column,
const QRegularExpressionMatch &match,
int capIndex)
{
addLinkSpecForAbsoluteFilePath(linkSpecs, filePath, lineNo, match.capturedStart(capIndex),
match.capturedLength(capIndex));
addLinkSpecForAbsoluteFilePath(linkSpecs, filePath, lineNo, column,
match.capturedStart(capIndex), match.capturedLength(capIndex));
}
void OutputLineParser::addLinkSpecForAbsoluteFilePath(OutputLineParser::LinkSpecs &linkSpecs,
const FilePath &filePath, int lineNo, const QRegularExpressionMatch &match,
const QString &capName)
void OutputLineParser::addLinkSpecForAbsoluteFilePath(
OutputLineParser::LinkSpecs &linkSpecs,
const FilePath &filePath,
int lineNo,
int column,
const QRegularExpressionMatch &match,
const QString &capName)
{
addLinkSpecForAbsoluteFilePath(linkSpecs, filePath, lineNo, match.capturedStart(capName),
match.capturedLength(capName));
addLinkSpecForAbsoluteFilePath(linkSpecs, filePath, lineNo, column,
match.capturedStart(capName), match.capturedLength(capName));
}
bool Utils::OutputLineParser::fileExists(const FilePath &fp) const

View File

@@ -93,12 +93,13 @@ protected:
Utils::FilePath absoluteFilePath(const Utils::FilePath &filePath) const;
static QString createLinkTarget(const FilePath &filePath, int line, int column);
static void addLinkSpecForAbsoluteFilePath(LinkSpecs &linkSpecs, const FilePath &filePath,
int lineNo, int pos, int len);
int lineNo, int column, int pos, int len);
static void addLinkSpecForAbsoluteFilePath(LinkSpecs &linkSpecs, const FilePath &filePath,
int lineNo, const QRegularExpressionMatch &match,
int capIndex);
int lineNo, int column,
const QRegularExpressionMatch &match, int capIndex);
static void addLinkSpecForAbsoluteFilePath(LinkSpecs &linkSpecs, const FilePath &filePath,
int lineNo, const QRegularExpressionMatch &match,
int lineNo, int column,
const QRegularExpressionMatch &match,
const QString &capName);
bool fileExists(const Utils::FilePath &fp) const;

View File

@@ -43,6 +43,7 @@ static const QList<Tool> &sTools()
{
static QList<Tool> tools;
if (tools.isEmpty()) {
// clang-format off
if (HostOsInfo::isWindowsHost()) {
tools << Tool{{"powershell", "-command Expand-Archive -Force '%{src}' '%{dest}'", CommandLine::Raw},
{"application/zip"},
@@ -74,6 +75,10 @@ static const QList<Tool> &sTools()
tools << Tool{{"cmake", {"-E", "tar", "xvjf", "%{src}"}},
{"application/x-bzip-compressed-tar"},
additionalCMakeDirs};
// Keep this at the end so its only used as last resort. Otherwise it might be used for
// .tar.gz files.
tools << Tool{{"gzip", {"-d", "%{src}", "-c"}}, {"application/gzip"}, {}};
// clang-format on
}
return tools;
}
@@ -147,6 +152,45 @@ void Unarchiver::start()
m_sourceAndCommand->m_sourceFile, m_destDir);
m_destDir.ensureWritableDir();
if (command.executable().fileName() == "gzip") {
std::shared_ptr<QFile> outputFile = std::make_shared<QFile>(
(m_destDir / m_gzipFileDestName).toFSPathString());
if (!outputFile->open(QIODevice::WriteOnly)) {
emit outputReceived(Tr::tr("Failed to open output file."));
emit done(DoneResult::Error);
return;
}
m_process.reset(new Process);
QObject::connect(m_process.get(), &Process::readyReadStandardOutput, this, [this, outputFile] {
const QByteArray data = m_process->readAllRawStandardOutput();
if (outputFile->write(data) != data.size()) {
emit outputReceived(Tr::tr("Failed to write output file."));
emit done(DoneResult::Error);
}
});
QObject::connect(m_process.get(), &Process::readyReadStandardError, this, [this] {
emit outputReceived(m_process->readAllStandardError());
});
QObject::connect(m_process.get(), &Process::done, this, [outputFile, this] {
outputFile->close();
const bool success = m_process->result() == ProcessResult::FinishedWithSuccess;
if (!success) {
outputFile->remove();
emit outputReceived(Tr::tr("Command failed."));
}
emit done(toDoneResult(success));
});
emit outputReceived(
Tr::tr("Running %1\nin \"%2\".\n\n", "Running <cmd> in <workingdirectory>")
.arg(command.toUserOutput(), m_destDir.toUserOutput()));
m_process->setCommand(command);
m_process->setWorkingDirectory(m_destDir);
m_process->start();
return;
}
m_process.reset(new Process);
m_process->setProcessChannelMode(QProcess::MergedChannels);
QObject::connect(m_process.get(), &Process::readyReadStandardOutput, this, [this] {

View File

@@ -32,7 +32,10 @@ public:
void setSourceAndCommand(const SourceAndCommand &data) { m_sourceAndCommand = data; }
void setDestDir(const FilePath &destDir) { m_destDir = destDir; }
void setGZipFileDestName(const QString &gzipFileDestName)
{
m_gzipFileDestName = gzipFileDestName;
}
void start();
signals:
@@ -43,6 +46,7 @@ private:
std::optional<SourceAndCommand> m_sourceAndCommand;
FilePath m_destDir;
std::unique_ptr<Process> m_process;
QString m_gzipFileDestName;
};
class QTCREATOR_UTILS_EXPORT UnarchiverTaskAdapter : public Tasking::TaskAdapter<Unarchiver>

View File

@@ -62,7 +62,7 @@ OutputLineParser::Result JavaParser::handleLine(const QString &line, OutputForma
absoluteFilePath(file),
lineno);
LinkSpecs linkSpecs;
addLinkSpecForAbsoluteFilePath(linkSpecs, task.file, task.line, match, 2);
addLinkSpecForAbsoluteFilePath(linkSpecs, task.file, task.line, task.column, match, 2);
scheduleTask(task, 1);
return {Status::Done, linkSpecs};
}

View File

@@ -15,7 +15,7 @@
],
"Description" : "Visualize CPU and Memory consumption for running applications",
"LongDescription" : [
"Select an application to monitor its performance in real-time.",
"Select an application to monitor its performance in real-time."
],
"Url" : "https://www.qt.io",
${IDE_PLUGIN_DEPENDENCIES}

View File

@@ -117,8 +117,8 @@ OutputLineParser::Result IarParser::parseWarningOrErrorOrFatalErrorDetailsMessag
m_expectSnippet = false;
m_expectFilePath = false;
LinkSpecs linkSpecs;
addLinkSpecForAbsoluteFilePath(linkSpecs, m_lastTask.file, m_lastTask.line, match,
FilePathIndex);
addLinkSpecForAbsoluteFilePath(
linkSpecs, m_lastTask.file, m_lastTask.line, m_lastTask.column, match, FilePathIndex);
return {Status::InProgress, linkSpecs};
}

View File

@@ -62,8 +62,8 @@ OutputLineParser::Result KeilParser::parseArmWarningOrErrorDetailsMessage(const
const QString descr = match.captured(DescriptionIndex);
newTask(CompileTask(type, descr, absoluteFilePath(fileName), lineno));
LinkSpecs linkSpecs;
addLinkSpecForAbsoluteFilePath(linkSpecs, m_lastTask.file, m_lastTask.line, match,
FilePathIndex);
addLinkSpecForAbsoluteFilePath(
linkSpecs, m_lastTask.file, m_lastTask.line, m_lastTask.column, match, FilePathIndex);
return {Status::InProgress, linkSpecs};
}
@@ -98,8 +98,8 @@ OutputLineParser::Result KeilParser::parseMcs51WarningOrErrorDetailsMessage1(con
match.captured(MessageTextIndex));
newTask(CompileTask(type, descr, absoluteFilePath(fileName), lineno));
LinkSpecs linkSpecs;
addLinkSpecForAbsoluteFilePath(linkSpecs, m_lastTask.file, m_lastTask.line, match,
FilePathIndex);
addLinkSpecForAbsoluteFilePath(
linkSpecs, m_lastTask.file, m_lastTask.line, m_lastTask.column, match, FilePathIndex);
return {Status::InProgress, linkSpecs};
}
@@ -119,8 +119,8 @@ OutputLineParser::Result KeilParser::parseMcs51WarningOrErrorDetailsMessage2(con
match.captured(MessageTextIndex));
newTask(CompileTask(type, descr, absoluteFilePath(fileName), lineno));
LinkSpecs linkSpecs;
addLinkSpecForAbsoluteFilePath(linkSpecs, m_lastTask.file, m_lastTask.line, match,
FilePathIndex);
addLinkSpecForAbsoluteFilePath(
linkSpecs, m_lastTask.file, m_lastTask.line, m_lastTask.column, match, FilePathIndex);
return {Status::InProgress, linkSpecs};
}

View File

@@ -73,8 +73,8 @@ OutputLineParser::Result SdccParser::handleLine(const QString &line, OutputForma
const QString descr = match.captured(MessageTextIndex);
newTask(CompileTask(type, descr, absoluteFilePath(fileName), lineno));
LinkSpecs linkSpecs;
addLinkSpecForAbsoluteFilePath(linkSpecs, m_lastTask.file, m_lastTask.line, match,
FilePathIndex);
addLinkSpecForAbsoluteFilePath(
linkSpecs, m_lastTask.file, m_lastTask.line, m_lastTask.column, match, FilePathIndex);
return {Status::InProgress, linkSpecs};
}
@@ -90,8 +90,8 @@ OutputLineParser::Result SdccParser::handleLine(const QString &line, OutputForma
const QString descr = match.captured(MessageTextIndex);
newTask(CompileTask(type, descr, absoluteFilePath(fileName), lineno));
LinkSpecs linkSpecs;
addLinkSpecForAbsoluteFilePath(linkSpecs, m_lastTask.file, m_lastTask.line, match,
FilePathIndex);
addLinkSpecForAbsoluteFilePath(
linkSpecs, m_lastTask.file, m_lastTask.line, m_lastTask.column, match, FilePathIndex);
return {Status::InProgress, linkSpecs};
}

View File

@@ -349,7 +349,7 @@ public:
ClangdClient * const q;
const CppEditor::ClangdSettings::Data settings;
ClangdFollowSymbol *followSymbol = nullptr;
QList<ClangdFollowSymbol *> followSymbolOps;
ClangdSwitchDeclDef *switchDeclDef = nullptr;
ClangdFindLocalReferences *findLocalRefs = nullptr;
std::optional<QVersionNumber> versionNumber;
@@ -501,8 +501,8 @@ ClangdClient::ClangdClient(Project *project, const Utils::FilePath &jsonDbDir, c
ClangdClient::~ClangdClient()
{
if (d->followSymbol)
d->followSymbol->clear();
for (ClangdFollowSymbol * const followSymbol : std::as_const(d->followSymbolOps))
followSymbol->clear();
delete d;
}
@@ -990,7 +990,7 @@ MessageId ClangdClient::requestSymbolInfo(const Utils::FilePath &filePath, const
#ifdef WITH_TESTS
ClangdFollowSymbol *ClangdClient::currentFollowSymbolOperation()
{
return d->followSymbol;
return d->followSymbolOps.isEmpty() ? nullptr : d->followSymbolOps.first();
}
#endif
@@ -1005,8 +1005,20 @@ void ClangdClient::followSymbol(TextDocument *document,
{
QTC_ASSERT(documentOpen(document), openDocument(document));
if (d->followSymbol)
d->followSymbol->cancel();
const ClangdFollowSymbol::Origin origin
= CppEditor::CppCodeModelSettings::isInteractiveFollowSymbol()
? ClangdFollowSymbol::Origin::User
: ClangdFollowSymbol::Origin::Code;
if (origin == ClangdFollowSymbol::Origin::User) {
for (auto it = d->followSymbolOps.begin(); it != d->followSymbolOps.end(); ) {
if ((*it)->isInteractive()) {
(*it)->cancel();
it = d->followSymbolOps.erase(it);
} else {
++it;
}
}
}
const QTextCursor adjustedCursor = d->adjustedCursor(cursor, document);
if (followTo == FollowTo::SymbolDef && !resolveTarget) {
@@ -1020,14 +1032,13 @@ void ClangdClient::followSymbol(TextDocument *document,
qCDebug(clangdLog) << "follow symbol requested" << document->filePath()
<< adjustedCursor.blockNumber() << adjustedCursor.positionInBlock();
auto clangdFollowSymbol = new ClangdFollowSymbol(this, adjustedCursor, editorWidget, document,
callback, followTo, openInSplit);
auto clangdFollowSymbol = new ClangdFollowSymbol(this, origin, adjustedCursor, editorWidget,
document, callback, followTo, openInSplit);
connect(clangdFollowSymbol, &ClangdFollowSymbol::done, this, [this, clangdFollowSymbol] {
clangdFollowSymbol->deleteLater();
if (clangdFollowSymbol == d->followSymbol)
d->followSymbol = nullptr;
d->followSymbolOps.removeOne(clangdFollowSymbol);
});
d->followSymbol = clangdFollowSymbol;
d->followSymbolOps << clangdFollowSymbol;
}
void ClangdClient::switchDeclDef(TextDocument *document, const QTextCursor &cursor,

View File

@@ -73,10 +73,10 @@ private:
class ClangdFollowSymbol::Private
{
public:
Private(ClangdFollowSymbol *q, ClangdClient *client, const QTextCursor &cursor,
Private(ClangdFollowSymbol *q, ClangdClient *client, Origin origin, const QTextCursor &cursor,
CppEditorWidget *editorWidget, const FilePath &filePath, const LinkHandler &callback,
bool openInSplit)
: q(q), client(client), cursor(cursor), editorWidget(editorWidget),
: q(q), client(client), origin(origin), cursor(cursor), editorWidget(editorWidget),
uri(client->hostPathToServerUri(filePath)), callback(callback),
virtualFuncAssistProvider(q),
docRevision(editorWidget ? editorWidget->textDocument()->document()->revision() : -1),
@@ -94,6 +94,7 @@ public:
ClangdFollowSymbol * const q;
ClangdClient * const client;
const Origin origin;
const QTextCursor cursor;
const QPointer<CppEditor::CppEditorWidget> editorWidget;
const DocumentUri uri;
@@ -117,11 +118,11 @@ public:
bool done = false;
};
ClangdFollowSymbol::ClangdFollowSymbol(ClangdClient *client, const QTextCursor &cursor,
CppEditorWidget *editorWidget, TextDocument *document, const LinkHandler &callback,
FollowTo followTo, bool openInSplit)
ClangdFollowSymbol::ClangdFollowSymbol(ClangdClient *client, Origin origin,
const QTextCursor &cursor, CppEditorWidget *editorWidget, TextDocument *document,
const LinkHandler &callback, FollowTo followTo, bool openInSplit)
: QObject(client),
d(new Private(this, client, cursor, editorWidget, document->filePath(), callback,
d(new Private(this, client, origin, cursor, editorWidget, document->filePath(), callback,
openInSplit))
{
// Abort if the user does something else with the document in the meantime.
@@ -193,6 +194,11 @@ void ClangdFollowSymbol::clear()
d->pendingGotoDefRequests.clear();
}
bool ClangdFollowSymbol::isInteractive() const
{
return d->origin == Origin::User;
}
void ClangdFollowSymbol::emitDone(const Link &link)
{
if (d->done)

View File

@@ -23,7 +23,9 @@ class ClangdFollowSymbol : public QObject
{
Q_OBJECT
public:
ClangdFollowSymbol(ClangdClient *client, const QTextCursor &cursor,
enum class Origin { User, Code };
ClangdFollowSymbol(ClangdClient *client, Origin origin, const QTextCursor &cursor,
CppEditor::CppEditorWidget *editorWidget,
TextEditor::TextDocument *document, const Utils::LinkHandler &callback,
FollowTo followTo, bool openInSplit);
@@ -31,6 +33,8 @@ public:
void cancel();
void clear();
bool isInteractive() const;
signals:
void done();

View File

@@ -15,7 +15,7 @@
"Category" : "Build Systems",
"Description" : "Automate the configuration of build systems with CMake",
"LongDescription" : [
"CMake controls the software compilation process by using simple configuration files, called CMakeLists.txt files."
"CMake controls the software compilation process by using simple configuration files, called CMakeLists.txt files.",
"You also need:",
"- CMake",
"Qt Online Installer installs a CMake version that you can use."

View File

@@ -93,8 +93,8 @@ OutputLineParser::Result CMakeParser::handleLine(const QString &line, OutputForm
match.captured(2).toInt());
m_lines = 1;
LinkSpecs linkSpecs;
addLinkSpecForAbsoluteFilePath(linkSpecs, m_lastTask.file, m_lastTask.line,
match, 1);
addLinkSpecForAbsoluteFilePath(
linkSpecs, m_lastTask.file, m_lastTask.line, m_lastTask.column, match, 1);
m_errorOrWarningLine.file = m_lastTask.file;
m_errorOrWarningLine.line = m_lastTask.line;
@@ -107,8 +107,8 @@ OutputLineParser::Result CMakeParser::handleLine(const QString &line, OutputForm
m_lastTask = BuildSystemTask(Task::Error, QString(),
absoluteFilePath(FilePath::fromUserInput(match.captured(1))));
LinkSpecs linkSpecs;
addLinkSpecForAbsoluteFilePath(linkSpecs, m_lastTask.file, m_lastTask.line,
match, 1);
addLinkSpecForAbsoluteFilePath(
linkSpecs, m_lastTask.file, m_lastTask.line, m_lastTask.column, match, 1);
m_lines = 1;
return {Status::InProgress, linkSpecs};
}
@@ -121,8 +121,8 @@ OutputLineParser::Result CMakeParser::handleLine(const QString &line, OutputForm
match.captured(3).toInt());
m_lines = 1;
LinkSpecs linkSpecs;
addLinkSpecForAbsoluteFilePath(linkSpecs, m_lastTask.file, m_lastTask.line,
match, 1);
addLinkSpecForAbsoluteFilePath(
linkSpecs, m_lastTask.file, m_lastTask.line, m_lastTask.column, match, 1);
m_errorOrWarningLine.file = m_lastTask.file;
m_errorOrWarningLine.line = m_lastTask.line;
@@ -174,8 +174,13 @@ OutputLineParser::Result CMakeParser::handleLine(const QString &line, OutputForm
m_lastTask.line = match.captured(1).toInt();
m_expectTripleLineErrorData = LINE_DESCRIPTION;
LinkSpecs linkSpecs;
addLinkSpecForAbsoluteFilePath(linkSpecs, m_lastTask.file, m_lastTask.line, 0,
match.capturedStart());
addLinkSpecForAbsoluteFilePath(
linkSpecs,
m_lastTask.file,
m_lastTask.line,
m_lastTask.column,
0,
match.capturedStart());
return {Status::InProgress, linkSpecs};
}
case LINE_DESCRIPTION:

View File

@@ -210,9 +210,11 @@ static CMakeBuildTarget toBuildTarget(const TargetDetails &t,
const FilePath &sourceDirectory,
const FilePath &buildDirectory,
bool relativeLibs,
const QSet<FilePath> &artifacts)
const QSet<FilePath> &sharedLibraryArtifacts)
{
const FilePath currentBuildDir = buildDirectory.resolvePath(t.buildDir);
const QSet<FilePath> sharedLibraryArtifactsPaths
= transform(sharedLibraryArtifacts, &FilePath::parentDir);
CMakeBuildTarget ct;
ct.title = t.name;
@@ -306,7 +308,6 @@ static CMakeBuildTarget toBuildTarget(const TargetDetails &t,
if (f.role == "libraries")
tmp = tmp.parentDir();
std::optional<QString> dllName;
if (buildDir.osType() == OsTypeWindows && (f.role == "libraries")) {
const auto partAsFilePath = FilePath::fromUserInput(part);
part = partAsFilePath.fileName();
@@ -314,24 +315,6 @@ static CMakeBuildTarget toBuildTarget(const TargetDetails &t,
// Skip object libraries on Windows. This case can happen with static qml plugins
if (part.endsWith(".obj") || part.endsWith(".o"))
continue;
// Only consider dlls, not static libraries
for (const QString &suffix :
{QString(".lib"), QString(".dll.a"), QString(".a")}) {
if (part.endsWith(suffix) && !dllName)
dllName = part.chopped(suffix.length()).append(".dll");
}
// MinGW has libQt6Core.a -> Qt6Core.dll
// but libFoo.dll.a was already handled above
const QString mingwPrefix("lib");
const QString mingwSuffix("a");
const QString completeSuffix = partAsFilePath.completeSuffix();
if (part.startsWith(mingwPrefix) && completeSuffix == mingwSuffix) {
dllName = part.chopped(mingwSuffix.length() + 1/*the '.'*/)
.sliced(mingwPrefix.length())
.append(".dll");
}
}
if (!tmp.isEmpty() && tmp.isDir()) {
@@ -345,18 +328,15 @@ static CMakeBuildTarget toBuildTarget(const TargetDetails &t,
{"/lib", "/lib64", "/usr/lib", "/usr/lib64", "/usr/local/lib"}))
librarySeachPaths.append(tmp);
if (buildDir.osType() == OsTypeWindows && dllName) {
const auto validPath = [&artifacts](const FilePath& path) {
return path.exists() || artifacts.contains(path);
};
if (validPath(tmp.pathAppended(*dllName)))
if (buildDir.osType() == OsTypeWindows) {
if (sharedLibraryArtifactsPaths.contains(tmp))
librarySeachPaths.append(tmp);
// Libraries often have their import libs in ../lib and the
// actual dll files in ../bin on windows. Qt is one example of that.
if (tmp.fileName() == "lib") {
const FilePath path = tmp.parentDir().pathAppended("bin");
if (path.isDir() && validPath(path.pathAppended(*dllName)))
if (path.isDir())
librarySeachPaths.append(path);
}
}
@@ -375,17 +355,19 @@ static QList<CMakeBuildTarget> generateBuildTargets(const QFuture<void> &cancelF
const FilePath &buildDirectory,
bool relativeLibs)
{
QSet<FilePath> artifacts;
QSet<FilePath> sharedLibraryArtifacts;
for (const TargetDetails &t : input.targetDetails)
for (const FilePath &p: t.artifacts)
artifacts.insert(buildDirectory.resolvePath(p));
if (t.type == "MODULE_LIBRARY" || t.type == "SHARED_LIBRARY")
for (const FilePath &p : t.artifacts)
sharedLibraryArtifacts.insert(buildDirectory.resolvePath(p));
QList<CMakeBuildTarget> result;
result.reserve(input.targetDetails.size());
for (const TargetDetails &t : input.targetDetails) {
if (cancelFuture.isCanceled())
return {};
result.append(toBuildTarget(t, sourceDirectory, buildDirectory, relativeLibs, artifacts));
result.append(
toBuildTarget(t, sourceDirectory, buildDirectory, relativeLibs, sharedLibraryArtifacts));
}
return result;
}

View File

@@ -168,41 +168,38 @@ CopilotSettings::CopilotSettings()
setLayouter([this] {
using namespace Layouting;
auto warningLabel = new QLabel;
warningLabel->setWordWrap(true);
warningLabel->setTextInteractionFlags(
Qt::LinksAccessibleByMouse | Qt::LinksAccessibleByKeyboard | Qt::TextSelectableByMouse);
warningLabel->setText(
Tr::tr("Enabling %1 is subject to your agreement and abidance with your applicable "
"%1 terms. It is your responsibility to know and accept the requirements and "
"parameters of using tools like %1. This may include, but is not limited to, "
"ensuring you have the rights to allow %1 access to your code, as well as "
"understanding any implications of your use of %1 and suggestions produced "
"(like copyright, accuracy, etc.).")
.arg("Copilot"));
auto authWidget = new AuthWidget();
auto helpLabel = new QLabel();
helpLabel->setTextFormat(Qt::MarkdownText);
helpLabel->setWordWrap(true);
helpLabel->setTextInteractionFlags(
Qt::LinksAccessibleByMouse | Qt::LinksAccessibleByKeyboard | Qt::TextSelectableByMouse);
helpLabel->setOpenExternalLinks(true);
connect(helpLabel, &QLabel::linkHovered, [](const QString &link) {
QToolTip::showText(QCursor::pos(), link);
});
// clang-format off
helpLabel->setText(Tr::tr(
"The Copilot plugin requires node.js and the Copilot neovim plugin. "
"If you install the neovim plugin as described in %1, "
"the plugin will find the agent.js file automatically.\n\n"
"Otherwise you need to specify the path to the %2 "
"file from the Copilot neovim plugin.",
"Markdown text for the copilot instruction label")
.arg("[README.md](https://github.com/github/copilot.vim)")
.arg("[agent.js](https://github.com/github/copilot.vim/tree/release/dist)"));
Label warningLabel {
wordWrap(true),
textInteractionFlags(
Qt::LinksAccessibleByMouse | Qt::LinksAccessibleByKeyboard | Qt::TextSelectableByMouse),
text(Tr::tr("Enabling %1 is subject to your agreement and abidance with your applicable "
"%1 terms. It is your responsibility to know and accept the requirements and "
"parameters of using tools like %1. This may include, but is not limited to, "
"ensuring you have the rights to allow %1 access to your code, as well as "
"understanding any implications of your use of %1 and suggestions produced "
"(like copyright, accuracy, etc.).")
.arg("Copilot")),
};
Label helpLabel {
textFormat(Qt::MarkdownText),
wordWrap(true),
textInteractionFlags(
Qt::LinksAccessibleByMouse | Qt::LinksAccessibleByKeyboard | Qt::TextSelectableByMouse),
openExternalLinks(true),
onLinkHovered([](const QString &link) { QToolTip::showText(QCursor::pos(), link); }, this),
text(Tr::tr(
"The Copilot plugin requires node.js and the Copilot neovim plugin. "
"If you install the neovim plugin as described in %1, "
"the plugin will find the agent.js file automatically.\n\n"
"Otherwise you need to specify the path to the %2 "
"file from the Copilot neovim plugin.",
"Markdown text for the copilot instruction label")
.arg("[README.md](https://github.com/github/copilot.vim)")
.arg("[agent.js](https://github.com/github/copilot.vim/tree/release/dist)"))
};
return Column {
Group {
@@ -213,7 +210,7 @@ CopilotSettings::CopilotSettings()
}
},
Form {
authWidget, br,
new AuthWidget, br,
enableCopilot, br,
nodeJsPath, br,
distPath, br,

View File

@@ -251,6 +251,9 @@ bool CorePlugin::initialize(const QStringList &arguments, QString *errorMessage)
expander->registerVariable("HostOs:ExecutableSuffix",
Tr::tr("The platform executable suffix."),
[] { return QString(Utils::HostOsInfo::withExecutableSuffix("")); });
expander->registerFileVariables("IDE:Executable",
Tr::tr("The path to the running %1 itself.").arg(QGuiApplication::applicationDisplayName()),
[]() { return FilePath::fromUserInput(QCoreApplication::applicationFilePath()); });
expander->registerVariable("IDE:ResourcePath",
Tr::tr("The directory where %1 finds its pre-installed resources.")
.arg(QGuiApplication::applicationDisplayName()),

View File

@@ -301,7 +301,6 @@ public:
WindowSupport *m_windowSupport = nullptr;
EditorManager *m_editorManager = nullptr;
ExternalToolManager *m_externalToolManager = nullptr;
MessageManager *m_messageManager = nullptr;
ProgressManagerPrivate *m_progressManager = nullptr;
JsExpander *m_jsExpander = nullptr;
VcsManager *m_vcsManager = nullptr;
@@ -1395,7 +1394,6 @@ void ICorePrivate::init()
m_rightNavigationWidget = new NavigationWidget(m_toggleRightSideBarAction, Side::Right);
m_rightPaneWidget = new RightPaneWidget();
m_messageManager = new MessageManager;
m_editorManager = new EditorManager(this);
m_externalToolManager = new ExternalToolManager();
@@ -1454,8 +1452,7 @@ ICorePrivate::~ICorePrivate()
delete m_externalToolManager;
m_externalToolManager = nullptr;
delete m_messageManager;
m_messageManager = nullptr;
MessageManager::destroy();
delete m_shortcutSettings;
m_shortcutSettings = nullptr;
delete m_toolSettings;

View File

@@ -237,98 +237,6 @@ private:
QList<std::optional<LocatorFilterEntries>> m_outputData;
};
// This instance of this object is created by LocatorMatcher tree.
// It starts a separate thread which collects and deduplicates the results reported
// by LocatorStorage instances. The ResultsCollector is started as a first task in
// LocatorMatcher and runs in parallel to all the filters started by LocatorMatcher.
// When all the results are reported (the expected number of reports is set with setFilterCount()),
// the ResultsCollector finishes. The intermediate results are reported with
// serialOutputDataReady() signal.
// The object of ResultsCollector is registered in Tasking namespace under the
// ResultsCollectorTask name.
class ResultsCollector : public QObject
{
Q_OBJECT
public:
~ResultsCollector();
void setFilterCount(int count);
void start();
bool isRunning() const { return m_watcher.get(); }
std::shared_ptr<ResultsDeduplicator> deduplicator() const { return m_deduplicator; }
signals:
void serialOutputDataReady(const LocatorFilterEntries &serialOutputData);
void done();
private:
int m_filterCount = 0;
std::unique_ptr<QFutureWatcher<LocatorFilterEntries>> m_watcher;
std::shared_ptr<ResultsDeduplicator> m_deduplicator;
};
ResultsCollector::~ResultsCollector()
{
if (!isRunning())
return;
m_deduplicator->cancel();
if (Utils::futureSynchronizer()) {
Utils::futureSynchronizer()->addFuture(m_watcher->future());
return;
}
m_watcher->future().waitForFinished();
}
void ResultsCollector::setFilterCount(int count)
{
QTC_ASSERT(!isRunning(), return);
QTC_ASSERT(count >= 0, return);
m_filterCount = count;
}
void ResultsCollector::start()
{
QTC_ASSERT(!m_watcher, return);
QTC_ASSERT(!isRunning(), return);
if (m_filterCount == 0) {
emit done();
return;
}
m_deduplicator.reset(new ResultsDeduplicator(m_filterCount));
m_watcher.reset(new QFutureWatcher<LocatorFilterEntries>);
connect(m_watcher.get(), &QFutureWatcherBase::resultReadyAt, this, [this](int index) {
emit serialOutputDataReady(m_watcher->resultAt(index));
});
connect(m_watcher.get(), &QFutureWatcherBase::finished, this, [this] {
emit done();
m_watcher.release()->deleteLater();
m_deduplicator.reset();
});
// TODO: When filterCount == 1, deliver results directly and finish?
auto deduplicate = [](QPromise<LocatorFilterEntries> &promise,
const std::shared_ptr<ResultsDeduplicator> &deduplicator) {
deduplicator->run(promise);
};
m_watcher->setFuture(Utils::asyncRun(deduplicate, m_deduplicator));
}
class ResultsCollectorTaskAdapter : public TaskAdapter<ResultsCollector>
{
public:
ResultsCollectorTaskAdapter() {
connect(task(), &ResultsCollector::done, this, [this] { emit done(DoneResult::Success); });
}
void start() final { task()->start(); }
};
using ResultsCollectorTask = CustomTask<ResultsCollectorTaskAdapter>;
class LocatorStoragePrivate
{
public:
@@ -425,23 +333,39 @@ void LocatorMatcher::start()
QTC_ASSERT(!isRunning(), return);
d->m_output = {};
const Storage<ResultsCollector *> collectorStorage;
const int filterCount = d->m_tasks.size();
if (filterCount <= 0)
return;
struct ResultsCollector
{
~ResultsCollector() {
if (m_deduplicator)
m_deduplicator->cancel();
}
std::shared_ptr<ResultsDeduplicator> m_deduplicator;
};
const Storage<ResultsCollector> collectorStorage;
const LoopList iterator(d->m_tasks);
const auto onCollectorSetup = [this, filterCount = d->m_tasks.size(), collectorStorage](
ResultsCollector &collector) {
*collectorStorage = &collector;
collector.setFilterCount(filterCount);
connect(&collector, &ResultsCollector::serialOutputDataReady,
this, [this](const LocatorFilterEntries &serialOutputData) {
const auto onCollectorSetup = [this, filterCount, collectorStorage](
Async<LocatorFilterEntries> &async) {
const std::shared_ptr<ResultsDeduplicator> deduplicator(new ResultsDeduplicator(filterCount));
collectorStorage->m_deduplicator = deduplicator;
Async<LocatorFilterEntries> *asyncPtr = &async;
connect(asyncPtr, &AsyncBase::resultReadyAt, this, [this, asyncPtr](int index) {
const LocatorFilterEntries serialOutputData = asyncPtr->resultAt(index);
d->m_output += serialOutputData;
emit serialOutputDataReady(serialOutputData);
});
// TODO: When filterCount == 1, deliver results directly and finish?
async.setConcurrentCallData(&ResultsDeduplicator::run, deduplicator);
};
const auto onCollectorDone = [collectorStorage] { *collectorStorage = nullptr; };
const auto onCollectorDone = [collectorStorage] { collectorStorage->m_deduplicator->cancel(); };
const auto onTaskTreeSetup = [iterator, input = d->m_input, collectorStorage](TaskTree &taskTree) {
const std::shared_ptr<ResultsDeduplicator> deduplicator = (*collectorStorage)->deduplicator();
const std::shared_ptr<ResultsDeduplicator> deduplicator = collectorStorage->m_deduplicator;
const Storage<LocatorStorage> storage = iterator->storage;
const auto onSetup = [storage, input, index = iterator.iteration(), deduplicator] {
*storage = std::make_shared<LocatorStoragePrivate>(input, index, deduplicator);
@@ -458,7 +382,7 @@ void LocatorMatcher::start()
const Group root {
parallel,
collectorStorage,
ResultsCollectorTask(onCollectorSetup, onCollectorDone),
AsyncTask<LocatorFilterEntries>(onCollectorSetup, onCollectorDone),
Group {
parallelLimit(d->m_parallelLimit),
iterator,
@@ -1472,5 +1396,3 @@ LocatorMatcherTask LocatorFileCache::matcher() const
}
} // Core
#include "ilocatorfilter.moc"

View File

@@ -5,113 +5,88 @@
#include "messageoutputwindow.h"
#include <extensionsystem/pluginmanager.h>
#include <utils/qtcassert.h>
#include <QFont>
#include <QThread>
#include <QTime>
#include <memory>
/*!
\class Core::MessageManager
\namespace Core::MessageManager
\inheaderfile coreplugin/messagemanager.h
\ingroup mainclasses
\inmodule QtCreator
\brief The MessageManager class is used to post messages in the
\brief The MessageManager namespace is used to post messages in the
\uicontrol{General Messages} pane.
*/
namespace Core {
namespace Core::MessageManager {
static MessageManager *m_instance = nullptr;
static Internal::MessageOutputWindow *m_messageOutputWindow = nullptr;
static std::unique_ptr<Internal::MessageOutputWindow> s_messageOutputWindow;
enum class Flag { Silent, Flash, Disrupt };
static void showOutputPane(Flag flags)
{
QTC_ASSERT(m_messageOutputWindow, return);
QTC_ASSERT(s_messageOutputWindow, return);
switch (flags) {
case Core::Flag::Silent:
case Flag::Silent:
break;
case Core::Flag::Flash:
m_messageOutputWindow->flash();
case Flag::Flash:
s_messageOutputWindow->flash();
break;
case Core::Flag::Disrupt:
m_messageOutputWindow->popup(IOutputPane::ModeSwitch | IOutputPane::WithFocus);
case Flag::Disrupt:
s_messageOutputWindow->popup(IOutputPane::ModeSwitch | IOutputPane::WithFocus);
break;
}
}
static void doWrite(const QString &text, Flag flags)
{
QTC_ASSERT(m_messageOutputWindow, return);
QTC_ASSERT(s_messageOutputWindow, return);
showOutputPane(flags);
m_messageOutputWindow->append(text + '\n');
s_messageOutputWindow->append(text + '\n');
}
static void write(const QString &text, Flag flags)
static void writeImpl(const QString &text, Flag flags)
{
QTC_ASSERT(m_instance, return);
if (QThread::currentThread() == m_instance->thread())
doWrite(text, flags);
else
QMetaObject::invokeMethod(m_instance, [text, flags] {
doWrite(text, flags);
}, Qt::QueuedConnection);
QTC_ASSERT(s_messageOutputWindow, return);
QMetaObject::invokeMethod(s_messageOutputWindow.get(), [text, flags] { doWrite(text, flags); });
}
/*!
\internal
*/
MessageManager::MessageManager()
void init()
{
m_instance = this;
m_messageOutputWindow = nullptr;
s_messageOutputWindow.reset(new Internal::MessageOutputWindow);
}
/*!
\internal
*/
MessageManager::~MessageManager()
void destroy()
{
if (m_messageOutputWindow) {
ExtensionSystem::PluginManager::removeObject(m_messageOutputWindow);
delete m_messageOutputWindow;
}
m_instance = nullptr;
s_messageOutputWindow.reset();
}
/*!
\internal
*/
void MessageManager::init()
void setFont(const QFont &font)
{
m_messageOutputWindow = new Internal::MessageOutputWindow;
ExtensionSystem::PluginManager::addObject(m_messageOutputWindow);
QTC_ASSERT(s_messageOutputWindow, return);
s_messageOutputWindow->setFont(font);
}
/*!
\internal
*/
void MessageManager::setFont(const QFont &font)
void setWheelZoomEnabled(bool enabled)
{
QTC_ASSERT(m_messageOutputWindow, return);
m_messageOutputWindow->setFont(font);
}
/*!
\internal
*/
void MessageManager::setWheelZoomEnabled(bool enabled)
{
QTC_ASSERT(m_messageOutputWindow, return);
m_messageOutputWindow->setWheelZoomEnabled(enabled);
QTC_ASSERT(s_messageOutputWindow, return);
s_messageOutputWindow->setWheelZoomEnabled(enabled);
}
/*!
@@ -124,9 +99,9 @@ void MessageManager::setWheelZoomEnabled(bool enabled)
\sa writeFlashing()
\sa writeDisrupting()
*/
void MessageManager::writeSilently(const QString &message)
void writeSilently(const QString &message)
{
Core::write(message, Flag::Silent);
writeImpl(message, Flag::Silent);
}
/*!
@@ -141,9 +116,9 @@ void MessageManager::writeSilently(const QString &message)
\sa writeSilently()
\sa writeDisrupting()
*/
void MessageManager::writeFlashing(const QString &message)
void writeFlashing(const QString &message)
{
Core::write(message, Flag::Flash);
writeImpl(message, Flag::Flash);
}
/*!
@@ -156,15 +131,15 @@ void MessageManager::writeFlashing(const QString &message)
\sa writeSilently()
\sa writeFlashing()
*/
void MessageManager::writeDisrupting(const QString &message)
void writeDisrupting(const QString &message)
{
Core::write(message, Flag::Disrupt);
writeImpl(message, Flag::Disrupt);
}
/*!
\overload writeSilently()
*/
void MessageManager::writeSilently(const QStringList &messages)
void writeSilently(const QStringList &messages)
{
writeSilently(messages.join('\n'));
}
@@ -172,7 +147,7 @@ void MessageManager::writeSilently(const QStringList &messages)
/*!
\overload writeFlashing()
*/
void MessageManager::writeFlashing(const QStringList &messages)
void writeFlashing(const QStringList &messages)
{
writeFlashing(messages.join('\n'));
}
@@ -180,9 +155,9 @@ void MessageManager::writeFlashing(const QStringList &messages)
/*!
\overload writeDisrupting()
*/
void MessageManager::writeDisrupting(const QStringList &messages)
void writeDisrupting(const QStringList &messages)
{
writeDisrupting(messages.join('\n'));
}
} // namespace Core
} // namespace Core::MessageManager

View File

@@ -5,47 +5,26 @@
#include "core_global.h"
#include <QMetaType>
#include <QObject>
#include <QStringList>
QT_BEGIN_NAMESPACE
class QFont;
QT_END_NAMESPACE
namespace Core {
namespace Core::MessageManager {
class ICore;
CORE_EXPORT void setFont(const QFont &font);
CORE_EXPORT void setWheelZoomEnabled(bool enabled);
namespace Internal {
class ICorePrivate;
class MainWindow;
}
CORE_EXPORT void writeSilently(const QString &message);
CORE_EXPORT void writeFlashing(const QString &message);
CORE_EXPORT void writeDisrupting(const QString &message);
class CORE_EXPORT MessageManager : public QObject
{
Q_OBJECT
CORE_EXPORT void writeSilently(const QStringList &messages);
CORE_EXPORT void writeFlashing(const QStringList &messages);
CORE_EXPORT void writeDisrupting(const QStringList &messages);
public:
static void setFont(const QFont &font);
static void setWheelZoomEnabled(bool enabled);
void init();
void destroy();
static void writeSilently(const QString &message);
static void writeFlashing(const QString &message);
static void writeDisrupting(const QString &message);
static void writeSilently(const QStringList &messages);
static void writeFlashing(const QStringList &messages);
static void writeDisrupting(const QStringList &messages);
private:
MessageManager();
~MessageManager() override;
static void init();
friend class ICore;
friend class Internal::ICorePrivate;
friend class Internal::MainWindow;
};
} // namespace Core
} // namespace Core::MessageManager

View File

@@ -83,6 +83,7 @@ bool operator==(const CppEditor::CppCodeModelSettings &s1,
&& s1.useBuiltinPreprocessor == s2.useBuiltinPreprocessor
&& s1.indexerFileSizeLimitInMb == s2.indexerFileSizeLimitInMb
&& s1.m_categorizeFindReferences == s2.m_categorizeFindReferences
&& s1.interactiveFollowSymbol == s2.interactiveFollowSymbol
&& s1.ignoreFiles == s2.ignoreFiles && s1.ignorePattern == s2.ignorePattern;
}
@@ -204,6 +205,16 @@ void CppCodeModelSettings::setCategorizeFindReferences(bool categorize)
globalInstance().m_categorizeFindReferences = categorize;
}
bool CppCodeModelSettings::isInteractiveFollowSymbol()
{
return globalInstance().interactiveFollowSymbol;
}
void CppCodeModelSettings::setInteractiveFollowSymbol(bool interactive)
{
globalInstance().interactiveFollowSymbol = interactive;
}
CppCodeModelProjectSettings::CppCodeModelProjectSettings(ProjectExplorer::Project *project)
: m_project(project)
{

View File

@@ -55,6 +55,9 @@ public:
static bool categorizeFindReferences();
static void setCategorizeFindReferences(bool categorize);
static bool isInteractiveFollowSymbol();
static void setInteractiveFollowSymbol(bool interactive);
QString ignorePattern;
PCHUsage pchUsage = PchUse_BuildSystem;
int indexerFileSizeLimitInMb = 5;
@@ -63,7 +66,10 @@ public:
bool useBuiltinPreprocessor = true;
bool ignoreFiles = false;
bool enableIndexing = true;
bool m_categorizeFindReferences = false; // Ephemeral!
// Ephemeral!
bool m_categorizeFindReferences = false;
bool interactiveFollowSymbol = true;
private:
CppCodeModelSettings(Utils::QtcSettings *s) { fromSettings(s); }
@@ -76,6 +82,14 @@ private:
namespace Internal {
void setupCppCodeModelSettingsPage();
void setupCppCodeModelProjectSettingsPanel();
class NonInteractiveFollowSymbolMarker
{
public:
NonInteractiveFollowSymbolMarker() { CppCodeModelSettings::setInteractiveFollowSymbol(false); }
~NonInteractiveFollowSymbolMarker() { CppCodeModelSettings::setInteractiveFollowSymbol(true); }
};
} // namespace Internal
} // namespace CppEditor

View File

@@ -623,6 +623,7 @@ void CppEditorWidget::renameUsages(const QString &replacement, QTextCursor curso
const CursorInEditor cursorInEditor{cursor, textDocument()->filePath(), this, textDocument()};
CppModelManager::globalRename(cursorInEditor, replacement);
};
NonInteractiveFollowSymbolMarker niMarker;
CppModelManager::followSymbol(CursorInEditor{cursor,
textDocument()->filePath(),
this,

View File

@@ -260,15 +260,14 @@ static void extractNames(const CppRefactoringFilePtr &file,
class GetterSetterRefactoringHelper
{
public:
GetterSetterRefactoringHelper(CppQuickFixOperation *operation,
const FilePath &filePath,
Class *clazz)
GetterSetterRefactoringHelper(CppQuickFixOperation *operation, Class *clazz)
: m_operation(operation)
, m_changes(m_operation->snapshot())
, m_locator(m_changes)
, m_headerFile(m_changes.cppFile(filePath))
, m_headerFile(operation->currentFile())
, m_sourceFile([&] {
FilePath cppFilePath = correspondingHeaderOrSource(filePath, &m_isHeaderHeaderFile);
FilePath cppFilePath = correspondingHeaderOrSource(m_headerFile->filePath(),
&m_isHeaderHeaderFile);
if (!m_isHeaderHeaderFile || !cppFilePath.exists()) {
// there is no "source" file
return m_headerFile;
@@ -1271,11 +1270,10 @@ private:
const ClassSpecifierAST *m_classAST;
InsertionPointLocator::AccessSpec m_accessSpec;
GenerateConstructorRefactoringHelper(CppQuickFixOperation *operation,
const FilePath &filePath,
Class *clazz,
const ClassSpecifierAST *classAST,
InsertionPointLocator::AccessSpec accessSpec)
: GetterSetterRefactoringHelper(operation, filePath, clazz)
: GetterSetterRefactoringHelper(operation, clazz)
, m_classAST(classAST)
, m_accessSpec(accessSpec)
{}
@@ -1416,7 +1414,6 @@ private:
}
};
GenerateConstructorRefactoringHelper helper(this,
currentFile()->filePath(),
m_classAST->symbol,
m_classAST,
accessSpec);
@@ -1509,7 +1506,7 @@ public:
void perform() override
{
GetterSetterRefactoringHelper helper(this, currentFile()->filePath(), m_data.clazz);
GetterSetterRefactoringHelper helper(this, m_data.clazz);
helper.performGeneration(m_data, m_generateFlags);
helper.applyChanges();
}
@@ -1829,9 +1826,7 @@ private:
}
if (m_candidates.empty())
return;
GetterSetterRefactoringHelper helper(this,
currentFile()->filePath(),
m_candidates.front().data.clazz);
GetterSetterRefactoringHelper helper(this, m_candidates.front().data.clazz);
for (MemberInfo &mi : m_candidates) {
if (mi.requestedFlags != 0) {
helper.performGeneration(mi.data, mi.requestedFlags);

View File

@@ -767,8 +767,7 @@ public:
printer.showTemplateParameters = true;
Utils::ChangeSet headerChangeSet;
const CppRefactoringChanges refactoring(snapshot());
const Utils::FilePath filePath = currentFile()->filePath();
const CppRefactoringFilePtr headerFile = refactoring.cppFile(filePath);
const CppRefactoringFilePtr headerFile = currentFile();
const LookupContext targetContext(headerFile->cppDocument(), snapshot());
const Class *targetClass = m_classAST->symbol;

View File

@@ -370,6 +370,7 @@ private:
if (!link.hasValidTarget())
collectOperations(interface, result);
};
NonInteractiveFollowSymbolMarker niMarker;
CppModelManager::followSymbol(cursorInEditor, followSymbolFallback, false, false,
FollowSymbolMode::Exact,
CppModelManager::Backend::Builtin);

View File

@@ -155,8 +155,7 @@ public:
// rewrite the function name
if (nameIncludesOperatorName(decl->name())) {
CppRefactoringFilePtr file = refactoring.cppFile(op->filePath());
const QString operatorNameText = file->textOf(declAST->core_declarator);
const QString operatorNameText = op->currentFile()->textOf(declAST->core_declarator);
oo.includeWhiteSpaceInOperatorName = operatorNameText.contains(QLatin1Char(' '));
}
const QString name = oo.prettyName(LookupContext::minimalName(decl, targetCoN,

View File

@@ -294,6 +294,7 @@ private:
// Force queued execution, as the built-in editor can run the callback synchronously.
const auto followSymbol = [cursorInEditor, callback] {
NonInteractiveFollowSymbolMarker niMarker;
CppModelManager::followSymbol(
cursorInEditor, callback, true, false, FollowSymbolMode::Exact);
};

View File

@@ -86,10 +86,10 @@ public:
};
MoveFuncDefRefactoringHelper(CppQuickFixOperation *operation, MoveType type,
const FilePath &fromFile, const FilePath &toFile)
const FilePath &toFile)
: m_operation(operation), m_type(type), m_changes(m_operation->snapshot())
{
m_fromFile = m_changes.cppFile(fromFile);
m_fromFile = operation->currentFile();
m_toFile = (m_type == MoveOutside) ? m_fromFile : m_changes.cppFile(toFile);
}
@@ -159,19 +159,18 @@ public:
, m_funcDef(funcDef)
, m_type(type)
, m_cppFilePath(cppFilePath)
, m_headerFilePath(funcDef->symbol->filePath())
{
if (m_type == MoveFuncDefRefactoringHelper::MoveOutside) {
setDescription(Tr::tr("Move Definition Outside Class"));
} else {
const FilePath resolved = m_cppFilePath.relativePathFrom(m_headerFilePath.parentDir());
const FilePath resolved = m_cppFilePath.relativePathFrom(filePath().parentDir());
setDescription(Tr::tr("Move Definition to %1").arg(resolved.displayName()));
}
}
void perform() override
{
MoveFuncDefRefactoringHelper helper(this, m_type, m_headerFilePath, m_cppFilePath);
MoveFuncDefRefactoringHelper helper(this, m_type, m_cppFilePath);
helper.performMove(m_funcDef);
helper.applyChanges();
}
@@ -180,7 +179,6 @@ private:
FunctionDefinitionAST *m_funcDef;
MoveFuncDefRefactoringHelper::MoveType m_type;
const FilePath m_cppFilePath;
const FilePath m_headerFilePath;
};
class MoveAllFuncDefOutsideOp : public CppQuickFixOperation
@@ -193,12 +191,11 @@ public:
, m_type(type)
, m_classDef(classDef)
, m_cppFilePath(cppFileName)
, m_headerFilePath(classDef->symbol->filePath())
{
if (m_type == MoveFuncDefRefactoringHelper::MoveOutside) {
setDescription(Tr::tr("Definitions Outside Class"));
} else {
const FilePath resolved = m_cppFilePath.relativePathFrom(m_headerFilePath.parentDir());
const FilePath resolved = m_cppFilePath.relativePathFrom(filePath().parentDir());
setDescription(Tr::tr("Move All Function Definitions to %1")
.arg(resolved.displayName()));
}
@@ -206,7 +203,7 @@ public:
void perform() override
{
MoveFuncDefRefactoringHelper helper(this, m_type, m_headerFilePath, m_cppFilePath);
MoveFuncDefRefactoringHelper helper(this, m_type, m_cppFilePath);
for (DeclarationListAST *it = m_classDef->member_specifier_list; it; it = it->next) {
if (FunctionDefinitionAST *funcAST = it->value->asFunctionDefinition()) {
if (funcAST->symbol && !funcAST->symbol->isGenerated())
@@ -220,7 +217,6 @@ private:
MoveFuncDefRefactoringHelper::MoveType m_type;
ClassSpecifierAST *m_classDef;
const FilePath m_cppFilePath;
const FilePath m_headerFilePath;
};
class MoveFuncDefToDeclOp : public CppQuickFixOperation

View File

@@ -235,29 +235,34 @@ public:
private:
void perform() override
{
const auto textDoc = const_cast<QTextDocument *>(currentFile()->document());
const int pos = currentFile()->cppDocument()->translationUnit()->getTokenPositionInDocument(
const CppRefactoringFilePtr file = currentFile();
const auto textDoc = const_cast<QTextDocument *>(file->document());
const int pos = file->cppDocument()->translationUnit()->getTokenPositionInDocument(
m_symbol->sourceLocation(), textDoc);
QTextCursor cursor(textDoc);
cursor.setPosition(pos);
const CursorInEditor cursorInEditor(cursor, currentFile()->filePath(), editor(),
const CursorInEditor cursorInEditor(cursor, file->filePath(), editor(),
editor()->textDocument());
const auto callback = [symbolLoc = m_symbol->toLink(), comments = m_commentTokens]
const auto callback = [symbolLoc = m_symbol->toLink(), comments = m_commentTokens, file]
(const Link &link) {
moveComments(link, symbolLoc, comments);
moveComments(file, link, symbolLoc, comments);
};
NonInteractiveFollowSymbolMarker niMarker;
CppCodeModelSettings::setInteractiveFollowSymbol(false);
CppModelManager::followSymbol(cursorInEditor, callback, true, false,
FollowSymbolMode::Exact);
}
static void moveComments(const Link &targetLoc, const Link &symbolLoc,
const QList<Token> &comments)
static void moveComments(
const CppRefactoringFilePtr &sourceFile,
const Link &targetLoc,
const Link &symbolLoc,
const QList<Token> &comments)
{
if (!targetLoc.hasValidTarget() || targetLoc.hasSameLocation(symbolLoc))
return;
CppRefactoringChanges changes(CppModelManager::snapshot());
const CppRefactoringFilePtr sourceFile = changes.cppFile(symbolLoc.targetFilePath);
const CppRefactoringFilePtr targetFile
= targetLoc.targetFilePath == symbolLoc.targetFilePath
? sourceFile

View File

@@ -41,6 +41,7 @@ public:
setDescription(
Tr::tr("Re-order Member Function Definitions According to Declaration Order"));
m_state->decls = decls;
m_state->currentFile = currentFile();
}
private:
@@ -71,6 +72,7 @@ private:
QList<Symbol *> decls;
QHash<FilePath, DefLocations> defLocations;
CppRefactoringFilePtr currentFile;
int remainingFollowSymbolOps = 0;
};
@@ -120,6 +122,7 @@ private:
// Force queued execution, as the built-in editor can run the callback synchronously.
const auto followSymbol = [cursorInEditor, callback] {
NonInteractiveFollowSymbolMarker niMarker;
CppModelManager::followSymbol(
cursorInEditor, callback, true, false, FollowSymbolMode::Exact);
};
@@ -157,7 +160,9 @@ private:
if (defLocsExpectedOrder == defLocsActualOrder)
continue;
CppRefactoringFilePtr file = factory.cppFile(it.key());
CppRefactoringFilePtr file = it.key() == state->currentFile->filePath()
? state->currentFile
: factory.cppFile(it.key());
ChangeSet changes;
for (int i = 0; i < defLocsActualOrder.size(); ++i) {
const DefLocation &actualLoc = defLocsActualOrder[i];

View File

@@ -15,7 +15,7 @@
"Category" : "Qt Creator",
"Description" : "Design Qt-widgets based UIs",
"LongDescription" : [
"Create widgets and forms that are integrated with Qt C++ code.",
"Create widgets and forms that are integrated with Qt C++ code."
],
"Url" : "https://www.qt.io",
${DESIGNER_PLUGIN_ARGUMENTS}

View File

@@ -26,7 +26,6 @@
#include <QAction>
#include <QMainWindow>
using namespace ExtensionSystem;
using namespace Core;
using namespace Utils;
@@ -45,7 +44,7 @@ public:
Theme::IconsBaseColor}});
const Icon FLAT_ACTIVE({{":/extensionmanager/images/mode_extensionmanager_mask.png",
Theme::IconsModeWelcomeActiveColor}});
setIcon(Utils::Icon::modeIcon(FLAT, FLAT, FLAT_ACTIVE));
setIcon(Icon::modeIcon(FLAT, FLAT, FLAT_ACTIVE));
setPriority(72);
using namespace Layouting;

View File

@@ -280,7 +280,7 @@ void ExtensionManagerWidget::updateView(const QModelIndex &current)
const LinksData linksData = current.data(RoleDescriptionLinks).value<LinksData>();
if (!linksData.isEmpty()) {
QString linksHtml;
const QStringList links = Utils::transform(linksData, [](const LinksData::Type &link) {
const QStringList links = transform(linksData, [](const LinksData::Type &link) {
const QString anchor = link.first.isEmpty() ? link.second : link.first;
return QString::fromLatin1("<a href=\"%1\">%2 &gt;</a>")
.arg(link.second).arg(anchor);
@@ -293,7 +293,7 @@ void ExtensionManagerWidget::updateView(const QModelIndex &current)
if (!imagesData.isEmpty()) {
const QString examplesBoxCss =
QString::fromLatin1("height: 168px; background-color: %1; ")
.arg(creatorTheme()->color(Theme::Token_Background_Default).name());
.arg(creatorColor(Theme::Token_Background_Default).name());
description.append(QString(R"(
<br/>
<div style="%1">%2</div>
@@ -362,8 +362,8 @@ void ExtensionManagerWidget::updateView(const QModelIndex &current)
if (!tags.isEmpty()) {
const QString tagTemplate = QString(R"(
<td style="border: 1px solid %1; padding: 3px; ">%2</td>
)").arg(creatorTheme()->color(Theme::Token_Stroke_Subtle).name());
const QStringList tagsFmt = Utils::transform(tags, [&tagTemplate](const QString &tag) {
)").arg(creatorColor(Theme::Token_Stroke_Subtle).name());
const QStringList tagsFmt = transform(tags, [&tagTemplate](const QString &tag) {
return tagTemplate.arg(tag);
});
description.append(QString(R"(
@@ -397,8 +397,7 @@ void ExtensionManagerWidget::updateView(const QModelIndex &current)
if (isPack) {
const PluginsData plugins = current.data(RolePlugins).value<PluginsData>();
const QStringList extensions = Utils::transform(plugins,
&QPair<QString, QString>::first);
const QStringList extensions = transform(plugins, &QPair<QString, QString>::first);
const QString extensionsFmt = extensions.join("<br/>");
description.append(QString(R"(
<div style="%1">%2</div>
@@ -422,7 +421,7 @@ void ExtensionManagerWidget::fetchAndInstallPlugin(const QUrl &url)
StorageStruct() {
progressDialog.reset(new QProgressDialog(Tr::tr("Downloading Plugin..."),
Tr::tr("Cancel"), 0, 0,
Core::ICore::dialogParent()));
ICore::dialogParent()));
progressDialog->setWindowModality(Qt::ApplicationModal);
progressDialog->setFixedSize(progressDialog->sizeHint());
progressDialog->setAutoClose(false);

View File

@@ -198,7 +198,7 @@ ExtensionsBrowser::ExtensionsBrowser(QWidget *parent)
auto manageLabel = new QLabel(Tr::tr("Manage Extensions"));
manageLabel->setFont(StyleHelper::uiFont(StyleHelper::UiElementH1));
d->searchBox = new Core::SearchBox;
d->searchBox = new SearchBox;
d->searchBox->setFixedWidth(itemSize.width());
d->updateButton = new Button(Tr::tr("Install..."), Button::MediumPrimary);
@@ -252,10 +252,8 @@ ExtensionsBrowser::ExtensionsBrowser(QWidget *parent)
connect(d->updateButton, &QAbstractButton::pressed, this, []() {
executePluginInstallWizard();
});
connect(ExtensionSystem::PluginManager::instance(),
&ExtensionSystem::PluginManager::pluginsChanged, this, updateModel);
connect(ExtensionSystem::PluginManager::instance(),
&ExtensionSystem::PluginManager::initializationDone,
connect(PluginManager::instance(), &PluginManager::pluginsChanged, this, updateModel);
connect(PluginManager::instance(), &PluginManager::initializationDone,
this, &ExtensionsBrowser::fetchExtensions);
connect(d->searchBox, &QLineEdit::textChanged,
d->filterProxyModel, &QSortFilterProxyModel::setFilterWildcard);

View File

@@ -3,9 +3,6 @@
#include "extensionsmodel.h"
#include "extensionsbrowser.h"
#include "extensionmanagertr.h"
#include "utils/algorithm.h"
#include <coreplugin/coreconstants.h>
@@ -30,16 +27,16 @@ namespace ExtensionManager::Internal {
Q_LOGGING_CATEGORY(modelLog, "qtc.extensionmanager.model", QtWarningMsg)
struct PluginDependency
struct Dependency
{
QString name;
QString version;
};
using PluginDependencies = QList<PluginDependency>;
using Dependencies = QList<Dependency>;
struct Plugin
{
PluginDependencies dependencies;
Dependencies dependencies;
QString copyright;
QString name;
QString packageUrl;
@@ -74,10 +71,10 @@ static Plugin pluginFromJson(const QJsonObject &obj)
const QJsonObject metaDataObj = obj.value("meta_data").toObject();
const QJsonArray dependenciesArray = metaDataObj.value("Dependencies").toArray();
PluginDependencies dependencies;
Dependencies dependencies;
for (const QJsonValueConstRef &dependencyVal : dependenciesArray) {
const QJsonObject dependencyObj = dependencyVal.toObject();
dependencies.append(PluginDependency{
dependencies.append(Dependency{
.name = dependencyObj.value("Name").toString(),
.version = dependencyObj.value("Version").toString(),
});
@@ -189,19 +186,12 @@ static Extensions parseExtensionsRepoReply(const QByteArray &jsonData)
return parsedExtensions;
}
class ExtensionsModelPrivate : public QObject
class ExtensionsModelPrivate
{
public:
ExtensionsModelPrivate(ExtensionsModel *parent)
: q(parent)
{
}
void setExtensions(const Extensions &extensions);
void removeLocalExtensions();
ExtensionsModel *q;
Extensions allExtensions; // Original, complete extensions entries
Extensions absentExtensions; // All packs + plugin extensions that are not (yet) installed
};
@@ -224,7 +214,7 @@ void ExtensionsModelPrivate::removeLocalExtensions()
ExtensionsModel::ExtensionsModel(QObject *parent)
: QAbstractListModel(parent)
, d(new ExtensionsModelPrivate(this))
, d(new ExtensionsModelPrivate)
{
}
@@ -250,7 +240,7 @@ static QVariant dataFromPluginSpec(const PluginSpec *pluginSpec, int role)
return pluginSpec->copyright();
case RoleDependencies: {
QStringList dependencies = transform(pluginSpec->dependencies(),
&ExtensionSystem::PluginDependency::toString);
&PluginDependency::toString);
dependencies.sort();
return dependencies;
}
@@ -301,7 +291,7 @@ static QStringList dependenciesFromExtension(const Extension &extension)
{
QStringList dependencies;
for (const Plugin &plugin : extension.plugins) {
for (const PluginDependency &dependency : plugin.dependencies) {
for (const Dependency &dependency : plugin.dependencies) {
const QString withVersion = QString::fromLatin1("%1 (%2)").arg(dependency.name)
.arg(dependency.version);
dependencies.append(withVersion);
@@ -404,8 +394,7 @@ void ExtensionsModel::setExtensionsJson(const QByteArray &json)
PluginSpec *ExtensionsModel::pluginSpecForName(const QString &pluginName)
{
return Utils::findOrDefault(PluginManager::plugins(),
Utils::equal(&PluginSpec::name, pluginName));
return findOrDefault(PluginManager::plugins(), equal(&PluginSpec::name, pluginName));
}
} // ExtensionManager::Internal

View File

@@ -39,10 +39,15 @@ add_qtc_plugin(Lua
meta/simpletypes.lua
meta/utils.lua
meta/widgets.lua
meta/wizard.lua
# generateqtbindings.cpp # Use this if you need to generate some code.
)
qt_add_resources(Lua lua_images_rcc
PREFIX "/lua"
FILES
images/settingscategory_lua.png
images/settingscategory_lua@2x.png
)
set_source_files_properties(luauibindings.cpp PROPERTY SKIP_AUTOMOC ON PROPERTY SKIP_AUTOGEN ON)
@@ -66,7 +71,6 @@ set(META_FILES
meta/simpletypes.lua
meta/utils.lua
meta/widgets.lua
meta/wizard.lua
)
qtc_copy_to_builddir(copy_lua_meta_files

View File

@@ -3,11 +3,22 @@
#include "../luaengine.h"
#include "../luaqttypes.h"
#include "../luatr.h"
#include <coreplugin/dialogs/ioptionspage.h>
#include <coreplugin/icore.h>
#include <utils/aspects.h>
#include <utils/infobar.h>
#include <utils/layoutbuilder.h>
#include <utils/networkaccessmanager.h>
#include <utils/stylehelper.h>
#include <QApplication>
#include <QCheckBox>
#include <QJsonArray>
#include <QJsonDocument>
#include <QMessageBox>
#include <QMetaEnum>
#include <QNetworkAccessManager>
#include <QNetworkReply>
@@ -37,35 +48,205 @@ static QString opToString(QNetworkAccessManager::Operation op)
void addFetchModule()
{
LuaEngine::registerProvider(
"Fetch", [](sol::state_view lua) -> sol::object {
const ScriptPluginSpec *pluginSpec = lua.get<ScriptPluginSpec *>("PluginSpec");
class Module : Utils::AspectContainer
{
Utils::StringListAspect pluginsAllowedToFetch{this};
Utils::StringListAspect pluginsNotAllowedToFetch{this};
sol::table async = lua.script("return require('async')", "_fetch_").get<sol::table>();
sol::function wrap = async["wrap"];
class LuaOptionsPage : public Core::IOptionsPage
{
public:
LuaOptionsPage(Module *module)
{
setId("BB.Lua.Fetch");
setDisplayName(Tr::tr("Network access"));
setCategory("ZY.Lua");
setDisplayCategory("Lua");
setCategoryIconPath(":/lua/images/settingscategory_lua.png");
setSettingsProvider(
[module] { return static_cast<Utils::AspectContainer *>(module); });
}
};
sol::table fetch = lua.create_table();
LuaOptionsPage settingsPage{this};
auto networkReplyType = lua.new_usertype<QNetworkReply>(
"QNetworkReply",
"error",
sol::property([](QNetworkReply *self) -> int { return self->error(); }),
"readAll",
[](QNetworkReply *r) { return r->readAll().toStdString(); },
"__tostring",
[](QNetworkReply *r) {
return QString("QNetworkReply(%1 \"%2\") => %3")
.arg(opToString(r->operation()))
.arg(r->url().toString())
.arg(r->error());
});
public:
Module()
{
setSettingsGroup("Lua.Fetch");
fetch["fetch_cb"] = [guard = pluginSpec->connectionGuard.get()](
const sol::table &options,
const sol::function &callback,
const sol::this_state &thisState) {
auto url = options.get<QString>("url");
pluginsAllowedToFetch.setSettingsKey("pluginsAllowedToFetch");
pluginsAllowedToFetch.setLabelText("Plugins allowed to fetch data from the internet");
pluginsAllowedToFetch.setToolTip(
"List of plugins that are allowed to fetch data from the internet");
pluginsAllowedToFetch.setUiAllowAdding(false);
pluginsAllowedToFetch.setUiAllowEditing(false);
pluginsNotAllowedToFetch.setSettingsKey("pluginsNotAllowedToFetch");
pluginsNotAllowedToFetch.setLabelText(
"Plugins not allowed to fetch data from the internet");
pluginsNotAllowedToFetch.setToolTip(
"List of plugins that are not allowed to fetch data from the internet");
pluginsNotAllowedToFetch.setUiAllowAdding(false);
pluginsNotAllowedToFetch.setUiAllowEditing(false);
setLayouter([this] {
using namespace Layouting;
// clang-format off
return Form {
pluginsAllowedToFetch, br,
pluginsNotAllowedToFetch, br,
};
// clang-format on
});
readSettings();
}
~Module() { writeSettings(); }
enum class IsAllowed { Yes, No, NeedsToAsk };
IsAllowed isAllowedToFetch(const QString &pluginName) const
{
if (pluginsAllowedToFetch().contains(pluginName))
return IsAllowed::Yes;
if (pluginsNotAllowedToFetch().contains(pluginName))
return IsAllowed::No;
return IsAllowed::NeedsToAsk;
}
void setAllowedToFetch(const QString &pluginName, IsAllowed allowed)
{
if (allowed == IsAllowed::Yes)
pluginsAllowedToFetch.appendValue(pluginName);
else if (allowed == IsAllowed::No)
pluginsNotAllowedToFetch.appendValue(pluginName);
if (allowed == IsAllowed::Yes)
pluginsNotAllowedToFetch.removeValue(pluginName);
else if (allowed == IsAllowed::No)
pluginsAllowedToFetch.removeValue(pluginName);
}
};
std::shared_ptr<Module> module = std::make_shared<Module>();
LuaEngine::registerProvider("Fetch", [mod = std::move(module)](sol::state_view lua) -> sol::object {
const ScriptPluginSpec *pluginSpec = lua.get<ScriptPluginSpec *>("PluginSpec");
sol::table async = lua.script("return require('async')", "_fetch_").get<sol::table>();
sol::function wrap = async["wrap"];
sol::table fetch = lua.create_table();
auto networkReplyType = lua.new_usertype<QNetworkReply>(
"QNetworkReply",
"error",
sol::property([](QNetworkReply *self) -> int { return self->error(); }),
"readAll",
[](QNetworkReply *r) { return r->readAll().toStdString(); },
"__tostring",
[](QNetworkReply *r) {
return QString("QNetworkReply(%1 \"%2\") => %3")
.arg(opToString(r->operation()))
.arg(r->url().toString())
.arg(r->error());
});
auto checkPermission = [mod,
pluginName = pluginSpec->name,
guard = pluginSpec->connectionGuard.get()](
QString url,
std::function<void()> fetch,
std::function<void()> notAllowed) {
auto isAllowed = mod->isAllowedToFetch(pluginName);
if (isAllowed == Module::IsAllowed::Yes) {
fetch();
return;
}
if (isAllowed == Module::IsAllowed::No) {
notAllowed();
return;
}
if (QApplication::activeModalWidget()) {
// We are already showing a modal dialog,
// so we have to use a QMessageBox instead of the info bar
auto msgBox = new QMessageBox(
QMessageBox::Question,
Tr::tr("Allow Internet access"),
Tr::tr("The plugin \"%1\" would like to fetch from the following url:\n%2")
.arg(pluginName)
.arg(url),
QMessageBox::Yes | QMessageBox::No,
Core::ICore::dialogParent());
msgBox->setCheckBox(new QCheckBox(Tr::tr("Remember choice")));
QObject::connect(
msgBox, &QMessageBox::accepted, guard, [mod, fetch, pluginName, msgBox]() {
if (msgBox->checkBox()->isChecked())
mod->setAllowedToFetch(pluginName, Module::IsAllowed::Yes);
fetch();
});
QObject::connect(
msgBox, &QMessageBox::rejected, guard, [mod, notAllowed, pluginName, msgBox]() {
if (msgBox->checkBox()->isChecked())
mod->setAllowedToFetch(pluginName, Module::IsAllowed::No);
notAllowed();
});
msgBox->show();
return;
}
Utils::InfoBarEntry entry{
Utils::Id::fromString("Fetch" + pluginName),
Tr::tr("The plugin \"%1\" would like to fetch data from the internet. Do "
"you want to allow this?")
.arg(pluginName)};
entry.setDetailsWidgetCreator([pluginName, url] {
const QString markdown = Tr::tr("The plugin \"**%1**\" would like to fetch "
"from the following url:\n\n")
.arg(pluginName)
+ QString("* [%3](%3)").arg(url);
QLabel *list = new QLabel();
list->setTextFormat(Qt::TextFormat::MarkdownText);
list->setText(markdown);
list->setMargin(Utils::StyleHelper::SpacingTokens::ExPaddingGapS);
return list;
});
entry.addCustomButton(Tr::tr("Always Allow"), [mod, pluginName, fetch]() {
mod->setAllowedToFetch(pluginName, Module::IsAllowed::Yes);
Core::ICore::infoBar()->removeInfo(Utils::Id::fromString("Fetch" + pluginName));
fetch();
});
entry.addCustomButton(Tr::tr("Allow once"), [pluginName, fetch]() {
Core::ICore::infoBar()->removeInfo(Utils::Id::fromString("Fetch" + pluginName));
fetch();
});
entry.setCancelButtonInfo(Tr::tr("Deny"), [mod, notAllowed, pluginName]() {
Core::ICore::infoBar()->removeInfo(Utils::Id::fromString("Fetch" + pluginName));
mod->setAllowedToFetch(pluginName, Module::IsAllowed::No);
notAllowed();
});
Core::ICore::infoBar()->addInfo(entry);
};
fetch["fetch_cb"] = [checkPermission,
pluginName = pluginSpec->name,
guard = pluginSpec->connectionGuard.get(),
mod](
const sol::table &options,
const sol::function &callback,
const sol::this_state &thisState) {
auto url = options.get<QString>("url");
auto actualFetch = [guard, url, options, callback, thisState]() {
auto method = (options.get_or<QString>("method", "GET")).toLower();
auto headers = options.get_or<sol::table>("headers", {});
auto data = options.get_or<QString>("body", {});
@@ -129,10 +310,17 @@ void addFetchModule()
}
};
fetch["fetch"] = wrap(fetch["fetch_cb"]);
checkPermission(url, actualFetch, [callback, pluginName]() {
callback(Tr::tr("Fetching is not allowed for the plugin \"%1\" (You can edit "
"permissions in Preferences => Lua)")
.arg(pluginName));
});
};
return fetch;
});
fetch["fetch"] = wrap(fetch["fetch_cb"]);
return fetch;
});
}
} // namespace Lua::Internal

View File

@@ -17,8 +17,10 @@
#include <utils/stylehelper.h>
#include <utils/unarchiver.h>
#include <QApplication>
#include <QJsonDocument>
#include <QLabel>
#include <QMessageBox>
#include <QTemporaryFile>
#include <QtConcurrent>
@@ -159,6 +161,7 @@ static Group installRecipe(
emitResult(sourceAndCommand.error());
return SetupResult::StopWithError;
}
unarchiver.setGZipFileDestName(installOptionsIt->name);
unarchiver.setSourceAndCommand(*sourceAndCommand);
unarchiver.setDestDir(destination(appDataPath, *installOptionsIt));
return SetupResult::Continue;
@@ -170,6 +173,12 @@ static Group installRecipe(
if (result == DoneWith::Cancel)
return DoneResult::Error;
const FilePath destDir = destination(appDataPath, *installOptionsIt);
const FilePath binary = destDir / installOptionsIt->name;
if (binary.isFile())
binary.setPermissions(QFile::ExeUser | QFile::ExeGroup | QFile::ExeOther);
expected_str<QJsonDocument> doc = getOrCreatePackageInfo(appDataPath);
if (!doc)
return emitResult(doc.error());
@@ -178,7 +187,7 @@ static Group installRecipe(
QJsonObject installedPackage;
installedPackage["version"] = installOptionsIt->version;
installedPackage["name"] = installOptionsIt->name;
installedPackage["path"] = destination(appDataPath, *installOptionsIt).toFSPathString();
installedPackage["path"] = destDir.toFSPathString();
obj[installOptionsIt->name] = installedPackage;
expected_str<void> res = savePackageInfo(appDataPath, QJsonDocument(obj));
@@ -301,41 +310,71 @@ void addInstallModule()
installOptionsList.append({url, name, version});
}
auto install = [&state, pluginSpec, installOptionsList, callback]() {
auto tree = state.createTree();
auto progress = new TaskProgress(tree);
progress->setDisplayName(Tr::tr("Installing package(s) %1").arg("..."));
tree->setRecipe(
installRecipe(pluginSpec->appDataPath, installOptionsList, callback));
tree->start();
};
auto denied = [callback]() { callback(false, "User denied installation"); };
if (QApplication::activeModalWidget()) {
auto msgBox = new QMessageBox(
QMessageBox::Question,
Tr::tr("Install package"),
msg,
QMessageBox::Yes | QMessageBox::No,
Core::ICore::dialogParent());
const QString details
= Tr::tr("The plugin \"%1\" would like to install the following "
"package(s):\n\n")
.arg(pluginSpec->name)
+ Utils::transform(installOptionsList, [](const InstallOptions &options) {
return QString("* %1 - %2 (from: %3)")
.arg(options.name, options.version, options.url.toString());
}).join("\n");
msgBox->setDetailedText(details);
auto guard = pluginSpec->connectionGuard.get();
QObject::connect(msgBox, &QMessageBox::accepted, guard, install);
QObject::connect(msgBox, &QMessageBox::rejected, guard, denied);
msgBox->show();
return;
}
const Utils::Id infoBarId = Utils::Id::fromString(
"Install" + pluginSpec->name + QString::number(qHash(installOptionsList)));
InfoBarEntry entry(infoBarId, msg, InfoBarEntry::GlobalSuppression::Enabled);
entry.addCustomButton(
Tr::tr("Install"),
[infoBarId, &state, pluginSpec, installOptionsList, callback]() {
auto tree = state.createTree();
entry.addCustomButton(Tr::tr("Install"), [install, infoBarId]() {
install();
Core::ICore::infoBar()->removeInfo(infoBarId);
});
auto progress = new TaskProgress(tree);
progress->setDisplayName(Tr::tr("Installing package(s) %1").arg("..."));
entry.setCancelButtonInfo(denied);
tree->setRecipe(
installRecipe(pluginSpec->appDataPath, installOptionsList, callback));
tree->start();
Core::ICore::infoBar()->removeInfo(infoBarId);
});
entry.setCancelButtonInfo(
[callback]() { callback(false, "User denied installation"); });
entry.setDetailsWidgetCreator([pluginSpec, installOptionsList]() -> QWidget * {
const QString markdown
= Tr::tr("The plugin \"**%1**\" would like to install the following "
"package(s):\n\n")
.arg(pluginSpec->name)
+ Utils::transform(installOptionsList, [](const InstallOptions &options) {
return QString("* %1 - %2 (from: [%3](%3))")
.arg(options.name, options.version, options.url.toString());
}).join("\n");
const QString details
= Tr::tr("The plugin \"**%1**\" would like to install the following "
"package(s):\n\n")
.arg(pluginSpec->name)
+ Utils::transform(installOptionsList, [](const InstallOptions &options) {
return QString("* %1 - %2 (from: [%3](%3))")
.arg(options.name, options.version, options.url.toString());
}).join("\n");
entry.setDetailsWidgetCreator([details]() -> QWidget * {
QLabel *list = new QLabel();
list->setTextFormat(Qt::TextFormat::MarkdownText);
list->setText(markdown);
list->setText(details);
list->setMargin(StyleHelper::SpacingTokens::ExPaddingGapS);
return list;
});

View File

@@ -29,11 +29,22 @@ void addProcessModule()
p->setEnvironment(Environment::systemEnvironment());
QObject::connect(p, &Process::done, guard, [p, cb]() { cb(p->exitCode()); });
};
process["commandOutput_cb"] =
[guard
= pluginSpec->connectionGuard.get()](const QString &cmdline, const sol::function &cb) {
Process *p = new Process;
p->setCommand(CommandLine::fromUserInput((cmdline)));
p->setEnvironment(Environment::systemEnvironment());
QObject::connect(p, &Process::done, guard, [p, cb]() { cb(p->allOutput()); });
p->start();
};
process["runInTerminal"] = wrap(process["runInTerminal_cb"]);
process["commandOutput"] = wrap(process["commandOutput_cb"]);
return process;
});

Binary file not shown.

After

Width:  |  Height:  |  Size: 513 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -68,7 +68,6 @@ QtcPlugin {
"simpletypes.lua",
"utils.lua",
"widgets.lua",
"wizard.lua",
]
qbs.install: true
qbs.installDir: qtc.ide_data_path + "/lua/meta/"

View File

@@ -4,6 +4,7 @@
#include "luaengine.h"
#include "luapluginspec.h"
#include "luatr.h"
#include <coreplugin/icore.h>
#include <coreplugin/messagemanager.h>
@@ -172,14 +173,6 @@ expected_str<void> LuaEngine::connectHooks(
return {};
}
expected_str<void> LuaEngine::connectHooks(sol::state_view lua, const sol::table &hookTable)
{
if (!hookTable)
return {};
return instance().connectHooks(lua, hookTable, "");
}
expected_str<LuaPluginSpec *> LuaEngine::loadPlugin(const Utils::FilePath &path)
{
auto contents = path.fileContents();
@@ -204,12 +197,16 @@ expected_str<LuaPluginSpec *> LuaEngine::loadPlugin(const Utils::FilePath &path)
sol::table pluginInfo = result.get<sol::table>();
if (!pluginInfo.valid())
return make_unexpected(QString("Script did not return a table with plugin info"));
return LuaPluginSpec::create(path, std::move(lua), pluginInfo);
return LuaPluginSpec::create(path, pluginInfo);
}
expected_str<void> LuaEngine::prepareSetup(
sol::state_view &lua, const LuaPluginSpec &pluginSpec, sol::optional<sol::table> hookTable)
expected_str<sol::protected_function> LuaEngine::prepareSetup(
sol::state_view lua, const LuaPluginSpec &pluginSpec)
{
auto contents = pluginSpec.filePath().fileContents();
if (!contents)
return make_unexpected(contents.error());
// TODO: Only open libraries requested by the plugin
lua.open_libraries(
sol::lib::base,
@@ -261,10 +258,29 @@ expected_str<void> LuaEngine::prepareSetup(
for (const auto &func : d->m_autoProviders)
func(lua);
if (hookTable)
return LuaEngine::connectHooks(lua, *hookTable);
sol::protected_function_result result = lua.safe_script(
std::string_view(contents->data(), contents->size()),
sol::script_pass_on_error,
pluginSpec.filePath().fileName().toUtf8().constData());
return {};
auto pluginTable = result.get<sol::optional<sol::table>>();
if (!pluginTable)
return make_unexpected(Tr::tr("Script did not return a table"));
auto hookTable = pluginTable->get<sol::optional<sol::table>>("hooks");
if (hookTable) {
auto connectResult = connectHooks(lua, *hookTable, {});
if (!connectResult)
return make_unexpected(connectResult.error());
}
auto setupFunction = pluginTable->get_or<sol::function>("setup", {});
if (!setupFunction)
return make_unexpected(Tr::tr("Plugin info table did not contain a setup function"));
return setupFunction;
}
bool LuaEngine::isCoroutine(lua_State *state)

View File

@@ -55,15 +55,13 @@ public:
static LuaEngine &instance();
Utils::expected_str<LuaPluginSpec *> loadPlugin(const Utils::FilePath &path);
Utils::expected_str<void> prepareSetup(
sol::state_view &lua, const LuaPluginSpec &pluginSpec, sol::optional<sol::table> hookTable);
Utils::expected_str<sol::protected_function> prepareSetup(
sol::state_view lua, const LuaPluginSpec &pluginSpec);
static void registerProvider(const QString &packageName, const PackageProvider &provider);
static void autoRegister(const std::function<void(sol::state_view)> &registerFunction);
static void registerHook(QString name, const std::function<void(sol::function)> &hookProvider);
static Utils::expected_str<void> connectHooks(sol::state_view lua, const sol::table &hookTable);
static bool isCoroutine(lua_State *state);
static sol::table toTable(const sol::state_view &lua, const QJsonValue &v);

View File

@@ -34,28 +34,19 @@ class LuaPluginSpecPrivate
{
public:
FilePath pluginScriptPath;
sol::state lua;
sol::table pluginTable;
sol::function setupFunction;
bool printToOutputPane = false;
std::unique_ptr<sol::state> activeLuaState;
};
LuaPluginSpec::LuaPluginSpec()
: d(new LuaPluginSpecPrivate())
{}
expected_str<LuaPluginSpec *> LuaPluginSpec::create(const FilePath &filePath,
sol::state lua,
sol::table pluginTable)
expected_str<LuaPluginSpec *> LuaPluginSpec::create(const FilePath &filePath, sol::table pluginTable)
{
std::unique_ptr<LuaPluginSpec> pluginSpec(new LuaPluginSpec());
pluginSpec->d->lua = std::move(lua);
pluginSpec->d->pluginTable = pluginTable;
pluginSpec->d->setupFunction = pluginTable.get_or<sol::function>("setup", {});
if (!pluginSpec->d->setupFunction)
if (!pluginTable.get_or<sol::function>("setup", {}))
return make_unexpected(QString("Plugin info table did not contain a setup function"));
QJsonValue v = LuaEngine::toJson(pluginTable);
@@ -75,6 +66,7 @@ expected_str<LuaPluginSpec *> LuaPluginSpec::create(const FilePath &filePath,
pluginSpec->setLocation(filePath.parentDir());
pluginSpec->d->pluginScriptPath = filePath;
pluginSpec->d->printToOutputPane = pluginTable.get_or("printToOutputPane", false);
return pluginSpec.release();
}
@@ -94,16 +86,19 @@ bool LuaPluginSpec::loadLibrary()
}
bool LuaPluginSpec::initializePlugin()
{
expected_str<void> setupResult
= LuaEngine::instance()
.prepareSetup(d->lua, *this, d->pluginTable.get<sol::optional<sol::table>>("hooks"));
QTC_ASSERT(!d->activeLuaState, return false);
std::unique_ptr<sol::state> activeLuaState = std::make_unique<sol::state>();
expected_str<sol::protected_function> setupResult
= LuaEngine::instance().prepareSetup(*activeLuaState, *this);
if (!setupResult) {
setError(Lua::Tr::tr("Failed to prepare plugin setup: %1").arg(setupResult.error()));
return false;
}
auto result = d->setupFunction.call();
auto result = setupResult->call();
if (result.get_type() == sol::type::boolean && result.get<bool>() == false) {
setError(Lua::Tr::tr("Plugin setup function returned false"));
@@ -117,6 +112,8 @@ bool LuaPluginSpec::initializePlugin()
}
}
d->activeLuaState = std::move(activeLuaState);
setState(PluginSpec::State::Initialized);
return true;
}
@@ -133,14 +130,18 @@ bool LuaPluginSpec::delayedInitialize()
}
ExtensionSystem::IPlugin::ShutdownFlag LuaPluginSpec::stop()
{
d->activeLuaState.reset();
return ExtensionSystem::IPlugin::ShutdownFlag::SynchronousShutdown;
}
void LuaPluginSpec::kill() {}
void LuaPluginSpec::kill()
{
d->activeLuaState.reset();
}
bool LuaPluginSpec::printToOutputPane() const
{
return d->pluginTable.get_or("printToOutputPane", false);
return d->printToOutputPane;
}
} // namespace Lua

View File

@@ -39,9 +39,8 @@ class LuaPluginSpec : public ExtensionSystem::PluginSpec
LuaPluginSpec();
public:
static Utils::expected_str<LuaPluginSpec *> create(const Utils::FilePath &filePath,
sol::state lua,
sol::table pluginTable);
static Utils::expected_str<LuaPluginSpec *> create(
const Utils::FilePath &filePath, sol::table pluginTable);
ExtensionSystem::IPlugin *plugin() const override;

View File

@@ -8,4 +8,10 @@ local process = {}
---@return number The exit code of the command
function process.runInTerminal(cmd) end
---@async
---Runs a command and returns the output!
---@param cmd string The command to run
---@return string The output of the command
function process.commandOutput(cmd) end
return process

View File

@@ -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

View File

@@ -7,6 +7,7 @@ local S = require('Settings')
local Gui = require('Gui')
local a = require('async')
local fetch = require('Fetch').fetch
local Install = require('Install')
Settings = {}
@@ -34,17 +35,12 @@ end
local function installOrUpdateServer()
local data = a.wait(fetch({
url = "https://api.github.com/repos/LuaLS/lua-language-server/releases?per_page=1",
convertToTable = true,
headers = {
Accept = "application/vnd.github.v3+json",
["X-GitHub-Api-Version"] = "2022-11-28"
}
url = "https://qtccache.qt.io/LuaLanguageServer/LatestRelease",
convertToTable = true
}))
if type(data) == "table" and #data > 0 then
local r = data[1]
Install = require('Install')
local lspPkgInfo = Install.packageInfo("lua-language-server")
if not lspPkgInfo or lspPkgInfo.version ~= r.tag_name then
local osTr = { mac = "darwin", windows = "win32", linux = "linux" }
@@ -83,7 +79,7 @@ local function installOrUpdateServer()
binary = "bin/lua-language-server.exe"
end
Settings.binary.defaultPath = lspPkgInfo.path:resolvePath(binary)
Settings.binary:setValue(lspPkgInfo.path:resolvePath(binary))
Settings:apply()
return
end
@@ -138,31 +134,53 @@ local function layoutSettings()
--- "using namespace Gui"
local _ENV = using(Gui)
local installButton = {}
if Settings.binary.expandedValue:isExecutableFile() == false then
installButton = {
"Language server not found:",
Row {
PushButton {
text = "Try to install lua language server",
onClicked = function() a.sync(installServer)() end,
},
st
}
}
end
local layout = Form {
Settings.binary, br,
Settings.developMode, br,
Settings.showSource, br,
Settings.showNode, br,
table.unpack(installButton)
Row {
PushButton {
text = "Update Lua Language Server",
onClicked = function() a.sync(installOrUpdateServer)() end,
},
st
}
}
return layout
end
local function binaryFromPkg()
local lspPkgInfo = Install.packageInfo("lua-language-server")
if lspPkgInfo then
local binary = "bin/lua-language-server"
if Utils.HostOsInfo.isWindowsHost() then
binary = "bin/lua-language-server.exe"
end
local binaryPath = lspPkgInfo.path:resolvePath(binary)
if binaryPath:isExecutableFile() == true then
return binaryPath
end
end
return nil
end
local function findBinary()
local binary = binaryFromPkg()
if binary then
return binary
end
-- Search for the binary in the PATH
local serverPath = Utils.FilePath.fromUserInput("lua-language-server")
local absolute = a.wait(serverPath:searchInPath()):resolveSymlinks()
if absolute:isExecutableFile() == true then
return absolute
end
return serverPath
end
local function setupAspect()
---@class Settings: AspectContainer
Settings = S.AspectContainer.create({
@@ -176,14 +194,9 @@ local function setupAspect()
labelText = "Binary:",
toolTip = "The path to the lua-language-server binary.",
expectedKind = S.Kind.ExistingCommand,
defaultPath = Utils.FilePath.fromUserInput("lua-language-server"),
defaultPath = findBinary(),
})
-- Search for the binary in the PATH
local serverPath = Settings.binary.defaultPath
local absolute = a.wait(serverPath:searchInPath()):resolveSymlinks()
if absolute:isExecutableFile() == true then
Settings.binary.defaultPath = absolute
end
Settings.developMode = S.BoolAspect.create({
settingsKey = "LuaCopilot.DevelopMode",
displayName = "Enable Develop Mode",

View File

@@ -30,7 +30,7 @@ MercurialSettings::MercurialSettings()
binaryPath.setExpectedKind(PathChooser::ExistingCommand);
binaryPath.setDefaultValue(Constants::MERCURIALDEFAULT);
binaryPath.setDisplayName(Tr::tr("Mercurial Command"));
binaryPath.setHistoryCompleter("Bazaar.Command.History");
binaryPath.setHistoryCompleter("Mercurial.Command.History");
binaryPath.setLabelText(Tr::tr("Command:"));
userName.setDisplayStyle(StringAspect::LineEditDisplay);

View File

@@ -56,7 +56,7 @@ inline Utils::OutputLineParser::LinkSpecs MesonOutputParser::addTask(
fileName,
match.captured(lineNumberCapIndex).toInt());
addTask(task);
addLinkSpecForAbsoluteFilePath(linkSpecs, task.file, task.line, match, 1);
addLinkSpecForAbsoluteFilePath(linkSpecs, task.file, task.line, task.column, match, 1);
#else
Q_UNUSED(type);
Q_UNUSED(line);

View File

@@ -39,7 +39,7 @@ NimParser::Result NimParser::handleLine(const QString &lne, OutputFormat)
const CompileTask t(type, message, absoluteFilePath(FilePath::fromUserInput(filename)),
lineNumber);
LinkSpecs linkSpecs;
addLinkSpecForAbsoluteFilePath(linkSpecs, t.file, t.line, match, 1);
addLinkSpecForAbsoluteFilePath(linkSpecs, t.file, t.line, t.column, match, 1);
scheduleTask(t, 1);
return {Status::Done, linkSpecs};
}

View File

@@ -65,7 +65,7 @@ OutputLineParser::Result ClangParser::handleLine(const QString &line, OutputForm
const int lineNo = match.captured(3).toInt();
const int column = 0;
LinkSpecs linkSpecs;
addLinkSpecForAbsoluteFilePath(linkSpecs, filePath, lineNo, match, 2);
addLinkSpecForAbsoluteFilePath(linkSpecs, filePath, lineNo, column, match, 2);
createOrAmendTask(Task::Unknown, lne.trimmed(), lne, false,
filePath, lineNo, column, linkSpecs);
return {Status::InProgress, linkSpecs};
@@ -84,7 +84,7 @@ OutputLineParser::Result ClangParser::handleLine(const QString &line, OutputForm
const FilePath filePath = absoluteFilePath(FilePath::fromUserInput(match.captured(1)));
LinkSpecs linkSpecs;
addLinkSpecForAbsoluteFilePath(linkSpecs, filePath, lineNo, match, 1);
addLinkSpecForAbsoluteFilePath(linkSpecs, filePath, lineNo, column, match, 1);
createOrAmendTask(taskType(match.captured(8)), match.captured(9), lne, false,
filePath, lineNo, column, linkSpecs);
return {Status::InProgress, linkSpecs};
@@ -235,7 +235,7 @@ void ProjectExplorerTest::testClangOutputParser_data()
68, 10,
QVector<QTextLayout::FormatRange>()
<< formatRange(34, 0)
<< formatRange(34, 28, "olpfile:///usr/include/c++/4.6/utility::68::-1")
<< formatRange(34, 28, "olpfile:///usr/include/c++/4.6/utility::68::10")
<< formatRange(62, 93)))
<< QString();
@@ -255,7 +255,7 @@ void ProjectExplorerTest::testClangOutputParser_data()
567, 51,
QVector<QTextLayout::FormatRange>()
<< formatRange(74, 0)
<< formatRange(74, 64, "olpfile:///home/code/src/creator/src/plugins/coreplugin/manhattanstyle.cpp::567::-1")
<< formatRange(74, 64, "olpfile:///home/code/src/creator/src/plugins/coreplugin/manhattanstyle.cpp::567::51")
<< formatRange(138, 202)))
<< QString();

View File

@@ -237,7 +237,7 @@ OutputLineParser::Result CustomParser::hasMatch(
const int lineNumber = match.captured(expression.lineNumberCap()).toInt();
const QString message = match.captured(expression.messageCap());
LinkSpecs linkSpecs;
addLinkSpecForAbsoluteFilePath(linkSpecs, fileName, lineNumber, match,
addLinkSpecForAbsoluteFilePath(linkSpecs, fileName, lineNumber, -1, match,
expression.fileNameCap());
scheduleTask(CompileTask(taskType, message, fileName, lineNumber), 1);
return {Status::Done, linkSpecs};

View File

@@ -221,7 +221,7 @@ OutputLineParser::Result GccParser::handleLine(const QString &line, OutputFormat
const int lineNo = match.captured(2).toInt();
const int column = match.captured(3).toInt();
LinkSpecs linkSpecs;
addLinkSpecForAbsoluteFilePath(linkSpecs, filePath, lineNo, match, "file");
addLinkSpecForAbsoluteFilePath(linkSpecs, filePath, lineNo, column, match, "file");
gccCreateOrAmendTask(
Task::Unknown, lne.trimmed(), lne, false, filePath, lineNo, column, linkSpecs);
return {Status::InProgress, linkSpecs};
@@ -234,7 +234,7 @@ OutputLineParser::Result GccParser::handleLine(const QString &line, OutputFormat
const FilePath filePath = absoluteFilePath(FilePath::fromUserInput(match.captured(3)));
LinkSpecs linkSpecs;
if (!filePath.isEmpty())
addLinkSpecForAbsoluteFilePath(linkSpecs, filePath, -1, match, 3);
addLinkSpecForAbsoluteFilePath(linkSpecs, filePath, -1, -1, match, 3);
gccCreateOrAmendTask(type, match.captured(2), lne, false, filePath, -1, 0, linkSpecs);
return {Status::Done, linkSpecs};
}
@@ -243,7 +243,12 @@ OutputLineParser::Result GccParser::handleLine(const QString &line, OutputFormat
const FilePath filePath = absoluteFilePath(FilePath::fromUserInput(data->rawFilePath));
LinkSpecs linkSpecs;
addLinkSpecForAbsoluteFilePath(
linkSpecs, filePath, data->line, data->fileOffset, data->rawFilePath.size());
linkSpecs,
filePath,
data->line,
data->column,
data->fileOffset,
data->rawFilePath.size());
gccCreateOrAmendTask(
data->type, data->description, lne, false, filePath, data->line, data->column, linkSpecs);
return {Status::InProgress, linkSpecs};
@@ -343,9 +348,9 @@ void ProjectExplorerTest::testGccOutputParsers_data()
9, 0,
QVector<QTextLayout::FormatRange>()
<< formatRange(46, 0)
<< formatRange(46, 29, "olpfile:///temp/test/untitled8/main.cpp::0::-1")
<< formatRange(46, 29, "olpfile:///temp/test/untitled8/main.cpp::0::0")
<< formatRange(75, 39)
<< formatRange(114, 29, "olpfile:///temp/test/untitled8/main.cpp::9::-1")
<< formatRange(114, 29, "olpfile:///temp/test/untitled8/main.cpp::9::0")
<< formatRange(143, 56))
<< CompileTask(Task::Error,
"(Each undeclared identifier is reported only once for each function it appears in.)",
@@ -514,9 +519,9 @@ void ProjectExplorerTest::testGccOutputParsers_data()
264, 0,
QVector<QTextLayout::FormatRange>()
<< formatRange(45, 0)
<< formatRange(45, 68, "olpfile:///home/code/src/creator/src/plugins/projectexplorer/gnumakeparser.cpp::0::-1")
<< formatRange(45, 68, "olpfile:///home/code/src/creator/src/plugins/projectexplorer/gnumakeparser.cpp::0::0")
<< formatRange(113, 106)
<< formatRange(219, 68, "olpfile:///home/code/src/creator/src/plugins/projectexplorer/gnumakeparser.cpp::264::-1")
<< formatRange(219, 68, "olpfile:///home/code/src/creator/src/plugins/projectexplorer/gnumakeparser.cpp::264::0")
<< formatRange(287, 57))
<< CompileTask(Task::Error,
"expected ';' before ':' token",
@@ -583,9 +588,9 @@ void ProjectExplorerTest::testGccOutputParsers_data()
194, 0,
QVector<QTextLayout::FormatRange>()
<< formatRange(50, 0)
<< formatRange(50, 67, "olpfile:///Qt/4.6.2-Symbian/s60sdk/epoc32/include/stdapis/stlport/stl/_tree.c::0::-1")
<< formatRange(50, 67, "olpfile:///Qt/4.6.2-Symbian/s60sdk/epoc32/include/stdapis/stlport/stl/_tree.c::0::0")
<< formatRange(117, 216)
<< formatRange(333, 67, "olpfile:///Qt/4.6.2-Symbian/s60sdk/epoc32/include/stdapis/stlport/stl/_tree.c::194::-1")
<< formatRange(333, 67, "olpfile:///Qt/4.6.2-Symbian/s60sdk/epoc32/include/stdapis/stlport/stl/_tree.c::194::0")
<< formatRange(400, 64)))
<< QString();
@@ -822,9 +827,9 @@ void ProjectExplorerTest::testGccOutputParsers_data()
1134, 26,
QVector<QTextLayout::FormatRange>()
<< formatRange(26, 22)
<< formatRange(48, 39, "olpfile:///Symbian/SDK/EPOC32/INCLUDE/GCCE/GCCE.h::15::-1")
<< formatRange(48, 39, "olpfile:///Symbian/SDK/EPOC32/INCLUDE/GCCE/GCCE.h::15::0")
<< formatRange(87, 46)
<< formatRange(133, 50, "olpfile:///Symbian/SDK/epoc32/include/variant/Symbian_OS.hrh::1134::-1")
<< formatRange(133, 50, "olpfile:///Symbian/SDK/epoc32/include/variant/Symbian_OS.hrh::1134::26")
<< formatRange(183, 44))}
<< QString();
@@ -929,7 +934,7 @@ void ProjectExplorerTest::testGccOutputParsers_data()
14, 25,
QVector<QTextLayout::FormatRange>()
<< formatRange(41, 22)
<< formatRange(63, 67, "olpfile:///home/code/src/creator/src/libs/extensionsystem/pluginerrorview.cpp::31::-1")
<< formatRange(63, 67, "olpfile:///home/code/src/creator/src/libs/extensionsystem/pluginerrorview.cpp::31::0")
<< formatRange(130, 146))}
<< QString();
@@ -953,11 +958,11 @@ void ProjectExplorerTest::testGccOutputParsers_data()
597, 5,
QVector<QTextLayout::FormatRange>()
<< formatRange(43, 22)
<< formatRange(65, 31, "olpfile:///usr/include/qt4/QtCore/QString::1::-1")
<< formatRange(65, 31, "olpfile:///usr/include/qt4/QtCore/QString::1::0")
<< formatRange(96, 40)
<< formatRange(136, 33, "olpfile:///usr/include/qt4/QtCore/qstring.h::0::-1")
<< formatRange(136, 33, "olpfile:///usr/include/qt4/QtCore/qstring.h::0::0")
<< formatRange(169, 28)
<< formatRange(197, 33, "olpfile:///usr/include/qt4/QtCore/qstring.h::597::-1")
<< formatRange(197, 33, "olpfile:///usr/include/qt4/QtCore/qstring.h::597::5")
<< formatRange(230, 99))}
<< QString();
@@ -1233,17 +1238,17 @@ void ProjectExplorerTest::testGccOutputParsers_data()
273, 25,
QVector<QTextLayout::FormatRange>()
<< formatRange(140, 22)
<< formatRange(162, 32, "olpfile:///usr/include/qt/QtCore/qlocale.h::43::-1")
<< formatRange(162, 32, "olpfile:///usr/include/qt/QtCore/qlocale.h::43::0")
<< formatRange(194, 27)
<< formatRange(221, 36, "olpfile:///usr/include/qt/QtCore/qtextstream.h::46::-1")
<< formatRange(221, 36, "olpfile:///usr/include/qt/QtCore/qtextstream.h::46::0")
<< formatRange(257, 27)
<< formatRange(284, 38, "olpfile:///qtc/src/shared/proparser/proitems.cpp::31::-1")
<< formatRange(284, 38, "olpfile:///qtc/src/shared/proparser/proitems.cpp::31::0")
<< formatRange(322, 5)
<< formatRange(327, 33, "olpfile:///usr/include/qt/QtCore/qvariant.h::0::-1")
<< formatRange(327, 33, "olpfile:///usr/include/qt/QtCore/qvariant.h::0::0")
<< formatRange(360, 51)
<< formatRange(411, 33, "olpfile:///usr/include/qt/QtCore/qvariant.h::273::-1")
<< formatRange(411, 33, "olpfile:///usr/include/qt/QtCore/qvariant.h::273::25")
<< formatRange(444, 229)
<< formatRange(673, 33, "olpfile:///usr/include/qt/QtCore/qvariant.h::399::-1")
<< formatRange(673, 33, "olpfile:///usr/include/qt/QtCore/qvariant.h::399::16")
<< formatRange(706, 221)),
compileTask(Task::Error,
"no match for operator+ (operand types are boxed_value<double> and boxed_value<double>)\n"
@@ -1477,13 +1482,13 @@ void ProjectExplorerTest::testGccOutputParsers_data()
FilePath::fromUserInput("/data/dev/creator/src/libs/utils/aspects.cpp"), 3454, 13,
QVector<QTextLayout::FormatRange>{
formatRange(82, 22),
formatRange(104, 44, "olpfile:///data/dev/creator/src/libs/utils/aspects.cpp::12::-1"),
formatRange(104, 44, "olpfile:///data/dev/creator/src/libs/utils/aspects.cpp::12::0"),
formatRange(148, 5),
formatRange(153, 48, "olpfile:///data/dev/creator/src/libs/utils/layoutbuilder.h::0::-1"),
formatRange(153, 48, "olpfile:///data/dev/creator/src/libs/utils/layoutbuilder.h::0::0"),
formatRange(201, 177),
formatRange(378, 44, "olpfile:///data/dev/creator/src/libs/utils/aspects.cpp::3454::-1"),
formatRange(378, 44, "olpfile:///data/dev/creator/src/libs/utils/aspects.cpp::3454::13"),
formatRange(422, 31),
formatRange(453, 48, "olpfile:///data/dev/creator/src/libs/utils/layoutbuilder.h::79::-1"),
formatRange(453, 48, "olpfile:///data/dev/creator/src/libs/utils/layoutbuilder.h::79::51"),
formatRange(501, 228)})})
<< QString();
}

View File

@@ -103,7 +103,7 @@ OutputLineParser::Result GnuMakeParser::handleLine(const QString &line, OutputFo
if (!m_suppressIssues) {
const FilePath file = absoluteFilePath(FilePath::fromUserInput(match.captured(1)));
const int lineNo = match.captured(4).toInt();
addLinkSpecForAbsoluteFilePath(linkSpecs, file, lineNo, match, 1);
addLinkSpecForAbsoluteFilePath(linkSpecs, file, lineNo, -1, match, 1);
emitTask(BuildSystemTask(res.type, res.description, file, lineNo));
}
return {Status::Done, linkSpecs};

View File

@@ -62,7 +62,7 @@ Utils::OutputLineParser::Result LdParser::handleLine(const QString &line, Utils:
if (match.hasMatch()) {
handle = true;
filePath = absoluteFilePath(Utils::FilePath::fromString(match.captured("file")));
addLinkSpecForAbsoluteFilePath(linkSpecs, filePath, 0, match, "file");
addLinkSpecForAbsoluteFilePath(linkSpecs, filePath, -1, -1, match, "file");
currentTask().setFile(filePath);
} else {
handle = !lne.isEmpty() && lne.at(0).isSpace();
@@ -135,7 +135,7 @@ Utils::OutputLineParser::Result LdParser::handleLine(const QString &line, Utils:
}
if (hasKeyword || filePath.fileName().endsWith(".o")) {
LinkSpecs linkSpecs;
addLinkSpecForAbsoluteFilePath(linkSpecs, filePath, lineno, match, capIndex);
addLinkSpecForAbsoluteFilePath(linkSpecs, filePath, lineno, -1, match, capIndex);
createOrAmendTask(type, description, line, false, filePath, lineno, 0, linkSpecs);
return {getStatus(), linkSpecs};
}

View File

@@ -59,7 +59,7 @@ OutputLineParser::Result LinuxIccParser::handleLine(const QString &line, OutputF
const FilePath filePath = absoluteFilePath(FilePath::fromUserInput(match.captured(1)));
const int lineNo = match.captured(2).toInt();
LinkSpecs linkSpecs;
addLinkSpecForAbsoluteFilePath(linkSpecs, filePath, lineNo, match, 1);
addLinkSpecForAbsoluteFilePath(linkSpecs, filePath, lineNo, -1, match, 1);
createOrAmendTask(type, match.captured(6).trimmed(), line, false, filePath, lineNo);
m_expectFirstLine = false;
return Status::InProgress;

View File

@@ -46,7 +46,7 @@ Utils::OutputLineParser::Result LldParser::handleLine(const QString &line, Utils
const auto file = absoluteFilePath(Utils::FilePath::fromUserInput(
trimmedLine.mid(filePathOffset, filePathLen).trimmed()));
LinkSpecs linkSpecs;
addLinkSpecForAbsoluteFilePath(linkSpecs, file, lineNo, filePathOffset, filePathLen);
addLinkSpecForAbsoluteFilePath(linkSpecs, file, lineNo, -1, filePathOffset, filePathLen);
scheduleTask(CompileTask(Task::Unknown, trimmedLine.mid(4).trimmed(),
file, lineNo), 1);
return {Status::Done, linkSpecs};

View File

@@ -114,7 +114,7 @@ OutputLineParser::Result MsvcParser::handleLine(const QString &line, OutputForma
const FilePath filePath = absoluteFilePath(FilePath::fromUserInput(match.captured(2)));
const int lineNo = match.captured(3).toInt();
LinkSpecs linkSpecs;
addLinkSpecForAbsoluteFilePath(linkSpecs, filePath, lineNo, match, 2);
addLinkSpecForAbsoluteFilePath(linkSpecs, filePath, lineNo, -1, match, 2);
createOrAmendTask(Task::Unknown, description, line, false, filePath, lineNo, 0, linkSpecs);
return {Status::InProgress, linkSpecs};
}
@@ -146,7 +146,7 @@ MsvcParser::Result MsvcParser::processCompileLine(const QString &line)
QPair<FilePath, int> position = parseFileName(match.captured(1));
const FilePath filePath = absoluteFilePath(position.first);
LinkSpecs linkSpecs;
addLinkSpecForAbsoluteFilePath(linkSpecs, filePath, position.second, match, 1);
addLinkSpecForAbsoluteFilePath(linkSpecs, filePath, position.second, -1, match, 1);
const QString &description = match.captured(3) + match.captured(4).trimmed();
createOrAmendTask(
taskType(match.captured(2)),
@@ -228,7 +228,7 @@ OutputLineParser::Result ClangClParser::handleLine(const QString &line, OutputFo
const FilePath file = absoluteFilePath(position.first);
const int lineNo = position.second;
LinkSpecs linkSpecs;
addLinkSpecForAbsoluteFilePath(linkSpecs, file, lineNo, match, 1);
addLinkSpecForAbsoluteFilePath(linkSpecs, file, lineNo, -1, match, 1);
createOrAmendTask(
taskType(match.captured(2)), match.captured(3).trimmed(), line, false, file, lineNo);
return {Status::InProgress, linkSpecs};

View File

@@ -93,7 +93,8 @@ OutputLineParser::Result SanitizerParser::handleContinuation(const QString &line
m_task.file = file;
m_task.line = summaryMatch.captured("line").toInt();
m_task.column = summaryMatch.captured("column").toInt();
addLinkSpecForAbsoluteFilePath(linkSpecs, file, m_task.line, summaryMatch, "file");
addLinkSpecForAbsoluteFilePath(
linkSpecs, file, m_task.line, m_task.column, summaryMatch, "file");
addLinkSpecs(linkSpecs);
}
} else {
@@ -107,7 +108,7 @@ OutputLineParser::Result SanitizerParser::handleContinuation(const QString &line
const FilePath file = absoluteFilePath(FilePath::fromUserInput(fileMatch.captured("file")));
if (fileExists(file)) {
addLinkSpecForAbsoluteFilePath(linkSpecs, file, fileMatch.captured("line").toInt(),
fileMatch, "file");
fileMatch.captured("column").toInt(), fileMatch, "file");
addLinkSpecs(linkSpecs);
}
}

View File

@@ -57,7 +57,8 @@ OutputLineParser::Result XcodebuildParser::handleLine(const QString &line, Outpu
absoluteFilePath(FilePath::fromString(
lne.left(filePathEndPos))));
LinkSpecs linkSpecs;
addLinkSpecForAbsoluteFilePath(linkSpecs, task.file, task.line, 0, filePathEndPos);
addLinkSpecForAbsoluteFilePath(linkSpecs, task.file, task.line, task.column, 0,
filePathEndPos);
scheduleTask(task, 1);
return {Status::Done, linkSpecs};
}

View File

@@ -46,7 +46,7 @@ OutputLineParser::Result QMakeParser::handleLine(const QString &line, OutputForm
BuildSystemTask t(type, description, absoluteFilePath(FilePath::fromUserInput(fileName)),
match.captured(2).toInt() /* line */);
LinkSpecs linkSpecs;
addLinkSpecForAbsoluteFilePath(linkSpecs, t.file, t.line, fileNameOffset,
addLinkSpecForAbsoluteFilePath(linkSpecs, t.file, t.line, t.column, fileNameOffset,
fileName.length());
scheduleTask(t, 1);
return {Status::Done, linkSpecs};

View File

@@ -45,7 +45,7 @@ Utils::OutputLineParser::Result QtParser::handleLine(const QString &line, Utils:
LinkSpecs linkSpecs;
const Utils::FilePath file
= absoluteFilePath(Utils::FilePath::fromUserInput(match.captured("file")));
addLinkSpecForAbsoluteFilePath(linkSpecs, file, lineno, match, "file");
addLinkSpecForAbsoluteFilePath(linkSpecs, file, lineno, -1, match, "file");
CompileTask task(type, match.captured("description").trimmed(), file, lineno);
task.column = match.captured("column").toInt();
scheduleTask(task, 1);
@@ -62,7 +62,7 @@ Utils::OutputLineParser::Result QtParser::handleLine(const QString &line, Utils:
message.prepend(": ").prepend(fileName);
} else if (fileName.endsWith(".ui")) {
filePath = absoluteFilePath(Utils::FilePath::fromUserInput(fileName));
addLinkSpecForAbsoluteFilePath(linkSpecs, filePath, -1, match, "file");
addLinkSpecForAbsoluteFilePath(linkSpecs, filePath, -1, -1, match, "file");
} else {
isUicMessage = false;
}
@@ -79,7 +79,7 @@ Utils::OutputLineParser::Result QtParser::handleLine(const QString &line, Utils:
LinkSpecs linkSpecs;
const Utils::FilePath file
= absoluteFilePath(Utils::FilePath::fromUserInput(match.captured("file")));
addLinkSpecForAbsoluteFilePath(linkSpecs, file, 0, match, "file");
addLinkSpecForAbsoluteFilePath(linkSpecs, file, -1, -1, match, "file");
CompileTask task(type, match.captured("description"), file);
scheduleTask(task, 1);
return {Status::Done, linkSpecs};
@@ -95,7 +95,7 @@ Utils::OutputLineParser::Result QtParser::handleLine(const QString &line, Utils:
if (!ok)
lineno = -1;
LinkSpecs linkSpecs;
addLinkSpecForAbsoluteFilePath(linkSpecs, file, lineno, match, "file");
addLinkSpecForAbsoluteFilePath(linkSpecs, file, lineno, -1, match, "file");
CompileTask task(type, match.captured("description"), file, lineno,
match.captured("column").toInt());
scheduleTask(task, 1);

View File

@@ -44,8 +44,8 @@ OutputLineParser::Result QtTestParser::handleLine(const QString &line, OutputFor
m_currentTask.file = absoluteFilePath(FilePath::fromString(
QDir::fromNativeSeparators(match.captured("file"))));
m_currentTask.line = match.captured("line").toInt();
addLinkSpecForAbsoluteFilePath(linkSpecs, m_currentTask.file, m_currentTask.line, match,
"file");
addLinkSpecForAbsoluteFilePath(
linkSpecs, m_currentTask.file, m_currentTask.line, m_currentTask.column, match, "file");
emitCurrentTask();
return {Status::Done, linkSpecs};
}

View File

@@ -8,6 +8,7 @@ local S = require('Settings')
local Gui = require('Gui')
local a = require('async')
local fetch = require('Fetch').fetch
local Install = require('Install')
Settings = {}
@@ -39,7 +40,6 @@ local function installOrUpdateServer()
if r.prerelease then
r = data[2]
end
Install = require('Install')
local lspPkgInfo = Install.packageInfo("rust-analyzer")
if not lspPkgInfo or lspPkgInfo.version ~= r.tag_name then
local osTr = { mac = "apple-darwin", windows = "pc-windows-msvc", linux = "unknown-linux-gnu" }
@@ -80,7 +80,7 @@ local function installOrUpdateServer()
binary = "rust-analyzer.exe"
end
Settings.binary.defaultPath = lspPkgInfo.path:resolvePath(binary)
Settings.binary:setValue(lspPkgInfo.path:resolvePath(binary))
Settings:apply()
return
end
@@ -130,8 +130,8 @@ local function layoutSettings()
Settings.binary, br,
Row {
PushButton {
text("Try to install Rust language server"),
onClicked(function() a.sync(installOrUpdateServer)() end),
text = "Try to install Rust language server",
onClicked = function() a.sync(installOrUpdateServer)() end,
br,
},
st
@@ -141,6 +141,36 @@ local function layoutSettings()
return layout
end
local function binaryFromPkg()
local lspPkgInfo = Install.packageInfo("rust-analyzer")
if lspPkgInfo then
local binary = "rust-analyzer"
if Utils.HostOsInfo.isWindowsHost() then
binary = "rust-analyzer.exe"
end
local binaryPath = lspPkgInfo.path:resolvePath(binary)
if binaryPath:isExecutableFile() == true then
return binaryPath
end
end
return nil
end
local function findBinary()
local binary = binaryFromPkg()
if binary then
return binary
end
-- Search for the binary in the PATH
local serverPath = Utils.FilePath.fromUserInput("rust-analyzer")
local absolute = a.wait(serverPath:searchInPath()):resolveSymlinks()
if absolute:isExecutableFile() == true then
return absolute
end
return serverPath
end
local function setupAspect()
---@class Settings: AspectContainer
Settings = S.AspectContainer.create({
@@ -154,14 +184,8 @@ local function setupAspect()
labelText = "Binary:",
toolTip = "The path to the rust analyzer binary.",
expectedKind = S.Kind.ExistingCommand,
defaultPath = Utils.FilePath.fromUserInput("rust-analyzer"),
defaultPath = findBinary(),
})
-- Search for the binary in the PATH
local serverPath = Settings.binary.defaultPath
local absolute = a.wait(serverPath:searchInPath()):resolveSymlinks()
if absolute:isExecutableFile() == true then
Settings.binary.defaultPath = absolute
end
return Settings
end

View File

@@ -16,7 +16,7 @@
"Description" : "Provides the technical basis for version control system (VCS) extensions",
"LongDescription" : [
"You also need:",
"- An extension for a VCS tool, such as Git, and the tool
"- An extension for a VCS tool, such as Git, and the tool"
],
"Url" : "https://www.qt.io",
${IDE_PLUGIN_DEPENDENCIES}

View File

@@ -1949,6 +1949,9 @@ void tst_Dumpers::dumper()
} while (localsBeginPos != -1);
actual.fromString(QString::fromLocal8Bit(contents));
context.nameSpace = actual["result"]["qtnamespace"].data();
int runtime = actual["result"]["runtime"].data().toFloat() * 1000;
qCDebug(lcDumpers, "CaseInner: %5d", runtime);
m_totalInnerTime += runtime;
actual = actual["result"]["data"];
}