Merge remote-tracking branch 'origin/master' into 4.15

Change-Id: Ia313b9a8bf82940e496b7456801faf552fe4b022
This commit is contained in:
Eike Ziller
2021-02-24 19:42:30 +01:00
37 changed files with 343 additions and 102 deletions

View File

@@ -33,9 +33,11 @@ Editing
### C++ ### C++
* Added options for generation of getters and setters (QTCREATORBUG-1532) * Added `Create Getter and Setter Member Functions` refactoring action
* Added `Create Constructor` refactoring operation (QTCREATORBUG-1532)
* Added filtering of `Find Usages` based on access type (QTCREATORBUG-19373) * Added `Generate Constructor` refactoring action
* Added filtering of `Find References to Symbol Under Cursor` based on access
type (QTCREATORBUG-19373)
* Added `Open in Editor` and `Open Type Hierarchy` to context menu on items in * Added `Open in Editor` and `Open Type Hierarchy` to context menu on items in
type hierarchy type hierarchy
* Added highlighting of previous class when navigating in type hierarchy * Added highlighting of previous class when navigating in type hierarchy

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.7 KiB

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 69 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.9 KiB

After

Width:  |  Height:  |  Size: 8.5 KiB

View File

@@ -1,6 +1,6 @@
/**************************************************************************** /****************************************************************************
** **
** Copyright (C) 2020 The Qt Company Ltd. ** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/ ** Contact: https://www.qt.io/licensing/
** **
** This file is part of the Qt Creator documentation. ** This file is part of the Qt Creator documentation.
@@ -51,6 +51,8 @@
\uicontrol {C++} > \uicontrol {Find References to Symbol Under Cursor} or \uicontrol {C++} > \uicontrol {Find References to Symbol Under Cursor} or
press \key {Ctrl+Shift+U}. press \key {Ctrl+Shift+U}.
\image qtcreator-find-references-to-symbol-under-cursor.png "Search results for finding references to symbols"
\note You can also select \uicontrol Edit > \uicontrol {Find/Replace} > \note You can also select \uicontrol Edit > \uicontrol {Find/Replace} >
\uicontrol {Advanced Find} > \uicontrol {C++ Symbols} to search for \uicontrol {Advanced Find} > \uicontrol {C++ Symbols} to search for
classes, functions, enums, and declarations either from files listed as classes, functions, enums, and declarations either from files listed as
@@ -100,6 +102,10 @@
\li To expand and collapse the list of all instances, click the \li To expand and collapse the list of all instances, click the
\inlineimage qtcreator-expand.png \inlineimage qtcreator-expand.png
(\uicontrol {Expand All}) button. (\uicontrol {Expand All}) button.
\li To filter the search results for the usage of symbols according to
access type, such as read, write, or declaration, click the
\inlineimage filtericon.png
(\uicontrol {Filter Tree}) button and select the access type.
\li To clear the search results, click the \li To clear the search results, click the
\inlineimage clean_pane_small.png \inlineimage clean_pane_small.png
(\uicontrol Clear) button. (\uicontrol Clear) button.
@@ -184,7 +190,8 @@
\section1 Creating Functions \section1 Creating Functions
You can apply refactoring actions to implement member functions, insert You can apply refactoring actions to implement member functions, insert
virtual functions of base classes, and greate getter and setter functions. virtual functions of base classes, create getter and setter functions,
and generate constructors.
\section2 Implementing Member Functions \section2 Implementing Member Functions
@@ -217,6 +224,16 @@
for member variables or only a getter or setter. for member variables or only a getter or setter.
\image qtcreator-refactoring-getters-and-setters.png "Getters and Setters dialog" \image qtcreator-refactoring-getters-and-setters.png "Getters and Setters dialog"
\section2 Generating Constructors
You can apply the \uicontrol {Generate Constructor} refactoring action to
create a public, protected, or private constructor for a class. Select the
class members to initialize in the constructor. Drag and drop the parameters
to specify their order in the constructor.
\image qtcreator-refactoring-constructor.png "Constructor dialog"
\endif \endif
\section1 Summary of Refactoring Actions \section1 Summary of Refactoring Actions
@@ -668,6 +685,10 @@
\li Creates either both getter and setter member functions for \li Creates either both getter and setter member functions for
member variables or only a getter or setter. member variables or only a getter or setter.
\li Member variable in class definition \li Member variable in class definition
\row
\li Generate Constructor
\li Creates a constructor for a class.
\li Class definition
\row \row
\li Move Function Definition \li Move Function Definition
\li Moves a function definition to the implementation file, outside \li Moves a function definition to the implementation file, outside

View File

@@ -139,7 +139,10 @@ ScrollView {
bottomPadding: 0 bottomPadding: 0
expanded: importExpanded expanded: importExpanded
expandOnClick: false expandOnClick: false
onToggleExpand: importExpanded = !importExpanded onToggleExpand: {
if (categoryModel.rowCount() > 0)
importExpanded = !importExpanded
}
onShowContextMenu: { onShowContextMenu: {
importToRemove = importUsed ? "" : importUrl importToRemove = importUsed ? "" : importUrl
contextMenu.popup() contextMenu.popup()

View File

@@ -989,6 +989,21 @@ protected:
out("const "); out("const ");
} }
} }
switch (ast->type) {
case PatternElement::Literal:
case PatternElement::Method:
case PatternElement::Binding:
break;
case PatternElement::Getter:
out("get ");
break;
case PatternElement::Setter:
out("set ");
break;
case PatternElement::SpreadElement:
out("...");
break;
}
out(ast->identifierToken); out(ast->identifierToken);
if (ast->initializer) { if (ast->initializer) {
if (ast->isVariableDeclaration()) if (ast->isVariableDeclaration())
@@ -1312,6 +1327,8 @@ protected:
bool visit(ArgumentList *ast) override bool visit(ArgumentList *ast) override
{ {
for (ArgumentList *it = ast; it; it = it->next) { for (ArgumentList *it = ast; it; it = it->next) {
if (it->isSpreadElement)
out("...");
accept(it->expression); accept(it->expression);
if (it->next) { if (it->next) {
out(", ", it->commaToken); out(", ", it->commaToken);

View File

@@ -403,7 +403,7 @@ AndroidDeviceInfoList AvdManagerOutputParser::listVirtualDevices(const AndroidCo
avdList = parseAvdList(output); avdList = parseAvdList(output);
} while (output.contains(avdManufacturerError)); } while (output.contains(avdManufacturerError));
for (const QString &avdPathStr : avdErrorPaths) for (const QString &avdPathStr : qAsConst(avdErrorPaths))
AvdConfigEditManufacturerTag(avdPathStr, true); AvdConfigEditManufacturerTag(avdPathStr, true);
return avdList; return avdList;

View File

@@ -1494,7 +1494,7 @@ FilePath AndroidConfig::getJdkPath()
#endif // Q_OS_WIN #endif // Q_OS_WIN
} }
for (const QString &version : allVersions) { for (const QString &version : qAsConst(allVersions)) {
settings->beginGroup(version); settings->beginGroup(version);
jdkHome = FilePath::fromUserInput(settings->value("JavaHome").toString()); jdkHome = FilePath::fromUserInput(settings->value("JavaHome").toString());
settings->endGroup(); settings->endGroup();

View File

@@ -538,7 +538,7 @@ void AndroidRunnerWorker::asyncStartHelper()
forceStop(); forceStop();
asyncStartLogcat(); asyncStartLogcat();
for (const QString &entry : m_beforeStartAdbCommands) for (const QString &entry : qAsConst(m_beforeStartAdbCommands))
runAdb(entry.split(' ', Qt::SkipEmptyParts)); runAdb(entry.split(' ', Qt::SkipEmptyParts));
QStringList args({"shell", "am", "start"}); QStringList args({"shell", "am", "start"});
@@ -825,7 +825,7 @@ void AndroidRunnerWorker::onProcessIdChanged(qint64 pid)
m_debugServerProcess.reset(); m_debugServerProcess.reset();
// Run adb commands after application quit. // Run adb commands after application quit.
for (const QString &entry: m_afterFinishAdbCommands) for (const QString &entry: qAsConst(m_afterFinishAdbCommands))
runAdb(entry.split(' ', Qt::SkipEmptyParts)); runAdb(entry.split(' ', Qt::SkipEmptyParts));
} else { } else {
// In debugging cases this will be funneled to the engine to actually start // In debugging cases this will be funneled to the engine to actually start

View File

@@ -566,7 +566,7 @@ void SdkManagerOutputParser::compilePackageAssociations()
deleteAlreadyInstalled(images); deleteAlreadyInstalled(images);
// Associate the system images with sdk platforms. // Associate the system images with sdk platforms.
for (AndroidSdkPackage *image : images) { for (AndroidSdkPackage *image : qAsConst(images)) {
int imageApi = m_systemImages[image]; int imageApi = m_systemImages[image];
auto itr = std::find_if(m_packages.begin(), m_packages.end(), auto itr = std::find_if(m_packages.begin(), m_packages.end(),
[imageApi](const AndroidSdkPackage *p) { [imageApi](const AndroidSdkPackage *p) {
@@ -1151,7 +1151,7 @@ void AndroidSdkManagerPrivate::parseCommonArguments(QFutureInterface<QString> &f
void AndroidSdkManagerPrivate::clearPackages() void AndroidSdkManagerPrivate::clearPackages()
{ {
for (AndroidSdkPackage *p : m_allPackages) for (AndroidSdkPackage *p : qAsConst(m_allPackages))
delete p; delete p;
m_allPackages.clear(); m_allPackages.clear();
} }

View File

@@ -298,7 +298,7 @@ void AndroidSdkModel::selectMissingEssentials()
} }
// Select SDK platform // Select SDK platform
for (const SdkPlatform *platform : m_sdkPlatforms) { for (const SdkPlatform *platform : qAsConst(m_sdkPlatforms)) {
if (!platform->installedLocation().isEmpty()) { if (!platform->installedLocation().isEmpty()) {
pendingPkgs.removeOne(platform->sdkStylePath()); pendingPkgs.removeOne(platform->sdkStylePath());
} else if (pendingPkgs.contains(platform->sdkStylePath()) && } else if (pendingPkgs.contains(platform->sdkStylePath()) &&

View File

@@ -154,7 +154,7 @@ SdkPlatform::SdkPlatform(QVersionNumber version, QString sdkStylePathStr, int ap
SdkPlatform::~SdkPlatform() SdkPlatform::~SdkPlatform()
{ {
for (SystemImage *image : m_systemImages) for (SystemImage *image : qAsConst(m_systemImages))
delete image; delete image;
m_systemImages.clear(); m_systemImages.clear();
} }

View File

@@ -177,7 +177,7 @@ void AvdDialog::updateDeviceDefinitionComboBox()
m_avdDialog.deviceDefinitionTypeComboBox->currentText()); m_avdDialog.deviceDefinitionTypeComboBox->currentText());
m_avdDialog.deviceDefinitionComboBox->clear(); m_avdDialog.deviceDefinitionComboBox->clear();
for (const DeviceDefinitionStruct &item : m_deviceDefinitionsList) { for (const DeviceDefinitionStruct &item : qAsConst(m_deviceDefinitionsList)) {
if (item.deviceType == curDeviceType) if (item.deviceType == curDeviceType)
m_avdDialog.deviceDefinitionComboBox->addItem(item.name_id); m_avdDialog.deviceDefinitionComboBox->addItem(item.name_id);
} }
@@ -231,7 +231,7 @@ void AvdDialog::updateApiLevelComboBox()
}); });
m_avdDialog.targetApiComboBox->clear(); m_avdDialog.targetApiComboBox->clear();
for (SystemImage *image : filteredList) { for (SystemImage *image : qAsConst(filteredList)) {
QString imageString = "android-" % QString::number(image->apiLevel()); QString imageString = "android-" % QString::number(image->apiLevel());
const QStringList imageSplits = image->sdkStylePath().split(';'); const QStringList imageSplits = image->sdkStylePath().split(';');
if (imageSplits.size() == 4) if (imageSplits.size() == 4)

View File

@@ -25,12 +25,21 @@
#include "javalanguageserver.h" #include "javalanguageserver.h"
#include "androidconfigurations.h"
#include "androidconstants.h" #include "androidconstants.h"
#include "androidmanager.h"
#include <languageclient/client.h> #include <languageclient/client.h>
#include <languageclient/languageclientinterface.h>
#include <languageclient/languageclientutils.h> #include <languageclient/languageclientutils.h>
#include <projectexplorer/kitinformation.h>
#include <projectexplorer/project.h>
#include <projectexplorer/projectnodes.h>
#include <projectexplorer/target.h>
#include <qtsupport/qtkitinformation.h>
#include <utils/environment.h> #include <utils/environment.h>
#include <utils/pathchooser.h> #include <utils/pathchooser.h>
#include <utils/temporarydirectory.h>
#include <utils/variablechooser.h> #include <utils/variablechooser.h>
#include <QGridLayout> #include <QGridLayout>
@@ -39,7 +48,6 @@
using namespace Utils; using namespace Utils;
constexpr char languageServerKey[] = "languageServer"; constexpr char languageServerKey[] = "languageServer";
constexpr char workspaceKey[] = "workspace";
namespace Android { namespace Android {
namespace Internal { namespace Internal {
@@ -67,7 +75,6 @@ JLSSettingsWidget::JLSSettingsWidget(const JLSSettings *settings, QWidget *paren
, m_name(new QLineEdit(settings->m_name, this)) , m_name(new QLineEdit(settings->m_name, this))
, m_java(new PathChooser(this)) , m_java(new PathChooser(this))
, m_ls(new PathChooser(this)) , m_ls(new PathChooser(this))
, m_workspace(new PathChooser(this))
{ {
int row = 0; int row = 0;
auto *mainLayout = new QGridLayout; auto *mainLayout = new QGridLayout;
@@ -88,11 +95,6 @@ JLSSettingsWidget::JLSSettingsWidget(const JLSSettings *settings, QWidget *paren
m_ls->setPath(QDir::toNativeSeparators(settings->m_languageServer)); m_ls->setPath(QDir::toNativeSeparators(settings->m_languageServer));
mainLayout->addWidget(m_ls, row, 1); mainLayout->addWidget(m_ls, row, 1);
mainLayout->addWidget(new QLabel(tr("Workspace:")), ++row, 0);
m_workspace->setExpectedKind(Utils::PathChooser::Directory);
m_workspace->setPath(QDir::toNativeSeparators(settings->m_workspace));
mainLayout->addWidget(m_workspace, row, 1);
setLayout(mainLayout); setLayout(mainLayout);
} }
@@ -117,9 +119,6 @@ bool JLSSettings::applyFromSettingsWidget(QWidget *widget)
changed |= m_languageServer != jlswidget->languageServer(); changed |= m_languageServer != jlswidget->languageServer();
m_languageServer = jlswidget->languageServer(); m_languageServer = jlswidget->languageServer();
changed |= m_workspace != jlswidget->workspace();
m_workspace = jlswidget->workspace();
changed |= m_executable != jlswidget->java(); changed |= m_executable != jlswidget->java();
m_executable = jlswidget->java(); m_executable = jlswidget->java();
@@ -130,8 +129,7 @@ bool JLSSettings::applyFromSettingsWidget(QWidget *widget)
"-noverify " "-noverify "
"-Xmx1G " "-Xmx1G "
"-jar \"%1\" " "-jar \"%1\" "
"-configuration \"%2\" " "-configuration \"%2\"";
"-data \"%3\"";
QFileInfo languageServerFileInfo(m_languageServer); QFileInfo languageServerFileInfo(m_languageServer);
QDir configDir = languageServerFileInfo.absoluteDir(); QDir configDir = languageServerFileInfo.absoluteDir();
@@ -145,7 +143,7 @@ bool JLSSettings::applyFromSettingsWidget(QWidget *widget)
configDir.cd("config_mac"); configDir.cd("config_mac");
} }
if (configDir.exists()) { if (configDir.exists()) {
arguments = arguments.arg(m_languageServer, configDir.absolutePath(), m_workspace); arguments = arguments.arg(m_languageServer, configDir.absolutePath());
changed |= m_arguments != arguments; changed |= m_arguments != arguments;
m_arguments = arguments; m_arguments = arguments;
} }
@@ -159,14 +157,13 @@ QWidget *JLSSettings::createSettingsWidget(QWidget *parent) const
bool JLSSettings::isValid() const bool JLSSettings::isValid() const
{ {
return StdIOSettings::isValid() && !m_languageServer.isEmpty() && !m_workspace.isEmpty(); return StdIOSettings::isValid() && !m_languageServer.isEmpty();
} }
QVariantMap JLSSettings::toMap() const QVariantMap JLSSettings::toMap() const
{ {
QVariantMap map = StdIOSettings::toMap(); QVariantMap map = StdIOSettings::toMap();
map.insert(languageServerKey, m_languageServer); map.insert(languageServerKey, m_languageServer);
map.insert(workspaceKey, m_workspace);
return map; return map;
} }
@@ -174,7 +171,6 @@ void JLSSettings::fromMap(const QVariantMap &map)
{ {
StdIOSettings::fromMap(map); StdIOSettings::fromMap(map);
m_languageServer = map[languageServerKey].toString(); m_languageServer = map[languageServerKey].toString();
m_workspace = map[workspaceKey].toString();
} }
LanguageClient::BaseSettings *JLSSettings::copy() const LanguageClient::BaseSettings *JLSSettings::copy() const
@@ -182,12 +178,39 @@ LanguageClient::BaseSettings *JLSSettings::copy() const
return new JLSSettings(*this); return new JLSSettings(*this);
} }
class JLSInterface : public LanguageClient::StdIOClientInterface
{
public:
JLSInterface() = default;
QString workspaceDir() const { return m_workspaceDir.path(); }
private:
TemporaryDirectory m_workspaceDir = TemporaryDirectory("QtCreator-jls-XXXXXX");
};
LanguageClient::BaseClientInterface *JLSSettings::createInterface() const
{
auto interface = new JLSInterface();
interface->setExecutable(m_executable);
QString arguments = this->arguments();
arguments += QString(" -data \"%1\"").arg(interface->workspaceDir());
interface->setArguments(arguments);
return interface;
}
class JLSClient : public LanguageClient::Client class JLSClient : public LanguageClient::Client
{ {
public: public:
using Client::Client; using Client::Client;
void executeCommand(const LanguageServerProtocol::Command &command) override; void executeCommand(const LanguageServerProtocol::Command &command) override;
void setCurrentProject(ProjectExplorer::Project *project) override;
void updateProjectFiles();
void updateTarget(ProjectExplorer::Target *target);
private:
ProjectExplorer::Target *m_currentTarget = nullptr;
}; };
void JLSClient::executeCommand(const LanguageServerProtocol::Command &command) void JLSClient::executeCommand(const LanguageServerProtocol::Command &command)
@@ -206,6 +229,127 @@ void JLSClient::executeCommand(const LanguageServerProtocol::Command &command)
} }
} }
void JLSClient::setCurrentProject(ProjectExplorer::Project *project)
{
Client::setCurrentProject(project);
QTC_ASSERT(project, return);
updateTarget(project->activeTarget());
updateProjectFiles();
connect(project, &ProjectExplorer::Project::activeTargetChanged,
this, &JLSClient::updateTarget);
}
static void generateProjectFile(const FilePath &projectDir,
const QString &qtSrc,
const QString &projectName)
{
const FilePath projectFilePath = projectDir.pathAppended(".project");
QFile projectFile(projectFilePath.toString());
if (projectFile.open(QFile::Truncate | QFile::WriteOnly)) {
QXmlStreamWriter writer(&projectFile);
writer.setAutoFormatting(true);
writer.writeStartDocument();
writer.writeComment("Autogenerated by Qt Creator. "
"Changes to this file will not be taken into account.");
writer.writeStartElement("projectDescription");
writer.writeTextElement("name", projectName);
writer.writeStartElement("natures");
writer.writeTextElement("nature", "org.eclipse.jdt.core.javanature");
writer.writeEndElement(); // natures
writer.writeStartElement("linkedResources");
writer.writeStartElement("link");
writer.writeTextElement("name", "qtSrc");
writer.writeTextElement("type", "2");
writer.writeTextElement("location", qtSrc);
writer.writeEndElement(); // link
writer.writeEndElement(); // linkedResources
writer.writeEndElement(); // projectDescription
writer.writeEndDocument();
projectFile.close();
}
}
static void generateClassPathFile(const FilePath &projectDir,
const QString &sourceDir,
const QStringList &libs)
{
const FilePath classPathFilePath = projectDir.pathAppended(".classpath");
QFile classPathFile(classPathFilePath.toString());
if (classPathFile.open(QFile::Truncate | QFile::WriteOnly)) {
QXmlStreamWriter writer(&classPathFile);
writer.setAutoFormatting(true);
writer.writeStartDocument();
writer.writeComment("Autogenerated by Qt Creator. "
"Changes to this file will not be taken into account.");
writer.writeStartElement("classpath");
writer.writeEmptyElement("classpathentry");
writer.writeAttribute("kind", "src");
writer.writeAttribute("path", sourceDir);
writer.writeEmptyElement("classpathentry");
writer.writeAttribute("kind", "src");
writer.writeAttribute("path", "qtSrc");
for (const QString &lib : libs) {
writer.writeEmptyElement("classpathentry");
writer.writeAttribute("kind", "lib");
writer.writeAttribute("path", lib);
}
writer.writeEndElement(); // classpath
writer.writeEndDocument();
classPathFile.close();
}
}
void JLSClient::updateProjectFiles()
{
using namespace ProjectExplorer;
if (!m_currentTarget)
return;
if (Target *target = m_currentTarget) {
Kit *kit = m_currentTarget->kit();
if (DeviceTypeKitAspect::deviceTypeId(kit) != Android::Constants::ANDROID_DEVICE_TYPE)
return;
if (ProjectNode *node = project()->findNodeForBuildKey(target->activeBuildKey())) {
QtSupport::BaseQtVersion *version = QtSupport::QtKitAspect::qtVersion(kit);
if (!version)
return;
const QString qtSrc = version->prefix().toString() + "/src/android/java/src";
const FilePath &projectDir = project()->rootProjectDirectory();
if (!projectDir.exists())
return;
const FilePath packageSourceDir = FilePath::fromVariant(
node->data(Constants::AndroidPackageSourceDir));
FilePath sourceDir = packageSourceDir.pathAppended("src");
if (!sourceDir.exists())
return;
sourceDir = sourceDir.relativeChildPath(projectDir);
const FilePath &sdkLocation = AndroidConfigurations::currentConfig().sdkLocation();
const QString &targetSDK = AndroidManager::buildTargetSDK(m_currentTarget);
const QString androidJar = QString("%1/platforms/%2/android.jar")
.arg(sdkLocation.toString(), targetSDK);
QStringList libs(androidJar);
QDir libDir(packageSourceDir.pathAppended("libs").toString());
libs << Utils::transform(libDir.entryInfoList({"*.jar"}, QDir::Files),
&QFileInfo::absoluteFilePath);
generateProjectFile(projectDir, qtSrc, project()->displayName());
generateClassPathFile(projectDir, sourceDir.toString(), libs);
}
}
}
void JLSClient::updateTarget(ProjectExplorer::Target *target)
{
if (m_currentTarget) {
disconnect(m_currentTarget, &ProjectExplorer::Target::parsingFinished,
this, &JLSClient::updateProjectFiles);
}
m_currentTarget = target;
if (m_currentTarget) {
connect(m_currentTarget, &ProjectExplorer::Target::parsingFinished,
this, &JLSClient::updateProjectFiles);
}
updateProjectFiles();
}
LanguageClient::Client *JLSSettings::createClient(LanguageClient::BaseClientInterface *interface) const LanguageClient::Client *JLSSettings::createClient(LanguageClient::BaseClientInterface *interface) const
{ {
return new JLSClient(interface); return new JLSClient(interface);

View File

@@ -42,9 +42,9 @@ public:
void fromMap(const QVariantMap &map) final; void fromMap(const QVariantMap &map) final;
LanguageClient::BaseSettings *copy() const final; LanguageClient::BaseSettings *copy() const final;
LanguageClient::Client *createClient(LanguageClient::BaseClientInterface *interface) const final; LanguageClient::Client *createClient(LanguageClient::BaseClientInterface *interface) const final;
LanguageClient::BaseClientInterface *createInterface() const override;
QString m_languageServer; QString m_languageServer;
QString m_workspace;
private: private:
JLSSettings(const JLSSettings &other) = default; JLSSettings(const JLSSettings &other) = default;

View File

@@ -128,7 +128,7 @@ void ClangToolsUnitTests::testProject()
QVERIFY(waitForFinishedTool.wait(m_timeout)); QVERIFY(waitForFinishedTool.wait(m_timeout));
// Check for errors // Check for errors
const QString errorText = waitForFinishedTool.takeFirst().first().toString(); const QString errorText = waitForFinishedTool.takeFirst().constFirst().toString();
const bool finishedSuccessfully = errorText.isEmpty(); const bool finishedSuccessfully = errorText.isEmpty();
if (!finishedSuccessfully) if (!finishedSuccessfully)
qWarning("Error: %s", qPrintable(errorText)); qWarning("Error: %s", qPrintable(errorText));

View File

@@ -245,7 +245,7 @@ static FilePath qmakeFromCMakeCache(const CMakeConfig &config)
if (!qmakeLocationTxt.open(QIODevice::ReadOnly)) { if (!qmakeLocationTxt.open(QIODevice::ReadOnly)) {
return FilePath(); return FilePath();
} }
FilePath qmakeLocation = FilePath::fromUtf8(qmakeLocationTxt.readLine().data()); FilePath qmakeLocation = FilePath::fromUtf8(qmakeLocationTxt.readLine().constData());
qCDebug(cmInputLog) << "qmake location: " << qmakeLocation.toUserOutput(); qCDebug(cmInputLog) << "qmake location: " << qmakeLocation.toUserOutput();
return qmakeLocation; return qmakeLocation;

View File

@@ -100,6 +100,13 @@ Client::Client(BaseClientInterface *clientInterface)
&Client::rehighlight); &Client::rehighlight);
} }
QString Client::name() const
{
if (m_project && !m_project->displayName().isEmpty())
return tr("%1 for %2").arg(m_displayName, m_project->displayName());
return m_displayName;
}
static void updateEditorToolBar(QList<TextEditor::TextDocument *> documents) static void updateEditorToolBar(QList<TextEditor::TextDocument *> documents)
{ {
for (TextEditor::TextDocument *document : documents) { for (TextEditor::TextDocument *document : documents) {
@@ -790,16 +797,7 @@ void Client::projectOpened(ProjectExplorer::Project *project)
void Client::projectClosed(ProjectExplorer::Project *project) void Client::projectClosed(ProjectExplorer::Project *project)
{ {
if (project == m_project) { if (sendWorkspceFolderChanges()) {
if (m_state == Initialized) {
shutdown();
} else {
m_state = Shutdown; // otherwise the manager would try to restart this server
emit finished();
}
}
if (!sendWorkspceFolderChanges())
return;
WorkspaceFoldersChangeEvent event; WorkspaceFoldersChangeEvent event;
event.setRemoved({WorkSpaceFolder(DocumentUri::fromFilePath(project->projectDirectory()), event.setRemoved({WorkSpaceFolder(DocumentUri::fromFilePath(project->projectDirectory()),
project->displayName())}); project->displayName())});
@@ -807,6 +805,16 @@ void Client::projectClosed(ProjectExplorer::Project *project)
params.setEvent(event); params.setEvent(event);
DidChangeWorkspaceFoldersNotification change(params); DidChangeWorkspaceFoldersNotification change(params);
sendContent(change); sendContent(change);
}
if (project == m_project) {
if (m_state == Initialized) {
shutdown();
} else {
m_state = Shutdown; // otherwise the manager would try to restart this server
emit finished();
}
m_project = nullptr;
}
} }
void Client::setSupportedLanguage(const LanguageFilter &filter) void Client::setSupportedLanguage(const LanguageFilter &filter)
@@ -1260,6 +1268,8 @@ void Client::shutDownCallback(const ShutdownRequest::Response &shutdownResponse)
bool Client::sendWorkspceFolderChanges() const bool Client::sendWorkspceFolderChanges() const
{ {
if (!reachable())
return false;
if (m_dynamicCapabilities.isRegistered( if (m_dynamicCapabilities.isRegistered(
DidChangeWorkspaceFoldersNotification::methodName).value_or(false)) { DidChangeWorkspaceFoldersNotification::methodName).value_or(false)) {
return true; return true;

View File

@@ -87,7 +87,7 @@ public:
// basic properties // basic properties
Utils::Id id() const { return m_id; } Utils::Id id() const { return m_id; }
void setName(const QString &name) { m_displayName = name; } void setName(const QString &name) { m_displayName = name; }
QString name() const { return m_displayName; } QString name() const;
void sendContent(const LanguageServerProtocol::IContent &content); void sendContent(const LanguageServerProtocol::IContent &content);
void cancelRequest(const LanguageServerProtocol::MessageId &id); void cancelRequest(const LanguageServerProtocol::MessageId &id);
@@ -134,10 +134,10 @@ public:
bool documentUpdatePostponed(const Utils::FilePath &fileName) const; bool documentUpdatePostponed(const Utils::FilePath &fileName) const;
// workspace control // workspace control
void setCurrentProject(ProjectExplorer::Project *project); virtual void setCurrentProject(ProjectExplorer::Project *project);
const ProjectExplorer::Project *project() const; const ProjectExplorer::Project *project() const;
void projectOpened(ProjectExplorer::Project *project); virtual void projectOpened(ProjectExplorer::Project *project);
void projectClosed(ProjectExplorer::Project *project); virtual void projectClosed(ProjectExplorer::Project *project);
// commands // commands
void requestCodeActions(const LanguageServerProtocol::DocumentUri &uri, void requestCodeActions(const LanguageServerProtocol::DocumentUri &uri,

View File

@@ -89,9 +89,7 @@ void BaseClientInterface::parseData(const QByteArray &data)
} }
} }
StdIOClientInterface::StdIOClientInterface(const QString &executable, const QString &arguments) StdIOClientInterface::StdIOClientInterface()
: m_executable(executable)
, m_arguments(arguments)
{ {
connect(&m_process, &QProcess::readyReadStandardError, connect(&m_process, &QProcess::readyReadStandardError,
this, &StdIOClientInterface::readError); this, &StdIOClientInterface::readError);
@@ -99,9 +97,6 @@ StdIOClientInterface::StdIOClientInterface(const QString &executable, const QStr
this, &StdIOClientInterface::readOutput); this, &StdIOClientInterface::readOutput);
connect(&m_process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), connect(&m_process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
this, &StdIOClientInterface::onProcessFinished); this, &StdIOClientInterface::onProcessFinished);
m_process.setArguments(Utils::QtcProcess::splitArgs(m_arguments));
m_process.setProgram(m_executable);
} }
StdIOClientInterface::~StdIOClientInterface() StdIOClientInterface::~StdIOClientInterface()
@@ -109,11 +104,6 @@ StdIOClientInterface::~StdIOClientInterface()
Utils::SynchronousProcess::stopProcess(m_process); Utils::SynchronousProcess::stopProcess(m_process);
} }
bool StdIOClientInterface::needsRestart(const StdIOSettings *settings) const
{
return m_executable != settings->m_executable || m_arguments != settings->arguments();
}
bool StdIOClientInterface::start() bool StdIOClientInterface::start()
{ {
m_process.start(); m_process.start();
@@ -124,6 +114,16 @@ bool StdIOClientInterface::start()
return true; return true;
} }
void StdIOClientInterface::setExecutable(const QString &executable)
{
m_process.setProgram(executable);
}
void StdIOClientInterface::setArguments(const QString &arguments)
{
m_process.setArguments(Utils::QtcProcess::splitArgs(arguments));
}
void StdIOClientInterface::setWorkingDirectory(const QString &workingDirectory) void StdIOClientInterface::setWorkingDirectory(const QString &workingDirectory)
{ {
m_process.setWorkingDirectory(workingDirectory); m_process.setWorkingDirectory(workingDirectory);

View File

@@ -25,6 +25,8 @@
#pragma once #pragma once
#include "languageclient_global.h"
#include <languageserverprotocol/basemessage.h> #include <languageserverprotocol/basemessage.h>
#include <QBuffer> #include <QBuffer>
@@ -34,13 +36,13 @@ namespace LanguageClient {
class StdIOSettings; class StdIOSettings;
class BaseClientInterface : public QObject class LANGUAGECLIENT_EXPORT BaseClientInterface : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
BaseClientInterface(); BaseClientInterface();
virtual ~BaseClientInterface(); ~BaseClientInterface() override;
void sendMessage(const LanguageServerProtocol::BaseMessage &message); void sendMessage(const LanguageServerProtocol::BaseMessage &message);
virtual bool start() { return true; } virtual bool start() { return true; }
@@ -61,23 +63,23 @@ private:
LanguageServerProtocol::BaseMessage m_currentMessage; LanguageServerProtocol::BaseMessage m_currentMessage;
}; };
class StdIOClientInterface : public BaseClientInterface class LANGUAGECLIENT_EXPORT StdIOClientInterface : public BaseClientInterface
{ {
Q_OBJECT Q_OBJECT
public: public:
StdIOClientInterface(const QString &executable, const QString &arguments); StdIOClientInterface();
~StdIOClientInterface() override; ~StdIOClientInterface() override;
StdIOClientInterface() = delete;
StdIOClientInterface(const StdIOClientInterface &) = delete; StdIOClientInterface(const StdIOClientInterface &) = delete;
StdIOClientInterface(StdIOClientInterface &&) = delete; StdIOClientInterface(StdIOClientInterface &&) = delete;
StdIOClientInterface &operator=(const StdIOClientInterface &) = delete; StdIOClientInterface &operator=(const StdIOClientInterface &) = delete;
StdIOClientInterface &operator=(StdIOClientInterface &&) = delete; StdIOClientInterface &operator=(StdIOClientInterface &&) = delete;
bool needsRestart(const StdIOSettings *settings) const;
bool start() override; bool start() override;
// These functions only have an effect if they are called before start
void setExecutable(const QString &executable);
void setArguments(const QString &arguments);
void setWorkingDirectory(const QString &workingDirectory); void setWorkingDirectory(const QString &workingDirectory);
protected: protected:
@@ -88,9 +90,6 @@ private:
void readError(); void readError();
void readOutput(); void readOutput();
void onProcessFinished(int exitCode, QProcess::ExitStatus exitStatus); void onProcessFinished(int exitCode, QProcess::ExitStatus exitStatus);
const QString m_executable;
const QString m_arguments;
}; };
} // namespace LanguageClient } // namespace LanguageClient

View File

@@ -472,13 +472,17 @@ void LanguageClientManager::documentOpened(Core::IDocument *document)
continue; continue;
// check whether we already have a client running for this project // check whether we already have a client running for this project
if (Utils::findOrDefault(clients, Client *clientForProject = Utils::findOrDefault(clients,
[project](const QPointer<Client> &client) { [project](Client *client) {
return client->project() == project; return client->project()
})) { == project;
continue; });
if (!clientForProject) {
clientForProject = startClient(setting, project);
clients << clientForProject;
} }
clients << startClient(setting, project); QTC_ASSERT(clientForProject, continue);
openDocumentWithClient(textDocument, clientForProject);
} }
} else if (setting->m_startBehavior == BaseSettings::RequiresFile && clients.isEmpty()) { } else if (setting->m_startBehavior == BaseSettings::RequiresFile && clients.isEmpty()) {
clients << startClient(setting); clients << startClient(setting);

View File

@@ -722,7 +722,10 @@ Utils::CommandLine StdIOSettings::command() const
BaseClientInterface *StdIOSettings::createInterface() const BaseClientInterface *StdIOSettings::createInterface() const
{ {
return new StdIOClientInterface(m_executable, arguments()); auto interface = new StdIOClientInterface;
interface->setExecutable(m_executable);
interface->setArguments(arguments());
return interface;
} }
class JsonTreeItemDelegate : public QStyledItemDelegate class JsonTreeItemDelegate : public QStyledItemDelegate

View File

@@ -62,7 +62,7 @@ void OutputParserTester::testParsing(const QString &lines,
{ {
const auto terminator = new TestTerminator(this); const auto terminator = new TestTerminator(this);
if (!lineParsers().isEmpty()) if (!lineParsers().isEmpty())
terminator->setRedirectionDetector(lineParsers().last()); terminator->setRedirectionDetector(lineParsers().constLast());
addLineParser(terminator); addLineParser(terminator);
reset(); reset();
@@ -113,7 +113,7 @@ TestTerminator::TestTerminator(OutputParserTester *t) :
m_tester(t) m_tester(t)
{ {
if (!t->lineParsers().isEmpty()) { if (!t->lineParsers().isEmpty()) {
for (const Utils::FilePath &searchDir : t->lineParsers().first()->searchDirectories()) for (const Utils::FilePath &searchDir : t->lineParsers().constFirst()->searchDirectories())
addSearchDir(searchDir); addSearchDir(searchDir);
} }
} }

View File

@@ -96,6 +96,18 @@ QHash<int, QByteArray> ItemLibraryCategoriesModel::roleNames() const
return m_roleNames; return m_roleNames;
} }
void ItemLibraryCategoriesModel::expandCategories(bool expand)
{
int i = 0;
for (const auto &category : std::as_const(m_categoryList)) {
if (category->categoryExpanded() != expand) {
category->setExpanded(expand);
emit dataChanged(index(i), index(i), {m_roleNames.key("categoryExpanded")});
}
++i;
}
}
void ItemLibraryCategoriesModel::addCategory(ItemLibraryCategory *category) void ItemLibraryCategoriesModel::addCategory(ItemLibraryCategory *category)
{ {
m_categoryList.append(category); m_categoryList.append(category);

View File

@@ -48,6 +48,7 @@ public:
QHash<int, QByteArray> roleNames() const override; QHash<int, QByteArray> roleNames() const override;
void addCategory(ItemLibraryCategory *category); void addCategory(ItemLibraryCategory *category);
void expandCategories(bool expand = true);
const QList<QPointer<ItemLibraryCategory>> &categorySections() const; const QList<QPointer<ItemLibraryCategory>> &categorySections() const;

View File

@@ -78,6 +78,10 @@ bool ItemLibraryCategory::updateItemVisibility(const QString &searchText, bool *
hasVisibleItems = true; hasVisibleItems = true;
} }
// expand category if it has an item matching search criteria
if (hasVisibleItems && !categoryExpanded())
setExpanded(true);
return hasVisibleItems; return hasVisibleItems;
} }

View File

@@ -80,25 +80,28 @@ QObject *ItemLibraryImport::categoryModel()
return &m_categoryModel; return &m_categoryModel;
} }
void ItemLibraryImport::expandCategories(bool expand)
{
m_categoryModel.expandCategories(expand);
}
bool ItemLibraryImport::updateCategoryVisibility(const QString &searchText, bool *changed) bool ItemLibraryImport::updateCategoryVisibility(const QString &searchText, bool *changed)
{ {
bool hasVisibleItems = false; bool hasVisibleCategories = false;
*changed = false; *changed = false;
for (const auto &category : m_categoryModel.categorySections()) { for (const auto &category : m_categoryModel.categorySections()) {
bool categoryChanged = false; bool categoryChanged = false;
hasVisibleItems = category->updateItemVisibility(searchText, &categoryChanged); bool hasVisibleItems = category->updateItemVisibility(searchText, &categoryChanged);
categoryChanged |= category->setVisible(hasVisibleItems); categoryChanged |= category->setVisible(hasVisibleItems);
*changed |= categoryChanged; *changed |= categoryChanged;
*changed |= hasVisibleItems;
if (hasVisibleItems)
hasVisibleCategories = true;
} }
if (*changed) return hasVisibleCategories;
m_categoryModel.resetModel();
return hasVisibleItems;
} }
Import ItemLibraryImport::importEntry() const Import ItemLibraryImport::importEntry() const

View File

@@ -63,6 +63,7 @@ public:
void setImportUsed(bool importUsed); void setImportUsed(bool importUsed);
void sortCategorySections(); void sortCategorySections();
void setImportExpanded(bool expanded = true); void setImportExpanded(bool expanded = true);
void expandCategories(bool expand = true);
static QString userComponentsTitle(); static QString userComponentsTitle();

View File

@@ -61,34 +61,28 @@ bool ItemLibraryModel::loadExpandedState(const QString &sectionName)
void ItemLibraryModel::expandAll() void ItemLibraryModel::expandAll()
{ {
bool changed = false; int i = 0;
for (const QPointer<ItemLibraryImport> &import : std::as_const(m_importList)) { for (const QPointer<ItemLibraryImport> &import : std::as_const(m_importList)) {
if (import->hasCategories() && !import->importExpanded()) { if (!import->importExpanded()) {
changed = true;
import->setImportExpanded(); import->setImportExpanded();
emit dataChanged(index(i), index(i), {m_roleNames.key("importExpanded")});
saveExpandedState(true, import->importUrl()); saveExpandedState(true, import->importUrl());
} }
} import->expandCategories(true);
++i;
if (changed) {
beginResetModel();
endResetModel();
} }
} }
void ItemLibraryModel::collapseAll() void ItemLibraryModel::collapseAll()
{ {
bool changed = false; int i = 0;
for (const QPointer<ItemLibraryImport> &import : std::as_const(m_importList)) { for (const QPointer<ItemLibraryImport> &import : std::as_const(m_importList)) {
if (import->hasCategories() && import->importExpanded()) { if (import->hasCategories() && import->importExpanded()) {
changed = true;
import->setImportExpanded(false); import->setImportExpanded(false);
emit dataChanged(index(i), index(i), {m_roleNames.key("importExpanded")});
saveExpandedState(false, import->importUrl()); saveExpandedState(false, import->importUrl());
} }
} ++i;
if (changed) {
beginResetModel();
endResetModel();
} }
} }
@@ -329,9 +323,18 @@ void ItemLibraryModel::updateVisibility(bool *changed)
{ {
for (ItemLibraryImport *import : std::as_const(m_importList)) { for (ItemLibraryImport *import : std::as_const(m_importList)) {
bool categoryChanged = false; bool categoryChanged = false;
import->updateCategoryVisibility(m_searchText, &categoryChanged); bool hasVisibleItems = import->updateCategoryVisibility(m_searchText, &categoryChanged);
*changed |= categoryChanged; *changed |= categoryChanged;
// expand import if it has an item matching search criteria
if (hasVisibleItems && !import->importExpanded())
import->setImportExpanded();
}
if (changed) {
beginResetModel();
endResetModel();
} }
} }

View File

@@ -275,6 +275,7 @@ void ItemLibraryWidget::handleAddImport(int index)
m_model->changeImports({import}, {}); m_model->changeImports({import}, {});
QmlDesignerPlugin::instance()->currentDesignDocument()->updateSubcomponentManager(); QmlDesignerPlugin::instance()->currentDesignDocument()->updateSubcomponentManager();
m_stackedWidget->setCurrentIndex(0); // switch to the Components view after import is added m_stackedWidget->setCurrentIndex(0); // switch to the Components view after import is added
updateSearch();
} }
void ItemLibraryWidget::delayedUpdateModel() void ItemLibraryWidget::delayedUpdateModel()

View File

@@ -134,7 +134,7 @@ public:
} }
} }
void storeIcon(Utils::SmallStringView name, Sqlite::TimeStamp newTimeStamp, const QIcon &icon) void storeIcon(Utils::SmallStringView name, Sqlite::TimeStamp newTimeStamp, const QIcon &icon) override
{ {
try { try {
Sqlite::ImmediateTransaction transaction{database}; Sqlite::ImmediateTransaction transaction{database};

View File

@@ -337,7 +337,9 @@ void SubComponentManager::registerQmlFile(const QFileInfo &fileInfo, const QStri
ItemLibraryEntry itemLibraryEntry; ItemLibraryEntry itemLibraryEntry;
itemLibraryEntry.setType(componentName.toUtf8()); itemLibraryEntry.setType(componentName.toUtf8());
itemLibraryEntry.setName(baseComponentName); itemLibraryEntry.setName(baseComponentName);
#ifndef QMLDESIGNER_TEST
itemLibraryEntry.setCategory(ItemLibraryImport::userComponentsTitle()); itemLibraryEntry.setCategory(ItemLibraryImport::userComponentsTitle());
#endif
itemLibraryEntry.setCustomComponentSource(fileInfo.absoluteFilePath()); itemLibraryEntry.setCustomComponentSource(fileInfo.absoluteFilePath());
if (!qualifier.isEmpty()) { if (!qualifier.isEmpty()) {
itemLibraryEntry.setRequiredImport(fixedQualifier); itemLibraryEntry.setRequiredImport(fixedQualifier);

View File

@@ -12,6 +12,17 @@ function foo(a, b) {
var foo = function (a, b) {} var foo = function (a, b) {}
function spread() {
iterableObj = [1, 2]
obj = {
"a": 42
}
foo(...iterableObj)
let arr = [...iterableObj, '4', 'five', 6]
foo(-1, ...args, 2, ...[3])
console.log(Math.max(...[1, 2, 3, 4]))
}
const func1 = x => x * 2 const func1 = x => x * 2
const func2 = x => { const func2 = x => {
return x * 7 return x * 7