Merge remote-tracking branch 'origin/8.0'

Change-Id: I3f218b52bf6904daca3779fb677e51f6f51f2f9f
This commit is contained in:
Eike Ziller
2022-06-23 11:17:33 +02:00
239 changed files with 2001 additions and 1532 deletions

View File

@@ -7,7 +7,7 @@ on:
- 'doc/**'
env:
QT_VERSION: 6.3.0
QT_VERSION: 6.3.1
CLANG_VERSION: 14.0.3
ELFUTILS_VERSION: 0.175
CMAKE_VERSION: 3.21.1

View File

@@ -1,6 +1,6 @@
set(IDE_VERSION "7.82.0") # The IDE version.
set(IDE_VERSION_COMPAT "7.82.0") # The IDE Compatibility version.
set(IDE_VERSION_DISPLAY "8.0.0-beta1") # The IDE display version.
set(IDE_VERSION "7.83.0") # The IDE version.
set(IDE_VERSION_COMPAT "7.83.0") # The IDE Compatibility version.
set(IDE_VERSION_DISPLAY "8.0.0-beta2") # The IDE display version.
set(IDE_COPYRIGHT_YEAR "2022") # The IDE current copyright year.
set(IDE_SETTINGSVARIANT "QtProject") # The IDE settings variation.

View File

@@ -13,7 +13,7 @@ instructions:
instructions:
- type: EnvironmentVariable
variableName: QTC_QT_BASE_URL
variableValue: "http://ci-files02-hki.intra.qt.io/packages/jenkins/archive/qt/6.3/6.3.0-final-released/Qt6.3.0"
variableValue: "http://ci-files02-hki.intra.qt.io/packages/jenkins/archive/qt/6.3/6.3.1-final-released/Qt6.3.1"
- type: EnvironmentVariable
variableName: QTC_QT_MODULES
variableValue: "qt5compat qtbase qtdeclarative qtimageformats qtquick3d qtquickcontrols2 qtquicktimeline qtserialport qtshadertools qtsvg qttools qttranslations"

View File

@@ -31,6 +31,15 @@ instructions:
condition: property
property: host.os
in_values: [MacOS, Linux, Windows]
- type: ExecuteCommand
command: "pip3 install wget colorlog"
maxTimeInSeconds: 1200
maxTimeBetweenOutput: 120
userMessageOnFailure: "Failed to install Python packages, check logs."
enable_if:
condition: property
property: host.os
in_values: [MacOS, Linux]
- type: ExecuteCommand
command: "python3 -u {{.AgentWorkingDir}}/build/qtsdk/packaging-tools/install_qt.py --qt-path {{.AgentWorkingDir}}/build/qt_install_dir --temp-path {{.AgentWorkingDir}}/build/qt_temp --base-url {{.Env.QTC_QT_BASE_URL}} --base-url-postfix={{.Env.QTC_QT_POSTFIX}} --icu7z http://master.qt.io/development_releases/prebuilt/icu/prebuilt/56.1/icu-linux-g++-Rhel7.2-x64.7z {{.Env.QTC_QT_MODULES}}"
executeCommandArgumentSplitingBehavior: SplitAfterVariableSubstitution
@@ -52,10 +61,10 @@ instructions:
property: host.os
equals_value: MacOS
- type: ExecuteCommand
command: "pip.exe install pywin32"
command: "pip.exe install pywin32 wget colorlog"
maxTimeInSeconds: 1200
maxTimeBetweenOutput: 120
userMessageOnFailure: "Failed to install win32api, check logs."
userMessageOnFailure: "Failed to install Python packages, check logs."
enable_if:
condition: property
property: host.os

View File

@@ -1,17 +1,20 @@
import qbs
import qbs.Environment
import qbs.FileInfo
import qbs.Utilities
Module {
property string qtcreator_display_version: '8.0.0-beta1'
Depends { name: "cpp"; required: false }
property string qtcreator_display_version: '8.0.0-beta2'
property string ide_version_major: '7'
property string ide_version_minor: '82'
property string ide_version_minor: '83'
property string ide_version_release: '0'
property string qtcreator_version: ide_version_major + '.' + ide_version_minor + '.'
+ ide_version_release
property string ide_compat_version_major: '7'
property string ide_compat_version_minor: '82'
property string ide_compat_version_minor: '83'
property string ide_compat_version_release: '0'
property string qtcreator_compat_version: ide_compat_version_major + '.'
+ ide_compat_version_minor + '.' + ide_compat_version_release
@@ -92,4 +95,12 @@ Module {
"QT_USE_QSTRINGBUILDER",
].concat(testsEnabled ? ["WITH_TESTS"] : [])
.concat(qbs.toolchain.contains("msvc") ? ["_CRT_SECURE_NO_WARNINGS"] : [])
Properties {
condition: cpp.present && qbs.toolchain.contains("msvc") && product.Qt
&& Utilities.versionCompare(Qt.core.version, "6.3") >= 0
&& Utilities.versionCompare(cpp.compilerVersion, "19.10") >= 0
&& Utilities.versionCompare(qbs.version, "1.23") < 0
cpp.cxxFlags: "/permissive-"
}
}

View File

@@ -1,6 +1,6 @@
QTCREATOR_VERSION = 7.82.0
QTCREATOR_COMPAT_VERSION = 7.82.0
QTCREATOR_DISPLAY_VERSION = 8.0.0-beta1
QTCREATOR_VERSION = 7.83.0
QTCREATOR_COMPAT_VERSION = 7.83.0
QTCREATOR_DISPLAY_VERSION = 8.0.0-beta2
QTCREATOR_COPYRIGHT_YEAR = 2022
IDE_DISPLAY_NAME = Qt Creator

View File

@@ -238,7 +238,7 @@ def deploy_clang(install_dir, llvm_install_dir, chrpath_bin):
clanglibdirtarget = os.path.join(install_dir, 'bin', 'clang', 'lib')
if not os.path.exists(clanglibdirtarget):
os.makedirs(clanglibdirtarget)
for binary in ['clang', 'clang-cl', 'clangd', 'clang-tidy', 'clazy-standalone']:
for binary in ['clangd', 'clang-tidy', 'clazy-standalone']:
binary_filepath = os.path.join(llvm_install_dir, 'bin', binary + '.exe')
if os.path.exists(binary_filepath):
deployinfo.append((binary_filepath, clangbindirtarget))
@@ -248,7 +248,7 @@ def deploy_clang(install_dir, llvm_install_dir, chrpath_bin):
clangbinary_targetdir = os.path.join(install_dir, 'libexec', 'qtcreator', 'clang', 'bin')
if not os.path.exists(clangbinary_targetdir):
os.makedirs(clangbinary_targetdir)
for binary in ['clang', 'clangd', 'clang-tidy', 'clazy-standalone']:
for binary in ['clangd', 'clang-tidy', 'clazy-standalone']:
binary_filepath = os.path.join(llvm_install_dir, 'bin', binary)
if os.path.exists(binary_filepath):
deployinfo.append((binary_filepath, clangbinary_targetdir))
@@ -262,7 +262,7 @@ def deploy_clang(install_dir, llvm_install_dir, chrpath_bin):
if not os.path.exists(clanglibs_targetdir):
os.makedirs(clanglibs_targetdir)
# on RHEL ClazyPlugin is in lib64
for lib_pattern in ['lib64/ClazyPlugin.so', 'lib/ClazyPlugin.so', 'lib/libclang-cpp.so*']:
for lib_pattern in ['lib64/ClazyPlugin.so', 'lib/ClazyPlugin.so']:
for lib in glob(os.path.join(llvm_install_dir, lib_pattern)):
deployinfo.append((lib, clanglibs_targetdir))
resourcetarget = os.path.join(install_dir, 'libexec', 'qtcreator', 'clang', 'lib', 'clang')

View File

@@ -111,21 +111,14 @@ fi
# copy clang if needed
if [ $LLVM_INSTALL_DIR ]; then
if [ "$LLVM_INSTALL_DIR"/lib/libclang-cpp.dylib -nt "$libexec_path"/clang/lib/libclang-cpp.dylib ]; then
if [ "$LLVM_INSTALL_DIR"/bin/clangd -nt "$libexec_path"/clang/bin/clangd ]; then
echo "- Copying clang"
mkdir -p "$app_path/Contents/Frameworks" || exit 1
# use recursive copy to make it copy symlinks as symlinks
mkdir -p "$libexec_path/clang/bin"
mkdir -p "$libexec_path/clang/lib"
cp -Rf "$LLVM_INSTALL_DIR"/lib/clang "$libexec_path/clang/lib/" || exit 1
cp -Rf "$LLVM_INSTALL_DIR"/lib/libclang-cpp.dylib "$libexec_path/clang/lib/" || exit 1
cp -Rf "$LLVM_INSTALL_DIR"/lib/ClazyPlugin.dylib "$libexec_path/clang/lib/" || exit 1
clangsource="$LLVM_INSTALL_DIR"/bin/clang
clanglinktarget="$(readlink "$clangsource")"
cp -Rf "$clangsource" "$libexec_path/clang/bin/" || exit 1
if [ $clanglinktarget ]; then
cp -Rf "$(dirname "$clangsource")/$clanglinktarget" "$libexec_path/clang/bin/$clanglinktarget" || exit 1
fi
clangdsource="$LLVM_INSTALL_DIR"/bin/clangd
cp -Rf "$clangdsource" "$libexec_path/clang/bin/" || exit 1
clangtidysource="$LLVM_INSTALL_DIR"/bin/clang-tidy

View File

@@ -29,7 +29,6 @@ import collections
import glob
import struct
import sys
import base64
import re
import time
import inspect
@@ -45,6 +44,14 @@ except:
"Native combined debugging might not work.")
pass
try:
# That fails on some QNX via Windows installations
import base64
def hexencode_(s):
return base64.b16encode(s).decode('utf8')
except:
def hexencode_(s):
return ''.join(["%x" % c for c in s])
if sys.version_info[0] >= 3:
toInteger = int
@@ -550,7 +557,7 @@ class DumperBase():
return s.encode('hex')
if isinstance(s, str):
s = s.encode('utf8')
return base64.b16encode(s).decode('utf8')
return hexencode_(s)
def isQt3Support(self):
# assume no Qt 3 support by default

View File

@@ -33,7 +33,11 @@
"name": "PySideVersion",
"trDisplayName": "PySide version:",
"type": "ComboBox",
"data": { "items": [ "PySide2", "PySide6" ] }
"data":
{
"index": 1,
"items": [ "PySide2", "PySide6" ]
}
}
]
},

View File

@@ -34,7 +34,11 @@
"name": "PySideVersion",
"trDisplayName": "PySide version:",
"type": "ComboBox",
"data": { "items": [ "PySide2", "PySide6" ] }
"data":
{
"index": 1,
"items": [ "PySide2", "PySide6" ]
}
},
{
"name": "Class",

View File

@@ -39,7 +39,7 @@
"type": "ComboBox",
"data":
{
"index": 2,
"index": 0,
"items":
[
{

View File

@@ -34,7 +34,11 @@
"name": "PySideVersion",
"trDisplayName": "PySide version:",
"type": "ComboBox",
"data": { "items": [ "PySide2", "PySide6" ] }
"data":
{
"index": 1,
"items": [ "PySide2", "PySide6" ]
}
},
{
"name": "Class",

View File

@@ -34,7 +34,11 @@
"name": "PySideVersion",
"trDisplayName": "PySide version:",
"type": "ComboBox",
"data": { "items": [ "PySide2", "PySide6" ] }
"data":
{
"index": 1,
"items": [ "PySide2", "PySide6" ]
}
},
{
"name": "Class",

View File

@@ -49,6 +49,16 @@ Utils::optional<CompletionItem::InsertTextFormat> CompletionItem::insertTextForm
return Utils::nullopt;
}
Utils::optional<QList<CompletionItem::CompletionItemTag>> CompletionItem::tags() const
{
if (const auto value = optionalValue<QJsonArray>(tagsKey)) {
QList<CompletionItemTag> tags;
for (auto it = value->cbegin(); it != value->cend(); ++it)
tags << static_cast<CompletionItemTag>(it->toInt());
return tags;
}
return {};
}
CompletionItemResolveRequest::CompletionItemResolveRequest(const CompletionItem &params)
: Request(methodName, params)

View File

@@ -214,6 +214,27 @@ public:
void setData(const QJsonValue &data) { insert(dataKey, data); }
void clearData() { remove(dataKey); }
/**
* Completion item tags are extra annotations that tweak the rendering of a
* completion item.
* @since 3.15.0
*/
enum CompletionItemTag {
Deprecated = 1,
};
/**
* Tags for this completion item.
* @since 3.15.0
*/
Utils::optional<QList<CompletionItemTag>> tags() const;
/**
* Indicates if this item is deprecated.
* @deprecated Use `tags` instead if supported.
*/
Utils::optional<bool> deprecated() const { return optionalValue<bool>(deprecatedKey); }
bool isValid() const override { return contains(labelKey); }
};

View File

@@ -209,6 +209,7 @@ constexpr char symbolKindKey[] = "symbolKind";
constexpr char syncKindKey[] = "syncKind";
constexpr char synchronizationKey[] = "synchronization";
constexpr char tabSizeKey[] = "tabSize";
constexpr char tagsKey[] = "tags";
constexpr char targetKey[] = "target";
constexpr char textDocumentKey[] = "textDocument";
constexpr char textDocumentSyncKey[] = "textDocumentSync";

View File

@@ -334,7 +334,7 @@ protected:
_doc->fileName(),
line, column,
QmlJS::FindExportedCppTypes::tr(
"The module URI cannot be determined by static analysis. The type will be available\n"
"The module URI cannot be determined by static analysis. The type will not be available\n"
"globally in the QML editor. You can add a \"// @uri My.Module.Uri\" annotation to let\n"
"the QML editor know about a likely URI."));
}

View File

@@ -2378,10 +2378,14 @@ const Value *TypeScope::lookupMember(const QString &name, const Context *context
continue;
if (const Value *v = import->lookupMember(name, context, foundInObject)) {
// FIXME if we have multiple non-aliased imports containing this object we'd have to
// disambiguate (and inform the user) about this issue
if (info.as().isEmpty()) {
i.used = true;
return v;
}
}
}
if (foundInObject)
*foundInObject = nullptr;
return nullptr;

View File

@@ -465,7 +465,8 @@ Import LinkPrivate::importNonFile(const Document::Ptr &doc, const ImportInfo &im
"For Qbs projects, declare and set a qmlImportPaths property in your product "
"to add import paths.\n"
"For qmlproject projects, use the importPaths property to add import paths.\n"
"For CMake projects, make sure QML_IMPORT_PATH variable is in CMakeCache.txt.\n")
"For CMake projects, make sure QML_IMPORT_PATH variable is in CMakeCache.txt.\n"
"For qmlRegister... calls, make sure that you define the Module URI as a string literal.\n")
.arg(importInfo.name(), m_importPaths.join(QLatin1Char('\n'))));
}

View File

@@ -446,6 +446,20 @@ bool pInfoLessThanImports(const ModelManagerInterface::ProjectInfo &p1,
}
static QList<Utils::FilePath> generatedQrc(QStringList applicationDirectories)
{
QList<Utils::FilePath> res;
for (const QString &pathStr : applicationDirectories) {
Utils::FilePath path = Utils::FilePath::fromString(pathStr);
Utils::FilePath generatedQrcDir = path.pathAppended(".rcc");
if (generatedQrcDir.isReadableDir()) {
for (const Utils::FilePath & qrcPath: generatedQrcDir.dirEntries(FileFilter(QStringList({QStringLiteral(u"*.qrc")}), QDir::Files)))
res.append(qrcPath.canonicalPath());
}
}
return res;
}
void ModelManagerInterface::iterateQrcFiles(
ProjectExplorer::Project *project, QrcResourceSelector resources,
const std::function<void(QrcParser::ConstPtr)> &callback)
@@ -461,18 +475,21 @@ void ModelManagerInterface::iterateQrcFiles(
Utils::sort(pInfos, &pInfoLessThanAll);
}
QSet<QString> pathsChecked;
QSet<Utils::FilePath> pathsChecked;
for (const ModelManagerInterface::ProjectInfo &pInfo : qAsConst(pInfos)) {
QStringList qrcFilePaths;
if (resources == ActiveQrcResources)
qrcFilePaths = pInfo.activeResourceFiles;
else
qrcFilePaths = pInfo.allResourceFiles;
for (const QString &qrcFilePath : qAsConst(qrcFilePaths)) {
for (const Utils::FilePath &p : generatedQrc(pInfo.applicationDirectories))
qrcFilePaths.append(p.toString());
for (const QString &qrcFilePathStr : qAsConst(qrcFilePaths)) {
auto qrcFilePath = Utils::FilePath::fromString(qrcFilePathStr);
if (pathsChecked.contains(qrcFilePath))
continue;
pathsChecked.insert(qrcFilePath);
QrcParser::ConstPtr qrcFile = m_qrcCache.parsedPath(qrcFilePath);
QrcParser::ConstPtr qrcFile = m_qrcCache.parsedPath(qrcFilePath.toString());
if (qrcFile.isNull())
continue;
callback(qrcFile);
@@ -589,6 +606,8 @@ void ModelManagerInterface::updateProjectInfo(const ProjectInfo &pinfo, ProjectE
m_qrcContents = pinfo.resourceFileContents;
for (const QString &newQrc : qAsConst(pinfo.allResourceFiles))
m_qrcCache.addPath(newQrc, m_qrcContents.value(newQrc));
for (const Utils::FilePath &newQrc : generatedQrc(pinfo.applicationDirectories))
m_qrcCache.addPath(newQrc.toString(), m_qrcContents.value(newQrc.toString()));
for (const QString &oldQrc : qAsConst(oldInfo.allResourceFiles))
m_qrcCache.removePath(oldQrc);
@@ -1180,6 +1199,29 @@ void ModelManagerInterface::maybeScan(const PathsAndLanguages &importPaths)
}
}
static QList<Utils::FilePath> minimalPrefixPaths(const QStringList &paths)
{
QList<Utils::FilePath> sortedPaths;
// find minimal prefix, ensure '/' at end
for (const QString &pathStr : qAsConst(paths)) {
Utils::FilePath path = Utils::FilePath::fromString(pathStr);
if (!path.endsWith("/"))
path.setPath(path.path() + "/");
if (path.path().length() > 1)
sortedPaths.append(path);
}
std::sort(sortedPaths.begin(), sortedPaths.end());
QList<Utils::FilePath> res;
QString lastPrefix;
for (auto it = sortedPaths.begin(); it != sortedPaths.end(); ++it) {
if (lastPrefix.isEmpty() || !it->startsWith(lastPrefix)) {
lastPrefix = it->path();
res.append(*it);
}
}
return res;
}
void ModelManagerInterface::updateImportPaths()
{
if (m_indexerDisabled)
@@ -1243,6 +1285,7 @@ void ModelManagerInterface::updateImportPaths()
m_allImportPaths = allImportPaths;
m_activeBundles = activeBundles;
m_extendedBundles = extendedBundles;
m_applicationPaths = minimalPrefixPaths(allApplicationDirectories);
}
@@ -1253,10 +1296,13 @@ void ModelManagerInterface::updateImportPaths()
QSet<QString> newLibraries;
for (const Document::Ptr &doc : qAsConst(snapshot))
findNewLibraryImports(doc, snapshot, this, &importedFiles, &scannedPaths, &newLibraries);
for (const QString &path : qAsConst(allApplicationDirectories)) {
allImportPaths.maybeInsert(FilePath::fromString(path), Dialect::Qml);
findNewQmlApplicationInPath(FilePath::fromString(path), snapshot, this, &newLibraries);
for (const QString &pathStr : qAsConst(allApplicationDirectories)) {
Utils::FilePath path = Utils::FilePath::fromString(pathStr);
allImportPaths.maybeInsert(path, Dialect::Qml);
findNewQmlApplicationInPath(path, snapshot, this, &newLibraries);
}
for (const Utils::FilePath &qrcPath : generatedQrc(allApplicationDirectories))
updateQrcFile(qrcPath.toString());
updateSourceFiles(importedFiles, true);
@@ -1668,4 +1714,47 @@ void ModelManagerInterface::resetCodeModel()
updateImportPaths();
}
Utils::FilePath ModelManagerInterface::fileToSource(const Utils::FilePath &path)
{
if (!path.scheme().isEmpty())
return path;
for (const Utils::FilePath &p : m_applicationPaths) {
if (!p.isEmpty() && path.startsWith(p.path())) {
// if it is an applicationPath (i.e. in the build directory)
// try to use the path from the build dir as resource path
// and recover the path of the corresponding source file
QString reducedPath = path.path().mid(p.path().size());
QString reversePath(reducedPath);
std::reverse(reversePath.begin(), reversePath.end());
if (!reversePath.endsWith('/'))
reversePath.append('/');
QrcParser::MatchResult res;
iterateQrcFiles(nullptr,
QrcResourceSelector::AllQrcResources,
[&](const QrcParser::ConstPtr &qrcFile) {
if (!qrcFile)
return;
QrcParser::MatchResult matchNow = qrcFile->longestReverseMatches(
reversePath);
if (matchNow.matchDepth < res.matchDepth)
return;
if (matchNow.matchDepth == res.matchDepth) {
res.reversedPaths += matchNow.reversedPaths;
res.sourceFiles += matchNow.sourceFiles;
} else {
res = matchNow;
}
});
std::sort(res.sourceFiles.begin(), res.sourceFiles.end());
if (!res.sourceFiles.isEmpty()) {
return res.sourceFiles.first();
}
qCWarning(qmljsLog) << "Could not find source file for file" << path
<< "in application path" << p;
}
}
return path;
}
} // namespace QmlJS

View File

@@ -34,6 +34,7 @@
#include <utils/environment.h>
#include <utils/futuresynchronizer.h>
#include <utils/qrcparser.h>
#include <utils/filepath.h>
#include <QFuture>
#include <QHash>
@@ -149,6 +150,7 @@ public:
ProjectExplorer::Project *project = nullptr,
bool addDirs = false,
QrcResourceSelector resources = AllQrcResources);
Utils::FilePath fileToSource(const Utils::FilePath &file);
QList<ProjectInfo> projectInfos() const;
bool containsProject(ProjectExplorer::Project *project) const;
@@ -254,6 +256,7 @@ private:
QmlJS::Snapshot m_validSnapshot;
QmlJS::Snapshot m_newestSnapshot;
PathsAndLanguages m_allImportPaths;
QList<Utils::FilePath> m_applicationPaths;
QStringList m_defaultImportPaths;
QmlJS::QmlLanguageBundles m_activeBundles;
QmlJS::QmlLanguageBundles m_extendedBundles;

View File

@@ -264,13 +264,20 @@ void PluginDumper::qmlPluginTypeDumpDone(QtcProcess *process)
return;
const Snapshot snapshot = m_modelManager->snapshot();
LibraryInfo libraryInfo = snapshot.libraryInfo(libraryPath);
bool privatePlugin = libraryPath.endsWith(QLatin1String("private"));
const bool privatePlugin = libraryPath.endsWith(QLatin1String("private"));
if (process->exitCode() != 0) {
if (process->exitCode() || process->error() != QProcess::UnknownError) {
const QString errorMessages = qmlPluginDumpErrorMessage(process);
if (!privatePlugin)
ModelManagerInterface::writeWarning(qmldumpErrorMessage(libraryPath, errorMessages));
libraryInfo.setPluginTypeInfoStatus(LibraryInfo::DumpError, qmldumpFailedMessage(libraryPath, errorMessages));
libraryInfo.setPluginTypeInfoStatus(LibraryInfo::DumpError,
qmldumpFailedMessage(libraryPath, errorMessages));
if (process->error() != QProcess::UnknownError) {
libraryInfo.updateFingerprint();
m_modelManager->updateLibraryInfo(libraryPath, libraryInfo);
return;
}
const QByteArray output = process->readAllStandardOutput();
@@ -324,23 +331,6 @@ void PluginDumper::qmlPluginTypeDumpDone(QtcProcess *process)
}
}
void PluginDumper::qmlPluginTypeDumpError(QtcProcess *process)
{
process->deleteLater();
const FilePath libraryPath = m_runningQmldumps.take(process);
if (libraryPath.isEmpty())
return;
const QString errorMessages = qmlPluginDumpErrorMessage(process);
const Snapshot snapshot = m_modelManager->snapshot();
LibraryInfo libraryInfo = snapshot.libraryInfo(libraryPath);
if (!libraryPath.path().endsWith(QLatin1String("private"), Qt::CaseInsensitive))
ModelManagerInterface::writeWarning(qmldumpErrorMessage(libraryPath, errorMessages));
libraryInfo.setPluginTypeInfoStatus(LibraryInfo::DumpError, qmldumpFailedMessage(libraryPath, errorMessages));
libraryInfo.updateFingerprint();
m_modelManager->updateLibraryInfo(libraryPath, libraryInfo);
}
void PluginDumper::pluginChanged(const QString &pluginLibrary)
{
const int pluginIndex = m_libraryToPluginIndex.value(pluginLibrary, -1);
@@ -628,8 +618,7 @@ void PluginDumper::runQmlDump(const ModelManagerInterface::ProjectInfo &info,
process->setEnvironment(info.qmlDumpEnvironment);
process->setWorkingDirectory(importPath);
process->setCommand({info.qmlDumpPath, arguments});
connect(process, &QtcProcess::finished, this, [this, process] { qmlPluginTypeDumpDone(process); });
connect(process, &QtcProcess::errorOccurred, this, [this, process] { qmlPluginTypeDumpError(process); });
connect(process, &QtcProcess::done, this, [this, process] { qmlPluginTypeDumpDone(process); });
process->start();
m_runningQmldumps.insert(process, importPath);
}

View File

@@ -60,7 +60,6 @@ private:
const QString &importUri, const QString &importVersion);
Q_INVOKABLE void dumpAllPlugins();
void qmlPluginTypeDumpDone(Utils::QtcProcess *process);
void qmlPluginTypeDumpError(Utils::QtcProcess *process);
void pluginChanged(const QString &pluginLibrary);
private:

View File

@@ -20,9 +20,13 @@ endif()
find_library(DbgEngLib dbgeng)
set(ArchSuffix 32)
set(ArchSuffix "32")
if (CMAKE_SIZEOF_VOID_P EQUAL 8)
set(ArchSuffix 64)
set(ArchSuffix "64")
endif()
if (MSVC_CXX_ARCHITECTURE_ID MATCHES "^ARM")
set(ArchSuffix "arm${ArchSuffix}")
endif()
add_qtc_library(qtcreatorcdbext SHARED

View File

@@ -1138,6 +1138,9 @@ void StringAspect::addToLayout(LayoutBuilder &builder)
&FancyLineEdit::textEdited,
this,
&StringAspect::setValue);
connect(d->m_lineEditDisplay, &FancyLineEdit::editingFinished, this, [this] {
setValue(d->m_lineEditDisplay->text());
});
}
}
if (d->m_useResetButton) {
@@ -2442,6 +2445,10 @@ void AspectContainerData::append(const BaseAspect::Data::Ptr &data)
m_data.append(data);
}
// BaseAspect::Data
BaseAspect::Data::~Data() = default;
void BaseAspect::Data::Ptr::operator=(const Ptr &other)
{
if (this == &other)

View File

@@ -145,7 +145,7 @@ public:
// The (unique) address of the "owning" aspect's meta object is used as identifier.
using ClassId = const void *;
virtual ~Data() = default;
virtual ~Data();
Id id() const { return m_id; }
ClassId classId() const { return m_classId; }

View File

@@ -50,7 +50,7 @@ FilePath BuildableHelperLibrary::qtChooserToQmakePath(const FilePath &qtChooser)
proc.runBlocking();
if (proc.result() != ProcessResult::FinishedWithSuccess)
return {};
const QString output = proc.stdOut();
const QString output = proc.cleanedStdOut();
int pos = output.indexOf(toolDir);
if (pos == -1)
return {};

View File

@@ -277,8 +277,8 @@ void DeviceShell::startupFailed(const CommandLine &cmdLine)
bool DeviceShell::start()
{
m_shellProcess = new QtcProcess();
connect(m_shellProcess, &QtcProcess::done, this, [this] { emit done(); });
connect(m_shellProcess, &QtcProcess::errorOccurred, this, &DeviceShell::errorOccurred);
connect(m_shellProcess, &QtcProcess::done, m_shellProcess,
[this] { emit done(m_shellProcess->resultData()); });
connect(m_shellProcess, &QObject::destroyed, this, [this] { m_shellProcess = nullptr; });
connect(&m_thread, &QThread::finished, m_shellProcess, [this] { closeShellProcess(); });

View File

@@ -36,6 +36,7 @@
namespace Utils {
class CommandLine;
class ProcessResultData;
class QtcProcess;
class DeviceShellImpl;
@@ -69,8 +70,7 @@ public:
State state() const;
signals:
void done();
void errorOccurred(QProcess::ProcessError error);
void done(const ProcessResultData &resultData);
protected:
virtual void startupFailed(const CommandLine &cmdLine);

View File

@@ -945,8 +945,30 @@ QString FilePath::displayName(const QString &args) const
.arg(m_data, args, deviceName);
}
/// Constructs a FilePath from \a filename
/// \a filename is not checked for validity.
/*!
Constructs a FilePath from \a filepath
\a filepath is not checked for validity. It can be given in the following forms:
\list
\li /some/absolute/local/path
\li some/relative/path
\li scheme://host/absolute/path
\li scheme://host/./relative/path \note the ./ is verbatim part of the path
\endlist
Some decoding happens when parsing the \a filepath
A sequence %25 present in the host part is replaced by % in the host name,
a sequence %2f present in the host part is replaced by / in the host name.
The path part might consist of several parts separated by /, independent
of the platform or file system.
To create FilePath objects from strings possibly containing backslashes as
path separator, use \c fromUserInput.
\sa toString, fromUserInput
*/
FilePath FilePath::fromString(const QString &filepath)
{
FilePath fn;
@@ -1285,9 +1307,16 @@ FilePath FilePath::searchInDirectories(const FilePaths &dirs) const
return Environment::systemEnvironment().searchInDirectories(path(), dirs);
}
FilePath FilePath::searchInPath(const QList<FilePath> &additionalDirs) const
FilePath FilePath::searchInPath(const FilePaths &additionalDirs, PathAmending amending) const
{
return searchInDirectories(deviceEnvironment().path() + additionalDirs);
FilePaths directories = deviceEnvironment().path();
if (!additionalDirs.isEmpty()) {
if (amending == AppendToPath)
directories.append(additionalDirs);
else
directories = additionalDirs + directories;
}
return searchInDirectories(directories);
}
Environment FilePath::deviceEnvironment() const

View File

@@ -164,13 +164,16 @@ public:
[[nodiscard]] FilePath relativeChildPath(const FilePath &parent) const;
[[nodiscard]] FilePath relativePath(const FilePath &anchor) const;
[[nodiscard]] FilePath searchInDirectories(const QList<FilePath> &dirs) const;
[[nodiscard]] FilePath searchInPath(const QList<FilePath> &additionalDirs = {}) const;
[[nodiscard]] Environment deviceEnvironment() const;
[[nodiscard]] FilePath onDevice(const FilePath &deviceTemplate) const;
[[nodiscard]] FilePath withNewPath(const QString &newPath) const;
void iterateDirectory(const std::function<bool(const FilePath &item)> &callBack,
const FileFilter &filter) const;
enum PathAmending { AppendToPath, PrependToPath };
[[nodiscard]] FilePath searchInPath(const QList<FilePath> &additionalDirs = {},
PathAmending = AppendToPath) const;
// makes sure that capitalization of directories is canonical
// on Windows and macOS. This is rarely needed.
[[nodiscard]] FilePath normalizedPathName() const;

View File

@@ -31,6 +31,10 @@
#include <QOpenGLContext>
#endif
#ifdef Q_OS_LINUX
#include <sys/sysinfo.h>
#endif
#ifdef Q_OS_WIN
#include <qt_windows.h>
#endif
@@ -65,8 +69,9 @@ HostOsInfo::HostArchitecture HostOsInfo::hostArchitecture()
case PROCESSOR_ARCHITECTURE_IA64:
return HostOsInfo::HostArchitectureItanium;
case PROCESSOR_ARCHITECTURE_ARM:
case PROCESSOR_ARCHITECTURE_ARM64:
return HostOsInfo::HostArchitectureArm;
case PROCESSOR_ARCHITECTURE_ARM64:
return HostOsInfo::HostArchitectureArm64;
default:
return HostOsInfo::HostArchitectureUnknown;
}
@@ -110,3 +115,27 @@ bool HostOsInfo::canCreateOpenGLContext(QString *errorMessage)
return canCreate;
#endif
}
optional<quint64> HostOsInfo::totalMemoryInstalledInBytes()
{
#ifdef Q_OS_LINUX
struct sysinfo info;
if (sysinfo(&info) == -1)
return {};
return info.totalram;
#elif defined(Q_OS_WIN)
MEMORYSTATUSEX statex;
statex.dwLength = sizeof statex;
if (!GlobalMemoryStatusEx(&statex))
return {};
return statex.ullTotalPhys;
#elif defined(Q_OS_MACOS)
int mib[] = {CTL_HW, HW_MEMSIZE};
int64_t ram;
size_t length = sizeof(int64_t);
if (sysctl(mib, 2, &ram, &length, nullptr, 0) == -1)
return {};
return ram;
#endif
return {};
}

View File

@@ -27,6 +27,7 @@
#include "utils_global.h"
#include "optional.h"
#include "osspecificaspects.h"
QT_BEGIN_NAMESPACE
@@ -60,7 +61,7 @@ public:
}
enum HostArchitecture { HostArchitectureX86, HostArchitectureAMD64, HostArchitectureItanium,
HostArchitectureArm, HostArchitectureUnknown };
HostArchitectureArm, HostArchitectureArm64, HostArchitectureUnknown };
static HostArchitecture hostArchitecture();
static constexpr bool isWindowsHost() { return hostOs() == OsTypeWindows; }
@@ -104,6 +105,8 @@ public:
static bool canCreateOpenGLContext(QString *errorMessage);
static optional<quint64> totalMemoryInstalledInBytes();
private:
static Qt::CaseSensitivity m_overrideFileNameCaseSensitivity;
static bool m_useOverrideFileNameCaseSensitivity;

View File

@@ -178,7 +178,7 @@ class PathChooserPrivate
public:
PathChooserPrivate();
FilePath expandedPath(const QString &path) const;
FilePath expandedPath(const FilePath &path) const;
QHBoxLayout *m_hLayout = nullptr;
FancyLineEdit *m_lineEdit = nullptr;
@@ -202,12 +202,12 @@ PathChooserPrivate::PathChooserPrivate()
{
}
FilePath PathChooserPrivate::expandedPath(const QString &input) const
FilePath PathChooserPrivate::expandedPath(const FilePath &input) const
{
if (input.isEmpty())
return {};
FilePath path = FilePath::fromUserInput(input);
FilePath path = input;
Environment env = path.deviceEnvironment();
m_environmentChange.applyToEnvironment(env);
@@ -353,7 +353,7 @@ FilePath PathChooser::rawFilePath() const
FilePath PathChooser::filePath() const
{
return d->expandedPath(rawFilePath().toString());
return d->expandedPath(rawFilePath());
}
FilePath PathChooser::absoluteFilePath() const
@@ -529,11 +529,11 @@ FancyLineEdit::ValidationFunction PathChooser::defaultValidationFunction() const
bool PathChooser::validatePath(FancyLineEdit *edit, QString *errorMessage) const
{
QString path = edit->text();
QString input = edit->text();
if (path.isEmpty()) {
if (input.isEmpty()) {
if (!d->m_defaultValue.isEmpty()) {
path = d->m_defaultValue;
input = d->m_defaultValue;
} else {
if (errorMessage)
*errorMessage = tr("The path must not be empty.");
@@ -541,10 +541,10 @@ bool PathChooser::validatePath(FancyLineEdit *edit, QString *errorMessage) const
}
}
const FilePath filePath = d->expandedPath(path);
const FilePath filePath = d->expandedPath(FilePath::fromUserInput(input));
if (filePath.isEmpty()) {
if (errorMessage)
*errorMessage = tr("The path \"%1\" expanded to an empty string.").arg(QDir::toNativeSeparators(path));
*errorMessage = tr("The path \"%1\" expanded to an empty string.").arg(input);
return false;
}

View File

@@ -57,6 +57,7 @@ public:
const QLocale *locale = nullptr) const;
void collectResourceFilesForSourceFile(const QString &sourceFile, QStringList *res,
const QLocale *locale = nullptr) const;
QrcParser::MatchResult longestReverseMatches(const QString &) const;
QStringList errorMessages() const;
QStringList languages() const;
@@ -65,6 +66,7 @@ private:
const QStringList allUiLanguages(const QLocale *locale) const;
SMap m_resources;
SMap m_reverseResources;
SMap m_files;
QStringList m_languages;
QStringList m_errorMessages;
@@ -207,6 +209,11 @@ void QrcParser::collectFilesAtPath(const QString &path, QStringList *res, const
d->collectFilesAtPath(path, res, locale);
}
QrcParser::MatchResult QrcParser::longestReverseMatches(const QString &p) const
{
return d->longestReverseMatches(p);
}
/*!
Returns \c true if \a path is a non-empty directory and matches \a locale.
@@ -414,8 +421,14 @@ bool QrcParserPrivate::parseFile(const QString &path, const QString &contents)
else
accessPath = language + prefix + fileName;
QStringList &resources = m_resources[accessPath];
if (!resources.contains(filePath))
if (!resources.contains(filePath)) {
resources.append(filePath);
QString reversePath(accessPath);
std::reverse(reversePath.begin(), reversePath.end());
if (!reversePath.endsWith('/'))
reversePath.append('/');
m_reverseResources[reversePath].append(filePath);
}
QStringList &files = m_files[filePath];
if (!files.contains(accessPath))
files.append(accessPath);
@@ -517,6 +530,37 @@ void QrcParserPrivate::collectResourceFilesForSourceFile(const QString &sourceFi
}
}
QrcParser::MatchResult QrcParserPrivate::longestReverseMatches(const QString &reversePath) const
{
QrcParser::MatchResult res;
if (reversePath.length() == 1)
return res;
auto lastMatch = m_reverseResources.end();
qsizetype matchedUntil = 0;
for (qsizetype i = 1, j = 0; i < reversePath.size(); i = j + 1) {
j = reversePath.indexOf(u'/', i);
if (j == -1)
j = reversePath.size() - 1;
auto match = m_reverseResources.lowerBound(reversePath.mid(0, j + 1));
QString pNow = reversePath.left(j + 1);
if (match == m_reverseResources.end() || match.key().left(j + 1) != pNow)
break;
++res.matchDepth;
matchedUntil = j + 1;
lastMatch = match;
}
res.reversedPaths.clear();
res.sourceFiles.clear();
for (auto it = lastMatch; it != m_reverseResources.end()
&& it.key().left(matchedUntil) == reversePath.left(matchedUntil);
++it) {
res.reversedPaths.append(it.key());
for (const QString &filePath : it.value())
res.sourceFiles.append(Utils::FilePath::fromString(filePath));
}
return res;
}
QStringList QrcParserPrivate::errorMessages() const
{
return m_errorMessages;

View File

@@ -26,6 +26,7 @@
#pragma once
#include "utils_global.h"
#include "utils/filepath.h"
#include <QSharedPointer>
#include <QString>
@@ -47,12 +48,20 @@ class QrcCachePrivate;
class QTCREATOR_UTILS_EXPORT QrcParser
{
public:
struct MatchResult
{
int matchDepth = {};
QStringList reversedPaths;
QList<Utils::FilePath> sourceFiles;
};
typedef QSharedPointer<QrcParser> Ptr;
typedef QSharedPointer<const QrcParser> ConstPtr;
~QrcParser();
bool parseFile(const QString &path, const QString &contents);
QString firstFileAtPath(const QString &path, const QLocale &locale) const;
void collectFilesAtPath(const QString &path, QStringList *res, const QLocale *locale = nullptr) const;
MatchResult longestReverseMatches(const QString &) const;
bool hasDirAtPath(const QString &path, const QLocale *locale = nullptr) const;
void collectFilesInPath(const QString &path, QMap<QString, QStringList> *res, bool addDirs = false,
const QLocale *locale = nullptr) const;

View File

@@ -1034,7 +1034,7 @@ QtcProcess::QtcProcess(QObject *parent)
Q_UNUSED(qProcessProcessErrorMeta)
if (processLog().isDebugEnabled()) {
connect(this, &QtcProcess::finished, [this] {
connect(this, &QtcProcess::done, [this] {
if (!d->m_process.get())
return;
const QVariant n = d->m_process.get()->property(QTC_PROCESS_NUMBER);
@@ -1051,17 +1051,17 @@ QtcProcess::QtcProcess(QObject *parent)
qCDebug(processLog).nospace() << "Process " << number << " finished: "
<< "result=" << int(result())
<< ", ex=" << exitCode()
<< ", " << stdOut().size() << " bytes stdout: "
<< stdOut().left(20)
<< ", " << stdErr().size() << " bytes stderr: "
<< stdErr().left(1000)
<< ", " << cleanedStdOut().size() << " bytes stdout: "
<< cleanedStdOut().left(20)
<< ", " << cleanedStdErr().size() << " bytes stderr: "
<< cleanedStdErr().left(1000)
<< ", " << msElapsed << " ms elapsed";
if (processStdoutLog().isDebugEnabled() && !stdOut().isEmpty())
if (processStdoutLog().isDebugEnabled() && !cleanedStdOut().isEmpty())
qCDebug(processStdoutLog).nospace()
<< "Process " << number << " sdout: " << stdOut();
if (processStderrLog().isDebugEnabled() && !stdErr().isEmpty())
<< "Process " << number << " sdout: " << cleanedStdOut();
if (processStderrLog().isDebugEnabled() && !cleanedStdErr().isEmpty())
qCDebug(processStderrLog).nospace()
<< "Process " << number << " stderr: " << stdErr();
<< "Process " << number << " stderr: " << cleanedStdErr();
});
}
}
@@ -1617,12 +1617,6 @@ void QtcProcess::stop()
d->m_killTimer.start(d->m_process->m_setup.m_reaperTimeout);
}
QString QtcProcess::locateBinary(const QString &binary)
{
const QByteArray path = qgetenv("PATH");
return locateBinary(QString::fromLocal8Bit(path), binary);
}
/*!
\class Utils::SynchronousProcess
@@ -1691,8 +1685,8 @@ QString QtcProcess::allOutput() const
{
QTC_CHECK(d->m_stdOut.keepRawData);
QTC_CHECK(d->m_stdErr.keepRawData);
const QString out = stdOut();
const QString err = stdErr();
const QString out = cleanedStdOut();
const QString err = cleanedStdErr();
if (!out.isEmpty() && !err.isEmpty()) {
QString result = out;
@@ -1748,12 +1742,12 @@ static QStringList splitLines(const QString &text)
const QStringList QtcProcess::stdOutLines() const
{
return splitLines(stdOut());
return splitLines(cleanedStdOut());
}
const QStringList QtcProcess::stdErrLines() const
{
return splitLines(stdErr());
return splitLines(cleanedStdErr());
}
QTCREATOR_UTILS_EXPORT QDebug operator<<(QDebug str, const QtcProcess &r)

View File

@@ -144,10 +144,10 @@ public:
// These (or some of them) may be potentially moved outside of the class.
// For some we may aggregate in another public utils class (or subclass of QtcProcess)?
// TODO: How below 3 methods relate to QtcProcess? Action: move them somewhere else.
// TODO: How below 2 methods relate to QtcProcess?
// Action: move/merge them somewhere else, FilePath::searchInPath() ?
// Helpers to find binaries. Do not use it for other path variables
// and file types.
static QString locateBinary(const QString &binary);
static QString locateBinary(const QString &path, const QString &binary);
static QString normalizeNewlines(const QString &text);
@@ -189,8 +189,8 @@ public:
QString stdOut() const; // possibly with CR
QString stdErr() const; // possibly with CR
QString cleanedStdOut() const; // with CR removed
QString cleanedStdErr() const; // with CR removed
QString cleanedStdOut() const; // with sequences of CR squashed and CR LF replaced by LF
QString cleanedStdErr() const; // with sequences of CR squashed and CR LF replaced by LF
const QStringList stdOutLines() const; // split, CR removed
const QStringList stdErrLines() const; // split, CR removed

View File

@@ -271,8 +271,8 @@ void ShellCommand::run(QFutureInterface<void> &future)
proc.setExitCodeInterpreter(job.exitCodeInterpreter);
proc.setTimeoutS(job.timeoutS);
runCommand(proc, job.command, job.workingDirectory);
stdOut += proc.stdOut();
stdErr += proc.stdErr();
stdOut += proc.cleanedStdOut();
stdErr += proc.cleanedStdErr();
d->m_lastExecExitCode = proc.exitCode();
d->m_lastExecSuccess = proc.result() == ProcessResult::FinishedWithSuccess;
if (!d->m_lastExecSuccess)
@@ -352,11 +352,11 @@ void ShellCommand::runFullySynchronous(QtcProcess &process, const FilePath &work
process.runBlocking();
if (!d->m_aborted) {
const QString stdErr = process.stdErr();
const QString stdErr = process.cleanedStdErr();
if (!stdErr.isEmpty() && !(d->m_flags & SuppressStdErr))
emit append(stdErr);
const QString stdOut = process.stdOut();
const QString stdOut = process.cleanedStdOut();
if (!stdOut.isEmpty() && d->m_flags & ShowStdOut) {
if (d->m_flags & SilentOutput)
emit appendSilently(stdOut);

View File

@@ -29,6 +29,11 @@
#include "hostosinfo.h"
#include "qtcassert.h"
#ifdef QT_WIDGETS_LIB
#include <QApplication>
#include <QClipboard>
#endif
#include <QCoreApplication>
#include <QDir>
#include <QJsonArray>
@@ -469,4 +474,16 @@ QTCREATOR_UTILS_EXPORT QString languageNameFromLanguageCode(const QString &langu
return languageName;
}
#ifdef QT_WIDGETS_LIB
QTCREATOR_UTILS_EXPORT void setClipboardAndSelection(const QString &text)
{
QClipboard *clipboard = QApplication::clipboard();
clipboard->setText(text);
if (clipboard->supportsSelection())
clipboard->setText(text, QClipboard::Selection);
}
#endif
} // namespace Utils

View File

@@ -122,4 +122,12 @@ QTCREATOR_UTILS_EXPORT QString wildcardToRegularExpression(const QString &origin
QTCREATOR_UTILS_EXPORT QString languageNameFromLanguageCode(const QString &languageCode);
#ifdef QT_WIDGETS_LIB
// Feeds the global clipboard and, when present, the primary selection
QTCREATOR_UTILS_EXPORT void setClipboardAndSelection(const QString &text);
#endif
} // namespace Utils

View File

@@ -36,4 +36,6 @@ TemporaryFile::TemporaryFile(const QString &pattern) :
QTC_CHECK(!QFileInfo(pattern).isAbsolute());
}
TemporaryFile::~TemporaryFile() = default;
} // namespace Utils

View File

@@ -35,6 +35,7 @@ class QTCREATOR_UTILS_EXPORT TemporaryFile : public QTemporaryFile
{
public:
explicit TemporaryFile(const QString &pattern);
~TemporaryFile();
};
} // namespace Utils

View File

@@ -34,7 +34,7 @@ Project {
}
Depends { name: "Qt"; submodules: ["concurrent", "network", "qml", "widgets", "xml"] }
Depends { name: "Qt.macextras"; condition: qbs.targetOS.contains("macos") }
Depends { name: "Qt.macextras"; condition: Qt.core.versionMajor < 6 && qbs.targetOS.contains("macos") }
Depends { name: "app_version_header" }
files: [

View File

@@ -611,9 +611,11 @@ bool AndroidBuildApkStep::init()
QStringList argumentsPasswordConcealed = arguments;
if (m_signPackage) {
arguments << "--sign" << m_keystorePath.toString() << m_certificateAlias
arguments << "--release"
<< "--sign" << m_keystorePath.toString() << m_certificateAlias
<< "--storepass" << m_keystorePasswd;
argumentsPasswordConcealed << "--sign" << "******"
argumentsPasswordConcealed << "--release"
<< "--sign" << "******"
<< "--storepass" << "******";
if (!m_certificatePasswd.isEmpty()) {
arguments << "--keypass" << m_certificatePasswd;
@@ -1065,7 +1067,7 @@ QAbstractItemModel *AndroidBuildApkStep::keystoreCertificates()
if (keytoolProc.result() > ProcessResult::FinishedWithError)
QMessageBox::critical(nullptr, tr("Error"), tr("Failed to run keytool."));
else
model = new CertificatesModel(keytoolProc.stdOut(), this);
model = new CertificatesModel(keytoolProc.cleanedStdOut(), this);
return model;
}

View File

@@ -140,11 +140,16 @@ void AndroidDebugSupport::start()
solibSearchPath.append(qtVersion->qtSoPaths());
solibSearchPath.append(uniquePaths(extraLibs));
FilePath buildDir = AndroidManager::buildDirectory(target);
const RunConfiguration *activeRunConfig = target->activeRunConfiguration();
FilePath buildDir;
if (activeRunConfig)
buildDir = activeRunConfig->buildTargetInfo().workingDirectory;
solibSearchPath.append(activeRunConfig->buildTargetInfo().workingDirectory.toString());
solibSearchPath.append(buildDir.toString());
const auto androidLibsPath = AndroidManager::androidBuildDirectory(target)
.pathAppended("libs")
.pathAppended(AndroidManager::apkDevicePreferredAbi(target))
.toString();
solibSearchPath.append(androidLibsPath);
solibSearchPath.removeDuplicates();
setSolibSearchPath(solibSearchPath);
qCDebug(androidDebugSupportLog) << "SoLibSearchPath: "<<solibSearchPath;

View File

@@ -213,12 +213,12 @@ bool AndroidDeployQtStep::init()
m_serialNumber = info.serialNumber;
qCDebug(deployStepLog) << "Selected device info:" << info;
gatherFilesToPull();
AndroidManager::setDeviceSerialNumber(target(), m_serialNumber);
AndroidManager::setDeviceApiLevel(target(), info.sdk);
AndroidManager::setDeviceAbis(target(), info.cpuAbi);
gatherFilesToPull();
emit addOutput(tr("Deploying to %1").arg(m_serialNumber), OutputFormat::NormalMessage);
m_uninstallPreviousPackageRun = m_uninstallPreviousPackage->value();

View File

@@ -787,8 +787,8 @@ SdkToolResult AndroidManager::runCommand(const CommandLine &command,
qCDebug(androidManagerLog) << "Running command (sync):" << command.toUserOutput();
cmdProc.setCommand(command);
cmdProc.runBlocking(EventLoopMode::On);
cmdResult.m_stdOut = cmdProc.stdOut().trimmed();
cmdResult.m_stdErr = cmdProc.stdErr().trimmed();
cmdResult.m_stdOut = cmdProc.cleanedStdOut().trimmed();
cmdResult.m_stdErr = cmdProc.cleanedStdErr().trimmed();
cmdResult.m_success = cmdProc.result() == ProcessResult::FinishedWithSuccess;
qCDebug(androidManagerLog) << "Command finshed (sync):" << command.toUserOutput()
<< "Success:" << cmdResult.m_success

View File

@@ -186,7 +186,7 @@ static void sdkManagerCommand(const AndroidConfig &config, const QStringList &ar
proc.runBlocking(EventLoopMode::On);
if (assertionFound) {
output.success = false;
output.stdOutput = proc.stdOut();
output.stdOutput = proc.cleanedStdOut();
output.stdError = QCoreApplication::translate("Android::Internal::AndroidSdkManager",
"The operation requires user interaction. "
"Use the \"sdkmanager\" command-line tool.");

View File

@@ -51,10 +51,8 @@ BoostTestOutputReader::BoostTestOutputReader(const QFutureInterface<TestResultPt
, m_logLevel(log)
, m_reportLevel(report)
{
if (m_testApplication) {
connect(m_testApplication, &Utils::QtcProcess::finished,
this, &BoostTestOutputReader::onFinished);
}
if (m_testApplication)
connect(m_testApplication, &Utils::QtcProcess::done, this, &BoostTestOutputReader::onDone);
}
// content of "error:..." / "info:..." / ... messages
@@ -406,7 +404,7 @@ TestResultPtr BoostTestOutputReader::createDefaultResult() const
return TestResultPtr(result);
}
void BoostTestOutputReader::onFinished() {
void BoostTestOutputReader::onDone() {
int exitCode = m_testApplication->exitCode();
if (m_reportLevel == ReportLevel::No && m_testCaseCount != -1) {
int reportedFailsAndSkips = m_summary[ResultType::Fail] + m_summary[ResultType::Skip];

View File

@@ -47,7 +47,7 @@ protected:
TestResultPtr createDefaultResult() const override;
private:
void onFinished();
void onDone();
void sendCompleteInformation();
void handleMessageMatch(const QRegularExpressionMatch &match);
void reportNoOutputFinish(const QString &description, ResultType type);

View File

@@ -45,9 +45,8 @@ GTestOutputReader::GTestOutputReader(const QFutureInterface<TestResultPtr> &futu
, m_projectFile(projectFile)
{
if (m_testApplication) {
connect(m_testApplication, &Utils::QtcProcess::finished,
this, [this]() {
int exitCode = m_testApplication->exitCode();
connect(m_testApplication, &Utils::QtcProcess::done, this, [this] {
const int exitCode = m_testApplication->exitCode();
if (exitCode == 1 && !m_description.isEmpty()) {
createAndReportResult(tr("Running tests failed.\n %1\nExecutable: %2")
.arg(m_description).arg(id()), ResultType::MessageFatal);

View File

@@ -197,7 +197,7 @@ bool TestRunner::currentConfigValid()
m_fakeFutureInterface->reportFinished();
onFinished();
} else {
onProcessFinished();
onProcessDone();
}
return false;
}
@@ -263,21 +263,20 @@ void TestRunner::scheduleNext()
return;
if (!m_currentConfig->project())
onProcessFinished();
onProcessDone();
setUpProcess();
QTC_ASSERT(m_currentProcess, onProcessFinished(); return);
QTC_ASSERT(m_currentProcess, onProcessDone(); return);
QTC_ASSERT(!m_currentOutputReader, delete m_currentOutputReader);
m_currentOutputReader = m_currentConfig->outputReader(*m_fakeFutureInterface, m_currentProcess);
QTC_ASSERT(m_currentOutputReader, onProcessFinished();return);
QTC_ASSERT(m_currentOutputReader, onProcessDone();return);
connect(m_currentOutputReader, &TestOutputReader::newOutputLineAvailable,
TestResultsPane::instance(), &TestResultsPane::addOutputLine);
setUpProcessEnv();
connect(m_currentProcess, &Utils::QtcProcess::finished,
this, &TestRunner::onProcessFinished);
connect(m_currentProcess, &Utils::QtcProcess::done, this, &TestRunner::onProcessDone);
const int timeout = AutotestPlugin::settings()->timeout;
m_cancelTimer.setInterval(timeout);
m_cancelTimer.start();
@@ -292,7 +291,7 @@ void TestRunner::scheduleNext()
reportResult(ResultType::MessageFatal,
tr("Failed to start test for project \"%1\".").arg(m_currentConfig->displayName())
+ processInformation(m_currentProcess) + rcInfo(m_currentConfig));
onProcessFinished();
onProcessDone();
}
}
@@ -315,7 +314,7 @@ void TestRunner::cancelCurrent(TestRunner::CancelReason reason)
}
}
void TestRunner::onProcessFinished()
void TestRunner::onProcessDone()
{
if (m_executingTests && m_currentConfig) {
QTC_CHECK(m_fakeFutureInterface);

View File

@@ -90,7 +90,7 @@ private:
void setUpProcessEnv();
void scheduleNext();
void cancelCurrent(CancelReason reason);
void onProcessFinished();
void onProcessDone();
void resetInternalPointers();
void runTests();

View File

@@ -91,12 +91,12 @@ UvscServerProvider::UvscServerProvider(const UvscServerProvider &other)
setEngineType(UvscEngineType);
}
void UvscServerProvider::setToolsIniFile(const Utils::FilePath &toolsIniFile)
void UvscServerProvider::setToolsIniFile(const FilePath &toolsIniFile)
{
m_toolsIniFile = toolsIniFile;
}
Utils::FilePath UvscServerProvider::toolsIniFile() const
FilePath UvscServerProvider::toolsIniFile() const
{
return m_toolsIniFile;
}
@@ -251,8 +251,7 @@ bool UvscServerProvider::fromMap(const QVariantMap &data)
return true;
}
Utils::FilePath UvscServerProvider::projectFilePath(DebuggerRunTool *runTool,
QString &errorMessage) const
FilePath UvscServerProvider::projectFilePath(DebuggerRunTool *runTool, QString &errorMessage) const
{
const FilePath projectPath = buildProjectFilePath(runTool);
std::ofstream ofs(projectPath.toString().toStdString(), std::ofstream::out);
@@ -332,12 +331,12 @@ void UvscServerProviderConfigWidget::discard()
IDebugServerProviderConfigWidget::discard();
}
void UvscServerProviderConfigWidget::setToolsIniFile(const Utils::FilePath &toolsIniFile)
void UvscServerProviderConfigWidget::setToolsIniFile(const FilePath &toolsIniFile)
{
m_toolsIniChooser->setFilePath(toolsIniFile);
}
Utils::FilePath UvscServerProviderConfigWidget::toolsIniFile() const
FilePath UvscServerProviderConfigWidget::toolsIniFile() const
{
return m_toolsIniChooser->filePath();
}
@@ -386,21 +385,16 @@ UvscServerProviderRunner::UvscServerProviderRunner(ProjectExplorer::RunControl *
this->runControl()->setApplicationProcessHandle(pid);
reportStarted();
});
connect(&m_process, &QtcProcess::finished, this, [this] {
const QProcess::ProcessError error = m_process.error();
const QString message = (error == QProcess::UnknownError)
? m_process.exitMessage()
: userMessageForProcessError(error, m_process.commandLine().executable());
appendMessage(message, Utils::NormalMessageFormat);
connect(&m_process, &QtcProcess::done, this, [this] {
appendMessage(m_process.exitMessage(), NormalMessageFormat);
reportStopped();
});
}
void UvscServerProviderRunner::start()
{
const QString msg = RunControl::tr("Starting %1 ...")
.arg(m_process.commandLine().toUserOutput());
appendMessage(msg, Utils::NormalMessageFormat);
const QString msg = RunControl::tr("Starting %1 ...").arg(m_process.commandLine().displayName());
appendMessage(msg, NormalMessageFormat);
m_process.start();
}

View File

@@ -153,7 +153,7 @@ bool BazaarClient::synchronousUncommit(const FilePath &workingDir,
QtcProcess proc;
vcsFullySynchronousExec(proc, workingDir, args);
VcsOutputWindow::append(proc.stdOut());
VcsOutputWindow::append(proc.cleanedStdOut());
return proc.result() == ProcessResult::FinishedWithSuccess;
}

View File

@@ -34,11 +34,16 @@
#include <utils/fileutils.h>
#include <utils/genericconstants.h>
#include <utils/mimeutils.h>
#include <utils/qtcprocess.h>
#include <QFile>
#include <QFileInfo>
#include <QRegularExpression>
#include <QVersionNumber>
#include <QXmlStreamReader>
using namespace Utils;
namespace Beautifier {
namespace Internal {
@@ -47,12 +52,65 @@ const char COMMAND[] = "command";
const char SUPPORTED_MIME[] = "supportedMime";
}
class VersionUpdater
{
public:
VersionUpdater()
{
QObject::connect(&m_process, &QtcProcess::done, [this] {
if (m_process.result() != ProcessResult::FinishedWithSuccess)
return;
m_versionNumber = parseVersion(m_process.cleanedStdOut());
if (m_versionNumber.isNull())
m_versionNumber = parseVersion(m_process.cleanedStdErr());
});
}
void setVersionRegExp(const QRegularExpression &versionRegExp)
{
m_versionRegExp = versionRegExp;
}
void update(const FilePath &executable)
{
m_versionNumber = {};
if (m_versionRegExp.pattern().isEmpty())
return;
m_process.close();
m_process.setCommand({executable, {"--version"}});
m_process.start();
}
QVersionNumber version() const
{
if (m_process.state() != QProcess::NotRunning)
m_process.waitForFinished(-1);
return m_versionNumber;
}
private:
QVersionNumber parseVersion(const QString &text) const
{
const QRegularExpressionMatch match = m_versionRegExp.match(text);
if (!match.hasMatch())
return {};
return {match.captured(1).toInt(), match.captured(2).toInt()};
}
QRegularExpression m_versionRegExp;
mutable QtcProcess m_process;
QVersionNumber m_versionNumber;
};
AbstractSettings::AbstractSettings(const QString &name, const QString &ending)
: m_ending(ending)
, m_styleDir(Core::ICore::userResourcePath(Beautifier::Constants::SETTINGS_DIRNAME)
.pathAppended(name)
.toString())
, m_name(name)
, m_versionUpdater(new VersionUpdater)
{
}
@@ -122,29 +180,28 @@ QString AbstractSettings::styleFileName(const QString &key) const
return m_styleDir.absoluteFilePath(key + m_ending);
}
Utils::FilePath AbstractSettings::command() const
FilePath AbstractSettings::command() const
{
return Utils::FilePath::fromString(m_command);
return FilePath::fromString(m_command);
}
void AbstractSettings::setCommand(const QString &command)
void AbstractSettings::setCommand(const QString &cmd)
{
if (command == m_command)
if (cmd == m_command)
return;
m_command = command;
updateVersion();
m_command = cmd;
m_versionUpdater->update(command());
}
int AbstractSettings::version() const
QVersionNumber AbstractSettings::version() const
{
return m_version;
return m_versionUpdater->version();
}
void AbstractSettings::updateVersion()
void AbstractSettings::setVersionRegExp(const QRegularExpression &versionRegExp)
{
// If a beautifier needs to know the current tool's version, reimplement and store the version
// in m_version.
m_versionUpdater->setVersionRegExp(versionRegExp);
}
QString AbstractSettings::supportedMimeTypesAsString() const
@@ -157,7 +214,7 @@ void AbstractSettings::setSupportedMimeTypes(const QString &mimes)
const QStringList stringTypes = mimes.split(';');
QStringList types;
for (const QString &type : stringTypes) {
const Utils::MimeType mime = Utils::mimeTypeForName(type.trimmed());
const MimeType mime = mimeTypeForName(type.trimmed());
if (!mime.isValid())
continue;
const QString canonicalName = mime.name();
@@ -179,8 +236,8 @@ bool AbstractSettings::isApplicable(const Core::IDocument *document) const
if (m_supportedMimeTypes.isEmpty())
return true;
const Utils::MimeType documentMimeType = Utils::mimeTypeForName(document->mimeType());
return Utils::anyOf(m_supportedMimeTypes, [&documentMimeType](const QString &mime) {
const MimeType documentMimeType = mimeTypeForName(document->mimeType());
return anyOf(m_supportedMimeTypes, [&documentMimeType](const QString &mime) {
return documentMimeType.inherits(mime);
});
}
@@ -246,7 +303,7 @@ void AbstractSettings::save()
continue;
}
Utils::FileSaver saver(Utils::FilePath::fromUserInput(fi.absoluteFilePath()));
FileSaver saver(FilePath::fromUserInput(fi.absoluteFilePath()));
if (saver.hasError()) {
BeautifierPlugin::showError(tr("Cannot open file \"%1\": %2.")
.arg(saver.filePath().toUserOutput())

View File

@@ -35,12 +35,21 @@
#include <QStringList>
#include <QVector>
#include <memory>
QT_BEGIN_NAMESPACE
class QRegularExpression;
class QVersionNumber;
QT_END_NAMESPACE
namespace Core { class IDocument; }
namespace Utils { class FilePath; }
namespace Beautifier {
namespace Internal {
class VersionUpdater;
class AbstractSettings : public QObject
{
Q_OBJECT
@@ -66,9 +75,8 @@ public:
virtual QString styleFileName(const QString &key) const;
Utils::FilePath command() const;
void setCommand(const QString &command);
int version() const;
virtual void updateVersion();
void setCommand(const QString &cmd);
QVersionNumber version() const;
QString supportedMimeTypesAsString() const;
void setSupportedMimeTypes(const QString &mimes);
@@ -81,9 +89,10 @@ signals:
void supportedMimeTypesChanged();
protected:
void setVersionRegExp(const QRegularExpression &versionRegExp);
QMap<QString, QString> m_styles;
QMap<QString, QVariant> m_settings;
int m_version = 0;
QString m_ending;
QDir m_styleDir;
@@ -92,6 +101,7 @@ protected:
private:
QString m_name;
std::unique_ptr<VersionUpdater> m_versionUpdater;
QStringList m_stylesToRemove;
QSet<QString> m_changedStyles;
QString m_command;

View File

@@ -53,6 +53,7 @@
#include <QAction>
#include <QMenu>
#include <QVersionNumber>
using namespace TextEditor;
@@ -150,10 +151,10 @@ Command ArtisticStyle::command(const QString &cfgFile) const
command.addOption("-q");
command.addOption("--options=" + cfgFile);
const int version = m_settings.version();
if (version > ArtisticStyleSettings::Version_2_03) {
const QVersionNumber version = m_settings.version();
if (version > QVersionNumber(2, 3)) {
command.setProcessing(Command::PipeProcessing);
if (version == ArtisticStyleSettings::Version_2_04)
if (version == QVersionNumber(2, 4))
command.setPipeAddsNewline(true);
command.setReturnsCRLF(Utils::HostOsInfo::isWindowsHost());
command.addOption("-z2");

View File

@@ -57,9 +57,7 @@ const char SETTINGS_NAME[] = "artisticstyle";
ArtisticStyleSettings::ArtisticStyleSettings() :
AbstractSettings(SETTINGS_NAME, ".astyle")
{
connect(&m_versionWatcher, &QFutureWatcherBase::finished,
this, &ArtisticStyleSettings::helperSetVersion);
setVersionRegExp(QRegularExpression("([2-9]{1})\\.([0-9]{1,2})(\\.[1-9]{1})?$"));
setCommand("astyle");
m_settings.insert(USE_OTHER_FILES, QVariant(true));
m_settings.insert(USE_SPECIFIC_CONFIG_FILE, QVariant(false));
@@ -70,48 +68,6 @@ ArtisticStyleSettings::ArtisticStyleSettings() :
read();
}
static int parseVersion(const QString &text)
{
// The version in Artistic Style is printed like "Artistic Style Version 2.04"
const QRegularExpression rx("([2-9]{1})\\.([0-9]{1,2})(\\.[1-9]{1})?$");
const QRegularExpressionMatch match = rx.match(text);
if (match.hasMatch()) {
const int major = match.captured(1).toInt() * 100;
const int minor = match.captured(2).toInt();
return major + minor;
}
return 0;
}
static int updateVersionHelper(const FilePath &command)
{
QtcProcess process;
process.setCommand({command, {"--version"}});
process.runBlocking();
if (process.result() != ProcessResult::FinishedWithSuccess)
return 0;
// Astyle prints the version on stdout or stderr, depending on platform
const int version = parseVersion(process.stdOut().trimmed());
if (version != 0)
return version;
return parseVersion(process.stdErr().trimmed());
}
void ArtisticStyleSettings::updateVersion()
{
if (m_versionFuture.isRunning())
m_versionFuture.cancel();
m_versionFuture = runAsync(updateVersionHelper, command());
m_versionWatcher.setFuture(m_versionFuture);
}
void ArtisticStyleSettings::helperSetVersion()
{
m_version = m_versionWatcher.result();
}
bool ArtisticStyleSettings::useOtherFiles() const
{
return m_settings.value(USE_OTHER_FILES).toBool();
@@ -132,12 +88,12 @@ void ArtisticStyleSettings::setUseSpecificConfigFile(bool useSpecificConfigFile)
m_settings.insert(USE_SPECIFIC_CONFIG_FILE, QVariant(useSpecificConfigFile));
}
Utils::FilePath ArtisticStyleSettings::specificConfigFile() const
FilePath ArtisticStyleSettings::specificConfigFile() const
{
return Utils::FilePath::fromString(m_settings.value(SPECIFIC_CONFIG_FILE).toString());
return FilePath::fromString(m_settings.value(SPECIFIC_CONFIG_FILE).toString());
}
void ArtisticStyleSettings::setSpecificConfigFile(const Utils::FilePath &specificConfigFile)
void ArtisticStyleSettings::setSpecificConfigFile(const FilePath &specificConfigFile)
{
m_settings.insert(SPECIFIC_CONFIG_FILE, QVariant(specificConfigFile.toString()));
}
@@ -182,7 +138,7 @@ QString ArtisticStyleSettings::documentationFilePath() const
void ArtisticStyleSettings::createDocumentationFile() const
{
Utils::QtcProcess process;
QtcProcess process;
process.setTimeoutS(2);
process.setCommand({command(), {"-h"}});
process.runBlocking();
@@ -204,7 +160,7 @@ void ArtisticStyleSettings::createDocumentationFile() const
stream.writeStartElement(Constants::DOCUMENTATION_XMLROOT);
// astyle writes its output to 'error'...
const QStringList lines = process.stdErr().split(QLatin1Char('\n'));
const QStringList lines = process.cleanedStdErr().split(QLatin1Char('\n'));
QStringList keys;
QStringList docu;
for (QString line : lines) {

View File

@@ -29,9 +29,6 @@
#include <utils/fileutils.h>
#include <QFuture>
#include <QFutureWatcher>
namespace Beautifier {
namespace Internal {
@@ -40,15 +37,8 @@ class ArtisticStyleSettings : public AbstractSettings
Q_OBJECT
public:
enum ArtisticStyleVersion {
Version_2_03 = 203,
Version_2_04 = 204
};
ArtisticStyleSettings();
void updateVersion() override;
bool useOtherFiles() const;
void setUseOtherFiles(bool useOtherFiles);
@@ -69,11 +59,6 @@ public:
QString documentationFilePath() const override;
void createDocumentationFile() const override;
private:
void helperSetVersion();
QFuture<int> m_versionFuture;
QFutureWatcher<int> m_versionWatcher;
};
} // namespace Internal

View File

@@ -49,6 +49,7 @@
#include <QAction>
#include <QMenu>
#include <QVersionNumber>
using namespace TextEditor;
@@ -180,7 +181,7 @@ Command Uncrustify::command(const QString &cfgFile, bool fragment) const
Command command;
command.setExecutable(m_settings.command().toString());
command.setProcessing(Command::PipeProcessing);
if (m_settings.version() >= 62) {
if (m_settings.version() >= QVersionNumber(0, 62)) {
command.addOption("--assume");
command.addOption("%file");
} else {

View File

@@ -30,7 +30,6 @@
#include "../beautifierconstants.h"
#include <coreplugin/icore.h>
#include <utils/qtcprocess.h>
#include <QDateTime>
@@ -56,6 +55,7 @@ const char SETTINGS_NAME[] = "uncrustify";
UncrustifySettings::UncrustifySettings() :
AbstractSettings(SETTINGS_NAME, ".cfg")
{
setVersionRegExp(QRegularExpression("([0-9]{1})\\.([0-9]{2})"));
setCommand("uncrustify");
m_settings.insert(USE_OTHER_FILES, QVariant(true));
m_settings.insert(USE_HOME_FILE, QVariant(false));
@@ -210,33 +210,5 @@ void UncrustifySettings::createDocumentationFile() const
}
}
static bool parseVersion(const QString &text, int &version)
{
// The version in Uncrustify is printed like "uncrustify 0.62"
const QRegularExpression rx("([0-9]{1})\\.([0-9]{2})");
const QRegularExpressionMatch match = rx.match(text);
if (!match.hasMatch())
return false;
const int major = match.captured(1).toInt() * 100;
const int minor = match.captured(2).toInt();
version = major + minor;
return true;
}
void UncrustifySettings::updateVersion()
{
m_versionProcess.reset(new QtcProcess);
connect(m_versionProcess.get(), &QtcProcess::finished, this, [this] {
if (m_versionProcess->exitStatus() == QProcess::NormalExit) {
if (!parseVersion(QString::fromUtf8(m_versionProcess->readAllStandardOutput()), m_version))
parseVersion(QString::fromUtf8(m_versionProcess->readAllStandardError()), m_version);
}
m_versionProcess.release()->deleteLater();
});
m_versionProcess->setCommand({ command(), { "--version" } });
m_versionProcess->start();
}
} // namespace Internal
} // namespace Beautifier

View File

@@ -26,9 +26,6 @@
#pragma once
#include "../abstractsettings.h"
#include <utils/fileutils.h>
namespace Utils { class QtcProcess; }
namespace Beautifier {
namespace Internal {
@@ -59,16 +56,11 @@ public:
QString documentationFilePath() const override;
void createDocumentationFile() const override;
void updateVersion() override;
Utils::FilePath specificConfigFile() const;
void setSpecificConfigFile(const Utils::FilePath &filePath);
bool useSpecificConfigFile() const;
void setUseSpecificConfigFile(bool useConfigFile);
private:
std::unique_ptr<Utils::QtcProcess> m_versionProcess;
};
} // namespace Internal

View File

@@ -88,8 +88,8 @@ public:
private:
void handleDone()
{
const QString stdOut = m_appRunner.stdOut();
const QString stdErr = m_appRunner.stdErr();
const QString stdOut = m_appRunner.cleanedStdOut();
const QString stdErr = m_appRunner.cleanedStdErr();
// FIXME: Needed in a post-adb world?
// adb does not forward exit codes and all stderr goes to stdout.

View File

@@ -55,7 +55,7 @@ public:
setId("QdbDebuggeeRunner");
connect(&m_launcher, &QtcProcess::started, this, &RunWorker::reportStarted);
connect(&m_launcher, &QtcProcess::finished, this, &RunWorker::reportStopped);
connect(&m_launcher, &QtcProcess::done, this, &RunWorker::reportStopped);
connect(&m_launcher, &QtcProcess::readyReadStandardOutput, [this] {
appendMessage(QString::fromUtf8(m_launcher.readAllStandardOutput()), StdOutFormat);

View File

@@ -22,6 +22,7 @@ add_qtc_plugin(ClangCodeModel
clangdquickfixfactory.cpp clangdquickfixfactory.h
clangdqpropertyhighlighter.cpp clangdqpropertyhighlighter.h
clangdsemantichighlighting.cpp clangdsemantichighlighting.h
clangdswitchdecldef.cpp clangdswitchdecldef.h
clangeditordocumentprocessor.cpp clangeditordocumentprocessor.h
clangfixitoperation.cpp clangfixitoperation.h
clangdlocatorfilters.cpp clangdlocatorfilters.h

View File

@@ -46,6 +46,8 @@ QtcPlugin {
"clangdquickfixfactory.h",
"clangdsemantichighlighting.cpp",
"clangdsemantichighlighting.h",
"clangdswitchdecldef.cpp",
"clangdswitchdecldef.h",
"clangeditordocumentprocessor.cpp",
"clangeditordocumentprocessor.h",
"clangfixitoperation.cpp",

View File

@@ -30,6 +30,7 @@
#include "clangdast.h"
#include "clangdfollowsymbol.h"
#include "clangdlocatorfilters.h"
#include "clangdswitchdecldef.h"
#include "clangpreprocessorassistproposalitem.h"
#include "clangtextmark.h"
#include "clangutils.h"
@@ -59,7 +60,6 @@
#include <cppeditor/semantichighlighter.h>
#include <cppeditor/cppsemanticinfo.h>
#include <languageclient/diagnosticmanager.h>
#include <languageclient/documentsymbolcache.h>
#include <languageclient/languageclientcompletionassist.h>
#include <languageclient/languageclientfunctionhint.h>
#include <languageclient/languageclienthoverhandler.h>
@@ -117,8 +117,8 @@ namespace ClangCodeModel {
namespace Internal {
Q_LOGGING_CATEGORY(clangdLog, "qtc.clangcodemodel.clangd", QtWarningMsg);
Q_LOGGING_CATEGORY(clangdLogAst, "qtc.clangcodemodel.clangd.ast", QtWarningMsg);
static Q_LOGGING_CATEGORY(clangdLogServer, "qtc.clangcodemodel.clangd.server", QtWarningMsg);
static Q_LOGGING_CATEGORY(clangdLogAst, "qtc.clangcodemodel.clangd.ast", QtWarningMsg);
static Q_LOGGING_CATEGORY(clangdLogCompletion, "qtc.clangcodemodel.clangd.completion",
QtWarningMsg);
static QString indexingToken() { return "backgroundIndexProgress"; }
@@ -310,58 +310,6 @@ public:
bool categorize = CppEditor::codeModelSettings()->categorizeFindReferences();
};
class SwitchDeclDefData {
public:
SwitchDeclDefData(quint64 id, TextDocument *doc, const QTextCursor &cursor,
CppEditor::CppEditorWidget *editorWidget,
const Utils::LinkHandler &callback)
: id(id), document(doc), uri(DocumentUri::fromFilePath(doc->filePath())),
cursor(cursor), editorWidget(editorWidget), callback(callback) {}
Utils::optional<ClangdAstNode> getFunctionNode() const
{
QTC_ASSERT(ast, return {});
const ClangdAstPath path = getAstPath(*ast, Range(cursor));
for (auto it = path.rbegin(); it != path.rend(); ++it) {
if (it->role() == "declaration"
&& (it->kind() == "CXXMethod" || it->kind() == "CXXConversion"
|| it->kind() == "CXXConstructor" || it->kind() == "CXXDestructor")) {
return *it;
}
}
return {};
}
QTextCursor cursorForFunctionName(const ClangdAstNode &functionNode) const
{
QTC_ASSERT(docSymbols, return {});
const auto symbolList = Utils::get_if<QList<DocumentSymbol>>(&*docSymbols);
if (!symbolList)
return {};
const Range &astRange = functionNode.range();
QList symbolsToCheck = *symbolList;
while (!symbolsToCheck.isEmpty()) {
const DocumentSymbol symbol = symbolsToCheck.takeFirst();
if (symbol.range() == astRange)
return symbol.selectionRange().start().toTextCursor(document->document());
if (symbol.range().contains(astRange))
symbolsToCheck << symbol.children().value_or(QList<DocumentSymbol>());
}
return {};
}
const quint64 id;
const QPointer<TextDocument> document;
const DocumentUri uri;
const QTextCursor cursor;
const QPointer<CppEditor::CppEditorWidget> editorWidget;
Utils::LinkHandler callback;
Utils::optional<DocumentSymbolsResult> docSymbols;
Utils::optional<ClangdAstNode> ast;
};
class LocalRefsData {
public:
LocalRefsData(quint64 id, TextDocument *doc, const QTextCursor &cursor,
@@ -699,7 +647,7 @@ public:
const CppEditor::ClangdSettings::Data settings;
QHash<quint64, ReferencesData> runningFindUsages;
ClangdFollowSymbol *followSymbol = nullptr;
Utils::optional<SwitchDeclDefData> switchDeclDefData;
ClangdSwitchDeclDef *switchDeclDef = nullptr;
Utils::optional<LocalRefsData> localRefsData;
Utils::optional<QVersionNumber> versionNumber;
@@ -741,6 +689,7 @@ public:
private:
QIcon icon() const override;
QString text() const override;
};
class ClangdClient::ClangdCompletionAssistProcessor : public LanguageClientCompletionAssistProcessor
@@ -1015,15 +964,6 @@ ClangdClient::ClangdClient(Project *project, const Utils::FilePath &jsonDbDir)
QTC_CHECK(d->runningFindUsages.isEmpty());
});
connect(documentSymbolCache(), &DocumentSymbolCache::gotSymbols, this,
[this](const DocumentUri &uri, const DocumentSymbolsResult &symbols) {
if (!d->switchDeclDefData || d->switchDeclDefData->uri != uri)
return;
d->switchDeclDefData->docSymbols = symbols;
if (d->switchDeclDefData->ast)
d->handleDeclDefSwitchReplies();
});
start();
}
@@ -1682,26 +1622,13 @@ void ClangdClient::switchDeclDef(TextDocument *document, const QTextCursor &curs
qCDebug(clangdLog) << "switch decl/dev requested" << document->filePath()
<< cursor.blockNumber() << cursor.positionInBlock();
d->switchDeclDefData.emplace(++d->nextJobId, document, cursor, editorWidget, callback);
// Retrieve AST and document symbols.
const auto astHandler = [this, id = d->switchDeclDefData->id](const ClangdAstNode &ast,
const MessageId &) {
qCDebug(clangdLog) << "received ast for decl/def switch";
if (!d->switchDeclDefData || d->switchDeclDefData->id != id
|| !d->switchDeclDefData->document)
return;
if (!ast.isValid()) {
d->switchDeclDefData.reset();
return;
}
d->switchDeclDefData->ast = ast;
if (d->switchDeclDefData->docSymbols)
d->handleDeclDefSwitchReplies();
};
d->getAndHandleAst(document, astHandler, AstCallbackMode::SyncIfPossible);
documentSymbolCache()->requestSymbols(d->switchDeclDefData->uri, Schedule::Now);
if (d->switchDeclDef)
delete d->switchDeclDef;
d->switchDeclDef = new ClangdSwitchDeclDef(this, document, cursor, editorWidget, callback);
connect(d->switchDeclDef, &ClangdSwitchDeclDef::done, this, [this] {
delete d->switchDeclDef;
d->switchDeclDef = nullptr;
});
}
void ClangdClient::switchHeaderSource(const Utils::FilePath &filePath, bool inNextSplit)
@@ -1979,35 +1906,6 @@ void ClangdClient::setVirtualRanges(const Utils::FilePath &filePath, const QList
d->highlightingData[doc].virtualRanges = {ranges, revision};
}
void ClangdClient::Private::handleDeclDefSwitchReplies()
{
if (!switchDeclDefData->document) {
switchDeclDefData.reset();
return;
}
// Find the function declaration or definition associated with the cursor.
// For instance, the cursor could be somwehere inside a function body or
// on a function return type, or ...
if (clangdLogAst().isDebugEnabled())
switchDeclDefData->ast->print(0);
const Utils::optional<ClangdAstNode> functionNode = switchDeclDefData->getFunctionNode();
if (!functionNode) {
switchDeclDefData.reset();
return;
}
// Unfortunately, the AST does not contain the location of the actual function name symbol,
// so we have to look for it in the document symbols.
const QTextCursor funcNameCursor = switchDeclDefData->cursorForFunctionName(*functionNode);
if (!funcNameCursor.isNull()) {
q->followSymbol(switchDeclDefData->document.data(), funcNameCursor,
switchDeclDefData->editorWidget, std::move(switchDeclDefData->callback),
true, false);
}
switchDeclDefData.reset();
}
Utils::optional<QString> ClangdClient::Private::getContainingFunctionName(
const ClangdAstPath &astPath, const Range& range)
{
@@ -2551,6 +2449,8 @@ ClangdCompletionItem::SpecialQtType ClangdCompletionItem::getQtType(const Comple
QIcon ClangdCompletionItem::icon() const
{
if (isDeprecated())
return Utils::Icons::WARNING.icon();
const SpecialQtType qtType = getQtType(item());
switch (qtType) {
case SpecialQtType::Signal:
@@ -2566,6 +2466,14 @@ QIcon ClangdCompletionItem::icon() const
return LanguageClientCompletionItem::icon();
}
QString ClangdCompletionItem::text() const
{
const QString clangdValue = LanguageClientCompletionItem::text();
if (isDeprecated())
return "[[deprecated]]" + clangdValue;
return clangdValue;
}
MessageId ClangdClient::Private::getAndHandleAst(const TextDocOrFile &doc,
const AstHandler &astHandler,
AstCallbackMode callbackMode, const Range &range)

View File

@@ -51,6 +51,7 @@ namespace Internal {
class ClangdAstNode;
Q_DECLARE_LOGGING_CATEGORY(clangdLog);
Q_DECLARE_LOGGING_CATEGORY(clangdLogAst);
void setupClangdConfigFile();

View File

@@ -38,6 +38,7 @@
#include <texteditor/codeassist/iassistprovider.h>
#include <texteditor/textdocument.h>
#include <QApplication>
#include <QPointer>
using namespace CppEditor;
@@ -133,6 +134,7 @@ public:
SymbolDataList symbolsToDisplay;
std::set<FilePath> openedFiles;
VirtualFunctionAssistProcessor *virtualFuncAssistProcessor = nullptr;
QMetaObject::Connection focusChangedConnection;
bool finished = false;
};
@@ -143,6 +145,16 @@ ClangdFollowSymbol::ClangdFollowSymbol(ClangdClient *client, const QTextCursor &
d(new Private(this, client, cursor, editorWidget, document->filePath(), callback,
openInSplit))
{
// Abort if the user does something else with the document in the meantime.
connect(document, &TextDocument::contentsChanged, this, &ClangdFollowSymbol::done,
Qt::QueuedConnection);
if (editorWidget) {
connect(editorWidget, &CppEditorWidget::cursorPositionChanged,
this, &ClangdFollowSymbol::done, Qt::QueuedConnection);
}
d->focusChangedConnection = connect(qApp, &QApplication::focusChanged,
this, &ClangdFollowSymbol::done, Qt::QueuedConnection);
// Step 1: Follow the symbol via "Go to Definition". At the same time, request the
// AST node corresponding to the cursor position, so we can find out whether
// we have to look for overrides.
@@ -402,8 +414,10 @@ void ClangdFollowSymbol::Private::handleGotoImplementationResult(
// As soon as we know that there is more than one candidate, we start the code assist
// procedure, to let the user know that things are happening.
if (allLinks.size() > 1 && !virtualFuncAssistProcessor && editorWidget)
if (allLinks.size() > 1 && !virtualFuncAssistProcessor && editorWidget) {
QObject::disconnect(focusChangedConnection);
editorWidget->invokeTextEditorWidgetAssist(FollowSymbol, &virtualFuncAssistProvider);
}
if (!pendingGotoImplRequests.isEmpty())
return;

View File

@@ -0,0 +1,188 @@
/****************************************************************************
**
** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#include "clangdswitchdecldef.h"
#include "clangdast.h"
#include "clangdclient.h"
#include <cppeditor/cppeditorwidget.h>
#include <languageclient/documentsymbolcache.h>
#include <languageserverprotocol/lsptypes.h>
#include <texteditor/textdocument.h>
#include <utils/optional.h>
#include <utils/qtcassert.h>
#include <QApplication>
#include <QTextCursor>
using namespace CppEditor;
using namespace LanguageClient;
using namespace LanguageServerProtocol;
using namespace TextEditor;
using namespace Utils;
namespace ClangCodeModel::Internal {
class ClangdSwitchDeclDef::Private
{
public:
Private(ClangdSwitchDeclDef * q, ClangdClient *client, TextDocument *doc,
const QTextCursor &cursor, CppEditorWidget *editorWidget, const LinkHandler &callback)
: q(q), client(client), document(doc), uri(DocumentUri::fromFilePath(doc->filePath())),
cursor(cursor), editorWidget(editorWidget), callback(callback)
{}
optional<ClangdAstNode> getFunctionNode() const;
QTextCursor cursorForFunctionName(const ClangdAstNode &functionNode) const;
void handleDeclDefSwitchReplies();
ClangdSwitchDeclDef * const q;
ClangdClient * const client;
const QPointer<TextDocument> document;
const DocumentUri uri;
const QTextCursor cursor;
const QPointer<CppEditorWidget> editorWidget;
const LinkHandler callback;
optional<ClangdAstNode> ast;
optional<DocumentSymbolsResult> docSymbols;
};
ClangdSwitchDeclDef::ClangdSwitchDeclDef(ClangdClient *client, TextDocument *doc,
const QTextCursor &cursor, CppEditorWidget *editorWidget, const LinkHandler &callback)
: QObject(client), d(new Private(this, client, doc, cursor, editorWidget, callback))
{
// Abort if the user does something else with the document in the meantime.
connect(doc, &TextDocument::contentsChanged, this, &ClangdSwitchDeclDef::done,
Qt::QueuedConnection);
if (editorWidget) {
connect(editorWidget, &CppEditorWidget::cursorPositionChanged,
this, &ClangdSwitchDeclDef::done, Qt::QueuedConnection);
}
connect(qApp, &QApplication::focusChanged,
this, &ClangdSwitchDeclDef::done, Qt::QueuedConnection);
connect(client->documentSymbolCache(), &DocumentSymbolCache::gotSymbols, this,
[this](const DocumentUri &uri, const DocumentSymbolsResult &symbols) {
if (uri != d->uri)
return;
d->docSymbols = symbols;
if (d->ast)
d->handleDeclDefSwitchReplies();
});
// Retrieve AST and document symbols.
const auto astHandler = [this, self = QPointer(this)]
(const ClangdAstNode &ast, const MessageId &) {
qCDebug(clangdLog) << "received ast for decl/def switch";
if (!self)
return;
if (!d->document) {
emit done();
return;
}
if (!ast.isValid()) {
emit done();
return;
}
d->ast = ast;
if (d->docSymbols)
d->handleDeclDefSwitchReplies();
};
client->getAndHandleAst(doc, astHandler, ClangdClient::AstCallbackMode::SyncIfPossible, {});
client->documentSymbolCache()->requestSymbols(d->uri, Schedule::Now);
}
ClangdSwitchDeclDef::~ClangdSwitchDeclDef()
{
delete d;
}
optional<ClangdAstNode> ClangdSwitchDeclDef::Private::getFunctionNode() const
{
QTC_ASSERT(ast, return {});
const ClangdAstPath path = getAstPath(*ast, Range(cursor));
for (auto it = path.rbegin(); it != path.rend(); ++it) {
if (it->role() == "declaration"
&& (it->kind() == "CXXMethod" || it->kind() == "CXXConversion"
|| it->kind() == "CXXConstructor" || it->kind() == "CXXDestructor"
|| it->kind() == "Function")) {
return *it;
}
}
return {};
}
QTextCursor ClangdSwitchDeclDef::Private::cursorForFunctionName(const ClangdAstNode &functionNode) const
{
QTC_ASSERT(docSymbols, return {});
const auto symbolList = Utils::get_if<QList<DocumentSymbol>>(&*docSymbols);
if (!symbolList)
return {};
const Range &astRange = functionNode.range();
QList symbolsToCheck = *symbolList;
while (!symbolsToCheck.isEmpty()) {
const DocumentSymbol symbol = symbolsToCheck.takeFirst();
if (symbol.range() == astRange)
return symbol.selectionRange().start().toTextCursor(document->document());
if (symbol.range().contains(astRange))
symbolsToCheck << symbol.children().value_or(QList<DocumentSymbol>());
}
return {};
}
void ClangdSwitchDeclDef::Private::handleDeclDefSwitchReplies()
{
if (!document) {
emit q->done();
return;
}
// Find the function declaration or definition associated with the cursor.
// For instance, the cursor could be somwehere inside a function body or
// on a function return type, or ...
if (clangdLogAst().isDebugEnabled())
ast->print(0);
const Utils::optional<ClangdAstNode> functionNode = getFunctionNode();
if (!functionNode) {
emit q->done();
return;
}
// Unfortunately, the AST does not contain the location of the actual function name symbol,
// so we have to look for it in the document symbols.
const QTextCursor funcNameCursor = cursorForFunctionName(*functionNode);
if (!funcNameCursor.isNull()) {
client->followSymbol(document.data(), funcNameCursor, editorWidget, callback,
true, false);
}
emit q->done();
}
} // namespace ClangCodeModel::Internal

View File

@@ -0,0 +1,59 @@
/****************************************************************************
**
** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#pragma once
#include <utils/link.h>
#include <QObject>
namespace CppEditor { class CppEditorWidget; }
namespace TextEditor { class TextDocument; }
QT_BEGIN_NAMESPACE
class QTextCursor;
QT_END_NAMESPACE
namespace ClangCodeModel::Internal {
class ClangdClient;
class ClangdSwitchDeclDef : public QObject
{
Q_OBJECT
public:
ClangdSwitchDeclDef(ClangdClient *client, TextEditor::TextDocument *doc,
const QTextCursor &cursor, CppEditor::CppEditorWidget *editorWidget,
const Utils::LinkHandler &callback);
~ClangdSwitchDeclDef();
signals:
void done();
private:
class Private;
Private * const d;
};
} // namespace ClangCodeModel::Internal

View File

@@ -62,10 +62,12 @@
#include <projectexplorer/taskhub.h>
#include <utils/algorithm.h>
#include <utils/infobar.h>
#include <utils/qtcassert.h>
#include <utils/runextensions.h>
#include <QApplication>
#include <QLabel>
#include <QMenu>
#include <QTextBlock>
#include <QTimer>
@@ -124,6 +126,40 @@ static Client *clientForGeneratedFile(const Utils::FilePath &filePath)
return nullptr;
}
static void checkSystemForClangdSuitability()
{
if (ClangdSettings::haveCheckedHardwareRequirements())
return;
if (ClangdSettings::hardwareFulfillsRequirements())
return;
ClangdSettings::setUseClangd(false);
const QString warnStr = ClangModelManagerSupport::tr("The use of clangd for the C/C++ "
"code model was disabled, because it is likely that its memory requirements "
"would be higher than what your system can handle.");
const Utils::Id clangdWarningSetting("WarnAboutClangd");
Utils::InfoBarEntry info(clangdWarningSetting, warnStr);
info.setDetailsWidgetCreator([] {
const auto label = new QLabel(ClangModelManagerSupport::tr(
"With clangd enabled, Qt Creator fully supports modern C++ "
"when highlighting code, completing symbols and so on.<br>"
"This comes at a higher cost in terms of CPU load and memory usage compared "
"to the built-in code model, which therefore might be the better choice "
"on older machines and/or with legacy code.<br>"
"You can enable/disable and fine-tune clangd <a href=\"dummy\">here</a>."));
label->setWordWrap(true);
QObject::connect(label, &QLabel::linkActivated, [] {
Core::ICore::showOptionsDialog(CppEditor::Constants::CPP_CLANGD_SETTINGS_ID);
});
return label;
});
info.addCustomButton(ClangModelManagerSupport::tr("Enable Anyway"), [clangdWarningSetting] {
ClangdSettings::setUseClangd(true);
Core::ICore::infoBar()->removeInfo(clangdWarningSetting);
});
Core::ICore::infoBar()->addInfo(info);
}
ClangModelManagerSupport::ClangModelManagerSupport()
{
QTC_CHECK(!m_instance);
@@ -132,6 +168,7 @@ ClangModelManagerSupport::ClangModelManagerSupport()
watchForExternalChanges();
watchForInternalChanges();
setupClangdConfigFile();
checkSystemForClangdSuitability();
cppModelManager()->setCurrentDocumentFilter(std::make_unique<ClangdCurrentDocumentFilter>());
cppModelManager()->setLocatorFilter(std::make_unique<ClangGlobalSymbolFilter>());
cppModelManager()->setClassesFilter(std::make_unique<ClangClassesFilter>());

View File

@@ -29,7 +29,6 @@
#include "clangdclient.h"
#include "clangdiagnostictooltipwidget.h"
#include "clangeditordocumentprocessor.h"
#include "clangmodelmanagersupport.h"
#include "clangutils.h"
#include <coreplugin/icore.h>
@@ -42,12 +41,11 @@
#include <utils/fadingindicator.h>
#include <utils/qtcassert.h>
#include <utils/stringutils.h>
#include <utils/theme/theme.h>
#include <utils/utilsicons.h>
#include <QAction>
#include <QApplication>
#include <QClipboard>
#include <QLayout>
#include <QRegularExpression>
#include <QRegularExpressionMatch>
@@ -319,7 +317,7 @@ ClangdTextMark::ClangdTextMark(const FilePath &filePath,
QObject::connect(action, &QAction::triggered, [diag = m_diagnostic]() {
const QString text = ClangDiagnosticWidget::createText({diag},
ClangDiagnosticWidget::InfoBar);
QApplication::clipboard()->setText(text, QClipboard::Clipboard);
setClipboardAndSelection(text);
});
actions << action;

View File

@@ -132,7 +132,7 @@ void ClangToolRunner::onProcessDone()
if (m_process.result() == ProcessResult::StartFailed) {
emit finishedWithFailure(generalProcessError(m_name), commandlineAndOutput());
} else if (m_process.result() == ProcessResult::FinishedWithSuccess) {
qCDebug(LOG).noquote() << "Output:\n" << m_process.stdOut();
qCDebug(LOG).noquote() << "Output:\n" << m_process.cleanedStdOut();
emit finishedWithSuccess(m_fileToAnalyze);
} else if (m_process.result() == ProcessResult::FinishedWithError) {
emit finishedWithFailure(finishedWithBadExitCode(m_name, m_process.exitCode()),
@@ -149,7 +149,7 @@ QString ClangToolRunner::commandlineAndOutput() const
"Output:\n%3")
.arg(m_commandLine.toUserOutput())
.arg(m_process.error())
.arg(m_process.stdOut());
.arg(m_process.cleanedStdOut());
}
} // namespace Internal

View File

@@ -30,10 +30,9 @@
#include "diagnosticconfigswidget.h"
#include <utils/utilsicons.h>
#include <utils/stringutils.h>
#include <QAction>
#include <QApplication>
#include <QClipboard>
namespace ClangTools {
namespace Internal {
@@ -65,7 +64,7 @@ DiagnosticMark::DiagnosticMark(const Diagnostic &diagnostic)
const QString text = createFullLocationString(diagnostic.location)
+ ": "
+ diagnostic.description;
QApplication::clipboard()->setText(text);
Utils::setClipboardAndSelection(text);
});
actions << action;

View File

@@ -251,6 +251,8 @@ QPair<FilePath, QString> getClangIncludeDirAndVersion(ClangToolRunner *runner)
void DocumentClangToolRunner::runNext()
{
if (m_currentRunner)
m_currentRunner.release()->deleteLater();
m_currentRunner.reset(m_runnerCreators.isEmpty() ? nullptr : m_runnerCreators.takeFirst()());
if (m_currentRunner) {
auto [clangIncludeDir, clangVersion] = getClangIncludeDirAndVersion(m_currentRunner.get());
@@ -362,10 +364,7 @@ void DocumentClangToolRunner::cancel()
if (m_projectSettingsUpdate)
disconnect(m_projectSettingsUpdate);
m_runnerCreators.clear();
if (m_currentRunner) {
m_currentRunner->disconnect(this);
m_currentRunner.reset(nullptr);
}
}
bool DocumentClangToolRunner::isSuppressed(const Diagnostic &diagnostic) const

View File

@@ -63,7 +63,7 @@ static QString runExecutable(const Utils::CommandLine &commandLine, QueryFailMod
return {};
}
return cpp.stdOut();
return cpp.cleanedStdOut();
}
static QStringList queryClangTidyChecks(const FilePath &executable,

View File

@@ -1676,8 +1676,8 @@ ClearCasePluginPrivate::runCleartool(const FilePath &workingDir,
response.error = proc.result() != ProcessResult::FinishedWithSuccess;
if (response.error)
response.message = proc.exitMessage();
response.stdErr = proc.stdErr();
response.stdOut = proc.stdOut();
response.stdErr = proc.cleanedStdErr();
response.stdOut = proc.cleanedStdOut();
return response;
}

View File

@@ -280,19 +280,19 @@ TextEditor::Keywords CMakeTool::keywords()
QtcProcess proc;
runCMake(proc, {"--help-command-list"}, 5);
if (proc.result() == ProcessResult::FinishedWithSuccess)
m_introspection->m_functions = proc.stdOut().split('\n');
m_introspection->m_functions = proc.cleanedStdOut().split('\n');
runCMake(proc, {"--help-commands"}, 5);
if (proc.result() == ProcessResult::FinishedWithSuccess)
parseFunctionDetailsOutput(proc.stdOut());
parseFunctionDetailsOutput(proc.cleanedStdOut());
runCMake(proc, {"--help-property-list"}, 5);
if (proc.result() == ProcessResult::FinishedWithSuccess)
m_introspection->m_variables = parseVariableOutput(proc.stdOut());
m_introspection->m_variables = parseVariableOutput(proc.cleanedStdOut());
runCMake(proc, {"--help-variable-list"}, 5);
if (proc.result() == ProcessResult::FinishedWithSuccess) {
m_introspection->m_variables.append(parseVariableOutput(proc.stdOut()));
m_introspection->m_variables.append(parseVariableOutput(proc.cleanedStdOut()));
m_introspection->m_variables = Utils::filteredUnique(m_introspection->m_variables);
Utils::sort(m_introspection->m_variables);
}
@@ -523,7 +523,7 @@ void CMakeTool::fetchFromCapabilities() const
if (cmake.result() == ProcessResult::FinishedWithSuccess) {
m_introspection->m_didRun = true;
parseFromCapabilities(cmake.stdOut());
parseFromCapabilities(cmake.cleanedStdOut());
} else {
qCCritical(cmakeToolLog) << "Fetching capabilities failed: " << cmake.allOutput() << cmake.error();
m_introspection->m_didRun = false;

View File

@@ -402,18 +402,18 @@ RawProjectParts generateRawProjectParts(const PreprocessedData &input,
const bool hasPchSource = anyOf(sources, [buildDirectory](const QString &path) {
return isPchFile(buildDirectory, FilePath::fromString(path));
});
if (!hasPchSource) {
QString headerMimeType;
if (ci.language == "C")
headerMimeType = CppEditor::Constants::C_HEADER_MIMETYPE;
else if (ci.language == "CXX")
headerMimeType = CppEditor::Constants::CPP_HEADER_MIMETYPE;
if (!hasPchSource) {
for (const SourceInfo &si : t.sources) {
if (si.isGenerated)
continue;
const auto mimeTypes = Utils::mimeTypesForFileName(si.path);
for (auto mime : mimeTypes)
for (const auto &mime : mimeTypes)
if (mime.name() == headerMimeType)
sources.push_back(sourceDir.absoluteFilePath(si.path));
}
@@ -422,7 +422,13 @@ RawProjectParts generateRawProjectParts(const PreprocessedData &input,
// Set project files except pch files
rpp.setFiles(Utils::filtered(sources, [buildDirectory](const QString &path) {
return !isPchFile(buildDirectory, FilePath::fromString(path));
}));
}), {}, [headerMimeType](const QString &path) {
// Similar to ProjectFile::classify but classify headers with language
// of compile group instead of ambiguous header
if (path.endsWith(".h"))
return headerMimeType;
return Utils::mimeTypeForFile(path).name();
});
FilePath precompiled_header
= FilePath::fromString(findOrDefault(t.sources, [&ending](const SourceInfo &si) {

View File

@@ -36,6 +36,7 @@
#include <projectexplorer/toolchain.h>
#include <projectexplorer/toolchainmanager.h>
#include <utils/algorithm.h>
#include <utils/hostosinfo.h>
#include <QtTest>
@@ -239,6 +240,7 @@ void CompilationDatabaseTests::testFilterCommand()
"SemaCodeComplete");
testData.getFilteredFlags();
if (Utils::HostOsInfo::isWindowsHost()) {
QCOMPARE(testData.flags,
(QStringList{"/Zc:inline", "/Zc:strictStrings", "/Zc:rvalueCast", "/Zi"}));
QCOMPARE(testData.headerPaths,
@@ -246,6 +248,7 @@ void CompilationDatabaseTests::testFilterCommand()
QCOMPARE(testData.macros, (Macros{{"UNICODE", "1"}, {"_HAS_EXCEPTIONS", "0"}, {"WIN32", "1"},
{"_WINDOWS", "1"}}));
QCOMPARE(testData.fileKind, CppEditor::ProjectFile::Kind::CXXSource);
}
}
void CompilationDatabaseTests::testFileKindDifferentFromExtension()

View File

@@ -206,7 +206,7 @@ void filteredFlags(const QString &fileName,
}
// Skip all remaining Windows flags except feature flags.
if (flag.startsWith("/") && !flag.startsWith("/Z"))
if (Utils::HostOsInfo::isWindowsHost() && flag.startsWith("/") && !flag.startsWith("/Z"))
continue;
filtered.push_back(flag);

View File

@@ -830,8 +830,7 @@ FilePath DocumentManager::getSaveFileName(const QString &title, const FilePath &
bool repeat;
do {
repeat = false;
filePath = FileUtils::getSaveFilePath(nullptr, title, path, filter, selectedFilter,
QFileDialog::DontConfirmOverwrite);
filePath = FileUtils::getSaveFilePath(nullptr, title, path, filter, selectedFilter);
if (!filePath.isEmpty()) {
// If the selected filter is All Files (*) we leave the name exactly as the user
// specified. Otherwise the suffix must be one available in the selected filter. If
@@ -852,10 +851,8 @@ FilePath DocumentManager::getSaveFileName(const QString &title, const FilePath &
suffixOk = true;
break;
}
if (!suffixOk && !suffixes.isEmpty())
if (!suffixOk && !suffixes.isEmpty()) {
filePath = filePath.stringAppended(suffixes.at(0));
}
}
if (filePath.exists()) {
if (QMessageBox::warning(ICore::dialogParent(), tr("Overwrite?"),
tr("An item named \"%1\" already exists at this location. "
@@ -865,6 +862,10 @@ FilePath DocumentManager::getSaveFileName(const QString &title, const FilePath &
}
}
}
}
}
}
} while (repeat);
if (!filePath.isEmpty())
setFileDialogLastVisitedDirectory(filePath.absolutePath());

View File

@@ -132,16 +132,10 @@ void ExecuteFilter::accept(const LocatorFilterEntry &selection,
p->runHeadCommand();
}
void ExecuteFilter::finished()
void ExecuteFilter::done()
{
QTC_ASSERT(m_process, return);
const QString commandName = headCommand();
QString message;
if (m_process->result() == ProcessResult::FinishedWithSuccess)
message = tr("Command \"%1\" finished.").arg(commandName);
else
message = tr("Command \"%1\" failed.").arg(commandName);
MessageManager::writeFlashing(message);
MessageManager::writeFlashing(m_process->exitMessage());
removeProcess();
runHeadCommand();
@@ -180,12 +174,6 @@ void ExecuteFilter::runHeadCommand()
m_process->setWorkingDirectory(d.workingDirectory);
m_process->setCommand(d.command);
m_process->start();
if (!m_process->waitForStarted(1000)) {
MessageManager::writeFlashing(
tr("Could not start process: %1.").arg(m_process->errorString()));
removeProcess();
runHeadCommand();
}
}
}
@@ -196,7 +184,7 @@ void ExecuteFilter::createProcess()
m_process = new Utils::QtcProcess;
m_process->setEnvironment(Utils::Environment::systemEnvironment());
connect(m_process, &QtcProcess::finished, this, &ExecuteFilter::finished);
connect(m_process, &QtcProcess::done, this, &ExecuteFilter::done);
connect(m_process, &QtcProcess::readyReadStandardOutput, this, &ExecuteFilter::readStandardOutput);
connect(m_process, &QtcProcess::readyReadStandardError, this, &ExecuteFilter::readStandardError);
}
@@ -207,7 +195,7 @@ void ExecuteFilter::removeProcess()
return;
m_taskQueue.dequeue();
delete m_process;
m_process->deleteLater();
m_process = nullptr;
}

View File

@@ -57,7 +57,7 @@ public:
QString *newText, int *selectionStart, int *selectionLength) const override;
private:
void finished();
void done();
void readStandardOutput();
void readStandardError();
void runHeadCommand();

View File

@@ -28,7 +28,6 @@
#include <utils/hostosinfo.h>
#include <utils/qtcassert.h>
#include <utils/qtcprocess.h>
#include <coreplugin/messagemanager.h>
@@ -37,11 +36,9 @@ using namespace Utils;
namespace Cppcheck {
namespace Internal {
CppcheckRunner::CppcheckRunner(CppcheckTool &tool) :
m_tool(tool),
m_process(new Utils::QtcProcess(this))
CppcheckRunner::CppcheckRunner(CppcheckTool &tool) : m_tool(tool)
{
if (Utils::HostOsInfo::hostOs() == Utils::OsTypeLinux) {
if (HostOsInfo::hostOs() == OsTypeLinux) {
QtcProcess getConf;
getConf.setCommand({"getconf", {"ARG_MAX"}});
getConf.start();
@@ -50,17 +47,15 @@ CppcheckRunner::CppcheckRunner(CppcheckTool &tool) :
m_maxArgumentsLength = std::max(argMax.toInt(), m_maxArgumentsLength);
}
m_process->setStdOutLineCallback([this](const QString &line) {
m_process.setStdOutLineCallback([this](const QString &line) {
m_tool.parseOutputLine(line);
});
m_process->setStdErrLineCallback([this](const QString &line) {
m_process.setStdErrLineCallback([this](const QString &line) {
m_tool.parseErrorLine(line);
});
connect(m_process, &QtcProcess::started,
this, &CppcheckRunner::handleStarted);
connect(m_process, &QtcProcess::finished,
this, &CppcheckRunner::handleFinished);
connect(&m_process, &QtcProcess::started, &m_tool, &CppcheckTool::startParsing);
connect(&m_process, &QtcProcess::done, this, &CppcheckRunner::handleDone);
m_queueTimer.setSingleShot(true);
const int checkDelayInMs = 200;
@@ -81,18 +76,18 @@ void CppcheckRunner::reconfigure(const FilePath &binary, const QString &argument
m_arguments = arguments;
}
void CppcheckRunner::addToQueue(const Utils::FilePaths &files,
void CppcheckRunner::addToQueue(const FilePaths &files,
const QString &additionalArguments)
{
Utils::FilePaths &existing = m_queue[additionalArguments];
FilePaths &existing = m_queue[additionalArguments];
if (existing.isEmpty()) {
existing = files;
} else {
std::copy_if(files.cbegin(), files.cend(), std::back_inserter(existing),
[&existing](const Utils::FilePath &file) { return !existing.contains(file); });
[&existing](const FilePath &file) { return !existing.contains(file); });
}
if (m_isRunning) {
if (m_process.isRunning()) {
stop(existing);
return;
}
@@ -100,16 +95,16 @@ void CppcheckRunner::addToQueue(const Utils::FilePaths &files,
m_queueTimer.start();
}
void CppcheckRunner::stop(const Utils::FilePaths &files)
void CppcheckRunner::stop(const FilePaths &files)
{
if (!m_isRunning)
if (!m_process.isRunning())
return;
if (files.isEmpty() || m_currentFiles == files)
m_process->kill();
m_process.stop();
}
void CppcheckRunner::removeFromQueue(const Utils::FilePaths &files)
void CppcheckRunner::removeFromQueue(const FilePaths &files)
{
if (m_queue.isEmpty())
return;
@@ -118,21 +113,21 @@ void CppcheckRunner::removeFromQueue(const Utils::FilePaths &files)
m_queue.clear();
} else {
for (auto it = m_queue.begin(), end = m_queue.end(); it != end;) {
for (const Utils::FilePath &file : files)
for (const FilePath &file : files)
it.value().removeOne(file);
it = !it.value().isEmpty() ? ++it : m_queue.erase(it);
}
}
}
const Utils::FilePaths &CppcheckRunner::currentFiles() const
const FilePaths &CppcheckRunner::currentFiles() const
{
return m_currentFiles;
}
QString CppcheckRunner::currentCommand() const
{
return m_process->commandLine().toUserOutput();
return m_process.commandLine().toUserOutput();
}
void CppcheckRunner::checkQueued()
@@ -140,7 +135,7 @@ void CppcheckRunner::checkQueued()
if (m_queue.isEmpty() || m_binary.isEmpty())
return;
Utils::FilePaths files = m_queue.begin().value();
FilePaths files = m_queue.begin().value();
QString arguments = m_arguments + ' ' + m_queue.begin().key();
m_currentFiles.clear();
int argumentsLength = arguments.length();
@@ -158,30 +153,19 @@ void CppcheckRunner::checkQueued()
else
m_queue.begin().value() = files;
m_process->setCommand(CommandLine(m_binary, arguments, CommandLine::Raw));
m_process->start();
m_process.setCommand(CommandLine(m_binary, arguments, CommandLine::Raw));
m_process.start();
}
void CppcheckRunner::handleStarted()
void CppcheckRunner::handleDone()
{
if (m_isRunning)
return;
m_isRunning = true;
m_tool.startParsing();
}
void CppcheckRunner::handleFinished()
{
if (m_process->error() != QProcess::FailedToStart) {
if (m_process.result() == ProcessResult::FinishedWithSuccess)
m_tool.finishParsing();
} else {
const QString message = tr("Cppcheck failed to start: \"%1\".").arg(currentCommand());
Core::MessageManager::writeSilently(message);
}
else
Core::MessageManager::writeSilently(m_process.exitMessage());
m_currentFiles.clear();
m_process->close();
m_isRunning = false;
m_process.close();
if (!m_queue.isEmpty())
checkQueued();

View File

@@ -26,12 +26,11 @@
#pragma once
#include <utils/filepath.h>
#include <utils/qtcprocess.h>
#include <QHash>
#include <QTimer>
namespace Utils { class QtcProcess; }
namespace Cppcheck {
namespace Internal {
@@ -58,18 +57,16 @@ private:
void checkQueued();
void readOutput();
void readError();
void handleStarted();
void handleFinished();
void handleDone();
CppcheckTool &m_tool;
Utils::QtcProcess *m_process = nullptr;
Utils::QtcProcess m_process;
Utils::FilePath m_binary;
QString m_arguments;
QHash<QString, Utils::FilePaths> m_queue;
Utils::FilePaths m_currentFiles;
QTimer m_queueTimer;
int m_maxArgumentsLength = 32767;
bool m_isRunning = false;
};
} // namespace Internal

View File

@@ -34,6 +34,7 @@
#include <projectexplorer/session.h>
#include <utils/algorithm.h>
#include <utils/hostosinfo.h>
#include <utils/qtcassert.h>
#include <utils/qtcprocess.h>
#include <utils/settingsutils.h>
@@ -81,6 +82,7 @@ static QString clangdSizeThresholdKey() { return QLatin1String("ClangdSizeThresh
static QString clangdUseGlobalSettingsKey() { return QLatin1String("useGlobalSettings"); }
static QString sessionsWithOneClangdKey() { return QLatin1String("SessionsWithOneClangd"); }
static QString diagnosticConfigIdKey() { return QLatin1String("diagnosticConfigId"); }
static QString checkedHardwareKey() { return QLatin1String("checkedHardware"); }
static FilePath g_defaultClangdFilePath;
static FilePath fallbackClangdFilePath()
@@ -206,6 +208,22 @@ bool ClangdSettings::useClangd() const
return m_data.useClangd && clangdVersion() >= QVersionNumber(14);
}
void ClangdSettings::setUseClangd(bool use) { instance().m_data.useClangd = use; }
bool ClangdSettings::hardwareFulfillsRequirements()
{
instance().m_data.haveCheckedHardwareReqirements = true;
instance().saveSettings();
const quint64 minRam = quint64(12) * 1024 * 1024 * 1024;
const Utils::optional<quint64> totalRam = Utils::HostOsInfo::totalMemoryInstalledInBytes();
return !totalRam || *totalRam >= minRam;
}
bool ClangdSettings::haveCheckedHardwareRequirements()
{
return instance().data().haveCheckedHardwareReqirements;
}
void ClangdSettings::setDefaultClangdPath(const FilePath &filePath)
{
g_defaultClangdFilePath = filePath;
@@ -350,8 +368,6 @@ void ClangdSettings::saveSettings()
}
#ifdef WITH_TESTS
void ClangdSettings::setUseClangd(bool use) { instance().m_data.useClangd = use; }
void ClangdSettings::setClangdFilePath(const FilePath &filePath)
{
instance().m_data.executableFilePath = filePath;
@@ -435,6 +451,7 @@ QVariantMap ClangdSettings::Data::toMap() const
map.insert(clangdSizeThresholdKey(), sizeThresholdInKb);
map.insert(sessionsWithOneClangdKey(), sessionsWithOneClangd);
map.insert(diagnosticConfigIdKey(), diagnosticConfigId.toSetting());
map.insert(checkedHardwareKey(), true);
return map;
}
@@ -451,6 +468,7 @@ void ClangdSettings::Data::fromMap(const QVariantMap &map)
sessionsWithOneClangd = map.value(sessionsWithOneClangdKey()).toStringList();
diagnosticConfigId = Id::fromSetting(map.value(diagnosticConfigIdKey(),
initialClangDiagnosticConfigId().toSetting()));
haveCheckedHardwareReqirements = map.value(checkedHardwareKey(), false).toBool();
}
} // namespace CppEditor

View File

@@ -111,7 +111,8 @@ public:
&& s1.autoIncludeHeaders == s2.autoIncludeHeaders
&& s1.documentUpdateThreshold == s2.documentUpdateThreshold
&& s1.sizeThresholdEnabled == s2.sizeThresholdEnabled
&& s1.sizeThresholdInKb == s2.sizeThresholdInKb;
&& s1.sizeThresholdInKb == s2.sizeThresholdInKb
&& s1.haveCheckedHardwareReqirements == s2.haveCheckedHardwareReqirements;
}
friend bool operator!=(const Data &s1, const Data &s2) { return !(s1 == s2); }
@@ -126,12 +127,17 @@ public:
bool enableIndexing = true;
bool autoIncludeHeaders = false;
bool sizeThresholdEnabled = false;
bool haveCheckedHardwareReqirements = false;
};
ClangdSettings(const Data &data) : m_data(data) {}
static ClangdSettings &instance();
bool useClangd() const;
static void setUseClangd(bool use);
static bool hardwareFulfillsRequirements();
static bool haveCheckedHardwareRequirements();
static void setDefaultClangdPath(const Utils::FilePath &filePath);
static void setCustomDiagnosticConfigs(const ClangDiagnosticConfigs &configs);
@@ -159,7 +165,6 @@ public:
static Utils::FilePath clangdUserConfigFilePath();
#ifdef WITH_TESTS
static void setUseClangd(bool use);
static void setClangdFilePath(const Utils::FilePath &filePath);
#endif

View File

@@ -135,6 +135,12 @@ static const char *DEFAULT_CODE_STYLE_SNIPPETS[]
"private:\n"
" int _a;\n"
" };\n"
"enum class E\n"
"{\n"
" V1,\n"
" V2,\n"
" V3\n"
"};\n"
"}\n"
"}\n",
"#include \"bar.h\"\n"

View File

@@ -50,7 +50,9 @@
#include <utils/minimizableinfobars.h>
#include <utils/qtcassert.h>
#include <utils/runextensions.h>
#include <utils/utilsicons.h>
#include <QApplication>
#include <QTextDocument>
const char NO_PROJECT_CONFIGURATION[] = "NoProject";
@@ -121,6 +123,9 @@ CppEditorDocument::CppEditorDocument()
connect(this, &IDocument::filePathChanged,
this, &CppEditorDocument::onFilePathChanged);
connect(mm(), &CppModelManager::diagnosticsChanged,
this, &CppEditorDocument::onDiagnosticsChanged);
connect(&m_parseContextModel, &ParseContextModel::preferredParseContextChanged,
this, &CppEditorDocument::reparseWithPreferredParseContext);
@@ -483,5 +488,51 @@ bool CppEditorDocument::save(QString *errorString, const FilePath &filePath, boo
return TextEditor::TextDocument::save(errorString, filePath, autoSave);
}
void CppEditorDocument::onDiagnosticsChanged(const QString &fileName, const QString &kind)
{
if (FilePath::fromString(fileName) != filePath())
return;
TextMarks removedMarks = marks();
const Utils::Id category = Utils::Id::fromString(kind);
for (const auto &diagnostic : mm()->diagnosticMessages()) {
if (FilePath::fromString(diagnostic.fileName()) == filePath()) {
auto it = std::find_if(std::begin(removedMarks),
std::end(removedMarks),
[&category, &diagnostic](TextMark *existing) {
return (diagnostic.line() == existing->lineNumber()
&& diagnostic.text() == existing->lineAnnotation()
&& category == existing->category());
});
if (it != std::end(removedMarks)) {
removedMarks.erase(it);
continue;
}
auto mark = new TextMark(filePath(), diagnostic.line(), category);
mark->setLineAnnotation(diagnostic.text());
mark->setToolTip(diagnostic.text());
mark->setIcon(diagnostic.isWarning() ? Utils::Icons::CODEMODEL_WARNING.icon()
: Utils::Icons::CODEMODEL_ERROR.icon());
mark->setColor(diagnostic.isWarning() ? Utils::Theme::CodeModel_Warning_TextMarkColor
: Utils::Theme::CodeModel_Error_TextMarkColor);
mark->setPriority(diagnostic.isWarning() ? TextEditor::TextMark::NormalPriority
: TextEditor::TextMark::HighPriority);
addMark(mark);
}
}
for (auto it = removedMarks.begin(); it != removedMarks.end(); ++it) {
if ((*it)->category() == category) {
removeMark(*it);
delete *it;
}
}
}
} // namespace Internal
} // namespace CppEditor

View File

@@ -94,6 +94,8 @@ private:
void onAboutToReload();
void onReloadFinished();
void onDiagnosticsChanged(const QString &fileName, const QString &kind);
void reparseWithPreferredParseContext(const QString &id);

View File

@@ -201,6 +201,8 @@ public:
std::unique_ptr<Core::ILocatorFilter> m_functionsFilter;
std::unique_ptr<Core::IFindFilter> m_symbolsFindFilter;
std::unique_ptr<Core::ILocatorFilter> m_currentDocumentFilter;
QList<Document::DiagnosticMessage> m_diagnosticMessages;
};
} // namespace Internal
@@ -1704,4 +1706,18 @@ QThreadPool *CppModelManager::sharedThreadPool()
return &d->m_threadPool;
}
bool CppModelManager::setExtraDiagnostics(const QString &fileName,
const QString &kind,
const QList<Document::DiagnosticMessage> &diagnostics)
{
d->m_diagnosticMessages = diagnostics;
emit diagnosticsChanged(fileName, kind);
return true;
}
const QList<Document::DiagnosticMessage> CppModelManager::diagnosticMessages()
{
return d->m_diagnosticMessages;
}
} // namespace CppEditor

View File

@@ -104,6 +104,12 @@ public:
QByteArray codeModelConfiguration() const;
CppLocatorData *locatorData() const;
bool setExtraDiagnostics(const QString &fileName,
const QString &kind,
const QList<Document::DiagnosticMessage> &diagnostics) override;
const QList<Document::DiagnosticMessage> diagnosticMessages();
QList<ProjectInfo::ConstPtr> projectInfos() const;
ProjectInfo::ConstPtr projectInfo(ProjectExplorer::Project *project) const;
QFuture<void> updateProjectInfo(const ProjectInfo::ConstPtr &newProjectInfo,
@@ -256,6 +262,8 @@ signals:
void abstractEditorSupportRemoved(const QString &filePath);
void fallbackProjectPartUpdated();
void diagnosticsChanged(const QString &fileName, const QString &kind);
public slots:
void updateModifiedSourceFiles();
void GC();

View File

@@ -87,7 +87,8 @@ const QVector<ProjectPart::ConstPtr> ProjectInfoGenerator::createProjectParts(
QVector<ProjectPart::ConstPtr> result;
ProjectFileCategorizer cat(rawProjectPart.displayName,
rawProjectPart.files,
rawProjectPart.fileIsActive);
rawProjectPart.fileIsActive,
rawProjectPart.getMimeType);
if (!cat.hasParts())
return result;

View File

@@ -1449,8 +1449,8 @@ CvsResponse CvsPluginPrivate::runCvs(const FilePath &workingDirectory,
command.runCommand(proc, {executable, m_settings.addOptions(arguments)});
response.result = CvsResponse::OtherError;
response.stdErr = proc.stdErr();
response.stdOut = proc.stdOut();
response.stdErr = proc.cleanedStdErr();
response.stdOut = proc.cleanedStdOut();
switch (proc.result()) {
case ProcessResult::FinishedWithSuccess:
response.result = CvsResponse::Ok;

View File

@@ -30,12 +30,12 @@
#include <coreplugin/editormanager/editormanager.h>
#include <utils/qtcassert.h>
#include <utils/stringutils.h>
#include <utils/utilsicons.h>
#include <QApplication>
#include <QAbstractTextDocumentLayout>
#include <QAction>
#include <QApplication>
#include <QClipboard>
#include <QContextMenuEvent>
#include <QFileInfo>
#include <QHeaderView>
@@ -54,12 +54,12 @@ DetailedErrorView::DetailedErrorView(QWidget *parent) :
m_copyAction->setIcon(Utils::Icons::COPY.icon());
m_copyAction->setShortcut(QKeySequence::Copy);
m_copyAction->setShortcutContext(Qt::WidgetWithChildrenShortcut);
connect(m_copyAction, &QAction::triggered, [this] {
connect(m_copyAction, &QAction::triggered, this, [this] {
const QModelIndexList selectedRows = selectionModel()->selectedRows();
QStringList data;
for (const QModelIndex &index : selectedRows)
data << model()->data(index, FullTextRole).toString();
QApplication::clipboard()->setText(data.join('\n'));
Utils::setClipboardAndSelection(data.join('\n'));
});
connect(this, &QAbstractItemView::clicked, [](const QModelIndex &index) {
if (index.column() == LocationColumn) {

Some files were not shown because too many files have changed in this diff Show More