forked from qt-creator/qt-creator
Merge remote-tracking branch 'origin/8.0'
Change-Id: I3f218b52bf6904daca3779fb677e51f6f51f2f9f
This commit is contained in:
2
.github/workflows/build_cmake.yml
vendored
2
.github/workflows/build_cmake.yml
vendored
@@ -7,7 +7,7 @@ on:
|
|||||||
- 'doc/**'
|
- 'doc/**'
|
||||||
|
|
||||||
env:
|
env:
|
||||||
QT_VERSION: 6.3.0
|
QT_VERSION: 6.3.1
|
||||||
CLANG_VERSION: 14.0.3
|
CLANG_VERSION: 14.0.3
|
||||||
ELFUTILS_VERSION: 0.175
|
ELFUTILS_VERSION: 0.175
|
||||||
CMAKE_VERSION: 3.21.1
|
CMAKE_VERSION: 3.21.1
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
set(IDE_VERSION "7.82.0") # The IDE version.
|
set(IDE_VERSION "7.83.0") # The IDE version.
|
||||||
set(IDE_VERSION_COMPAT "7.82.0") # The IDE Compatibility version.
|
set(IDE_VERSION_COMPAT "7.83.0") # The IDE Compatibility version.
|
||||||
set(IDE_VERSION_DISPLAY "8.0.0-beta1") # The IDE display 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_COPYRIGHT_YEAR "2022") # The IDE current copyright year.
|
||||||
|
|
||||||
set(IDE_SETTINGSVARIANT "QtProject") # The IDE settings variation.
|
set(IDE_SETTINGSVARIANT "QtProject") # The IDE settings variation.
|
||||||
|
@@ -13,7 +13,7 @@ instructions:
|
|||||||
instructions:
|
instructions:
|
||||||
- type: EnvironmentVariable
|
- type: EnvironmentVariable
|
||||||
variableName: QTC_QT_BASE_URL
|
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
|
- type: EnvironmentVariable
|
||||||
variableName: QTC_QT_MODULES
|
variableName: QTC_QT_MODULES
|
||||||
variableValue: "qt5compat qtbase qtdeclarative qtimageformats qtquick3d qtquickcontrols2 qtquicktimeline qtserialport qtshadertools qtsvg qttools qttranslations"
|
variableValue: "qt5compat qtbase qtdeclarative qtimageformats qtquick3d qtquickcontrols2 qtquicktimeline qtserialport qtshadertools qtsvg qttools qttranslations"
|
||||||
|
@@ -31,6 +31,15 @@ instructions:
|
|||||||
condition: property
|
condition: property
|
||||||
property: host.os
|
property: host.os
|
||||||
in_values: [MacOS, Linux, Windows]
|
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
|
- 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}}"
|
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
|
executeCommandArgumentSplitingBehavior: SplitAfterVariableSubstitution
|
||||||
@@ -52,10 +61,10 @@ instructions:
|
|||||||
property: host.os
|
property: host.os
|
||||||
equals_value: MacOS
|
equals_value: MacOS
|
||||||
- type: ExecuteCommand
|
- type: ExecuteCommand
|
||||||
command: "pip.exe install pywin32"
|
command: "pip.exe install pywin32 wget colorlog"
|
||||||
maxTimeInSeconds: 1200
|
maxTimeInSeconds: 1200
|
||||||
maxTimeBetweenOutput: 120
|
maxTimeBetweenOutput: 120
|
||||||
userMessageOnFailure: "Failed to install win32api, check logs."
|
userMessageOnFailure: "Failed to install Python packages, check logs."
|
||||||
enable_if:
|
enable_if:
|
||||||
condition: property
|
condition: property
|
||||||
property: host.os
|
property: host.os
|
||||||
|
@@ -1,17 +1,20 @@
|
|||||||
import qbs
|
import qbs
|
||||||
import qbs.Environment
|
import qbs.Environment
|
||||||
import qbs.FileInfo
|
import qbs.FileInfo
|
||||||
|
import qbs.Utilities
|
||||||
|
|
||||||
Module {
|
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_major: '7'
|
||||||
property string ide_version_minor: '82'
|
property string ide_version_minor: '83'
|
||||||
property string ide_version_release: '0'
|
property string ide_version_release: '0'
|
||||||
property string qtcreator_version: ide_version_major + '.' + ide_version_minor + '.'
|
property string qtcreator_version: ide_version_major + '.' + ide_version_minor + '.'
|
||||||
+ ide_version_release
|
+ ide_version_release
|
||||||
|
|
||||||
property string ide_compat_version_major: '7'
|
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 ide_compat_version_release: '0'
|
||||||
property string qtcreator_compat_version: ide_compat_version_major + '.'
|
property string qtcreator_compat_version: ide_compat_version_major + '.'
|
||||||
+ ide_compat_version_minor + '.' + ide_compat_version_release
|
+ ide_compat_version_minor + '.' + ide_compat_version_release
|
||||||
@@ -92,4 +95,12 @@ Module {
|
|||||||
"QT_USE_QSTRINGBUILDER",
|
"QT_USE_QSTRINGBUILDER",
|
||||||
].concat(testsEnabled ? ["WITH_TESTS"] : [])
|
].concat(testsEnabled ? ["WITH_TESTS"] : [])
|
||||||
.concat(qbs.toolchain.contains("msvc") ? ["_CRT_SECURE_NO_WARNINGS"] : [])
|
.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-"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
QTCREATOR_VERSION = 7.82.0
|
QTCREATOR_VERSION = 7.83.0
|
||||||
QTCREATOR_COMPAT_VERSION = 7.82.0
|
QTCREATOR_COMPAT_VERSION = 7.83.0
|
||||||
QTCREATOR_DISPLAY_VERSION = 8.0.0-beta1
|
QTCREATOR_DISPLAY_VERSION = 8.0.0-beta2
|
||||||
QTCREATOR_COPYRIGHT_YEAR = 2022
|
QTCREATOR_COPYRIGHT_YEAR = 2022
|
||||||
|
|
||||||
IDE_DISPLAY_NAME = Qt Creator
|
IDE_DISPLAY_NAME = Qt Creator
|
||||||
|
@@ -238,7 +238,7 @@ def deploy_clang(install_dir, llvm_install_dir, chrpath_bin):
|
|||||||
clanglibdirtarget = os.path.join(install_dir, 'bin', 'clang', 'lib')
|
clanglibdirtarget = os.path.join(install_dir, 'bin', 'clang', 'lib')
|
||||||
if not os.path.exists(clanglibdirtarget):
|
if not os.path.exists(clanglibdirtarget):
|
||||||
os.makedirs(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')
|
binary_filepath = os.path.join(llvm_install_dir, 'bin', binary + '.exe')
|
||||||
if os.path.exists(binary_filepath):
|
if os.path.exists(binary_filepath):
|
||||||
deployinfo.append((binary_filepath, clangbindirtarget))
|
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')
|
clangbinary_targetdir = os.path.join(install_dir, 'libexec', 'qtcreator', 'clang', 'bin')
|
||||||
if not os.path.exists(clangbinary_targetdir):
|
if not os.path.exists(clangbinary_targetdir):
|
||||||
os.makedirs(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)
|
binary_filepath = os.path.join(llvm_install_dir, 'bin', binary)
|
||||||
if os.path.exists(binary_filepath):
|
if os.path.exists(binary_filepath):
|
||||||
deployinfo.append((binary_filepath, clangbinary_targetdir))
|
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):
|
if not os.path.exists(clanglibs_targetdir):
|
||||||
os.makedirs(clanglibs_targetdir)
|
os.makedirs(clanglibs_targetdir)
|
||||||
# on RHEL ClazyPlugin is in lib64
|
# 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)):
|
for lib in glob(os.path.join(llvm_install_dir, lib_pattern)):
|
||||||
deployinfo.append((lib, clanglibs_targetdir))
|
deployinfo.append((lib, clanglibs_targetdir))
|
||||||
resourcetarget = os.path.join(install_dir, 'libexec', 'qtcreator', 'clang', 'lib', 'clang')
|
resourcetarget = os.path.join(install_dir, 'libexec', 'qtcreator', 'clang', 'lib', 'clang')
|
||||||
|
@@ -111,21 +111,14 @@ fi
|
|||||||
|
|
||||||
# copy clang if needed
|
# copy clang if needed
|
||||||
if [ $LLVM_INSTALL_DIR ]; then
|
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"
|
echo "- Copying clang"
|
||||||
mkdir -p "$app_path/Contents/Frameworks" || exit 1
|
mkdir -p "$app_path/Contents/Frameworks" || exit 1
|
||||||
# use recursive copy to make it copy symlinks as symlinks
|
# use recursive copy to make it copy symlinks as symlinks
|
||||||
mkdir -p "$libexec_path/clang/bin"
|
mkdir -p "$libexec_path/clang/bin"
|
||||||
mkdir -p "$libexec_path/clang/lib"
|
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/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
|
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
|
clangdsource="$LLVM_INSTALL_DIR"/bin/clangd
|
||||||
cp -Rf "$clangdsource" "$libexec_path/clang/bin/" || exit 1
|
cp -Rf "$clangdsource" "$libexec_path/clang/bin/" || exit 1
|
||||||
clangtidysource="$LLVM_INSTALL_DIR"/bin/clang-tidy
|
clangtidysource="$LLVM_INSTALL_DIR"/bin/clang-tidy
|
||||||
|
@@ -29,7 +29,6 @@ import collections
|
|||||||
import glob
|
import glob
|
||||||
import struct
|
import struct
|
||||||
import sys
|
import sys
|
||||||
import base64
|
|
||||||
import re
|
import re
|
||||||
import time
|
import time
|
||||||
import inspect
|
import inspect
|
||||||
@@ -45,6 +44,14 @@ except:
|
|||||||
"Native combined debugging might not work.")
|
"Native combined debugging might not work.")
|
||||||
pass
|
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:
|
if sys.version_info[0] >= 3:
|
||||||
toInteger = int
|
toInteger = int
|
||||||
@@ -550,7 +557,7 @@ class DumperBase():
|
|||||||
return s.encode('hex')
|
return s.encode('hex')
|
||||||
if isinstance(s, str):
|
if isinstance(s, str):
|
||||||
s = s.encode('utf8')
|
s = s.encode('utf8')
|
||||||
return base64.b16encode(s).decode('utf8')
|
return hexencode_(s)
|
||||||
|
|
||||||
def isQt3Support(self):
|
def isQt3Support(self):
|
||||||
# assume no Qt 3 support by default
|
# assume no Qt 3 support by default
|
||||||
|
@@ -33,7 +33,11 @@
|
|||||||
"name": "PySideVersion",
|
"name": "PySideVersion",
|
||||||
"trDisplayName": "PySide version:",
|
"trDisplayName": "PySide version:",
|
||||||
"type": "ComboBox",
|
"type": "ComboBox",
|
||||||
"data": { "items": [ "PySide2", "PySide6" ] }
|
"data":
|
||||||
|
{
|
||||||
|
"index": 1,
|
||||||
|
"items": [ "PySide2", "PySide6" ]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@@ -34,7 +34,11 @@
|
|||||||
"name": "PySideVersion",
|
"name": "PySideVersion",
|
||||||
"trDisplayName": "PySide version:",
|
"trDisplayName": "PySide version:",
|
||||||
"type": "ComboBox",
|
"type": "ComboBox",
|
||||||
"data": { "items": [ "PySide2", "PySide6" ] }
|
"data":
|
||||||
|
{
|
||||||
|
"index": 1,
|
||||||
|
"items": [ "PySide2", "PySide6" ]
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Class",
|
"name": "Class",
|
||||||
|
@@ -39,7 +39,7 @@
|
|||||||
"type": "ComboBox",
|
"type": "ComboBox",
|
||||||
"data":
|
"data":
|
||||||
{
|
{
|
||||||
"index": 2,
|
"index": 0,
|
||||||
"items":
|
"items":
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
|
@@ -34,7 +34,11 @@
|
|||||||
"name": "PySideVersion",
|
"name": "PySideVersion",
|
||||||
"trDisplayName": "PySide version:",
|
"trDisplayName": "PySide version:",
|
||||||
"type": "ComboBox",
|
"type": "ComboBox",
|
||||||
"data": { "items": [ "PySide2", "PySide6" ] }
|
"data":
|
||||||
|
{
|
||||||
|
"index": 1,
|
||||||
|
"items": [ "PySide2", "PySide6" ]
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Class",
|
"name": "Class",
|
||||||
|
@@ -34,7 +34,11 @@
|
|||||||
"name": "PySideVersion",
|
"name": "PySideVersion",
|
||||||
"trDisplayName": "PySide version:",
|
"trDisplayName": "PySide version:",
|
||||||
"type": "ComboBox",
|
"type": "ComboBox",
|
||||||
"data": { "items": [ "PySide2", "PySide6" ] }
|
"data":
|
||||||
|
{
|
||||||
|
"index": 1,
|
||||||
|
"items": [ "PySide2", "PySide6" ]
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Class",
|
"name": "Class",
|
||||||
|
@@ -49,6 +49,16 @@ Utils::optional<CompletionItem::InsertTextFormat> CompletionItem::insertTextForm
|
|||||||
return Utils::nullopt;
|
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 ¶ms)
|
CompletionItemResolveRequest::CompletionItemResolveRequest(const CompletionItem ¶ms)
|
||||||
: Request(methodName, params)
|
: Request(methodName, params)
|
||||||
|
@@ -214,6 +214,27 @@ public:
|
|||||||
void setData(const QJsonValue &data) { insert(dataKey, data); }
|
void setData(const QJsonValue &data) { insert(dataKey, data); }
|
||||||
void clearData() { remove(dataKey); }
|
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); }
|
bool isValid() const override { return contains(labelKey); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -209,6 +209,7 @@ constexpr char symbolKindKey[] = "symbolKind";
|
|||||||
constexpr char syncKindKey[] = "syncKind";
|
constexpr char syncKindKey[] = "syncKind";
|
||||||
constexpr char synchronizationKey[] = "synchronization";
|
constexpr char synchronizationKey[] = "synchronization";
|
||||||
constexpr char tabSizeKey[] = "tabSize";
|
constexpr char tabSizeKey[] = "tabSize";
|
||||||
|
constexpr char tagsKey[] = "tags";
|
||||||
constexpr char targetKey[] = "target";
|
constexpr char targetKey[] = "target";
|
||||||
constexpr char textDocumentKey[] = "textDocument";
|
constexpr char textDocumentKey[] = "textDocument";
|
||||||
constexpr char textDocumentSyncKey[] = "textDocumentSync";
|
constexpr char textDocumentSyncKey[] = "textDocumentSync";
|
||||||
|
@@ -334,7 +334,7 @@ protected:
|
|||||||
_doc->fileName(),
|
_doc->fileName(),
|
||||||
line, column,
|
line, column,
|
||||||
QmlJS::FindExportedCppTypes::tr(
|
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"
|
"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."));
|
"the QML editor know about a likely URI."));
|
||||||
}
|
}
|
||||||
|
@@ -2378,8 +2378,12 @@ const Value *TypeScope::lookupMember(const QString &name, const Context *context
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (const Value *v = import->lookupMember(name, context, foundInObject)) {
|
if (const Value *v = import->lookupMember(name, context, foundInObject)) {
|
||||||
i.used = true;
|
// FIXME if we have multiple non-aliased imports containing this object we'd have to
|
||||||
return v;
|
// disambiguate (and inform the user) about this issue
|
||||||
|
if (info.as().isEmpty()) {
|
||||||
|
i.used = true;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (foundInObject)
|
if (foundInObject)
|
||||||
|
@@ -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 "
|
"For Qbs projects, declare and set a qmlImportPaths property in your product "
|
||||||
"to add import paths.\n"
|
"to add import paths.\n"
|
||||||
"For qmlproject projects, use the importPaths property 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'))));
|
.arg(importInfo.name(), m_importPaths.join(QLatin1Char('\n'))));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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(
|
void ModelManagerInterface::iterateQrcFiles(
|
||||||
ProjectExplorer::Project *project, QrcResourceSelector resources,
|
ProjectExplorer::Project *project, QrcResourceSelector resources,
|
||||||
const std::function<void(QrcParser::ConstPtr)> &callback)
|
const std::function<void(QrcParser::ConstPtr)> &callback)
|
||||||
@@ -461,18 +475,21 @@ void ModelManagerInterface::iterateQrcFiles(
|
|||||||
Utils::sort(pInfos, &pInfoLessThanAll);
|
Utils::sort(pInfos, &pInfoLessThanAll);
|
||||||
}
|
}
|
||||||
|
|
||||||
QSet<QString> pathsChecked;
|
QSet<Utils::FilePath> pathsChecked;
|
||||||
for (const ModelManagerInterface::ProjectInfo &pInfo : qAsConst(pInfos)) {
|
for (const ModelManagerInterface::ProjectInfo &pInfo : qAsConst(pInfos)) {
|
||||||
QStringList qrcFilePaths;
|
QStringList qrcFilePaths;
|
||||||
if (resources == ActiveQrcResources)
|
if (resources == ActiveQrcResources)
|
||||||
qrcFilePaths = pInfo.activeResourceFiles;
|
qrcFilePaths = pInfo.activeResourceFiles;
|
||||||
else
|
else
|
||||||
qrcFilePaths = pInfo.allResourceFiles;
|
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))
|
if (pathsChecked.contains(qrcFilePath))
|
||||||
continue;
|
continue;
|
||||||
pathsChecked.insert(qrcFilePath);
|
pathsChecked.insert(qrcFilePath);
|
||||||
QrcParser::ConstPtr qrcFile = m_qrcCache.parsedPath(qrcFilePath);
|
QrcParser::ConstPtr qrcFile = m_qrcCache.parsedPath(qrcFilePath.toString());
|
||||||
if (qrcFile.isNull())
|
if (qrcFile.isNull())
|
||||||
continue;
|
continue;
|
||||||
callback(qrcFile);
|
callback(qrcFile);
|
||||||
@@ -589,6 +606,8 @@ void ModelManagerInterface::updateProjectInfo(const ProjectInfo &pinfo, ProjectE
|
|||||||
m_qrcContents = pinfo.resourceFileContents;
|
m_qrcContents = pinfo.resourceFileContents;
|
||||||
for (const QString &newQrc : qAsConst(pinfo.allResourceFiles))
|
for (const QString &newQrc : qAsConst(pinfo.allResourceFiles))
|
||||||
m_qrcCache.addPath(newQrc, m_qrcContents.value(newQrc));
|
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))
|
for (const QString &oldQrc : qAsConst(oldInfo.allResourceFiles))
|
||||||
m_qrcCache.removePath(oldQrc);
|
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()
|
void ModelManagerInterface::updateImportPaths()
|
||||||
{
|
{
|
||||||
if (m_indexerDisabled)
|
if (m_indexerDisabled)
|
||||||
@@ -1243,6 +1285,7 @@ void ModelManagerInterface::updateImportPaths()
|
|||||||
m_allImportPaths = allImportPaths;
|
m_allImportPaths = allImportPaths;
|
||||||
m_activeBundles = activeBundles;
|
m_activeBundles = activeBundles;
|
||||||
m_extendedBundles = extendedBundles;
|
m_extendedBundles = extendedBundles;
|
||||||
|
m_applicationPaths = minimalPrefixPaths(allApplicationDirectories);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1253,10 +1296,13 @@ void ModelManagerInterface::updateImportPaths()
|
|||||||
QSet<QString> newLibraries;
|
QSet<QString> newLibraries;
|
||||||
for (const Document::Ptr &doc : qAsConst(snapshot))
|
for (const Document::Ptr &doc : qAsConst(snapshot))
|
||||||
findNewLibraryImports(doc, snapshot, this, &importedFiles, &scannedPaths, &newLibraries);
|
findNewLibraryImports(doc, snapshot, this, &importedFiles, &scannedPaths, &newLibraries);
|
||||||
for (const QString &path : qAsConst(allApplicationDirectories)) {
|
for (const QString &pathStr : qAsConst(allApplicationDirectories)) {
|
||||||
allImportPaths.maybeInsert(FilePath::fromString(path), Dialect::Qml);
|
Utils::FilePath path = Utils::FilePath::fromString(pathStr);
|
||||||
findNewQmlApplicationInPath(FilePath::fromString(path), snapshot, this, &newLibraries);
|
allImportPaths.maybeInsert(path, Dialect::Qml);
|
||||||
|
findNewQmlApplicationInPath(path, snapshot, this, &newLibraries);
|
||||||
}
|
}
|
||||||
|
for (const Utils::FilePath &qrcPath : generatedQrc(allApplicationDirectories))
|
||||||
|
updateQrcFile(qrcPath.toString());
|
||||||
|
|
||||||
updateSourceFiles(importedFiles, true);
|
updateSourceFiles(importedFiles, true);
|
||||||
|
|
||||||
@@ -1668,4 +1714,47 @@ void ModelManagerInterface::resetCodeModel()
|
|||||||
updateImportPaths();
|
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
|
} // namespace QmlJS
|
||||||
|
@@ -34,6 +34,7 @@
|
|||||||
#include <utils/environment.h>
|
#include <utils/environment.h>
|
||||||
#include <utils/futuresynchronizer.h>
|
#include <utils/futuresynchronizer.h>
|
||||||
#include <utils/qrcparser.h>
|
#include <utils/qrcparser.h>
|
||||||
|
#include <utils/filepath.h>
|
||||||
|
|
||||||
#include <QFuture>
|
#include <QFuture>
|
||||||
#include <QHash>
|
#include <QHash>
|
||||||
@@ -149,6 +150,7 @@ public:
|
|||||||
ProjectExplorer::Project *project = nullptr,
|
ProjectExplorer::Project *project = nullptr,
|
||||||
bool addDirs = false,
|
bool addDirs = false,
|
||||||
QrcResourceSelector resources = AllQrcResources);
|
QrcResourceSelector resources = AllQrcResources);
|
||||||
|
Utils::FilePath fileToSource(const Utils::FilePath &file);
|
||||||
|
|
||||||
QList<ProjectInfo> projectInfos() const;
|
QList<ProjectInfo> projectInfos() const;
|
||||||
bool containsProject(ProjectExplorer::Project *project) const;
|
bool containsProject(ProjectExplorer::Project *project) const;
|
||||||
@@ -254,6 +256,7 @@ private:
|
|||||||
QmlJS::Snapshot m_validSnapshot;
|
QmlJS::Snapshot m_validSnapshot;
|
||||||
QmlJS::Snapshot m_newestSnapshot;
|
QmlJS::Snapshot m_newestSnapshot;
|
||||||
PathsAndLanguages m_allImportPaths;
|
PathsAndLanguages m_allImportPaths;
|
||||||
|
QList<Utils::FilePath> m_applicationPaths;
|
||||||
QStringList m_defaultImportPaths;
|
QStringList m_defaultImportPaths;
|
||||||
QmlJS::QmlLanguageBundles m_activeBundles;
|
QmlJS::QmlLanguageBundles m_activeBundles;
|
||||||
QmlJS::QmlLanguageBundles m_extendedBundles;
|
QmlJS::QmlLanguageBundles m_extendedBundles;
|
||||||
|
@@ -264,13 +264,20 @@ void PluginDumper::qmlPluginTypeDumpDone(QtcProcess *process)
|
|||||||
return;
|
return;
|
||||||
const Snapshot snapshot = m_modelManager->snapshot();
|
const Snapshot snapshot = m_modelManager->snapshot();
|
||||||
LibraryInfo libraryInfo = snapshot.libraryInfo(libraryPath);
|
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);
|
const QString errorMessages = qmlPluginDumpErrorMessage(process);
|
||||||
if (!privatePlugin)
|
if (!privatePlugin)
|
||||||
ModelManagerInterface::writeWarning(qmldumpErrorMessage(libraryPath, errorMessages));
|
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();
|
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)
|
void PluginDumper::pluginChanged(const QString &pluginLibrary)
|
||||||
{
|
{
|
||||||
const int pluginIndex = m_libraryToPluginIndex.value(pluginLibrary, -1);
|
const int pluginIndex = m_libraryToPluginIndex.value(pluginLibrary, -1);
|
||||||
@@ -628,8 +618,7 @@ void PluginDumper::runQmlDump(const ModelManagerInterface::ProjectInfo &info,
|
|||||||
process->setEnvironment(info.qmlDumpEnvironment);
|
process->setEnvironment(info.qmlDumpEnvironment);
|
||||||
process->setWorkingDirectory(importPath);
|
process->setWorkingDirectory(importPath);
|
||||||
process->setCommand({info.qmlDumpPath, arguments});
|
process->setCommand({info.qmlDumpPath, arguments});
|
||||||
connect(process, &QtcProcess::finished, this, [this, process] { qmlPluginTypeDumpDone(process); });
|
connect(process, &QtcProcess::done, this, [this, process] { qmlPluginTypeDumpDone(process); });
|
||||||
connect(process, &QtcProcess::errorOccurred, this, [this, process] { qmlPluginTypeDumpError(process); });
|
|
||||||
process->start();
|
process->start();
|
||||||
m_runningQmldumps.insert(process, importPath);
|
m_runningQmldumps.insert(process, importPath);
|
||||||
}
|
}
|
||||||
|
@@ -60,7 +60,6 @@ private:
|
|||||||
const QString &importUri, const QString &importVersion);
|
const QString &importUri, const QString &importVersion);
|
||||||
Q_INVOKABLE void dumpAllPlugins();
|
Q_INVOKABLE void dumpAllPlugins();
|
||||||
void qmlPluginTypeDumpDone(Utils::QtcProcess *process);
|
void qmlPluginTypeDumpDone(Utils::QtcProcess *process);
|
||||||
void qmlPluginTypeDumpError(Utils::QtcProcess *process);
|
|
||||||
void pluginChanged(const QString &pluginLibrary);
|
void pluginChanged(const QString &pluginLibrary);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@@ -20,9 +20,13 @@ endif()
|
|||||||
|
|
||||||
find_library(DbgEngLib dbgeng)
|
find_library(DbgEngLib dbgeng)
|
||||||
|
|
||||||
set(ArchSuffix 32)
|
set(ArchSuffix "32")
|
||||||
if (CMAKE_SIZEOF_VOID_P EQUAL 8)
|
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()
|
endif()
|
||||||
|
|
||||||
add_qtc_library(qtcreatorcdbext SHARED
|
add_qtc_library(qtcreatorcdbext SHARED
|
||||||
|
@@ -1138,6 +1138,9 @@ void StringAspect::addToLayout(LayoutBuilder &builder)
|
|||||||
&FancyLineEdit::textEdited,
|
&FancyLineEdit::textEdited,
|
||||||
this,
|
this,
|
||||||
&StringAspect::setValue);
|
&StringAspect::setValue);
|
||||||
|
connect(d->m_lineEditDisplay, &FancyLineEdit::editingFinished, this, [this] {
|
||||||
|
setValue(d->m_lineEditDisplay->text());
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (d->m_useResetButton) {
|
if (d->m_useResetButton) {
|
||||||
@@ -2442,6 +2445,10 @@ void AspectContainerData::append(const BaseAspect::Data::Ptr &data)
|
|||||||
m_data.append(data);
|
m_data.append(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BaseAspect::Data
|
||||||
|
|
||||||
|
BaseAspect::Data::~Data() = default;
|
||||||
|
|
||||||
void BaseAspect::Data::Ptr::operator=(const Ptr &other)
|
void BaseAspect::Data::Ptr::operator=(const Ptr &other)
|
||||||
{
|
{
|
||||||
if (this == &other)
|
if (this == &other)
|
||||||
|
@@ -145,7 +145,7 @@ public:
|
|||||||
// The (unique) address of the "owning" aspect's meta object is used as identifier.
|
// The (unique) address of the "owning" aspect's meta object is used as identifier.
|
||||||
using ClassId = const void *;
|
using ClassId = const void *;
|
||||||
|
|
||||||
virtual ~Data() = default;
|
virtual ~Data();
|
||||||
|
|
||||||
Id id() const { return m_id; }
|
Id id() const { return m_id; }
|
||||||
ClassId classId() const { return m_classId; }
|
ClassId classId() const { return m_classId; }
|
||||||
|
@@ -50,7 +50,7 @@ FilePath BuildableHelperLibrary::qtChooserToQmakePath(const FilePath &qtChooser)
|
|||||||
proc.runBlocking();
|
proc.runBlocking();
|
||||||
if (proc.result() != ProcessResult::FinishedWithSuccess)
|
if (proc.result() != ProcessResult::FinishedWithSuccess)
|
||||||
return {};
|
return {};
|
||||||
const QString output = proc.stdOut();
|
const QString output = proc.cleanedStdOut();
|
||||||
int pos = output.indexOf(toolDir);
|
int pos = output.indexOf(toolDir);
|
||||||
if (pos == -1)
|
if (pos == -1)
|
||||||
return {};
|
return {};
|
||||||
|
@@ -277,8 +277,8 @@ void DeviceShell::startupFailed(const CommandLine &cmdLine)
|
|||||||
bool DeviceShell::start()
|
bool DeviceShell::start()
|
||||||
{
|
{
|
||||||
m_shellProcess = new QtcProcess();
|
m_shellProcess = new QtcProcess();
|
||||||
connect(m_shellProcess, &QtcProcess::done, this, [this] { emit done(); });
|
connect(m_shellProcess, &QtcProcess::done, m_shellProcess,
|
||||||
connect(m_shellProcess, &QtcProcess::errorOccurred, this, &DeviceShell::errorOccurred);
|
[this] { emit done(m_shellProcess->resultData()); });
|
||||||
connect(m_shellProcess, &QObject::destroyed, this, [this] { m_shellProcess = nullptr; });
|
connect(m_shellProcess, &QObject::destroyed, this, [this] { m_shellProcess = nullptr; });
|
||||||
connect(&m_thread, &QThread::finished, m_shellProcess, [this] { closeShellProcess(); });
|
connect(&m_thread, &QThread::finished, m_shellProcess, [this] { closeShellProcess(); });
|
||||||
|
|
||||||
|
@@ -36,6 +36,7 @@
|
|||||||
namespace Utils {
|
namespace Utils {
|
||||||
|
|
||||||
class CommandLine;
|
class CommandLine;
|
||||||
|
class ProcessResultData;
|
||||||
class QtcProcess;
|
class QtcProcess;
|
||||||
|
|
||||||
class DeviceShellImpl;
|
class DeviceShellImpl;
|
||||||
@@ -69,8 +70,7 @@ public:
|
|||||||
State state() const;
|
State state() const;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void done();
|
void done(const ProcessResultData &resultData);
|
||||||
void errorOccurred(QProcess::ProcessError error);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void startupFailed(const CommandLine &cmdLine);
|
virtual void startupFailed(const CommandLine &cmdLine);
|
||||||
|
@@ -945,8 +945,30 @@ QString FilePath::displayName(const QString &args) const
|
|||||||
.arg(m_data, args, deviceName);
|
.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 FilePath::fromString(const QString &filepath)
|
||||||
{
|
{
|
||||||
FilePath fn;
|
FilePath fn;
|
||||||
@@ -1285,9 +1307,16 @@ FilePath FilePath::searchInDirectories(const FilePaths &dirs) const
|
|||||||
return Environment::systemEnvironment().searchInDirectories(path(), dirs);
|
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
|
Environment FilePath::deviceEnvironment() const
|
||||||
|
@@ -164,13 +164,16 @@ public:
|
|||||||
[[nodiscard]] FilePath relativeChildPath(const FilePath &parent) const;
|
[[nodiscard]] FilePath relativeChildPath(const FilePath &parent) const;
|
||||||
[[nodiscard]] FilePath relativePath(const FilePath &anchor) const;
|
[[nodiscard]] FilePath relativePath(const FilePath &anchor) const;
|
||||||
[[nodiscard]] FilePath searchInDirectories(const QList<FilePath> &dirs) const;
|
[[nodiscard]] FilePath searchInDirectories(const QList<FilePath> &dirs) const;
|
||||||
[[nodiscard]] FilePath searchInPath(const QList<FilePath> &additionalDirs = {}) const;
|
|
||||||
[[nodiscard]] Environment deviceEnvironment() const;
|
[[nodiscard]] Environment deviceEnvironment() const;
|
||||||
[[nodiscard]] FilePath onDevice(const FilePath &deviceTemplate) const;
|
[[nodiscard]] FilePath onDevice(const FilePath &deviceTemplate) const;
|
||||||
[[nodiscard]] FilePath withNewPath(const QString &newPath) const;
|
[[nodiscard]] FilePath withNewPath(const QString &newPath) const;
|
||||||
void iterateDirectory(const std::function<bool(const FilePath &item)> &callBack,
|
void iterateDirectory(const std::function<bool(const FilePath &item)> &callBack,
|
||||||
const FileFilter &filter) const;
|
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
|
// makes sure that capitalization of directories is canonical
|
||||||
// on Windows and macOS. This is rarely needed.
|
// on Windows and macOS. This is rarely needed.
|
||||||
[[nodiscard]] FilePath normalizedPathName() const;
|
[[nodiscard]] FilePath normalizedPathName() const;
|
||||||
|
@@ -31,6 +31,10 @@
|
|||||||
#include <QOpenGLContext>
|
#include <QOpenGLContext>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef Q_OS_LINUX
|
||||||
|
#include <sys/sysinfo.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
#include <qt_windows.h>
|
#include <qt_windows.h>
|
||||||
#endif
|
#endif
|
||||||
@@ -65,8 +69,9 @@ HostOsInfo::HostArchitecture HostOsInfo::hostArchitecture()
|
|||||||
case PROCESSOR_ARCHITECTURE_IA64:
|
case PROCESSOR_ARCHITECTURE_IA64:
|
||||||
return HostOsInfo::HostArchitectureItanium;
|
return HostOsInfo::HostArchitectureItanium;
|
||||||
case PROCESSOR_ARCHITECTURE_ARM:
|
case PROCESSOR_ARCHITECTURE_ARM:
|
||||||
case PROCESSOR_ARCHITECTURE_ARM64:
|
|
||||||
return HostOsInfo::HostArchitectureArm;
|
return HostOsInfo::HostArchitectureArm;
|
||||||
|
case PROCESSOR_ARCHITECTURE_ARM64:
|
||||||
|
return HostOsInfo::HostArchitectureArm64;
|
||||||
default:
|
default:
|
||||||
return HostOsInfo::HostArchitectureUnknown;
|
return HostOsInfo::HostArchitectureUnknown;
|
||||||
}
|
}
|
||||||
@@ -110,3 +115,27 @@ bool HostOsInfo::canCreateOpenGLContext(QString *errorMessage)
|
|||||||
return canCreate;
|
return canCreate;
|
||||||
#endif
|
#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 {};
|
||||||
|
}
|
||||||
|
@@ -27,6 +27,7 @@
|
|||||||
|
|
||||||
#include "utils_global.h"
|
#include "utils_global.h"
|
||||||
|
|
||||||
|
#include "optional.h"
|
||||||
#include "osspecificaspects.h"
|
#include "osspecificaspects.h"
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
@@ -60,7 +61,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
enum HostArchitecture { HostArchitectureX86, HostArchitectureAMD64, HostArchitectureItanium,
|
enum HostArchitecture { HostArchitectureX86, HostArchitectureAMD64, HostArchitectureItanium,
|
||||||
HostArchitectureArm, HostArchitectureUnknown };
|
HostArchitectureArm, HostArchitectureArm64, HostArchitectureUnknown };
|
||||||
static HostArchitecture hostArchitecture();
|
static HostArchitecture hostArchitecture();
|
||||||
|
|
||||||
static constexpr bool isWindowsHost() { return hostOs() == OsTypeWindows; }
|
static constexpr bool isWindowsHost() { return hostOs() == OsTypeWindows; }
|
||||||
@@ -104,6 +105,8 @@ public:
|
|||||||
|
|
||||||
static bool canCreateOpenGLContext(QString *errorMessage);
|
static bool canCreateOpenGLContext(QString *errorMessage);
|
||||||
|
|
||||||
|
static optional<quint64> totalMemoryInstalledInBytes();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static Qt::CaseSensitivity m_overrideFileNameCaseSensitivity;
|
static Qt::CaseSensitivity m_overrideFileNameCaseSensitivity;
|
||||||
static bool m_useOverrideFileNameCaseSensitivity;
|
static bool m_useOverrideFileNameCaseSensitivity;
|
||||||
|
@@ -178,7 +178,7 @@ class PathChooserPrivate
|
|||||||
public:
|
public:
|
||||||
PathChooserPrivate();
|
PathChooserPrivate();
|
||||||
|
|
||||||
FilePath expandedPath(const QString &path) const;
|
FilePath expandedPath(const FilePath &path) const;
|
||||||
|
|
||||||
QHBoxLayout *m_hLayout = nullptr;
|
QHBoxLayout *m_hLayout = nullptr;
|
||||||
FancyLineEdit *m_lineEdit = 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())
|
if (input.isEmpty())
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
FilePath path = FilePath::fromUserInput(input);
|
FilePath path = input;
|
||||||
|
|
||||||
Environment env = path.deviceEnvironment();
|
Environment env = path.deviceEnvironment();
|
||||||
m_environmentChange.applyToEnvironment(env);
|
m_environmentChange.applyToEnvironment(env);
|
||||||
@@ -353,7 +353,7 @@ FilePath PathChooser::rawFilePath() const
|
|||||||
|
|
||||||
FilePath PathChooser::filePath() const
|
FilePath PathChooser::filePath() const
|
||||||
{
|
{
|
||||||
return d->expandedPath(rawFilePath().toString());
|
return d->expandedPath(rawFilePath());
|
||||||
}
|
}
|
||||||
|
|
||||||
FilePath PathChooser::absoluteFilePath() const
|
FilePath PathChooser::absoluteFilePath() const
|
||||||
@@ -529,11 +529,11 @@ FancyLineEdit::ValidationFunction PathChooser::defaultValidationFunction() const
|
|||||||
|
|
||||||
bool PathChooser::validatePath(FancyLineEdit *edit, QString *errorMessage) 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()) {
|
if (!d->m_defaultValue.isEmpty()) {
|
||||||
path = d->m_defaultValue;
|
input = d->m_defaultValue;
|
||||||
} else {
|
} else {
|
||||||
if (errorMessage)
|
if (errorMessage)
|
||||||
*errorMessage = tr("The path must not be empty.");
|
*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 (filePath.isEmpty()) {
|
||||||
if (errorMessage)
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -57,6 +57,7 @@ public:
|
|||||||
const QLocale *locale = nullptr) const;
|
const QLocale *locale = nullptr) const;
|
||||||
void collectResourceFilesForSourceFile(const QString &sourceFile, QStringList *res,
|
void collectResourceFilesForSourceFile(const QString &sourceFile, QStringList *res,
|
||||||
const QLocale *locale = nullptr) const;
|
const QLocale *locale = nullptr) const;
|
||||||
|
QrcParser::MatchResult longestReverseMatches(const QString &) const;
|
||||||
|
|
||||||
QStringList errorMessages() const;
|
QStringList errorMessages() const;
|
||||||
QStringList languages() const;
|
QStringList languages() const;
|
||||||
@@ -65,6 +66,7 @@ private:
|
|||||||
const QStringList allUiLanguages(const QLocale *locale) const;
|
const QStringList allUiLanguages(const QLocale *locale) const;
|
||||||
|
|
||||||
SMap m_resources;
|
SMap m_resources;
|
||||||
|
SMap m_reverseResources;
|
||||||
SMap m_files;
|
SMap m_files;
|
||||||
QStringList m_languages;
|
QStringList m_languages;
|
||||||
QStringList m_errorMessages;
|
QStringList m_errorMessages;
|
||||||
@@ -207,6 +209,11 @@ void QrcParser::collectFilesAtPath(const QString &path, QStringList *res, const
|
|||||||
d->collectFilesAtPath(path, res, locale);
|
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.
|
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
|
else
|
||||||
accessPath = language + prefix + fileName;
|
accessPath = language + prefix + fileName;
|
||||||
QStringList &resources = m_resources[accessPath];
|
QStringList &resources = m_resources[accessPath];
|
||||||
if (!resources.contains(filePath))
|
if (!resources.contains(filePath)) {
|
||||||
resources.append(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];
|
QStringList &files = m_files[filePath];
|
||||||
if (!files.contains(accessPath))
|
if (!files.contains(accessPath))
|
||||||
files.append(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
|
QStringList QrcParserPrivate::errorMessages() const
|
||||||
{
|
{
|
||||||
return m_errorMessages;
|
return m_errorMessages;
|
||||||
|
@@ -26,6 +26,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "utils_global.h"
|
#include "utils_global.h"
|
||||||
|
#include "utils/filepath.h"
|
||||||
|
|
||||||
#include <QSharedPointer>
|
#include <QSharedPointer>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
@@ -47,12 +48,20 @@ class QrcCachePrivate;
|
|||||||
class QTCREATOR_UTILS_EXPORT QrcParser
|
class QTCREATOR_UTILS_EXPORT QrcParser
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
struct MatchResult
|
||||||
|
{
|
||||||
|
int matchDepth = {};
|
||||||
|
QStringList reversedPaths;
|
||||||
|
QList<Utils::FilePath> sourceFiles;
|
||||||
|
};
|
||||||
|
|
||||||
typedef QSharedPointer<QrcParser> Ptr;
|
typedef QSharedPointer<QrcParser> Ptr;
|
||||||
typedef QSharedPointer<const QrcParser> ConstPtr;
|
typedef QSharedPointer<const QrcParser> ConstPtr;
|
||||||
~QrcParser();
|
~QrcParser();
|
||||||
bool parseFile(const QString &path, const QString &contents);
|
bool parseFile(const QString &path, const QString &contents);
|
||||||
QString firstFileAtPath(const QString &path, const QLocale &locale) const;
|
QString firstFileAtPath(const QString &path, const QLocale &locale) const;
|
||||||
void collectFilesAtPath(const QString &path, QStringList *res, const QLocale *locale = nullptr) 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;
|
bool hasDirAtPath(const QString &path, const QLocale *locale = nullptr) const;
|
||||||
void collectFilesInPath(const QString &path, QMap<QString, QStringList> *res, bool addDirs = false,
|
void collectFilesInPath(const QString &path, QMap<QString, QStringList> *res, bool addDirs = false,
|
||||||
const QLocale *locale = nullptr) const;
|
const QLocale *locale = nullptr) const;
|
||||||
|
@@ -1034,7 +1034,7 @@ QtcProcess::QtcProcess(QObject *parent)
|
|||||||
Q_UNUSED(qProcessProcessErrorMeta)
|
Q_UNUSED(qProcessProcessErrorMeta)
|
||||||
|
|
||||||
if (processLog().isDebugEnabled()) {
|
if (processLog().isDebugEnabled()) {
|
||||||
connect(this, &QtcProcess::finished, [this] {
|
connect(this, &QtcProcess::done, [this] {
|
||||||
if (!d->m_process.get())
|
if (!d->m_process.get())
|
||||||
return;
|
return;
|
||||||
const QVariant n = d->m_process.get()->property(QTC_PROCESS_NUMBER);
|
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: "
|
qCDebug(processLog).nospace() << "Process " << number << " finished: "
|
||||||
<< "result=" << int(result())
|
<< "result=" << int(result())
|
||||||
<< ", ex=" << exitCode()
|
<< ", ex=" << exitCode()
|
||||||
<< ", " << stdOut().size() << " bytes stdout: "
|
<< ", " << cleanedStdOut().size() << " bytes stdout: "
|
||||||
<< stdOut().left(20)
|
<< cleanedStdOut().left(20)
|
||||||
<< ", " << stdErr().size() << " bytes stderr: "
|
<< ", " << cleanedStdErr().size() << " bytes stderr: "
|
||||||
<< stdErr().left(1000)
|
<< cleanedStdErr().left(1000)
|
||||||
<< ", " << msElapsed << " ms elapsed";
|
<< ", " << msElapsed << " ms elapsed";
|
||||||
if (processStdoutLog().isDebugEnabled() && !stdOut().isEmpty())
|
if (processStdoutLog().isDebugEnabled() && !cleanedStdOut().isEmpty())
|
||||||
qCDebug(processStdoutLog).nospace()
|
qCDebug(processStdoutLog).nospace()
|
||||||
<< "Process " << number << " sdout: " << stdOut();
|
<< "Process " << number << " sdout: " << cleanedStdOut();
|
||||||
if (processStderrLog().isDebugEnabled() && !stdErr().isEmpty())
|
if (processStderrLog().isDebugEnabled() && !cleanedStdErr().isEmpty())
|
||||||
qCDebug(processStderrLog).nospace()
|
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);
|
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
|
\class Utils::SynchronousProcess
|
||||||
|
|
||||||
@@ -1691,8 +1685,8 @@ QString QtcProcess::allOutput() const
|
|||||||
{
|
{
|
||||||
QTC_CHECK(d->m_stdOut.keepRawData);
|
QTC_CHECK(d->m_stdOut.keepRawData);
|
||||||
QTC_CHECK(d->m_stdErr.keepRawData);
|
QTC_CHECK(d->m_stdErr.keepRawData);
|
||||||
const QString out = stdOut();
|
const QString out = cleanedStdOut();
|
||||||
const QString err = stdErr();
|
const QString err = cleanedStdErr();
|
||||||
|
|
||||||
if (!out.isEmpty() && !err.isEmpty()) {
|
if (!out.isEmpty() && !err.isEmpty()) {
|
||||||
QString result = out;
|
QString result = out;
|
||||||
@@ -1748,12 +1742,12 @@ static QStringList splitLines(const QString &text)
|
|||||||
|
|
||||||
const QStringList QtcProcess::stdOutLines() const
|
const QStringList QtcProcess::stdOutLines() const
|
||||||
{
|
{
|
||||||
return splitLines(stdOut());
|
return splitLines(cleanedStdOut());
|
||||||
}
|
}
|
||||||
|
|
||||||
const QStringList QtcProcess::stdErrLines() const
|
const QStringList QtcProcess::stdErrLines() const
|
||||||
{
|
{
|
||||||
return splitLines(stdErr());
|
return splitLines(cleanedStdErr());
|
||||||
}
|
}
|
||||||
|
|
||||||
QTCREATOR_UTILS_EXPORT QDebug operator<<(QDebug str, const QtcProcess &r)
|
QTCREATOR_UTILS_EXPORT QDebug operator<<(QDebug str, const QtcProcess &r)
|
||||||
|
@@ -144,10 +144,10 @@ public:
|
|||||||
// These (or some of them) may be potentially moved outside of the class.
|
// 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)?
|
// 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
|
// Helpers to find binaries. Do not use it for other path variables
|
||||||
// and file types.
|
// and file types.
|
||||||
static QString locateBinary(const QString &binary);
|
|
||||||
static QString locateBinary(const QString &path, const QString &binary);
|
static QString locateBinary(const QString &path, const QString &binary);
|
||||||
static QString normalizeNewlines(const QString &text);
|
static QString normalizeNewlines(const QString &text);
|
||||||
|
|
||||||
@@ -189,8 +189,8 @@ public:
|
|||||||
QString stdOut() const; // possibly with CR
|
QString stdOut() const; // possibly with CR
|
||||||
QString stdErr() const; // possibly with CR
|
QString stdErr() const; // possibly with CR
|
||||||
|
|
||||||
QString cleanedStdOut() const; // with CR removed
|
QString cleanedStdOut() const; // with sequences of CR squashed and CR LF replaced by LF
|
||||||
QString cleanedStdErr() const; // with CR removed
|
QString cleanedStdErr() const; // with sequences of CR squashed and CR LF replaced by LF
|
||||||
|
|
||||||
const QStringList stdOutLines() const; // split, CR removed
|
const QStringList stdOutLines() const; // split, CR removed
|
||||||
const QStringList stdErrLines() const; // split, CR removed
|
const QStringList stdErrLines() const; // split, CR removed
|
||||||
|
@@ -271,8 +271,8 @@ void ShellCommand::run(QFutureInterface<void> &future)
|
|||||||
proc.setExitCodeInterpreter(job.exitCodeInterpreter);
|
proc.setExitCodeInterpreter(job.exitCodeInterpreter);
|
||||||
proc.setTimeoutS(job.timeoutS);
|
proc.setTimeoutS(job.timeoutS);
|
||||||
runCommand(proc, job.command, job.workingDirectory);
|
runCommand(proc, job.command, job.workingDirectory);
|
||||||
stdOut += proc.stdOut();
|
stdOut += proc.cleanedStdOut();
|
||||||
stdErr += proc.stdErr();
|
stdErr += proc.cleanedStdErr();
|
||||||
d->m_lastExecExitCode = proc.exitCode();
|
d->m_lastExecExitCode = proc.exitCode();
|
||||||
d->m_lastExecSuccess = proc.result() == ProcessResult::FinishedWithSuccess;
|
d->m_lastExecSuccess = proc.result() == ProcessResult::FinishedWithSuccess;
|
||||||
if (!d->m_lastExecSuccess)
|
if (!d->m_lastExecSuccess)
|
||||||
@@ -352,11 +352,11 @@ void ShellCommand::runFullySynchronous(QtcProcess &process, const FilePath &work
|
|||||||
process.runBlocking();
|
process.runBlocking();
|
||||||
|
|
||||||
if (!d->m_aborted) {
|
if (!d->m_aborted) {
|
||||||
const QString stdErr = process.stdErr();
|
const QString stdErr = process.cleanedStdErr();
|
||||||
if (!stdErr.isEmpty() && !(d->m_flags & SuppressStdErr))
|
if (!stdErr.isEmpty() && !(d->m_flags & SuppressStdErr))
|
||||||
emit append(stdErr);
|
emit append(stdErr);
|
||||||
|
|
||||||
const QString stdOut = process.stdOut();
|
const QString stdOut = process.cleanedStdOut();
|
||||||
if (!stdOut.isEmpty() && d->m_flags & ShowStdOut) {
|
if (!stdOut.isEmpty() && d->m_flags & ShowStdOut) {
|
||||||
if (d->m_flags & SilentOutput)
|
if (d->m_flags & SilentOutput)
|
||||||
emit appendSilently(stdOut);
|
emit appendSilently(stdOut);
|
||||||
|
@@ -29,6 +29,11 @@
|
|||||||
#include "hostosinfo.h"
|
#include "hostosinfo.h"
|
||||||
#include "qtcassert.h"
|
#include "qtcassert.h"
|
||||||
|
|
||||||
|
#ifdef QT_WIDGETS_LIB
|
||||||
|
#include <QApplication>
|
||||||
|
#include <QClipboard>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QJsonArray>
|
#include <QJsonArray>
|
||||||
@@ -469,4 +474,16 @@ QTCREATOR_UTILS_EXPORT QString languageNameFromLanguageCode(const QString &langu
|
|||||||
return languageName;
|
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
|
} // namespace Utils
|
||||||
|
@@ -122,4 +122,12 @@ QTCREATOR_UTILS_EXPORT QString wildcardToRegularExpression(const QString &origin
|
|||||||
|
|
||||||
QTCREATOR_UTILS_EXPORT QString languageNameFromLanguageCode(const QString &languageCode);
|
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
|
} // namespace Utils
|
||||||
|
@@ -36,4 +36,6 @@ TemporaryFile::TemporaryFile(const QString &pattern) :
|
|||||||
QTC_CHECK(!QFileInfo(pattern).isAbsolute());
|
QTC_CHECK(!QFileInfo(pattern).isAbsolute());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TemporaryFile::~TemporaryFile() = default;
|
||||||
|
|
||||||
} // namespace Utils
|
} // namespace Utils
|
||||||
|
@@ -35,6 +35,7 @@ class QTCREATOR_UTILS_EXPORT TemporaryFile : public QTemporaryFile
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit TemporaryFile(const QString &pattern);
|
explicit TemporaryFile(const QString &pattern);
|
||||||
|
~TemporaryFile();
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Utils
|
} // namespace Utils
|
||||||
|
@@ -34,7 +34,7 @@ Project {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Depends { name: "Qt"; submodules: ["concurrent", "network", "qml", "widgets", "xml"] }
|
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" }
|
Depends { name: "app_version_header" }
|
||||||
|
|
||||||
files: [
|
files: [
|
||||||
|
@@ -611,9 +611,11 @@ bool AndroidBuildApkStep::init()
|
|||||||
QStringList argumentsPasswordConcealed = arguments;
|
QStringList argumentsPasswordConcealed = arguments;
|
||||||
|
|
||||||
if (m_signPackage) {
|
if (m_signPackage) {
|
||||||
arguments << "--sign" << m_keystorePath.toString() << m_certificateAlias
|
arguments << "--release"
|
||||||
|
<< "--sign" << m_keystorePath.toString() << m_certificateAlias
|
||||||
<< "--storepass" << m_keystorePasswd;
|
<< "--storepass" << m_keystorePasswd;
|
||||||
argumentsPasswordConcealed << "--sign" << "******"
|
argumentsPasswordConcealed << "--release"
|
||||||
|
<< "--sign" << "******"
|
||||||
<< "--storepass" << "******";
|
<< "--storepass" << "******";
|
||||||
if (!m_certificatePasswd.isEmpty()) {
|
if (!m_certificatePasswd.isEmpty()) {
|
||||||
arguments << "--keypass" << m_certificatePasswd;
|
arguments << "--keypass" << m_certificatePasswd;
|
||||||
@@ -1065,7 +1067,7 @@ QAbstractItemModel *AndroidBuildApkStep::keystoreCertificates()
|
|||||||
if (keytoolProc.result() > ProcessResult::FinishedWithError)
|
if (keytoolProc.result() > ProcessResult::FinishedWithError)
|
||||||
QMessageBox::critical(nullptr, tr("Error"), tr("Failed to run keytool."));
|
QMessageBox::critical(nullptr, tr("Error"), tr("Failed to run keytool."));
|
||||||
else
|
else
|
||||||
model = new CertificatesModel(keytoolProc.stdOut(), this);
|
model = new CertificatesModel(keytoolProc.cleanedStdOut(), this);
|
||||||
|
|
||||||
return model;
|
return model;
|
||||||
}
|
}
|
||||||
|
@@ -140,11 +140,16 @@ void AndroidDebugSupport::start()
|
|||||||
solibSearchPath.append(qtVersion->qtSoPaths());
|
solibSearchPath.append(qtVersion->qtSoPaths());
|
||||||
solibSearchPath.append(uniquePaths(extraLibs));
|
solibSearchPath.append(uniquePaths(extraLibs));
|
||||||
|
|
||||||
|
FilePath buildDir = AndroidManager::buildDirectory(target);
|
||||||
const RunConfiguration *activeRunConfig = target->activeRunConfiguration();
|
const RunConfiguration *activeRunConfig = target->activeRunConfiguration();
|
||||||
FilePath buildDir;
|
|
||||||
if (activeRunConfig)
|
if (activeRunConfig)
|
||||||
buildDir = activeRunConfig->buildTargetInfo().workingDirectory;
|
solibSearchPath.append(activeRunConfig->buildTargetInfo().workingDirectory.toString());
|
||||||
solibSearchPath.append(buildDir.toString());
|
solibSearchPath.append(buildDir.toString());
|
||||||
|
const auto androidLibsPath = AndroidManager::androidBuildDirectory(target)
|
||||||
|
.pathAppended("libs")
|
||||||
|
.pathAppended(AndroidManager::apkDevicePreferredAbi(target))
|
||||||
|
.toString();
|
||||||
|
solibSearchPath.append(androidLibsPath);
|
||||||
solibSearchPath.removeDuplicates();
|
solibSearchPath.removeDuplicates();
|
||||||
setSolibSearchPath(solibSearchPath);
|
setSolibSearchPath(solibSearchPath);
|
||||||
qCDebug(androidDebugSupportLog) << "SoLibSearchPath: "<<solibSearchPath;
|
qCDebug(androidDebugSupportLog) << "SoLibSearchPath: "<<solibSearchPath;
|
||||||
|
@@ -213,12 +213,12 @@ bool AndroidDeployQtStep::init()
|
|||||||
m_serialNumber = info.serialNumber;
|
m_serialNumber = info.serialNumber;
|
||||||
qCDebug(deployStepLog) << "Selected device info:" << info;
|
qCDebug(deployStepLog) << "Selected device info:" << info;
|
||||||
|
|
||||||
gatherFilesToPull();
|
|
||||||
|
|
||||||
AndroidManager::setDeviceSerialNumber(target(), m_serialNumber);
|
AndroidManager::setDeviceSerialNumber(target(), m_serialNumber);
|
||||||
AndroidManager::setDeviceApiLevel(target(), info.sdk);
|
AndroidManager::setDeviceApiLevel(target(), info.sdk);
|
||||||
AndroidManager::setDeviceAbis(target(), info.cpuAbi);
|
AndroidManager::setDeviceAbis(target(), info.cpuAbi);
|
||||||
|
|
||||||
|
gatherFilesToPull();
|
||||||
|
|
||||||
emit addOutput(tr("Deploying to %1").arg(m_serialNumber), OutputFormat::NormalMessage);
|
emit addOutput(tr("Deploying to %1").arg(m_serialNumber), OutputFormat::NormalMessage);
|
||||||
|
|
||||||
m_uninstallPreviousPackageRun = m_uninstallPreviousPackage->value();
|
m_uninstallPreviousPackageRun = m_uninstallPreviousPackage->value();
|
||||||
|
@@ -787,8 +787,8 @@ SdkToolResult AndroidManager::runCommand(const CommandLine &command,
|
|||||||
qCDebug(androidManagerLog) << "Running command (sync):" << command.toUserOutput();
|
qCDebug(androidManagerLog) << "Running command (sync):" << command.toUserOutput();
|
||||||
cmdProc.setCommand(command);
|
cmdProc.setCommand(command);
|
||||||
cmdProc.runBlocking(EventLoopMode::On);
|
cmdProc.runBlocking(EventLoopMode::On);
|
||||||
cmdResult.m_stdOut = cmdProc.stdOut().trimmed();
|
cmdResult.m_stdOut = cmdProc.cleanedStdOut().trimmed();
|
||||||
cmdResult.m_stdErr = cmdProc.stdErr().trimmed();
|
cmdResult.m_stdErr = cmdProc.cleanedStdErr().trimmed();
|
||||||
cmdResult.m_success = cmdProc.result() == ProcessResult::FinishedWithSuccess;
|
cmdResult.m_success = cmdProc.result() == ProcessResult::FinishedWithSuccess;
|
||||||
qCDebug(androidManagerLog) << "Command finshed (sync):" << command.toUserOutput()
|
qCDebug(androidManagerLog) << "Command finshed (sync):" << command.toUserOutput()
|
||||||
<< "Success:" << cmdResult.m_success
|
<< "Success:" << cmdResult.m_success
|
||||||
|
@@ -186,7 +186,7 @@ static void sdkManagerCommand(const AndroidConfig &config, const QStringList &ar
|
|||||||
proc.runBlocking(EventLoopMode::On);
|
proc.runBlocking(EventLoopMode::On);
|
||||||
if (assertionFound) {
|
if (assertionFound) {
|
||||||
output.success = false;
|
output.success = false;
|
||||||
output.stdOutput = proc.stdOut();
|
output.stdOutput = proc.cleanedStdOut();
|
||||||
output.stdError = QCoreApplication::translate("Android::Internal::AndroidSdkManager",
|
output.stdError = QCoreApplication::translate("Android::Internal::AndroidSdkManager",
|
||||||
"The operation requires user interaction. "
|
"The operation requires user interaction. "
|
||||||
"Use the \"sdkmanager\" command-line tool.");
|
"Use the \"sdkmanager\" command-line tool.");
|
||||||
|
@@ -51,10 +51,8 @@ BoostTestOutputReader::BoostTestOutputReader(const QFutureInterface<TestResultPt
|
|||||||
, m_logLevel(log)
|
, m_logLevel(log)
|
||||||
, m_reportLevel(report)
|
, m_reportLevel(report)
|
||||||
{
|
{
|
||||||
if (m_testApplication) {
|
if (m_testApplication)
|
||||||
connect(m_testApplication, &Utils::QtcProcess::finished,
|
connect(m_testApplication, &Utils::QtcProcess::done, this, &BoostTestOutputReader::onDone);
|
||||||
this, &BoostTestOutputReader::onFinished);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// content of "error:..." / "info:..." / ... messages
|
// content of "error:..." / "info:..." / ... messages
|
||||||
@@ -406,7 +404,7 @@ TestResultPtr BoostTestOutputReader::createDefaultResult() const
|
|||||||
return TestResultPtr(result);
|
return TestResultPtr(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BoostTestOutputReader::onFinished() {
|
void BoostTestOutputReader::onDone() {
|
||||||
int exitCode = m_testApplication->exitCode();
|
int exitCode = m_testApplication->exitCode();
|
||||||
if (m_reportLevel == ReportLevel::No && m_testCaseCount != -1) {
|
if (m_reportLevel == ReportLevel::No && m_testCaseCount != -1) {
|
||||||
int reportedFailsAndSkips = m_summary[ResultType::Fail] + m_summary[ResultType::Skip];
|
int reportedFailsAndSkips = m_summary[ResultType::Fail] + m_summary[ResultType::Skip];
|
||||||
|
@@ -47,7 +47,7 @@ protected:
|
|||||||
TestResultPtr createDefaultResult() const override;
|
TestResultPtr createDefaultResult() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void onFinished();
|
void onDone();
|
||||||
void sendCompleteInformation();
|
void sendCompleteInformation();
|
||||||
void handleMessageMatch(const QRegularExpressionMatch &match);
|
void handleMessageMatch(const QRegularExpressionMatch &match);
|
||||||
void reportNoOutputFinish(const QString &description, ResultType type);
|
void reportNoOutputFinish(const QString &description, ResultType type);
|
||||||
|
@@ -45,9 +45,8 @@ GTestOutputReader::GTestOutputReader(const QFutureInterface<TestResultPtr> &futu
|
|||||||
, m_projectFile(projectFile)
|
, m_projectFile(projectFile)
|
||||||
{
|
{
|
||||||
if (m_testApplication) {
|
if (m_testApplication) {
|
||||||
connect(m_testApplication, &Utils::QtcProcess::finished,
|
connect(m_testApplication, &Utils::QtcProcess::done, this, [this] {
|
||||||
this, [this]() {
|
const int exitCode = m_testApplication->exitCode();
|
||||||
int exitCode = m_testApplication->exitCode();
|
|
||||||
if (exitCode == 1 && !m_description.isEmpty()) {
|
if (exitCode == 1 && !m_description.isEmpty()) {
|
||||||
createAndReportResult(tr("Running tests failed.\n %1\nExecutable: %2")
|
createAndReportResult(tr("Running tests failed.\n %1\nExecutable: %2")
|
||||||
.arg(m_description).arg(id()), ResultType::MessageFatal);
|
.arg(m_description).arg(id()), ResultType::MessageFatal);
|
||||||
|
@@ -197,7 +197,7 @@ bool TestRunner::currentConfigValid()
|
|||||||
m_fakeFutureInterface->reportFinished();
|
m_fakeFutureInterface->reportFinished();
|
||||||
onFinished();
|
onFinished();
|
||||||
} else {
|
} else {
|
||||||
onProcessFinished();
|
onProcessDone();
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -263,21 +263,20 @@ void TestRunner::scheduleNext()
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (!m_currentConfig->project())
|
if (!m_currentConfig->project())
|
||||||
onProcessFinished();
|
onProcessDone();
|
||||||
|
|
||||||
setUpProcess();
|
setUpProcess();
|
||||||
QTC_ASSERT(m_currentProcess, onProcessFinished(); return);
|
QTC_ASSERT(m_currentProcess, onProcessDone(); return);
|
||||||
QTC_ASSERT(!m_currentOutputReader, delete m_currentOutputReader);
|
QTC_ASSERT(!m_currentOutputReader, delete m_currentOutputReader);
|
||||||
m_currentOutputReader = m_currentConfig->outputReader(*m_fakeFutureInterface, m_currentProcess);
|
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,
|
connect(m_currentOutputReader, &TestOutputReader::newOutputLineAvailable,
|
||||||
TestResultsPane::instance(), &TestResultsPane::addOutputLine);
|
TestResultsPane::instance(), &TestResultsPane::addOutputLine);
|
||||||
|
|
||||||
setUpProcessEnv();
|
setUpProcessEnv();
|
||||||
|
|
||||||
connect(m_currentProcess, &Utils::QtcProcess::finished,
|
connect(m_currentProcess, &Utils::QtcProcess::done, this, &TestRunner::onProcessDone);
|
||||||
this, &TestRunner::onProcessFinished);
|
|
||||||
const int timeout = AutotestPlugin::settings()->timeout;
|
const int timeout = AutotestPlugin::settings()->timeout;
|
||||||
m_cancelTimer.setInterval(timeout);
|
m_cancelTimer.setInterval(timeout);
|
||||||
m_cancelTimer.start();
|
m_cancelTimer.start();
|
||||||
@@ -292,7 +291,7 @@ void TestRunner::scheduleNext()
|
|||||||
reportResult(ResultType::MessageFatal,
|
reportResult(ResultType::MessageFatal,
|
||||||
tr("Failed to start test for project \"%1\".").arg(m_currentConfig->displayName())
|
tr("Failed to start test for project \"%1\".").arg(m_currentConfig->displayName())
|
||||||
+ processInformation(m_currentProcess) + rcInfo(m_currentConfig));
|
+ 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) {
|
if (m_executingTests && m_currentConfig) {
|
||||||
QTC_CHECK(m_fakeFutureInterface);
|
QTC_CHECK(m_fakeFutureInterface);
|
||||||
|
@@ -90,7 +90,7 @@ private:
|
|||||||
void setUpProcessEnv();
|
void setUpProcessEnv();
|
||||||
void scheduleNext();
|
void scheduleNext();
|
||||||
void cancelCurrent(CancelReason reason);
|
void cancelCurrent(CancelReason reason);
|
||||||
void onProcessFinished();
|
void onProcessDone();
|
||||||
void resetInternalPointers();
|
void resetInternalPointers();
|
||||||
|
|
||||||
void runTests();
|
void runTests();
|
||||||
|
@@ -91,12 +91,12 @@ UvscServerProvider::UvscServerProvider(const UvscServerProvider &other)
|
|||||||
setEngineType(UvscEngineType);
|
setEngineType(UvscEngineType);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UvscServerProvider::setToolsIniFile(const Utils::FilePath &toolsIniFile)
|
void UvscServerProvider::setToolsIniFile(const FilePath &toolsIniFile)
|
||||||
{
|
{
|
||||||
m_toolsIniFile = toolsIniFile;
|
m_toolsIniFile = toolsIniFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
Utils::FilePath UvscServerProvider::toolsIniFile() const
|
FilePath UvscServerProvider::toolsIniFile() const
|
||||||
{
|
{
|
||||||
return m_toolsIniFile;
|
return m_toolsIniFile;
|
||||||
}
|
}
|
||||||
@@ -251,8 +251,7 @@ bool UvscServerProvider::fromMap(const QVariantMap &data)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Utils::FilePath UvscServerProvider::projectFilePath(DebuggerRunTool *runTool,
|
FilePath UvscServerProvider::projectFilePath(DebuggerRunTool *runTool, QString &errorMessage) const
|
||||||
QString &errorMessage) const
|
|
||||||
{
|
{
|
||||||
const FilePath projectPath = buildProjectFilePath(runTool);
|
const FilePath projectPath = buildProjectFilePath(runTool);
|
||||||
std::ofstream ofs(projectPath.toString().toStdString(), std::ofstream::out);
|
std::ofstream ofs(projectPath.toString().toStdString(), std::ofstream::out);
|
||||||
@@ -332,12 +331,12 @@ void UvscServerProviderConfigWidget::discard()
|
|||||||
IDebugServerProviderConfigWidget::discard();
|
IDebugServerProviderConfigWidget::discard();
|
||||||
}
|
}
|
||||||
|
|
||||||
void UvscServerProviderConfigWidget::setToolsIniFile(const Utils::FilePath &toolsIniFile)
|
void UvscServerProviderConfigWidget::setToolsIniFile(const FilePath &toolsIniFile)
|
||||||
{
|
{
|
||||||
m_toolsIniChooser->setFilePath(toolsIniFile);
|
m_toolsIniChooser->setFilePath(toolsIniFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
Utils::FilePath UvscServerProviderConfigWidget::toolsIniFile() const
|
FilePath UvscServerProviderConfigWidget::toolsIniFile() const
|
||||||
{
|
{
|
||||||
return m_toolsIniChooser->filePath();
|
return m_toolsIniChooser->filePath();
|
||||||
}
|
}
|
||||||
@@ -386,21 +385,16 @@ UvscServerProviderRunner::UvscServerProviderRunner(ProjectExplorer::RunControl *
|
|||||||
this->runControl()->setApplicationProcessHandle(pid);
|
this->runControl()->setApplicationProcessHandle(pid);
|
||||||
reportStarted();
|
reportStarted();
|
||||||
});
|
});
|
||||||
connect(&m_process, &QtcProcess::finished, this, [this] {
|
connect(&m_process, &QtcProcess::done, this, [this] {
|
||||||
const QProcess::ProcessError error = m_process.error();
|
appendMessage(m_process.exitMessage(), NormalMessageFormat);
|
||||||
const QString message = (error == QProcess::UnknownError)
|
|
||||||
? m_process.exitMessage()
|
|
||||||
: userMessageForProcessError(error, m_process.commandLine().executable());
|
|
||||||
appendMessage(message, Utils::NormalMessageFormat);
|
|
||||||
reportStopped();
|
reportStopped();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void UvscServerProviderRunner::start()
|
void UvscServerProviderRunner::start()
|
||||||
{
|
{
|
||||||
const QString msg = RunControl::tr("Starting %1 ...")
|
const QString msg = RunControl::tr("Starting %1 ...").arg(m_process.commandLine().displayName());
|
||||||
.arg(m_process.commandLine().toUserOutput());
|
appendMessage(msg, NormalMessageFormat);
|
||||||
appendMessage(msg, Utils::NormalMessageFormat);
|
|
||||||
|
|
||||||
m_process.start();
|
m_process.start();
|
||||||
}
|
}
|
||||||
|
@@ -153,7 +153,7 @@ bool BazaarClient::synchronousUncommit(const FilePath &workingDir,
|
|||||||
|
|
||||||
QtcProcess proc;
|
QtcProcess proc;
|
||||||
vcsFullySynchronousExec(proc, workingDir, args);
|
vcsFullySynchronousExec(proc, workingDir, args);
|
||||||
VcsOutputWindow::append(proc.stdOut());
|
VcsOutputWindow::append(proc.cleanedStdOut());
|
||||||
return proc.result() == ProcessResult::FinishedWithSuccess;
|
return proc.result() == ProcessResult::FinishedWithSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -34,11 +34,16 @@
|
|||||||
#include <utils/fileutils.h>
|
#include <utils/fileutils.h>
|
||||||
#include <utils/genericconstants.h>
|
#include <utils/genericconstants.h>
|
||||||
#include <utils/mimeutils.h>
|
#include <utils/mimeutils.h>
|
||||||
|
#include <utils/qtcprocess.h>
|
||||||
|
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
|
#include <QRegularExpression>
|
||||||
|
#include <QVersionNumber>
|
||||||
#include <QXmlStreamReader>
|
#include <QXmlStreamReader>
|
||||||
|
|
||||||
|
using namespace Utils;
|
||||||
|
|
||||||
namespace Beautifier {
|
namespace Beautifier {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
@@ -47,12 +52,65 @@ const char COMMAND[] = "command";
|
|||||||
const char SUPPORTED_MIME[] = "supportedMime";
|
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)
|
AbstractSettings::AbstractSettings(const QString &name, const QString &ending)
|
||||||
: m_ending(ending)
|
: m_ending(ending)
|
||||||
, m_styleDir(Core::ICore::userResourcePath(Beautifier::Constants::SETTINGS_DIRNAME)
|
, m_styleDir(Core::ICore::userResourcePath(Beautifier::Constants::SETTINGS_DIRNAME)
|
||||||
.pathAppended(name)
|
.pathAppended(name)
|
||||||
.toString())
|
.toString())
|
||||||
, m_name(name)
|
, 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);
|
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;
|
return;
|
||||||
|
|
||||||
m_command = command;
|
m_command = cmd;
|
||||||
updateVersion();
|
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
|
m_versionUpdater->setVersionRegExp(versionRegExp);
|
||||||
// in m_version.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString AbstractSettings::supportedMimeTypesAsString() const
|
QString AbstractSettings::supportedMimeTypesAsString() const
|
||||||
@@ -157,7 +214,7 @@ void AbstractSettings::setSupportedMimeTypes(const QString &mimes)
|
|||||||
const QStringList stringTypes = mimes.split(';');
|
const QStringList stringTypes = mimes.split(';');
|
||||||
QStringList types;
|
QStringList types;
|
||||||
for (const QString &type : stringTypes) {
|
for (const QString &type : stringTypes) {
|
||||||
const Utils::MimeType mime = Utils::mimeTypeForName(type.trimmed());
|
const MimeType mime = mimeTypeForName(type.trimmed());
|
||||||
if (!mime.isValid())
|
if (!mime.isValid())
|
||||||
continue;
|
continue;
|
||||||
const QString canonicalName = mime.name();
|
const QString canonicalName = mime.name();
|
||||||
@@ -179,8 +236,8 @@ bool AbstractSettings::isApplicable(const Core::IDocument *document) const
|
|||||||
if (m_supportedMimeTypes.isEmpty())
|
if (m_supportedMimeTypes.isEmpty())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
const Utils::MimeType documentMimeType = Utils::mimeTypeForName(document->mimeType());
|
const MimeType documentMimeType = mimeTypeForName(document->mimeType());
|
||||||
return Utils::anyOf(m_supportedMimeTypes, [&documentMimeType](const QString &mime) {
|
return anyOf(m_supportedMimeTypes, [&documentMimeType](const QString &mime) {
|
||||||
return documentMimeType.inherits(mime);
|
return documentMimeType.inherits(mime);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -246,7 +303,7 @@ void AbstractSettings::save()
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
Utils::FileSaver saver(Utils::FilePath::fromUserInput(fi.absoluteFilePath()));
|
FileSaver saver(FilePath::fromUserInput(fi.absoluteFilePath()));
|
||||||
if (saver.hasError()) {
|
if (saver.hasError()) {
|
||||||
BeautifierPlugin::showError(tr("Cannot open file \"%1\": %2.")
|
BeautifierPlugin::showError(tr("Cannot open file \"%1\": %2.")
|
||||||
.arg(saver.filePath().toUserOutput())
|
.arg(saver.filePath().toUserOutput())
|
||||||
|
@@ -35,12 +35,21 @@
|
|||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
#include <QVector>
|
#include <QVector>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
class QRegularExpression;
|
||||||
|
class QVersionNumber;
|
||||||
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
namespace Core { class IDocument; }
|
namespace Core { class IDocument; }
|
||||||
namespace Utils { class FilePath; }
|
namespace Utils { class FilePath; }
|
||||||
|
|
||||||
namespace Beautifier {
|
namespace Beautifier {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
|
class VersionUpdater;
|
||||||
|
|
||||||
class AbstractSettings : public QObject
|
class AbstractSettings : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@@ -66,9 +75,8 @@ public:
|
|||||||
virtual QString styleFileName(const QString &key) const;
|
virtual QString styleFileName(const QString &key) const;
|
||||||
|
|
||||||
Utils::FilePath command() const;
|
Utils::FilePath command() const;
|
||||||
void setCommand(const QString &command);
|
void setCommand(const QString &cmd);
|
||||||
int version() const;
|
QVersionNumber version() const;
|
||||||
virtual void updateVersion();
|
|
||||||
|
|
||||||
QString supportedMimeTypesAsString() const;
|
QString supportedMimeTypesAsString() const;
|
||||||
void setSupportedMimeTypes(const QString &mimes);
|
void setSupportedMimeTypes(const QString &mimes);
|
||||||
@@ -81,9 +89,10 @@ signals:
|
|||||||
void supportedMimeTypesChanged();
|
void supportedMimeTypesChanged();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
void setVersionRegExp(const QRegularExpression &versionRegExp);
|
||||||
|
|
||||||
QMap<QString, QString> m_styles;
|
QMap<QString, QString> m_styles;
|
||||||
QMap<QString, QVariant> m_settings;
|
QMap<QString, QVariant> m_settings;
|
||||||
int m_version = 0;
|
|
||||||
QString m_ending;
|
QString m_ending;
|
||||||
QDir m_styleDir;
|
QDir m_styleDir;
|
||||||
|
|
||||||
@@ -92,6 +101,7 @@ protected:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
QString m_name;
|
QString m_name;
|
||||||
|
std::unique_ptr<VersionUpdater> m_versionUpdater;
|
||||||
QStringList m_stylesToRemove;
|
QStringList m_stylesToRemove;
|
||||||
QSet<QString> m_changedStyles;
|
QSet<QString> m_changedStyles;
|
||||||
QString m_command;
|
QString m_command;
|
||||||
|
@@ -53,6 +53,7 @@
|
|||||||
|
|
||||||
#include <QAction>
|
#include <QAction>
|
||||||
#include <QMenu>
|
#include <QMenu>
|
||||||
|
#include <QVersionNumber>
|
||||||
|
|
||||||
using namespace TextEditor;
|
using namespace TextEditor;
|
||||||
|
|
||||||
@@ -150,10 +151,10 @@ Command ArtisticStyle::command(const QString &cfgFile) const
|
|||||||
command.addOption("-q");
|
command.addOption("-q");
|
||||||
command.addOption("--options=" + cfgFile);
|
command.addOption("--options=" + cfgFile);
|
||||||
|
|
||||||
const int version = m_settings.version();
|
const QVersionNumber version = m_settings.version();
|
||||||
if (version > ArtisticStyleSettings::Version_2_03) {
|
if (version > QVersionNumber(2, 3)) {
|
||||||
command.setProcessing(Command::PipeProcessing);
|
command.setProcessing(Command::PipeProcessing);
|
||||||
if (version == ArtisticStyleSettings::Version_2_04)
|
if (version == QVersionNumber(2, 4))
|
||||||
command.setPipeAddsNewline(true);
|
command.setPipeAddsNewline(true);
|
||||||
command.setReturnsCRLF(Utils::HostOsInfo::isWindowsHost());
|
command.setReturnsCRLF(Utils::HostOsInfo::isWindowsHost());
|
||||||
command.addOption("-z2");
|
command.addOption("-z2");
|
||||||
|
@@ -57,9 +57,7 @@ const char SETTINGS_NAME[] = "artisticstyle";
|
|||||||
ArtisticStyleSettings::ArtisticStyleSettings() :
|
ArtisticStyleSettings::ArtisticStyleSettings() :
|
||||||
AbstractSettings(SETTINGS_NAME, ".astyle")
|
AbstractSettings(SETTINGS_NAME, ".astyle")
|
||||||
{
|
{
|
||||||
connect(&m_versionWatcher, &QFutureWatcherBase::finished,
|
setVersionRegExp(QRegularExpression("([2-9]{1})\\.([0-9]{1,2})(\\.[1-9]{1})?$"));
|
||||||
this, &ArtisticStyleSettings::helperSetVersion);
|
|
||||||
|
|
||||||
setCommand("astyle");
|
setCommand("astyle");
|
||||||
m_settings.insert(USE_OTHER_FILES, QVariant(true));
|
m_settings.insert(USE_OTHER_FILES, QVariant(true));
|
||||||
m_settings.insert(USE_SPECIFIC_CONFIG_FILE, QVariant(false));
|
m_settings.insert(USE_SPECIFIC_CONFIG_FILE, QVariant(false));
|
||||||
@@ -70,48 +68,6 @@ ArtisticStyleSettings::ArtisticStyleSettings() :
|
|||||||
read();
|
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
|
bool ArtisticStyleSettings::useOtherFiles() const
|
||||||
{
|
{
|
||||||
return m_settings.value(USE_OTHER_FILES).toBool();
|
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));
|
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()));
|
m_settings.insert(SPECIFIC_CONFIG_FILE, QVariant(specificConfigFile.toString()));
|
||||||
}
|
}
|
||||||
@@ -182,7 +138,7 @@ QString ArtisticStyleSettings::documentationFilePath() const
|
|||||||
|
|
||||||
void ArtisticStyleSettings::createDocumentationFile() const
|
void ArtisticStyleSettings::createDocumentationFile() const
|
||||||
{
|
{
|
||||||
Utils::QtcProcess process;
|
QtcProcess process;
|
||||||
process.setTimeoutS(2);
|
process.setTimeoutS(2);
|
||||||
process.setCommand({command(), {"-h"}});
|
process.setCommand({command(), {"-h"}});
|
||||||
process.runBlocking();
|
process.runBlocking();
|
||||||
@@ -204,7 +160,7 @@ void ArtisticStyleSettings::createDocumentationFile() const
|
|||||||
stream.writeStartElement(Constants::DOCUMENTATION_XMLROOT);
|
stream.writeStartElement(Constants::DOCUMENTATION_XMLROOT);
|
||||||
|
|
||||||
// astyle writes its output to 'error'...
|
// 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 keys;
|
||||||
QStringList docu;
|
QStringList docu;
|
||||||
for (QString line : lines) {
|
for (QString line : lines) {
|
||||||
|
@@ -29,9 +29,6 @@
|
|||||||
|
|
||||||
#include <utils/fileutils.h>
|
#include <utils/fileutils.h>
|
||||||
|
|
||||||
#include <QFuture>
|
|
||||||
#include <QFutureWatcher>
|
|
||||||
|
|
||||||
namespace Beautifier {
|
namespace Beautifier {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
@@ -40,15 +37,8 @@ class ArtisticStyleSettings : public AbstractSettings
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum ArtisticStyleVersion {
|
|
||||||
Version_2_03 = 203,
|
|
||||||
Version_2_04 = 204
|
|
||||||
};
|
|
||||||
|
|
||||||
ArtisticStyleSettings();
|
ArtisticStyleSettings();
|
||||||
|
|
||||||
void updateVersion() override;
|
|
||||||
|
|
||||||
bool useOtherFiles() const;
|
bool useOtherFiles() const;
|
||||||
void setUseOtherFiles(bool useOtherFiles);
|
void setUseOtherFiles(bool useOtherFiles);
|
||||||
|
|
||||||
@@ -69,11 +59,6 @@ public:
|
|||||||
|
|
||||||
QString documentationFilePath() const override;
|
QString documentationFilePath() const override;
|
||||||
void createDocumentationFile() const override;
|
void createDocumentationFile() const override;
|
||||||
|
|
||||||
private:
|
|
||||||
void helperSetVersion();
|
|
||||||
QFuture<int> m_versionFuture;
|
|
||||||
QFutureWatcher<int> m_versionWatcher;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
|
@@ -49,6 +49,7 @@
|
|||||||
|
|
||||||
#include <QAction>
|
#include <QAction>
|
||||||
#include <QMenu>
|
#include <QMenu>
|
||||||
|
#include <QVersionNumber>
|
||||||
|
|
||||||
using namespace TextEditor;
|
using namespace TextEditor;
|
||||||
|
|
||||||
@@ -180,7 +181,7 @@ Command Uncrustify::command(const QString &cfgFile, bool fragment) const
|
|||||||
Command command;
|
Command command;
|
||||||
command.setExecutable(m_settings.command().toString());
|
command.setExecutable(m_settings.command().toString());
|
||||||
command.setProcessing(Command::PipeProcessing);
|
command.setProcessing(Command::PipeProcessing);
|
||||||
if (m_settings.version() >= 62) {
|
if (m_settings.version() >= QVersionNumber(0, 62)) {
|
||||||
command.addOption("--assume");
|
command.addOption("--assume");
|
||||||
command.addOption("%file");
|
command.addOption("%file");
|
||||||
} else {
|
} else {
|
||||||
|
@@ -30,7 +30,6 @@
|
|||||||
#include "../beautifierconstants.h"
|
#include "../beautifierconstants.h"
|
||||||
|
|
||||||
#include <coreplugin/icore.h>
|
#include <coreplugin/icore.h>
|
||||||
|
|
||||||
#include <utils/qtcprocess.h>
|
#include <utils/qtcprocess.h>
|
||||||
|
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
@@ -56,6 +55,7 @@ const char SETTINGS_NAME[] = "uncrustify";
|
|||||||
UncrustifySettings::UncrustifySettings() :
|
UncrustifySettings::UncrustifySettings() :
|
||||||
AbstractSettings(SETTINGS_NAME, ".cfg")
|
AbstractSettings(SETTINGS_NAME, ".cfg")
|
||||||
{
|
{
|
||||||
|
setVersionRegExp(QRegularExpression("([0-9]{1})\\.([0-9]{2})"));
|
||||||
setCommand("uncrustify");
|
setCommand("uncrustify");
|
||||||
m_settings.insert(USE_OTHER_FILES, QVariant(true));
|
m_settings.insert(USE_OTHER_FILES, QVariant(true));
|
||||||
m_settings.insert(USE_HOME_FILE, QVariant(false));
|
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 Internal
|
||||||
} // namespace Beautifier
|
} // namespace Beautifier
|
||||||
|
@@ -26,9 +26,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "../abstractsettings.h"
|
#include "../abstractsettings.h"
|
||||||
#include <utils/fileutils.h>
|
|
||||||
|
|
||||||
namespace Utils { class QtcProcess; }
|
|
||||||
|
|
||||||
namespace Beautifier {
|
namespace Beautifier {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
@@ -59,16 +56,11 @@ public:
|
|||||||
QString documentationFilePath() const override;
|
QString documentationFilePath() const override;
|
||||||
void createDocumentationFile() const override;
|
void createDocumentationFile() const override;
|
||||||
|
|
||||||
void updateVersion() override;
|
|
||||||
|
|
||||||
Utils::FilePath specificConfigFile() const;
|
Utils::FilePath specificConfigFile() const;
|
||||||
void setSpecificConfigFile(const Utils::FilePath &filePath);
|
void setSpecificConfigFile(const Utils::FilePath &filePath);
|
||||||
|
|
||||||
bool useSpecificConfigFile() const;
|
bool useSpecificConfigFile() const;
|
||||||
void setUseSpecificConfigFile(bool useConfigFile);
|
void setUseSpecificConfigFile(bool useConfigFile);
|
||||||
|
|
||||||
private:
|
|
||||||
std::unique_ptr<Utils::QtcProcess> m_versionProcess;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
|
@@ -88,8 +88,8 @@ public:
|
|||||||
private:
|
private:
|
||||||
void handleDone()
|
void handleDone()
|
||||||
{
|
{
|
||||||
const QString stdOut = m_appRunner.stdOut();
|
const QString stdOut = m_appRunner.cleanedStdOut();
|
||||||
const QString stdErr = m_appRunner.stdErr();
|
const QString stdErr = m_appRunner.cleanedStdErr();
|
||||||
|
|
||||||
// FIXME: Needed in a post-adb world?
|
// FIXME: Needed in a post-adb world?
|
||||||
// adb does not forward exit codes and all stderr goes to stdout.
|
// adb does not forward exit codes and all stderr goes to stdout.
|
||||||
|
@@ -55,7 +55,7 @@ public:
|
|||||||
setId("QdbDebuggeeRunner");
|
setId("QdbDebuggeeRunner");
|
||||||
|
|
||||||
connect(&m_launcher, &QtcProcess::started, this, &RunWorker::reportStarted);
|
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] {
|
connect(&m_launcher, &QtcProcess::readyReadStandardOutput, [this] {
|
||||||
appendMessage(QString::fromUtf8(m_launcher.readAllStandardOutput()), StdOutFormat);
|
appendMessage(QString::fromUtf8(m_launcher.readAllStandardOutput()), StdOutFormat);
|
||||||
|
@@ -22,6 +22,7 @@ add_qtc_plugin(ClangCodeModel
|
|||||||
clangdquickfixfactory.cpp clangdquickfixfactory.h
|
clangdquickfixfactory.cpp clangdquickfixfactory.h
|
||||||
clangdqpropertyhighlighter.cpp clangdqpropertyhighlighter.h
|
clangdqpropertyhighlighter.cpp clangdqpropertyhighlighter.h
|
||||||
clangdsemantichighlighting.cpp clangdsemantichighlighting.h
|
clangdsemantichighlighting.cpp clangdsemantichighlighting.h
|
||||||
|
clangdswitchdecldef.cpp clangdswitchdecldef.h
|
||||||
clangeditordocumentprocessor.cpp clangeditordocumentprocessor.h
|
clangeditordocumentprocessor.cpp clangeditordocumentprocessor.h
|
||||||
clangfixitoperation.cpp clangfixitoperation.h
|
clangfixitoperation.cpp clangfixitoperation.h
|
||||||
clangdlocatorfilters.cpp clangdlocatorfilters.h
|
clangdlocatorfilters.cpp clangdlocatorfilters.h
|
||||||
|
@@ -46,6 +46,8 @@ QtcPlugin {
|
|||||||
"clangdquickfixfactory.h",
|
"clangdquickfixfactory.h",
|
||||||
"clangdsemantichighlighting.cpp",
|
"clangdsemantichighlighting.cpp",
|
||||||
"clangdsemantichighlighting.h",
|
"clangdsemantichighlighting.h",
|
||||||
|
"clangdswitchdecldef.cpp",
|
||||||
|
"clangdswitchdecldef.h",
|
||||||
"clangeditordocumentprocessor.cpp",
|
"clangeditordocumentprocessor.cpp",
|
||||||
"clangeditordocumentprocessor.h",
|
"clangeditordocumentprocessor.h",
|
||||||
"clangfixitoperation.cpp",
|
"clangfixitoperation.cpp",
|
||||||
|
@@ -30,6 +30,7 @@
|
|||||||
#include "clangdast.h"
|
#include "clangdast.h"
|
||||||
#include "clangdfollowsymbol.h"
|
#include "clangdfollowsymbol.h"
|
||||||
#include "clangdlocatorfilters.h"
|
#include "clangdlocatorfilters.h"
|
||||||
|
#include "clangdswitchdecldef.h"
|
||||||
#include "clangpreprocessorassistproposalitem.h"
|
#include "clangpreprocessorassistproposalitem.h"
|
||||||
#include "clangtextmark.h"
|
#include "clangtextmark.h"
|
||||||
#include "clangutils.h"
|
#include "clangutils.h"
|
||||||
@@ -59,7 +60,6 @@
|
|||||||
#include <cppeditor/semantichighlighter.h>
|
#include <cppeditor/semantichighlighter.h>
|
||||||
#include <cppeditor/cppsemanticinfo.h>
|
#include <cppeditor/cppsemanticinfo.h>
|
||||||
#include <languageclient/diagnosticmanager.h>
|
#include <languageclient/diagnosticmanager.h>
|
||||||
#include <languageclient/documentsymbolcache.h>
|
|
||||||
#include <languageclient/languageclientcompletionassist.h>
|
#include <languageclient/languageclientcompletionassist.h>
|
||||||
#include <languageclient/languageclientfunctionhint.h>
|
#include <languageclient/languageclientfunctionhint.h>
|
||||||
#include <languageclient/languageclienthoverhandler.h>
|
#include <languageclient/languageclienthoverhandler.h>
|
||||||
@@ -117,8 +117,8 @@ namespace ClangCodeModel {
|
|||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
Q_LOGGING_CATEGORY(clangdLog, "qtc.clangcodemodel.clangd", QtWarningMsg);
|
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(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",
|
static Q_LOGGING_CATEGORY(clangdLogCompletion, "qtc.clangcodemodel.clangd.completion",
|
||||||
QtWarningMsg);
|
QtWarningMsg);
|
||||||
static QString indexingToken() { return "backgroundIndexProgress"; }
|
static QString indexingToken() { return "backgroundIndexProgress"; }
|
||||||
@@ -310,58 +310,6 @@ public:
|
|||||||
bool categorize = CppEditor::codeModelSettings()->categorizeFindReferences();
|
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 {
|
class LocalRefsData {
|
||||||
public:
|
public:
|
||||||
LocalRefsData(quint64 id, TextDocument *doc, const QTextCursor &cursor,
|
LocalRefsData(quint64 id, TextDocument *doc, const QTextCursor &cursor,
|
||||||
@@ -699,7 +647,7 @@ public:
|
|||||||
const CppEditor::ClangdSettings::Data settings;
|
const CppEditor::ClangdSettings::Data settings;
|
||||||
QHash<quint64, ReferencesData> runningFindUsages;
|
QHash<quint64, ReferencesData> runningFindUsages;
|
||||||
ClangdFollowSymbol *followSymbol = nullptr;
|
ClangdFollowSymbol *followSymbol = nullptr;
|
||||||
Utils::optional<SwitchDeclDefData> switchDeclDefData;
|
ClangdSwitchDeclDef *switchDeclDef = nullptr;
|
||||||
Utils::optional<LocalRefsData> localRefsData;
|
Utils::optional<LocalRefsData> localRefsData;
|
||||||
Utils::optional<QVersionNumber> versionNumber;
|
Utils::optional<QVersionNumber> versionNumber;
|
||||||
|
|
||||||
@@ -741,6 +689,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
QIcon icon() const override;
|
QIcon icon() const override;
|
||||||
|
QString text() const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ClangdClient::ClangdCompletionAssistProcessor : public LanguageClientCompletionAssistProcessor
|
class ClangdClient::ClangdCompletionAssistProcessor : public LanguageClientCompletionAssistProcessor
|
||||||
@@ -1015,15 +964,6 @@ ClangdClient::ClangdClient(Project *project, const Utils::FilePath &jsonDbDir)
|
|||||||
QTC_CHECK(d->runningFindUsages.isEmpty());
|
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();
|
start();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1682,26 +1622,13 @@ void ClangdClient::switchDeclDef(TextDocument *document, const QTextCursor &curs
|
|||||||
|
|
||||||
qCDebug(clangdLog) << "switch decl/dev requested" << document->filePath()
|
qCDebug(clangdLog) << "switch decl/dev requested" << document->filePath()
|
||||||
<< cursor.blockNumber() << cursor.positionInBlock();
|
<< cursor.blockNumber() << cursor.positionInBlock();
|
||||||
d->switchDeclDefData.emplace(++d->nextJobId, document, cursor, editorWidget, callback);
|
if (d->switchDeclDef)
|
||||||
|
delete d->switchDeclDef;
|
||||||
// Retrieve AST and document symbols.
|
d->switchDeclDef = new ClangdSwitchDeclDef(this, document, cursor, editorWidget, callback);
|
||||||
const auto astHandler = [this, id = d->switchDeclDefData->id](const ClangdAstNode &ast,
|
connect(d->switchDeclDef, &ClangdSwitchDeclDef::done, this, [this] {
|
||||||
const MessageId &) {
|
delete d->switchDeclDef;
|
||||||
qCDebug(clangdLog) << "received ast for decl/def switch";
|
d->switchDeclDef = nullptr;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClangdClient::switchHeaderSource(const Utils::FilePath &filePath, bool inNextSplit)
|
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};
|
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(
|
Utils::optional<QString> ClangdClient::Private::getContainingFunctionName(
|
||||||
const ClangdAstPath &astPath, const Range& range)
|
const ClangdAstPath &astPath, const Range& range)
|
||||||
{
|
{
|
||||||
@@ -2551,6 +2449,8 @@ ClangdCompletionItem::SpecialQtType ClangdCompletionItem::getQtType(const Comple
|
|||||||
|
|
||||||
QIcon ClangdCompletionItem::icon() const
|
QIcon ClangdCompletionItem::icon() const
|
||||||
{
|
{
|
||||||
|
if (isDeprecated())
|
||||||
|
return Utils::Icons::WARNING.icon();
|
||||||
const SpecialQtType qtType = getQtType(item());
|
const SpecialQtType qtType = getQtType(item());
|
||||||
switch (qtType) {
|
switch (qtType) {
|
||||||
case SpecialQtType::Signal:
|
case SpecialQtType::Signal:
|
||||||
@@ -2566,6 +2466,14 @@ QIcon ClangdCompletionItem::icon() const
|
|||||||
return LanguageClientCompletionItem::icon();
|
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,
|
MessageId ClangdClient::Private::getAndHandleAst(const TextDocOrFile &doc,
|
||||||
const AstHandler &astHandler,
|
const AstHandler &astHandler,
|
||||||
AstCallbackMode callbackMode, const Range &range)
|
AstCallbackMode callbackMode, const Range &range)
|
||||||
|
@@ -51,6 +51,7 @@ namespace Internal {
|
|||||||
class ClangdAstNode;
|
class ClangdAstNode;
|
||||||
|
|
||||||
Q_DECLARE_LOGGING_CATEGORY(clangdLog);
|
Q_DECLARE_LOGGING_CATEGORY(clangdLog);
|
||||||
|
Q_DECLARE_LOGGING_CATEGORY(clangdLogAst);
|
||||||
|
|
||||||
void setupClangdConfigFile();
|
void setupClangdConfigFile();
|
||||||
|
|
||||||
|
@@ -38,6 +38,7 @@
|
|||||||
#include <texteditor/codeassist/iassistprovider.h>
|
#include <texteditor/codeassist/iassistprovider.h>
|
||||||
#include <texteditor/textdocument.h>
|
#include <texteditor/textdocument.h>
|
||||||
|
|
||||||
|
#include <QApplication>
|
||||||
#include <QPointer>
|
#include <QPointer>
|
||||||
|
|
||||||
using namespace CppEditor;
|
using namespace CppEditor;
|
||||||
@@ -133,6 +134,7 @@ public:
|
|||||||
SymbolDataList symbolsToDisplay;
|
SymbolDataList symbolsToDisplay;
|
||||||
std::set<FilePath> openedFiles;
|
std::set<FilePath> openedFiles;
|
||||||
VirtualFunctionAssistProcessor *virtualFuncAssistProcessor = nullptr;
|
VirtualFunctionAssistProcessor *virtualFuncAssistProcessor = nullptr;
|
||||||
|
QMetaObject::Connection focusChangedConnection;
|
||||||
bool finished = false;
|
bool finished = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -143,6 +145,16 @@ ClangdFollowSymbol::ClangdFollowSymbol(ClangdClient *client, const QTextCursor &
|
|||||||
d(new Private(this, client, cursor, editorWidget, document->filePath(), callback,
|
d(new Private(this, client, cursor, editorWidget, document->filePath(), callback,
|
||||||
openInSplit))
|
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
|
// 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
|
// AST node corresponding to the cursor position, so we can find out whether
|
||||||
// we have to look for overrides.
|
// 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
|
// 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.
|
// 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);
|
editorWidget->invokeTextEditorWidgetAssist(FollowSymbol, &virtualFuncAssistProvider);
|
||||||
|
}
|
||||||
|
|
||||||
if (!pendingGotoImplRequests.isEmpty())
|
if (!pendingGotoImplRequests.isEmpty())
|
||||||
return;
|
return;
|
||||||
|
188
src/plugins/clangcodemodel/clangdswitchdecldef.cpp
Normal file
188
src/plugins/clangcodemodel/clangdswitchdecldef.cpp
Normal 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
|
59
src/plugins/clangcodemodel/clangdswitchdecldef.h
Normal file
59
src/plugins/clangcodemodel/clangdswitchdecldef.h
Normal 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
|
@@ -62,10 +62,12 @@
|
|||||||
#include <projectexplorer/taskhub.h>
|
#include <projectexplorer/taskhub.h>
|
||||||
|
|
||||||
#include <utils/algorithm.h>
|
#include <utils/algorithm.h>
|
||||||
|
#include <utils/infobar.h>
|
||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
#include <utils/runextensions.h>
|
#include <utils/runextensions.h>
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
|
#include <QLabel>
|
||||||
#include <QMenu>
|
#include <QMenu>
|
||||||
#include <QTextBlock>
|
#include <QTextBlock>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
@@ -124,6 +126,40 @@ static Client *clientForGeneratedFile(const Utils::FilePath &filePath)
|
|||||||
return nullptr;
|
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()
|
ClangModelManagerSupport::ClangModelManagerSupport()
|
||||||
{
|
{
|
||||||
QTC_CHECK(!m_instance);
|
QTC_CHECK(!m_instance);
|
||||||
@@ -132,6 +168,7 @@ ClangModelManagerSupport::ClangModelManagerSupport()
|
|||||||
watchForExternalChanges();
|
watchForExternalChanges();
|
||||||
watchForInternalChanges();
|
watchForInternalChanges();
|
||||||
setupClangdConfigFile();
|
setupClangdConfigFile();
|
||||||
|
checkSystemForClangdSuitability();
|
||||||
cppModelManager()->setCurrentDocumentFilter(std::make_unique<ClangdCurrentDocumentFilter>());
|
cppModelManager()->setCurrentDocumentFilter(std::make_unique<ClangdCurrentDocumentFilter>());
|
||||||
cppModelManager()->setLocatorFilter(std::make_unique<ClangGlobalSymbolFilter>());
|
cppModelManager()->setLocatorFilter(std::make_unique<ClangGlobalSymbolFilter>());
|
||||||
cppModelManager()->setClassesFilter(std::make_unique<ClangClassesFilter>());
|
cppModelManager()->setClassesFilter(std::make_unique<ClangClassesFilter>());
|
||||||
|
@@ -29,7 +29,6 @@
|
|||||||
#include "clangdclient.h"
|
#include "clangdclient.h"
|
||||||
#include "clangdiagnostictooltipwidget.h"
|
#include "clangdiagnostictooltipwidget.h"
|
||||||
#include "clangeditordocumentprocessor.h"
|
#include "clangeditordocumentprocessor.h"
|
||||||
#include "clangmodelmanagersupport.h"
|
|
||||||
#include "clangutils.h"
|
#include "clangutils.h"
|
||||||
|
|
||||||
#include <coreplugin/icore.h>
|
#include <coreplugin/icore.h>
|
||||||
@@ -42,12 +41,11 @@
|
|||||||
|
|
||||||
#include <utils/fadingindicator.h>
|
#include <utils/fadingindicator.h>
|
||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
|
#include <utils/stringutils.h>
|
||||||
#include <utils/theme/theme.h>
|
#include <utils/theme/theme.h>
|
||||||
#include <utils/utilsicons.h>
|
#include <utils/utilsicons.h>
|
||||||
|
|
||||||
#include <QAction>
|
#include <QAction>
|
||||||
#include <QApplication>
|
|
||||||
#include <QClipboard>
|
|
||||||
#include <QLayout>
|
#include <QLayout>
|
||||||
#include <QRegularExpression>
|
#include <QRegularExpression>
|
||||||
#include <QRegularExpressionMatch>
|
#include <QRegularExpressionMatch>
|
||||||
@@ -319,7 +317,7 @@ ClangdTextMark::ClangdTextMark(const FilePath &filePath,
|
|||||||
QObject::connect(action, &QAction::triggered, [diag = m_diagnostic]() {
|
QObject::connect(action, &QAction::triggered, [diag = m_diagnostic]() {
|
||||||
const QString text = ClangDiagnosticWidget::createText({diag},
|
const QString text = ClangDiagnosticWidget::createText({diag},
|
||||||
ClangDiagnosticWidget::InfoBar);
|
ClangDiagnosticWidget::InfoBar);
|
||||||
QApplication::clipboard()->setText(text, QClipboard::Clipboard);
|
setClipboardAndSelection(text);
|
||||||
});
|
});
|
||||||
actions << action;
|
actions << action;
|
||||||
|
|
||||||
|
@@ -132,7 +132,7 @@ void ClangToolRunner::onProcessDone()
|
|||||||
if (m_process.result() == ProcessResult::StartFailed) {
|
if (m_process.result() == ProcessResult::StartFailed) {
|
||||||
emit finishedWithFailure(generalProcessError(m_name), commandlineAndOutput());
|
emit finishedWithFailure(generalProcessError(m_name), commandlineAndOutput());
|
||||||
} else if (m_process.result() == ProcessResult::FinishedWithSuccess) {
|
} 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);
|
emit finishedWithSuccess(m_fileToAnalyze);
|
||||||
} else if (m_process.result() == ProcessResult::FinishedWithError) {
|
} else if (m_process.result() == ProcessResult::FinishedWithError) {
|
||||||
emit finishedWithFailure(finishedWithBadExitCode(m_name, m_process.exitCode()),
|
emit finishedWithFailure(finishedWithBadExitCode(m_name, m_process.exitCode()),
|
||||||
@@ -149,7 +149,7 @@ QString ClangToolRunner::commandlineAndOutput() const
|
|||||||
"Output:\n%3")
|
"Output:\n%3")
|
||||||
.arg(m_commandLine.toUserOutput())
|
.arg(m_commandLine.toUserOutput())
|
||||||
.arg(m_process.error())
|
.arg(m_process.error())
|
||||||
.arg(m_process.stdOut());
|
.arg(m_process.cleanedStdOut());
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
|
@@ -30,10 +30,9 @@
|
|||||||
#include "diagnosticconfigswidget.h"
|
#include "diagnosticconfigswidget.h"
|
||||||
|
|
||||||
#include <utils/utilsicons.h>
|
#include <utils/utilsicons.h>
|
||||||
|
#include <utils/stringutils.h>
|
||||||
|
|
||||||
#include <QAction>
|
#include <QAction>
|
||||||
#include <QApplication>
|
|
||||||
#include <QClipboard>
|
|
||||||
|
|
||||||
namespace ClangTools {
|
namespace ClangTools {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
@@ -65,7 +64,7 @@ DiagnosticMark::DiagnosticMark(const Diagnostic &diagnostic)
|
|||||||
const QString text = createFullLocationString(diagnostic.location)
|
const QString text = createFullLocationString(diagnostic.location)
|
||||||
+ ": "
|
+ ": "
|
||||||
+ diagnostic.description;
|
+ diagnostic.description;
|
||||||
QApplication::clipboard()->setText(text);
|
Utils::setClipboardAndSelection(text);
|
||||||
});
|
});
|
||||||
actions << action;
|
actions << action;
|
||||||
|
|
||||||
|
@@ -251,6 +251,8 @@ QPair<FilePath, QString> getClangIncludeDirAndVersion(ClangToolRunner *runner)
|
|||||||
|
|
||||||
void DocumentClangToolRunner::runNext()
|
void DocumentClangToolRunner::runNext()
|
||||||
{
|
{
|
||||||
|
if (m_currentRunner)
|
||||||
|
m_currentRunner.release()->deleteLater();
|
||||||
m_currentRunner.reset(m_runnerCreators.isEmpty() ? nullptr : m_runnerCreators.takeFirst()());
|
m_currentRunner.reset(m_runnerCreators.isEmpty() ? nullptr : m_runnerCreators.takeFirst()());
|
||||||
if (m_currentRunner) {
|
if (m_currentRunner) {
|
||||||
auto [clangIncludeDir, clangVersion] = getClangIncludeDirAndVersion(m_currentRunner.get());
|
auto [clangIncludeDir, clangVersion] = getClangIncludeDirAndVersion(m_currentRunner.get());
|
||||||
@@ -362,10 +364,7 @@ void DocumentClangToolRunner::cancel()
|
|||||||
if (m_projectSettingsUpdate)
|
if (m_projectSettingsUpdate)
|
||||||
disconnect(m_projectSettingsUpdate);
|
disconnect(m_projectSettingsUpdate);
|
||||||
m_runnerCreators.clear();
|
m_runnerCreators.clear();
|
||||||
if (m_currentRunner) {
|
m_currentRunner.reset(nullptr);
|
||||||
m_currentRunner->disconnect(this);
|
|
||||||
m_currentRunner.reset(nullptr);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DocumentClangToolRunner::isSuppressed(const Diagnostic &diagnostic) const
|
bool DocumentClangToolRunner::isSuppressed(const Diagnostic &diagnostic) const
|
||||||
|
@@ -63,7 +63,7 @@ static QString runExecutable(const Utils::CommandLine &commandLine, QueryFailMod
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
return cpp.stdOut();
|
return cpp.cleanedStdOut();
|
||||||
}
|
}
|
||||||
|
|
||||||
static QStringList queryClangTidyChecks(const FilePath &executable,
|
static QStringList queryClangTidyChecks(const FilePath &executable,
|
||||||
|
@@ -1676,8 +1676,8 @@ ClearCasePluginPrivate::runCleartool(const FilePath &workingDir,
|
|||||||
response.error = proc.result() != ProcessResult::FinishedWithSuccess;
|
response.error = proc.result() != ProcessResult::FinishedWithSuccess;
|
||||||
if (response.error)
|
if (response.error)
|
||||||
response.message = proc.exitMessage();
|
response.message = proc.exitMessage();
|
||||||
response.stdErr = proc.stdErr();
|
response.stdErr = proc.cleanedStdErr();
|
||||||
response.stdOut = proc.stdOut();
|
response.stdOut = proc.cleanedStdOut();
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -280,19 +280,19 @@ TextEditor::Keywords CMakeTool::keywords()
|
|||||||
QtcProcess proc;
|
QtcProcess proc;
|
||||||
runCMake(proc, {"--help-command-list"}, 5);
|
runCMake(proc, {"--help-command-list"}, 5);
|
||||||
if (proc.result() == ProcessResult::FinishedWithSuccess)
|
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);
|
runCMake(proc, {"--help-commands"}, 5);
|
||||||
if (proc.result() == ProcessResult::FinishedWithSuccess)
|
if (proc.result() == ProcessResult::FinishedWithSuccess)
|
||||||
parseFunctionDetailsOutput(proc.stdOut());
|
parseFunctionDetailsOutput(proc.cleanedStdOut());
|
||||||
|
|
||||||
runCMake(proc, {"--help-property-list"}, 5);
|
runCMake(proc, {"--help-property-list"}, 5);
|
||||||
if (proc.result() == ProcessResult::FinishedWithSuccess)
|
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);
|
runCMake(proc, {"--help-variable-list"}, 5);
|
||||||
if (proc.result() == ProcessResult::FinishedWithSuccess) {
|
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);
|
m_introspection->m_variables = Utils::filteredUnique(m_introspection->m_variables);
|
||||||
Utils::sort(m_introspection->m_variables);
|
Utils::sort(m_introspection->m_variables);
|
||||||
}
|
}
|
||||||
@@ -523,7 +523,7 @@ void CMakeTool::fetchFromCapabilities() const
|
|||||||
|
|
||||||
if (cmake.result() == ProcessResult::FinishedWithSuccess) {
|
if (cmake.result() == ProcessResult::FinishedWithSuccess) {
|
||||||
m_introspection->m_didRun = true;
|
m_introspection->m_didRun = true;
|
||||||
parseFromCapabilities(cmake.stdOut());
|
parseFromCapabilities(cmake.cleanedStdOut());
|
||||||
} else {
|
} else {
|
||||||
qCCritical(cmakeToolLog) << "Fetching capabilities failed: " << cmake.allOutput() << cmake.error();
|
qCCritical(cmakeToolLog) << "Fetching capabilities failed: " << cmake.allOutput() << cmake.error();
|
||||||
m_introspection->m_didRun = false;
|
m_introspection->m_didRun = false;
|
||||||
|
@@ -402,18 +402,18 @@ RawProjectParts generateRawProjectParts(const PreprocessedData &input,
|
|||||||
const bool hasPchSource = anyOf(sources, [buildDirectory](const QString &path) {
|
const bool hasPchSource = anyOf(sources, [buildDirectory](const QString &path) {
|
||||||
return isPchFile(buildDirectory, FilePath::fromString(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;
|
|
||||||
|
|
||||||
|
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) {
|
for (const SourceInfo &si : t.sources) {
|
||||||
if (si.isGenerated)
|
if (si.isGenerated)
|
||||||
continue;
|
continue;
|
||||||
const auto mimeTypes = Utils::mimeTypesForFileName(si.path);
|
const auto mimeTypes = Utils::mimeTypesForFileName(si.path);
|
||||||
for (auto mime : mimeTypes)
|
for (const auto &mime : mimeTypes)
|
||||||
if (mime.name() == headerMimeType)
|
if (mime.name() == headerMimeType)
|
||||||
sources.push_back(sourceDir.absoluteFilePath(si.path));
|
sources.push_back(sourceDir.absoluteFilePath(si.path));
|
||||||
}
|
}
|
||||||
@@ -421,8 +421,14 @@ RawProjectParts generateRawProjectParts(const PreprocessedData &input,
|
|||||||
|
|
||||||
// Set project files except pch files
|
// Set project files except pch files
|
||||||
rpp.setFiles(Utils::filtered(sources, [buildDirectory](const QString &path) {
|
rpp.setFiles(Utils::filtered(sources, [buildDirectory](const QString &path) {
|
||||||
return !isPchFile(buildDirectory, FilePath::fromString(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 precompiled_header
|
||||||
= FilePath::fromString(findOrDefault(t.sources, [&ending](const SourceInfo &si) {
|
= FilePath::fromString(findOrDefault(t.sources, [&ending](const SourceInfo &si) {
|
||||||
|
@@ -36,6 +36,7 @@
|
|||||||
#include <projectexplorer/toolchain.h>
|
#include <projectexplorer/toolchain.h>
|
||||||
#include <projectexplorer/toolchainmanager.h>
|
#include <projectexplorer/toolchainmanager.h>
|
||||||
#include <utils/algorithm.h>
|
#include <utils/algorithm.h>
|
||||||
|
#include <utils/hostosinfo.h>
|
||||||
|
|
||||||
#include <QtTest>
|
#include <QtTest>
|
||||||
|
|
||||||
@@ -239,13 +240,15 @@ void CompilationDatabaseTests::testFilterCommand()
|
|||||||
"SemaCodeComplete");
|
"SemaCodeComplete");
|
||||||
testData.getFilteredFlags();
|
testData.getFilteredFlags();
|
||||||
|
|
||||||
QCOMPARE(testData.flags,
|
if (Utils::HostOsInfo::isWindowsHost()) {
|
||||||
(QStringList{"/Zc:inline", "/Zc:strictStrings", "/Zc:rvalueCast", "/Zi"}));
|
QCOMPARE(testData.flags,
|
||||||
QCOMPARE(testData.headerPaths,
|
(QStringList{"/Zc:inline", "/Zc:strictStrings", "/Zc:rvalueCast", "/Zi"}));
|
||||||
toUserHeaderPaths(QStringList{"C:/build-qt_llvm-msvc2017_64bit-Debug/tools\\clang\\lib\\Sema"}));
|
QCOMPARE(testData.headerPaths,
|
||||||
QCOMPARE(testData.macros, (Macros{{"UNICODE", "1"}, {"_HAS_EXCEPTIONS", "0"}, {"WIN32", "1"},
|
toUserHeaderPaths(QStringList{"C:/build-qt_llvm-msvc2017_64bit-Debug/tools\\clang\\lib\\Sema"}));
|
||||||
{"_WINDOWS", "1"}}));
|
QCOMPARE(testData.macros, (Macros{{"UNICODE", "1"}, {"_HAS_EXCEPTIONS", "0"}, {"WIN32", "1"},
|
||||||
QCOMPARE(testData.fileKind, CppEditor::ProjectFile::Kind::CXXSource);
|
{"_WINDOWS", "1"}}));
|
||||||
|
QCOMPARE(testData.fileKind, CppEditor::ProjectFile::Kind::CXXSource);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CompilationDatabaseTests::testFileKindDifferentFromExtension()
|
void CompilationDatabaseTests::testFileKindDifferentFromExtension()
|
||||||
|
@@ -206,7 +206,7 @@ void filteredFlags(const QString &fileName,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Skip all remaining Windows flags except feature flags.
|
// Skip all remaining Windows flags except feature flags.
|
||||||
if (flag.startsWith("/") && !flag.startsWith("/Z"))
|
if (Utils::HostOsInfo::isWindowsHost() && flag.startsWith("/") && !flag.startsWith("/Z"))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
filtered.push_back(flag);
|
filtered.push_back(flag);
|
||||||
|
@@ -830,8 +830,7 @@ FilePath DocumentManager::getSaveFileName(const QString &title, const FilePath &
|
|||||||
bool repeat;
|
bool repeat;
|
||||||
do {
|
do {
|
||||||
repeat = false;
|
repeat = false;
|
||||||
filePath = FileUtils::getSaveFilePath(nullptr, title, path, filter, selectedFilter,
|
filePath = FileUtils::getSaveFilePath(nullptr, title, path, filter, selectedFilter);
|
||||||
QFileDialog::DontConfirmOverwrite);
|
|
||||||
if (!filePath.isEmpty()) {
|
if (!filePath.isEmpty()) {
|
||||||
// If the selected filter is All Files (*) we leave the name exactly as the user
|
// 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
|
// specified. Otherwise the suffix must be one available in the selected filter. If
|
||||||
@@ -852,18 +851,20 @@ FilePath DocumentManager::getSaveFileName(const QString &title, const FilePath &
|
|||||||
suffixOk = true;
|
suffixOk = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!suffixOk && !suffixes.isEmpty())
|
if (!suffixOk && !suffixes.isEmpty()) {
|
||||||
filePath = filePath.stringAppended(suffixes.at(0));
|
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. "
|
||||||
|
"Do you want to overwrite it?").arg(filePath.toUserOutput()),
|
||||||
|
QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) {
|
||||||
|
repeat = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (filePath.exists()) {
|
|
||||||
if (QMessageBox::warning(ICore::dialogParent(), tr("Overwrite?"),
|
|
||||||
tr("An item named \"%1\" already exists at this location. "
|
|
||||||
"Do you want to overwrite it?").arg(filePath.toUserOutput()),
|
|
||||||
QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) {
|
|
||||||
repeat = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} while (repeat);
|
} while (repeat);
|
||||||
if (!filePath.isEmpty())
|
if (!filePath.isEmpty())
|
||||||
|
@@ -132,16 +132,10 @@ void ExecuteFilter::accept(const LocatorFilterEntry &selection,
|
|||||||
p->runHeadCommand();
|
p->runHeadCommand();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExecuteFilter::finished()
|
void ExecuteFilter::done()
|
||||||
{
|
{
|
||||||
QTC_ASSERT(m_process, return);
|
QTC_ASSERT(m_process, return);
|
||||||
const QString commandName = headCommand();
|
MessageManager::writeFlashing(m_process->exitMessage());
|
||||||
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);
|
|
||||||
|
|
||||||
removeProcess();
|
removeProcess();
|
||||||
runHeadCommand();
|
runHeadCommand();
|
||||||
@@ -180,12 +174,6 @@ void ExecuteFilter::runHeadCommand()
|
|||||||
m_process->setWorkingDirectory(d.workingDirectory);
|
m_process->setWorkingDirectory(d.workingDirectory);
|
||||||
m_process->setCommand(d.command);
|
m_process->setCommand(d.command);
|
||||||
m_process->start();
|
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 = new Utils::QtcProcess;
|
||||||
m_process->setEnvironment(Utils::Environment::systemEnvironment());
|
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::readyReadStandardOutput, this, &ExecuteFilter::readStandardOutput);
|
||||||
connect(m_process, &QtcProcess::readyReadStandardError, this, &ExecuteFilter::readStandardError);
|
connect(m_process, &QtcProcess::readyReadStandardError, this, &ExecuteFilter::readStandardError);
|
||||||
}
|
}
|
||||||
@@ -207,7 +195,7 @@ void ExecuteFilter::removeProcess()
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
m_taskQueue.dequeue();
|
m_taskQueue.dequeue();
|
||||||
delete m_process;
|
m_process->deleteLater();
|
||||||
m_process = nullptr;
|
m_process = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -57,7 +57,7 @@ public:
|
|||||||
QString *newText, int *selectionStart, int *selectionLength) const override;
|
QString *newText, int *selectionStart, int *selectionLength) const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void finished();
|
void done();
|
||||||
void readStandardOutput();
|
void readStandardOutput();
|
||||||
void readStandardError();
|
void readStandardError();
|
||||||
void runHeadCommand();
|
void runHeadCommand();
|
||||||
|
@@ -28,7 +28,6 @@
|
|||||||
|
|
||||||
#include <utils/hostosinfo.h>
|
#include <utils/hostosinfo.h>
|
||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
#include <utils/qtcprocess.h>
|
|
||||||
|
|
||||||
#include <coreplugin/messagemanager.h>
|
#include <coreplugin/messagemanager.h>
|
||||||
|
|
||||||
@@ -37,11 +36,9 @@ using namespace Utils;
|
|||||||
namespace Cppcheck {
|
namespace Cppcheck {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
CppcheckRunner::CppcheckRunner(CppcheckTool &tool) :
|
CppcheckRunner::CppcheckRunner(CppcheckTool &tool) : m_tool(tool)
|
||||||
m_tool(tool),
|
|
||||||
m_process(new Utils::QtcProcess(this))
|
|
||||||
{
|
{
|
||||||
if (Utils::HostOsInfo::hostOs() == Utils::OsTypeLinux) {
|
if (HostOsInfo::hostOs() == OsTypeLinux) {
|
||||||
QtcProcess getConf;
|
QtcProcess getConf;
|
||||||
getConf.setCommand({"getconf", {"ARG_MAX"}});
|
getConf.setCommand({"getconf", {"ARG_MAX"}});
|
||||||
getConf.start();
|
getConf.start();
|
||||||
@@ -50,17 +47,15 @@ CppcheckRunner::CppcheckRunner(CppcheckTool &tool) :
|
|||||||
m_maxArgumentsLength = std::max(argMax.toInt(), m_maxArgumentsLength);
|
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_tool.parseOutputLine(line);
|
||||||
});
|
});
|
||||||
m_process->setStdErrLineCallback([this](const QString &line) {
|
m_process.setStdErrLineCallback([this](const QString &line) {
|
||||||
m_tool.parseErrorLine(line);
|
m_tool.parseErrorLine(line);
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(m_process, &QtcProcess::started,
|
connect(&m_process, &QtcProcess::started, &m_tool, &CppcheckTool::startParsing);
|
||||||
this, &CppcheckRunner::handleStarted);
|
connect(&m_process, &QtcProcess::done, this, &CppcheckRunner::handleDone);
|
||||||
connect(m_process, &QtcProcess::finished,
|
|
||||||
this, &CppcheckRunner::handleFinished);
|
|
||||||
|
|
||||||
m_queueTimer.setSingleShot(true);
|
m_queueTimer.setSingleShot(true);
|
||||||
const int checkDelayInMs = 200;
|
const int checkDelayInMs = 200;
|
||||||
@@ -81,18 +76,18 @@ void CppcheckRunner::reconfigure(const FilePath &binary, const QString &argument
|
|||||||
m_arguments = arguments;
|
m_arguments = arguments;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CppcheckRunner::addToQueue(const Utils::FilePaths &files,
|
void CppcheckRunner::addToQueue(const FilePaths &files,
|
||||||
const QString &additionalArguments)
|
const QString &additionalArguments)
|
||||||
{
|
{
|
||||||
Utils::FilePaths &existing = m_queue[additionalArguments];
|
FilePaths &existing = m_queue[additionalArguments];
|
||||||
if (existing.isEmpty()) {
|
if (existing.isEmpty()) {
|
||||||
existing = files;
|
existing = files;
|
||||||
} else {
|
} else {
|
||||||
std::copy_if(files.cbegin(), files.cend(), std::back_inserter(existing),
|
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);
|
stop(existing);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -100,16 +95,16 @@ void CppcheckRunner::addToQueue(const Utils::FilePaths &files,
|
|||||||
m_queueTimer.start();
|
m_queueTimer.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CppcheckRunner::stop(const Utils::FilePaths &files)
|
void CppcheckRunner::stop(const FilePaths &files)
|
||||||
{
|
{
|
||||||
if (!m_isRunning)
|
if (!m_process.isRunning())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (files.isEmpty() || m_currentFiles == files)
|
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())
|
if (m_queue.isEmpty())
|
||||||
return;
|
return;
|
||||||
@@ -118,21 +113,21 @@ void CppcheckRunner::removeFromQueue(const Utils::FilePaths &files)
|
|||||||
m_queue.clear();
|
m_queue.clear();
|
||||||
} else {
|
} else {
|
||||||
for (auto it = m_queue.begin(), end = m_queue.end(); it != end;) {
|
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.value().removeOne(file);
|
||||||
it = !it.value().isEmpty() ? ++it : m_queue.erase(it);
|
it = !it.value().isEmpty() ? ++it : m_queue.erase(it);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const Utils::FilePaths &CppcheckRunner::currentFiles() const
|
const FilePaths &CppcheckRunner::currentFiles() const
|
||||||
{
|
{
|
||||||
return m_currentFiles;
|
return m_currentFiles;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString CppcheckRunner::currentCommand() const
|
QString CppcheckRunner::currentCommand() const
|
||||||
{
|
{
|
||||||
return m_process->commandLine().toUserOutput();
|
return m_process.commandLine().toUserOutput();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CppcheckRunner::checkQueued()
|
void CppcheckRunner::checkQueued()
|
||||||
@@ -140,7 +135,7 @@ void CppcheckRunner::checkQueued()
|
|||||||
if (m_queue.isEmpty() || m_binary.isEmpty())
|
if (m_queue.isEmpty() || m_binary.isEmpty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Utils::FilePaths files = m_queue.begin().value();
|
FilePaths files = m_queue.begin().value();
|
||||||
QString arguments = m_arguments + ' ' + m_queue.begin().key();
|
QString arguments = m_arguments + ' ' + m_queue.begin().key();
|
||||||
m_currentFiles.clear();
|
m_currentFiles.clear();
|
||||||
int argumentsLength = arguments.length();
|
int argumentsLength = arguments.length();
|
||||||
@@ -158,30 +153,19 @@ void CppcheckRunner::checkQueued()
|
|||||||
else
|
else
|
||||||
m_queue.begin().value() = files;
|
m_queue.begin().value() = files;
|
||||||
|
|
||||||
m_process->setCommand(CommandLine(m_binary, arguments, CommandLine::Raw));
|
m_process.setCommand(CommandLine(m_binary, arguments, CommandLine::Raw));
|
||||||
m_process->start();
|
m_process.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CppcheckRunner::handleStarted()
|
void CppcheckRunner::handleDone()
|
||||||
{
|
{
|
||||||
if (m_isRunning)
|
if (m_process.result() == ProcessResult::FinishedWithSuccess)
|
||||||
return;
|
|
||||||
|
|
||||||
m_isRunning = true;
|
|
||||||
m_tool.startParsing();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CppcheckRunner::handleFinished()
|
|
||||||
{
|
|
||||||
if (m_process->error() != QProcess::FailedToStart) {
|
|
||||||
m_tool.finishParsing();
|
m_tool.finishParsing();
|
||||||
} else {
|
else
|
||||||
const QString message = tr("Cppcheck failed to start: \"%1\".").arg(currentCommand());
|
Core::MessageManager::writeSilently(m_process.exitMessage());
|
||||||
Core::MessageManager::writeSilently(message);
|
|
||||||
}
|
|
||||||
m_currentFiles.clear();
|
m_currentFiles.clear();
|
||||||
m_process->close();
|
m_process.close();
|
||||||
m_isRunning = false;
|
|
||||||
|
|
||||||
if (!m_queue.isEmpty())
|
if (!m_queue.isEmpty())
|
||||||
checkQueued();
|
checkQueued();
|
||||||
|
@@ -26,12 +26,11 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <utils/filepath.h>
|
#include <utils/filepath.h>
|
||||||
|
#include <utils/qtcprocess.h>
|
||||||
|
|
||||||
#include <QHash>
|
#include <QHash>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
|
||||||
namespace Utils { class QtcProcess; }
|
|
||||||
|
|
||||||
namespace Cppcheck {
|
namespace Cppcheck {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
@@ -58,18 +57,16 @@ private:
|
|||||||
void checkQueued();
|
void checkQueued();
|
||||||
void readOutput();
|
void readOutput();
|
||||||
void readError();
|
void readError();
|
||||||
void handleStarted();
|
void handleDone();
|
||||||
void handleFinished();
|
|
||||||
|
|
||||||
CppcheckTool &m_tool;
|
CppcheckTool &m_tool;
|
||||||
Utils::QtcProcess *m_process = nullptr;
|
Utils::QtcProcess m_process;
|
||||||
Utils::FilePath m_binary;
|
Utils::FilePath m_binary;
|
||||||
QString m_arguments;
|
QString m_arguments;
|
||||||
QHash<QString, Utils::FilePaths> m_queue;
|
QHash<QString, Utils::FilePaths> m_queue;
|
||||||
Utils::FilePaths m_currentFiles;
|
Utils::FilePaths m_currentFiles;
|
||||||
QTimer m_queueTimer;
|
QTimer m_queueTimer;
|
||||||
int m_maxArgumentsLength = 32767;
|
int m_maxArgumentsLength = 32767;
|
||||||
bool m_isRunning = false;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
|
@@ -34,6 +34,7 @@
|
|||||||
#include <projectexplorer/session.h>
|
#include <projectexplorer/session.h>
|
||||||
|
|
||||||
#include <utils/algorithm.h>
|
#include <utils/algorithm.h>
|
||||||
|
#include <utils/hostosinfo.h>
|
||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
#include <utils/qtcprocess.h>
|
#include <utils/qtcprocess.h>
|
||||||
#include <utils/settingsutils.h>
|
#include <utils/settingsutils.h>
|
||||||
@@ -81,6 +82,7 @@ static QString clangdSizeThresholdKey() { return QLatin1String("ClangdSizeThresh
|
|||||||
static QString clangdUseGlobalSettingsKey() { return QLatin1String("useGlobalSettings"); }
|
static QString clangdUseGlobalSettingsKey() { return QLatin1String("useGlobalSettings"); }
|
||||||
static QString sessionsWithOneClangdKey() { return QLatin1String("SessionsWithOneClangd"); }
|
static QString sessionsWithOneClangdKey() { return QLatin1String("SessionsWithOneClangd"); }
|
||||||
static QString diagnosticConfigIdKey() { return QLatin1String("diagnosticConfigId"); }
|
static QString diagnosticConfigIdKey() { return QLatin1String("diagnosticConfigId"); }
|
||||||
|
static QString checkedHardwareKey() { return QLatin1String("checkedHardware"); }
|
||||||
|
|
||||||
static FilePath g_defaultClangdFilePath;
|
static FilePath g_defaultClangdFilePath;
|
||||||
static FilePath fallbackClangdFilePath()
|
static FilePath fallbackClangdFilePath()
|
||||||
@@ -206,6 +208,22 @@ bool ClangdSettings::useClangd() const
|
|||||||
return m_data.useClangd && clangdVersion() >= QVersionNumber(14);
|
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)
|
void ClangdSettings::setDefaultClangdPath(const FilePath &filePath)
|
||||||
{
|
{
|
||||||
g_defaultClangdFilePath = filePath;
|
g_defaultClangdFilePath = filePath;
|
||||||
@@ -350,8 +368,6 @@ void ClangdSettings::saveSettings()
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WITH_TESTS
|
#ifdef WITH_TESTS
|
||||||
void ClangdSettings::setUseClangd(bool use) { instance().m_data.useClangd = use; }
|
|
||||||
|
|
||||||
void ClangdSettings::setClangdFilePath(const FilePath &filePath)
|
void ClangdSettings::setClangdFilePath(const FilePath &filePath)
|
||||||
{
|
{
|
||||||
instance().m_data.executableFilePath = filePath;
|
instance().m_data.executableFilePath = filePath;
|
||||||
@@ -435,6 +451,7 @@ QVariantMap ClangdSettings::Data::toMap() const
|
|||||||
map.insert(clangdSizeThresholdKey(), sizeThresholdInKb);
|
map.insert(clangdSizeThresholdKey(), sizeThresholdInKb);
|
||||||
map.insert(sessionsWithOneClangdKey(), sessionsWithOneClangd);
|
map.insert(sessionsWithOneClangdKey(), sessionsWithOneClangd);
|
||||||
map.insert(diagnosticConfigIdKey(), diagnosticConfigId.toSetting());
|
map.insert(diagnosticConfigIdKey(), diagnosticConfigId.toSetting());
|
||||||
|
map.insert(checkedHardwareKey(), true);
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -451,6 +468,7 @@ void ClangdSettings::Data::fromMap(const QVariantMap &map)
|
|||||||
sessionsWithOneClangd = map.value(sessionsWithOneClangdKey()).toStringList();
|
sessionsWithOneClangd = map.value(sessionsWithOneClangdKey()).toStringList();
|
||||||
diagnosticConfigId = Id::fromSetting(map.value(diagnosticConfigIdKey(),
|
diagnosticConfigId = Id::fromSetting(map.value(diagnosticConfigIdKey(),
|
||||||
initialClangDiagnosticConfigId().toSetting()));
|
initialClangDiagnosticConfigId().toSetting()));
|
||||||
|
haveCheckedHardwareReqirements = map.value(checkedHardwareKey(), false).toBool();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace CppEditor
|
} // namespace CppEditor
|
||||||
|
@@ -111,7 +111,8 @@ public:
|
|||||||
&& s1.autoIncludeHeaders == s2.autoIncludeHeaders
|
&& s1.autoIncludeHeaders == s2.autoIncludeHeaders
|
||||||
&& s1.documentUpdateThreshold == s2.documentUpdateThreshold
|
&& s1.documentUpdateThreshold == s2.documentUpdateThreshold
|
||||||
&& s1.sizeThresholdEnabled == s2.sizeThresholdEnabled
|
&& 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); }
|
friend bool operator!=(const Data &s1, const Data &s2) { return !(s1 == s2); }
|
||||||
|
|
||||||
@@ -126,12 +127,17 @@ public:
|
|||||||
bool enableIndexing = true;
|
bool enableIndexing = true;
|
||||||
bool autoIncludeHeaders = false;
|
bool autoIncludeHeaders = false;
|
||||||
bool sizeThresholdEnabled = false;
|
bool sizeThresholdEnabled = false;
|
||||||
|
bool haveCheckedHardwareReqirements = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
ClangdSettings(const Data &data) : m_data(data) {}
|
ClangdSettings(const Data &data) : m_data(data) {}
|
||||||
|
|
||||||
static ClangdSettings &instance();
|
static ClangdSettings &instance();
|
||||||
bool useClangd() const;
|
bool useClangd() const;
|
||||||
|
static void setUseClangd(bool use);
|
||||||
|
|
||||||
|
static bool hardwareFulfillsRequirements();
|
||||||
|
static bool haveCheckedHardwareRequirements();
|
||||||
|
|
||||||
static void setDefaultClangdPath(const Utils::FilePath &filePath);
|
static void setDefaultClangdPath(const Utils::FilePath &filePath);
|
||||||
static void setCustomDiagnosticConfigs(const ClangDiagnosticConfigs &configs);
|
static void setCustomDiagnosticConfigs(const ClangDiagnosticConfigs &configs);
|
||||||
@@ -159,7 +165,6 @@ public:
|
|||||||
static Utils::FilePath clangdUserConfigFilePath();
|
static Utils::FilePath clangdUserConfigFilePath();
|
||||||
|
|
||||||
#ifdef WITH_TESTS
|
#ifdef WITH_TESTS
|
||||||
static void setUseClangd(bool use);
|
|
||||||
static void setClangdFilePath(const Utils::FilePath &filePath);
|
static void setClangdFilePath(const Utils::FilePath &filePath);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@@ -135,6 +135,12 @@ static const char *DEFAULT_CODE_STYLE_SNIPPETS[]
|
|||||||
"private:\n"
|
"private:\n"
|
||||||
" int _a;\n"
|
" int _a;\n"
|
||||||
" };\n"
|
" };\n"
|
||||||
|
"enum class E\n"
|
||||||
|
"{\n"
|
||||||
|
" V1,\n"
|
||||||
|
" V2,\n"
|
||||||
|
" V3\n"
|
||||||
|
"};\n"
|
||||||
"}\n"
|
"}\n"
|
||||||
"}\n",
|
"}\n",
|
||||||
"#include \"bar.h\"\n"
|
"#include \"bar.h\"\n"
|
||||||
|
@@ -50,7 +50,9 @@
|
|||||||
#include <utils/minimizableinfobars.h>
|
#include <utils/minimizableinfobars.h>
|
||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
#include <utils/runextensions.h>
|
#include <utils/runextensions.h>
|
||||||
|
#include <utils/utilsicons.h>
|
||||||
|
|
||||||
|
#include <QApplication>
|
||||||
#include <QTextDocument>
|
#include <QTextDocument>
|
||||||
|
|
||||||
const char NO_PROJECT_CONFIGURATION[] = "NoProject";
|
const char NO_PROJECT_CONFIGURATION[] = "NoProject";
|
||||||
@@ -121,6 +123,9 @@ CppEditorDocument::CppEditorDocument()
|
|||||||
connect(this, &IDocument::filePathChanged,
|
connect(this, &IDocument::filePathChanged,
|
||||||
this, &CppEditorDocument::onFilePathChanged);
|
this, &CppEditorDocument::onFilePathChanged);
|
||||||
|
|
||||||
|
connect(mm(), &CppModelManager::diagnosticsChanged,
|
||||||
|
this, &CppEditorDocument::onDiagnosticsChanged);
|
||||||
|
|
||||||
connect(&m_parseContextModel, &ParseContextModel::preferredParseContextChanged,
|
connect(&m_parseContextModel, &ParseContextModel::preferredParseContextChanged,
|
||||||
this, &CppEditorDocument::reparseWithPreferredParseContext);
|
this, &CppEditorDocument::reparseWithPreferredParseContext);
|
||||||
|
|
||||||
@@ -483,5 +488,51 @@ bool CppEditorDocument::save(QString *errorString, const FilePath &filePath, boo
|
|||||||
return TextEditor::TextDocument::save(errorString, filePath, autoSave);
|
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 Internal
|
||||||
} // namespace CppEditor
|
} // namespace CppEditor
|
||||||
|
@@ -94,6 +94,8 @@ private:
|
|||||||
|
|
||||||
void onAboutToReload();
|
void onAboutToReload();
|
||||||
void onReloadFinished();
|
void onReloadFinished();
|
||||||
|
void onDiagnosticsChanged(const QString &fileName, const QString &kind);
|
||||||
|
|
||||||
|
|
||||||
void reparseWithPreferredParseContext(const QString &id);
|
void reparseWithPreferredParseContext(const QString &id);
|
||||||
|
|
||||||
|
@@ -201,6 +201,8 @@ public:
|
|||||||
std::unique_ptr<Core::ILocatorFilter> m_functionsFilter;
|
std::unique_ptr<Core::ILocatorFilter> m_functionsFilter;
|
||||||
std::unique_ptr<Core::IFindFilter> m_symbolsFindFilter;
|
std::unique_ptr<Core::IFindFilter> m_symbolsFindFilter;
|
||||||
std::unique_ptr<Core::ILocatorFilter> m_currentDocumentFilter;
|
std::unique_ptr<Core::ILocatorFilter> m_currentDocumentFilter;
|
||||||
|
|
||||||
|
QList<Document::DiagnosticMessage> m_diagnosticMessages;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
@@ -1704,4 +1706,18 @@ QThreadPool *CppModelManager::sharedThreadPool()
|
|||||||
return &d->m_threadPool;
|
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
|
} // namespace CppEditor
|
||||||
|
@@ -104,6 +104,12 @@ public:
|
|||||||
QByteArray codeModelConfiguration() const;
|
QByteArray codeModelConfiguration() const;
|
||||||
CppLocatorData *locatorData() 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;
|
QList<ProjectInfo::ConstPtr> projectInfos() const;
|
||||||
ProjectInfo::ConstPtr projectInfo(ProjectExplorer::Project *project) const;
|
ProjectInfo::ConstPtr projectInfo(ProjectExplorer::Project *project) const;
|
||||||
QFuture<void> updateProjectInfo(const ProjectInfo::ConstPtr &newProjectInfo,
|
QFuture<void> updateProjectInfo(const ProjectInfo::ConstPtr &newProjectInfo,
|
||||||
@@ -256,6 +262,8 @@ signals:
|
|||||||
void abstractEditorSupportRemoved(const QString &filePath);
|
void abstractEditorSupportRemoved(const QString &filePath);
|
||||||
void fallbackProjectPartUpdated();
|
void fallbackProjectPartUpdated();
|
||||||
|
|
||||||
|
void diagnosticsChanged(const QString &fileName, const QString &kind);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void updateModifiedSourceFiles();
|
void updateModifiedSourceFiles();
|
||||||
void GC();
|
void GC();
|
||||||
|
@@ -87,7 +87,8 @@ const QVector<ProjectPart::ConstPtr> ProjectInfoGenerator::createProjectParts(
|
|||||||
QVector<ProjectPart::ConstPtr> result;
|
QVector<ProjectPart::ConstPtr> result;
|
||||||
ProjectFileCategorizer cat(rawProjectPart.displayName,
|
ProjectFileCategorizer cat(rawProjectPart.displayName,
|
||||||
rawProjectPart.files,
|
rawProjectPart.files,
|
||||||
rawProjectPart.fileIsActive);
|
rawProjectPart.fileIsActive,
|
||||||
|
rawProjectPart.getMimeType);
|
||||||
|
|
||||||
if (!cat.hasParts())
|
if (!cat.hasParts())
|
||||||
return result;
|
return result;
|
||||||
|
@@ -1449,8 +1449,8 @@ CvsResponse CvsPluginPrivate::runCvs(const FilePath &workingDirectory,
|
|||||||
command.runCommand(proc, {executable, m_settings.addOptions(arguments)});
|
command.runCommand(proc, {executable, m_settings.addOptions(arguments)});
|
||||||
|
|
||||||
response.result = CvsResponse::OtherError;
|
response.result = CvsResponse::OtherError;
|
||||||
response.stdErr = proc.stdErr();
|
response.stdErr = proc.cleanedStdErr();
|
||||||
response.stdOut = proc.stdOut();
|
response.stdOut = proc.cleanedStdOut();
|
||||||
switch (proc.result()) {
|
switch (proc.result()) {
|
||||||
case ProcessResult::FinishedWithSuccess:
|
case ProcessResult::FinishedWithSuccess:
|
||||||
response.result = CvsResponse::Ok;
|
response.result = CvsResponse::Ok;
|
||||||
|
@@ -30,12 +30,12 @@
|
|||||||
#include <coreplugin/editormanager/editormanager.h>
|
#include <coreplugin/editormanager/editormanager.h>
|
||||||
|
|
||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
|
#include <utils/stringutils.h>
|
||||||
#include <utils/utilsicons.h>
|
#include <utils/utilsicons.h>
|
||||||
|
|
||||||
|
#include <QApplication>
|
||||||
#include <QAbstractTextDocumentLayout>
|
#include <QAbstractTextDocumentLayout>
|
||||||
#include <QAction>
|
#include <QAction>
|
||||||
#include <QApplication>
|
|
||||||
#include <QClipboard>
|
|
||||||
#include <QContextMenuEvent>
|
#include <QContextMenuEvent>
|
||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
#include <QHeaderView>
|
#include <QHeaderView>
|
||||||
@@ -54,12 +54,12 @@ DetailedErrorView::DetailedErrorView(QWidget *parent) :
|
|||||||
m_copyAction->setIcon(Utils::Icons::COPY.icon());
|
m_copyAction->setIcon(Utils::Icons::COPY.icon());
|
||||||
m_copyAction->setShortcut(QKeySequence::Copy);
|
m_copyAction->setShortcut(QKeySequence::Copy);
|
||||||
m_copyAction->setShortcutContext(Qt::WidgetWithChildrenShortcut);
|
m_copyAction->setShortcutContext(Qt::WidgetWithChildrenShortcut);
|
||||||
connect(m_copyAction, &QAction::triggered, [this] {
|
connect(m_copyAction, &QAction::triggered, this, [this] {
|
||||||
const QModelIndexList selectedRows = selectionModel()->selectedRows();
|
const QModelIndexList selectedRows = selectionModel()->selectedRows();
|
||||||
QStringList data;
|
QStringList data;
|
||||||
for (const QModelIndex &index : selectedRows)
|
for (const QModelIndex &index : selectedRows)
|
||||||
data << model()->data(index, FullTextRole).toString();
|
data << model()->data(index, FullTextRole).toString();
|
||||||
QApplication::clipboard()->setText(data.join('\n'));
|
Utils::setClipboardAndSelection(data.join('\n'));
|
||||||
});
|
});
|
||||||
connect(this, &QAbstractItemView::clicked, [](const QModelIndex &index) {
|
connect(this, &QAbstractItemView::clicked, [](const QModelIndex &index) {
|
||||||
if (index.column() == LocationColumn) {
|
if (index.column() == LocationColumn) {
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user