forked from qt-creator/qt-creator
Merge remote-tracking branch 'origin/8.0'
Change-Id: I9f41e115adb25c08acc01110b6027020eff1a1e7
This commit is contained in:
7
.github/pull_request_template.md
vendored
Normal file
7
.github/pull_request_template.md
vendored
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
Thank you for contributing to Qt Creator! Unfortunately the GitHub Qt Creator
|
||||||
|
presence is only a git mirror.
|
||||||
|
|
||||||
|
Please submit your patch via gerrit:
|
||||||
|
https://wiki.qt.io/Qt_Creator#Setting_up_Gerrit_to_contribute_back_to_Qt_Creator
|
||||||
|
|
||||||
|
We are sorry for the inconvenience.
|
||||||
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.2.3
|
QT_VERSION: 6.3.0
|
||||||
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
|
||||||
|
|||||||
22
dist/changes-8.0.0.md
vendored
22
dist/changes-8.0.0.md
vendored
@@ -10,17 +10,26 @@ the public Git repository. For example:
|
|||||||
git clone git://code.qt.io/qt-creator/qt-creator.git
|
git clone git://code.qt.io/qt-creator/qt-creator.git
|
||||||
git log --cherry-pick --pretty=oneline origin/7.0..v8.0.0
|
git log --cherry-pick --pretty=oneline origin/7.0..v8.0.0
|
||||||
|
|
||||||
|
Help
|
||||||
|
----
|
||||||
|
|
||||||
|
* Added support for mouse forward and backward buttons (QTCREATORBUG-25168)
|
||||||
|
|
||||||
Editing
|
Editing
|
||||||
-------
|
-------
|
||||||
|
|
||||||
* Added shortcut for adding next search match to multi-selection
|
* Added shortcut for adding next search match to multi-selection
|
||||||
* Added warning when editing generated file (QTCREATORBUG-27173)
|
* Added warning when editing generated file (QTCREATORBUG-27173)
|
||||||
|
* Added option for hiding line ending information
|
||||||
* Fixed updating of annotations (QTCREATORBUG-26812)
|
* Fixed updating of annotations (QTCREATORBUG-26812)
|
||||||
* Fixed that whitespace was not selected on double-click (QTCREATORBUG-24607)
|
* Fixed that whitespace was not selected on double-click (QTCREATORBUG-24607)
|
||||||
|
* Fixed `Rewrap Paragraph` when indenting with tabs (QTCREATORBUG-27602)
|
||||||
|
|
||||||
### C++
|
### C++
|
||||||
|
|
||||||
* Removed `libclang` based code model
|
* Removed `libclang` based code model
|
||||||
|
* Fixed that `Generate Setter and Getter` generated non-static methods for
|
||||||
|
static pointer types (QTCREATORBUG-27547)
|
||||||
* Clangd
|
* Clangd
|
||||||
* Increased minimum `Clangd` version to 14
|
* Increased minimum `Clangd` version to 14
|
||||||
* Improved performance of `compile_commands.json` creation
|
* Improved performance of `compile_commands.json` creation
|
||||||
@@ -64,6 +73,8 @@ Editing
|
|||||||
* Fixed semantic highlighting after server reset
|
* Fixed semantic highlighting after server reset
|
||||||
* Fixed that semantic update was delayed by `Document update threshold` even
|
* Fixed that semantic update was delayed by `Document update threshold` even
|
||||||
after saving
|
after saving
|
||||||
|
* Fixed that tooltips could appear while Qt Creator is not in the foreground
|
||||||
|
* Fixed synchronization of outline view (QTCREATORBUG-27595)
|
||||||
|
|
||||||
### Image Viewer
|
### Image Viewer
|
||||||
|
|
||||||
@@ -73,11 +84,14 @@ Projects
|
|||||||
--------
|
--------
|
||||||
|
|
||||||
* Added locator filter for starting run configurations
|
* Added locator filter for starting run configurations
|
||||||
|
* Added `BuildSystem:Name` variable for default build directory
|
||||||
|
(QTCREATORBUG-26147)
|
||||||
|
|
||||||
### CMake
|
### CMake
|
||||||
|
|
||||||
* Added `Profile` build configuration type that is `RelWithDebInfo` with `QML
|
* Added `Profile` build configuration type that is `RelWithDebInfo` with `QML
|
||||||
debugging and profiling`
|
debugging and profiling`
|
||||||
|
* Added `install` command to wizard generated projects
|
||||||
* Turned `QML debugging and profiling` option on by default for `Debug`
|
* Turned `QML debugging and profiling` option on by default for `Debug`
|
||||||
configurations
|
configurations
|
||||||
* Removed hardcoded `QT_QML_DEBUG` from wizard created project files
|
* Removed hardcoded `QT_QML_DEBUG` from wizard created project files
|
||||||
@@ -96,6 +110,7 @@ Analyzer
|
|||||||
### Coco
|
### Coco
|
||||||
|
|
||||||
* Added experimental `Coco` integration
|
* Added experimental `Coco` integration
|
||||||
|
* Added visualization of code coverage in code editor
|
||||||
|
|
||||||
### CppCheck
|
### CppCheck
|
||||||
|
|
||||||
@@ -129,6 +144,11 @@ Platforms
|
|||||||
* Added auto-detection for MSVC ARM toolchain and debugger
|
* Added auto-detection for MSVC ARM toolchain and debugger
|
||||||
* Fixed ABI detection on ARM Windows
|
* Fixed ABI detection on ARM Windows
|
||||||
|
|
||||||
|
### macOS
|
||||||
|
|
||||||
|
* Fixed import of existing builds of CMake projects that were done on the
|
||||||
|
command line (QTCREATORBUG-27591)
|
||||||
|
|
||||||
### Android
|
### Android
|
||||||
|
|
||||||
* Added option to connect physical device over WiFi
|
* Added option to connect physical device over WiFi
|
||||||
@@ -160,6 +180,7 @@ Aaron Barany
|
|||||||
Adam Treat
|
Adam Treat
|
||||||
Alesandro Portale
|
Alesandro Portale
|
||||||
Alessandro Portale
|
Alessandro Portale
|
||||||
|
Alexander Akulich
|
||||||
Alexander Drozdov
|
Alexander Drozdov
|
||||||
Alexandru Croitor
|
Alexandru Croitor
|
||||||
Andre Hartmann
|
Andre Hartmann
|
||||||
@@ -176,6 +197,7 @@ David Schulz
|
|||||||
Dmitry Shachnev
|
Dmitry Shachnev
|
||||||
Eike Ziller
|
Eike Ziller
|
||||||
Erik Verbruggen
|
Erik Verbruggen
|
||||||
|
Evgeny Shtanov
|
||||||
Fawzi Mohamed
|
Fawzi Mohamed
|
||||||
Henning Gruendl
|
Henning Gruendl
|
||||||
Ihor Ivlev
|
Ihor Ivlev
|
||||||
|
|||||||
@@ -162,6 +162,8 @@
|
|||||||
the application from running until the debug client connects to the
|
the application from running until the debug client connects to the
|
||||||
server. This enables debugging from the start.
|
server. This enables debugging from the start.
|
||||||
|
|
||||||
|
\note Setting breakpoints is only possible if the application is started with block mode.
|
||||||
|
|
||||||
\li Select \uicontrol Debug > \uicontrol {Start Debugging} >
|
\li Select \uicontrol Debug > \uicontrol {Start Debugging} >
|
||||||
\uicontrol {Attach to QML Port}.
|
\uicontrol {Attach to QML Port}.
|
||||||
|
|
||||||
|
|||||||
@@ -1740,6 +1740,11 @@ def qdump__QString(d, value):
|
|||||||
d.putArrayData(data, size, d.createType('@QChar'))
|
d.putArrayData(data, size, d.createType('@QChar'))
|
||||||
|
|
||||||
|
|
||||||
|
def qdump__QSettingsKey(d, value):
|
||||||
|
qdump__QString(d, value)
|
||||||
|
d.putBetterType(value.type)
|
||||||
|
|
||||||
|
|
||||||
def qdump__QStaticStringData(d, value):
|
def qdump__QStaticStringData(d, value):
|
||||||
size = value.type[0]
|
size = value.type[0]
|
||||||
(ref, size, alloc, pad, offset, data) = value.split('iii@p%ss' % (2 * size))
|
(ref, size, alloc, pad, offset, data) = value.split('iii@p%ss' % (2 * size))
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import QtQuick 2.0
|
import QtQuick 2.15
|
||||||
import QtTest 1.0
|
import QtTest 1.0
|
||||||
|
|
||||||
TestCase {
|
TestCase {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import QtQuick 2.0
|
import QtQuick %{QtQuickVersion}
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
|
|
||||||
|
|||||||
@@ -3,13 +3,16 @@
|
|||||||
"supportedProjectTypes": [ ],
|
"supportedProjectTypes": [ ],
|
||||||
"id": "Q.Qml.2",
|
"id": "Q.Qml.2",
|
||||||
"category": "R.Qt",
|
"category": "R.Qt",
|
||||||
"trDescription": "Creates a QML file with boilerplate code, starting with \"import QtQuick 2.0\".",
|
"trDescription": "Creates a QML file with boilerplate code, starting with \"import QtQuick\".",
|
||||||
"trDisplayName": "QML File (Qt Quick 2)",
|
"trDisplayName": "QML File (Qt Quick 2)",
|
||||||
"trDisplayCategory": "Qt",
|
"trDisplayCategory": "Qt",
|
||||||
"iconText": "qml",
|
"iconText": "qml",
|
||||||
"enabled": "%{JS: value('Plugins').indexOf('QmlJSEditor') >= 0}",
|
"enabled": "%{JS: value('Plugins').indexOf('QmlJSEditor') >= 0}",
|
||||||
|
|
||||||
"options": { "key": "DefaultSuffix", "value": "%{JS: Util.preferredSuffix('text/x-qml')}" },
|
"options": [
|
||||||
|
{"key": "DefaultSuffix", "value": "%{JS: Util.preferredSuffix('text/x-qml')}"},
|
||||||
|
{"key": "QtQuickVersion", "value": "%{JS: Util.qtQuickVersion(value('TargetPath'))}"}
|
||||||
|
],
|
||||||
|
|
||||||
"pages" :
|
"pages" :
|
||||||
[
|
[
|
||||||
|
|||||||
@@ -36,3 +36,5 @@ else()
|
|||||||
qt5_create_translation(QM_FILES ${CMAKE_SOURCE_DIR} ${TS_FILES})
|
qt5_create_translation(QM_FILES ${CMAKE_SOURCE_DIR} ${TS_FILES})
|
||||||
endif()
|
endif()
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
|
install(TARGETS %{ProjectName})
|
||||||
|
|||||||
@@ -3,3 +3,5 @@ cmake_minimum_required(VERSION 3.5)
|
|||||||
project(%{ProjectName} LANGUAGES C)
|
project(%{ProjectName} LANGUAGES C)
|
||||||
|
|
||||||
add_executable(%{ProjectName} %{CFileName})
|
add_executable(%{ProjectName} %{CFileName})
|
||||||
|
|
||||||
|
install(TARGETS %{ProjectName})
|
||||||
|
|||||||
@@ -6,3 +6,5 @@ set(CMAKE_CXX_STANDARD 17)
|
|||||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
|
||||||
add_executable(%{ProjectName} %{CppFileName})
|
add_executable(%{ProjectName} %{CppFileName})
|
||||||
|
|
||||||
|
install(TARGETS %{ProjectName})
|
||||||
|
|||||||
@@ -27,3 +27,5 @@ set_target_properties(%{TargetName} PROPERTIES
|
|||||||
|
|
||||||
target_link_libraries(%{TargetName}
|
target_link_libraries(%{TargetName}
|
||||||
PRIVATE Qt6::Quick)
|
PRIVATE Qt6::Quick)
|
||||||
|
|
||||||
|
install(TARGETS %{TargetName} BUNDLE DESTINATION .)
|
||||||
|
|||||||
@@ -71,6 +71,8 @@ set_target_properties(%{ProjectName} PROPERTIES
|
|||||||
WIN32_EXECUTABLE TRUE
|
WIN32_EXECUTABLE TRUE
|
||||||
)
|
)
|
||||||
|
|
||||||
|
install(TARGETS %{ProjectName} BUNDLE DESTINATION .)
|
||||||
|
|
||||||
if(QT_VERSION_MAJOR EQUAL 6)
|
if(QT_VERSION_MAJOR EQUAL 6)
|
||||||
qt_import_qml_plugins(%{ProjectName})
|
qt_import_qml_plugins(%{ProjectName})
|
||||||
qt_finalize_executable(%{ProjectName})
|
qt_finalize_executable(%{ProjectName})
|
||||||
|
|||||||
@@ -74,6 +74,8 @@ set_target_properties(%{ProjectName} PROPERTIES
|
|||||||
WIN32_EXECUTABLE TRUE
|
WIN32_EXECUTABLE TRUE
|
||||||
)
|
)
|
||||||
|
|
||||||
|
install(TARGETS %{ProjectName} BUNDLE DESTINATION .)
|
||||||
|
|
||||||
if(QT_VERSION_MAJOR EQUAL 6)
|
if(QT_VERSION_MAJOR EQUAL 6)
|
||||||
qt_finalize_executable(%{ProjectName})
|
qt_finalize_executable(%{ProjectName})
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
@@ -96,86 +96,6 @@ protected:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class ContainingFunctionAt: protected SymbolVisitor
|
|
||||||
{
|
|
||||||
TranslationUnit *translationUnit;
|
|
||||||
Symbol *root;
|
|
||||||
int line;
|
|
||||||
int column;
|
|
||||||
Symbol *functionSymbol;
|
|
||||||
bool foundFunction;
|
|
||||||
bool foundBlock;
|
|
||||||
|
|
||||||
bool scopeContains(Scope* scope, int line, int column){
|
|
||||||
if (!scope)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
int scopeStartLine{-1}, scopeStartColumn{-1}, scopeEndLine{-1}, scopeEndColumn{-1};
|
|
||||||
translationUnit->getPosition(scope->startOffset(), &scopeStartLine, &scopeStartColumn);
|
|
||||||
translationUnit->getPosition(scope->endOffset(), &scopeEndLine, &scopeEndColumn);
|
|
||||||
|
|
||||||
if (line < scopeStartLine || line > scopeEndLine)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (line > scopeStartLine && line < scopeEndLine)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
if (scopeStartLine == line && column >= scopeStartColumn)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
if (scopeEndLine == line && column <= scopeEndColumn)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
ContainingFunctionAt(TranslationUnit *unit, Symbol *root)
|
|
||||||
: translationUnit(unit), root(root), line(0), column(0), functionSymbol(nullptr)
|
|
||||||
, foundFunction(false), foundBlock(false) {}
|
|
||||||
|
|
||||||
Symbol *operator()(int line, int column)
|
|
||||||
{
|
|
||||||
this->line = line;
|
|
||||||
this->column = column;
|
|
||||||
this->functionSymbol = nullptr;
|
|
||||||
accept(root);
|
|
||||||
|
|
||||||
return foundBlock ? functionSymbol : nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
bool preVisit(Symbol *s) final
|
|
||||||
{
|
|
||||||
if (foundBlock)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (foundFunction) {
|
|
||||||
auto block = s->asBlock();
|
|
||||||
if (!block)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
if (scopeContains(block->asScope(), line, column)) {
|
|
||||||
foundBlock = true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto asFunction = s->asFunction();
|
|
||||||
if (asFunction) {
|
|
||||||
if (s->line() < line || (s->line() == line && s->column() <= column)) {
|
|
||||||
foundFunction = scopeContains(s->asScope(), line, column);
|
|
||||||
if (foundFunction)
|
|
||||||
functionSymbol = asFunction;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
class FindScopeAt: protected SymbolVisitor
|
class FindScopeAt: protected SymbolVisitor
|
||||||
{
|
{
|
||||||
TranslationUnit *_unit;
|
TranslationUnit *_unit;
|
||||||
@@ -592,11 +512,19 @@ QString Document::functionAt(int line, int column, int *lineOpeningDeclaratorPar
|
|||||||
if (line < 1 || column < 1)
|
if (line < 1 || column < 1)
|
||||||
return QString();
|
return QString();
|
||||||
|
|
||||||
Symbol *symbol = ContainingFunctionAt{translationUnit(), globalNamespace()}(line, column);
|
Symbol *symbol = lastVisibleSymbolAt(line, column);
|
||||||
if (!symbol)
|
if (!symbol)
|
||||||
return QString();
|
return QString();
|
||||||
|
|
||||||
|
// Find the enclosing function scope (which might be several levels up, or we might be standing
|
||||||
|
// on it)
|
||||||
Scope *scope = symbol->asScope();
|
Scope *scope = symbol->asScope();
|
||||||
|
if (!scope)
|
||||||
|
scope = symbol->enclosingScope();
|
||||||
|
|
||||||
|
while (scope && !scope->isFunction() )
|
||||||
|
scope = scope->enclosingScope();
|
||||||
|
|
||||||
if (!scope)
|
if (!scope)
|
||||||
return QString();
|
return QString();
|
||||||
|
|
||||||
|
|||||||
@@ -142,11 +142,30 @@ void FindUsages::reportResult(unsigned tokenIndex, const QList<LookupItem> &cand
|
|||||||
const int len = tk.utf16chars();
|
const int len = tk.utf16chars();
|
||||||
|
|
||||||
const Usage u(Utils::FilePath::fromString(_doc->fileName()), lineText,
|
const Usage u(Utils::FilePath::fromString(_doc->fileName()), lineText,
|
||||||
getType(line, col, tokenIndex), line, col - 1, len);
|
getContainingFunction(line, col), getType(line, col, tokenIndex),
|
||||||
|
line, col - 1, len);
|
||||||
_usages.append(u);
|
_usages.append(u);
|
||||||
_references.append(tokenIndex);
|
_references.append(tokenIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString FindUsages::getContainingFunction(int line, int column)
|
||||||
|
{
|
||||||
|
const QList<AST *> astPath = ASTPath(_doc)(line, column);
|
||||||
|
bool hasBlock = false;
|
||||||
|
for (auto it = astPath.crbegin(); it != astPath.crend(); ++it) {
|
||||||
|
if (!hasBlock && (*it)->asCompoundStatement())
|
||||||
|
hasBlock = true;
|
||||||
|
if (const auto func = (*it)->asFunctionDefinition()) {
|
||||||
|
if (!hasBlock)
|
||||||
|
return {};
|
||||||
|
if (!func->symbol)
|
||||||
|
return {};
|
||||||
|
return Overview().prettyName(func->symbol->name());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
class FindUsages::GetUsageType
|
class FindUsages::GetUsageType
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -42,11 +42,14 @@ public:
|
|||||||
enum class Type { Declaration, Initialization, Read, Write, WritableRef, Other };
|
enum class Type { Declaration, Initialization, Read, Write, WritableRef, Other };
|
||||||
|
|
||||||
Usage() = default;
|
Usage() = default;
|
||||||
Usage(const Utils::FilePath &path, const QString &lineText, Type t, int line, int col, int len)
|
Usage(const Utils::FilePath &path, const QString &lineText, const QString &func, Type t,
|
||||||
: path(path), lineText(lineText), type(t), line(line), col(col), len(len) {}
|
int line, int col, int len)
|
||||||
|
: path(path), lineText(lineText), containingFunction(func), type(t),
|
||||||
|
line(line), col(col), len(len) {}
|
||||||
|
|
||||||
Utils::FilePath path;
|
Utils::FilePath path;
|
||||||
QString lineText;
|
QString lineText;
|
||||||
|
QString containingFunction;
|
||||||
Type type = Type::Other;
|
Type type = Type::Other;
|
||||||
int line = 0;
|
int line = 0;
|
||||||
int col = 0;
|
int col = 0;
|
||||||
@@ -75,6 +78,7 @@ protected:
|
|||||||
void reportResult(unsigned tokenIndex, const Name *name, Scope *scope = nullptr);
|
void reportResult(unsigned tokenIndex, const Name *name, Scope *scope = nullptr);
|
||||||
void reportResult(unsigned tokenIndex, const QList<LookupItem> &candidates);
|
void reportResult(unsigned tokenIndex, const QList<LookupItem> &candidates);
|
||||||
Usage::Type getType(int line, int column, int tokenIndex);
|
Usage::Type getType(int line, int column, int tokenIndex);
|
||||||
|
QString getContainingFunction(int line, int column);
|
||||||
|
|
||||||
bool checkCandidates(const QList<LookupItem> &candidates) const;
|
bool checkCandidates(const QList<LookupItem> &candidates) const;
|
||||||
void checkExpression(unsigned startToken, unsigned endToken, Scope *scope = nullptr);
|
void checkExpression(unsigned startToken, unsigned endToken, Scope *scope = nullptr);
|
||||||
|
|||||||
@@ -557,9 +557,11 @@ void DiagramController::onBeginResetModel()
|
|||||||
void DiagramController::onEndResetModel()
|
void DiagramController::onEndResetModel()
|
||||||
{
|
{
|
||||||
updateAllDiagramsList();
|
updateAllDiagramsList();
|
||||||
foreach (MDiagram *diagram, m_allDiagrams) {
|
for (MDiagram *diagram : qAsConst(m_allDiagrams)) {
|
||||||
|
const QList<DElement *> elements = diagram->diagramElements();
|
||||||
// remove all elements which are not longer part of the model
|
// remove all elements which are not longer part of the model
|
||||||
foreach (DElement *element, diagram->diagramElements()) {
|
for (int i = elements.size() - 1; i >= 0; --i) {
|
||||||
|
DElement *element = elements.at(i);
|
||||||
if (element->modelUid().isValid()) {
|
if (element->modelUid().isValid()) {
|
||||||
MElement *modelElement = m_modelController->findElement(element->modelUid());
|
MElement *modelElement = m_modelController->findElement(element->modelUid());
|
||||||
if (!modelElement)
|
if (!modelElement)
|
||||||
@@ -567,7 +569,7 @@ void DiagramController::onEndResetModel()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// update all remaining elements from model
|
// update all remaining elements from model
|
||||||
foreach (DElement *element, diagram->diagramElements())
|
for (DElement *element : diagram->diagramElements())
|
||||||
updateElementFromModel(element, diagram, false);
|
updateElementFromModel(element, diagram, false);
|
||||||
}
|
}
|
||||||
emit endResetAllDiagrams();
|
emit endResetAllDiagrams();
|
||||||
|
|||||||
Submodule src/libs/qlitehtml updated: 6bfa7a2bea...076f57c943
@@ -76,6 +76,8 @@ bool allOf(const T &container, F predicate);
|
|||||||
/////////////////////////
|
/////////////////////////
|
||||||
template<typename T, typename F>
|
template<typename T, typename F>
|
||||||
void erase(T &container, F predicate);
|
void erase(T &container, F predicate);
|
||||||
|
template<typename T, typename F>
|
||||||
|
bool eraseOne(T &container, F predicate);
|
||||||
|
|
||||||
/////////////////////////
|
/////////////////////////
|
||||||
// contains
|
// contains
|
||||||
@@ -442,7 +444,15 @@ void erase(T &container, F predicate)
|
|||||||
container.erase(std::remove_if(std::begin(container), std::end(container), predicate),
|
container.erase(std::remove_if(std::begin(container), std::end(container), predicate),
|
||||||
std::end(container));
|
std::end(container));
|
||||||
}
|
}
|
||||||
|
template<typename T, typename F>
|
||||||
|
bool eraseOne(T &container, F predicate)
|
||||||
|
{
|
||||||
|
const auto it = std::find_if(std::begin(container), std::end(container), predicate);
|
||||||
|
if (it == std::end(container))
|
||||||
|
return false;
|
||||||
|
container.erase(it);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
//////////////////
|
//////////////////
|
||||||
// contains
|
// contains
|
||||||
|
|||||||
@@ -527,10 +527,11 @@ QString FilePath::fileNameWithPathComponents(int pathComponents) const
|
|||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If there are no more slashes before the found one, return the entire string
|
|
||||||
if (i > 0 && m_data.lastIndexOf(slash, i) != -1)
|
if (i > 0 && m_data.lastIndexOf(slash, i) != -1)
|
||||||
return m_data.mid(component);
|
return m_data.mid(component);
|
||||||
return m_data;
|
|
||||||
|
// If there are no more slashes before the found one, return the entire string
|
||||||
|
return displayName();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \returns the base name of the file without the path.
|
/// \returns the base name of the file without the path.
|
||||||
|
|||||||
@@ -89,21 +89,6 @@ CallerHandle::~CallerHandle()
|
|||||||
qDeleteAll(m_signals);
|
qDeleteAll(m_signals);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CallerHandle::waitForStarted(int msecs)
|
|
||||||
{
|
|
||||||
return waitForSignal(msecs, SignalType::Started);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CallerHandle::waitForReadyRead(int msces)
|
|
||||||
{
|
|
||||||
return waitForSignal(msces, SignalType::ReadyRead);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CallerHandle::waitForFinished(int msecs)
|
|
||||||
{
|
|
||||||
return waitForSignal(msecs, SignalType::Done);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CallerHandle::flush()
|
void CallerHandle::flush()
|
||||||
{
|
{
|
||||||
flushFor(SignalType::NoSignal);
|
flushFor(SignalType::NoSignal);
|
||||||
@@ -329,11 +314,11 @@ void CallerHandle::setProcessSetupData(ProcessSetupData *setup)
|
|||||||
m_setup = setup;
|
m_setup = setup;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CallerHandle::waitForSignal(int msecs, SignalType newSignal)
|
bool CallerHandle::waitForSignal(SignalType signalType, int msecs)
|
||||||
{
|
{
|
||||||
QTC_ASSERT(isCalledFromCallersThread(), return false);
|
QTC_ASSERT(isCalledFromCallersThread(), return false);
|
||||||
QTC_ASSERT(m_launcherHandle, return false);
|
QTC_ASSERT(m_launcherHandle, return false);
|
||||||
return m_launcherHandle->waitForSignal(msecs, newSignal);
|
return m_launcherHandle->waitForSignal(signalType, msecs);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called from caller's or launcher's thread.
|
// Called from caller's or launcher's thread.
|
||||||
@@ -351,7 +336,7 @@ bool CallerHandle::isCalledFromLaunchersThread() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Called from caller's thread exclusively.
|
// Called from caller's thread exclusively.
|
||||||
bool LauncherHandle::waitForSignal(int msecs, CallerHandle::SignalType newSignal)
|
bool LauncherHandle::waitForSignal(CallerHandle::SignalType newSignal, int msecs)
|
||||||
{
|
{
|
||||||
QTC_ASSERT(!isCalledFromLaunchersThread(), return false);
|
QTC_ASSERT(!isCalledFromLaunchersThread(), return false);
|
||||||
QDeadlineTimer deadline(msecs);
|
QDeadlineTimer deadline(msecs);
|
||||||
|
|||||||
@@ -73,9 +73,7 @@ public:
|
|||||||
LauncherHandle *launcherHandle() const { return m_launcherHandle; }
|
LauncherHandle *launcherHandle() const { return m_launcherHandle; }
|
||||||
void setLauncherHandle(LauncherHandle *handle) { QMutexLocker locker(&m_mutex); m_launcherHandle = handle; }
|
void setLauncherHandle(LauncherHandle *handle) { QMutexLocker locker(&m_mutex); m_launcherHandle = handle; }
|
||||||
|
|
||||||
bool waitForStarted(int msecs);
|
bool waitForSignal(CallerHandle::SignalType signalType, int msecs);
|
||||||
bool waitForReadyRead(int msces);
|
|
||||||
bool waitForFinished(int msecs);
|
|
||||||
|
|
||||||
// Returns the list of flushed signals.
|
// Returns the list of flushed signals.
|
||||||
void flush();
|
void flush();
|
||||||
@@ -109,8 +107,6 @@ signals:
|
|||||||
void done(const Utils::ProcessResultData &resultData);
|
void done(const Utils::ProcessResultData &resultData);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool waitForSignal(int msecs, SignalType newSignal);
|
|
||||||
|
|
||||||
// Called from caller's thread exclusively.
|
// Called from caller's thread exclusively.
|
||||||
void sendPacket(const Internal::LauncherPacket &packet);
|
void sendPacket(const Internal::LauncherPacket &packet);
|
||||||
// Called from caller's or launcher's thread.
|
// Called from caller's or launcher's thread.
|
||||||
@@ -158,7 +154,7 @@ public:
|
|||||||
// Called from caller's thread, moved to launcher's thread afterwards.
|
// Called from caller's thread, moved to launcher's thread afterwards.
|
||||||
LauncherHandle(quintptr token) : m_token(token) {}
|
LauncherHandle(quintptr token) : m_token(token) {}
|
||||||
// Called from caller's thread exclusively.
|
// Called from caller's thread exclusively.
|
||||||
bool waitForSignal(int msecs, CallerHandle::SignalType newSignal);
|
bool waitForSignal(CallerHandle::SignalType newSignal, int msecs);
|
||||||
CallerHandle *callerHandle() const { return m_callerHandle; }
|
CallerHandle *callerHandle() const { return m_callerHandle; }
|
||||||
void setCallerHandle(CallerHandle *handle) { QMutexLocker locker(&m_mutex); m_callerHandle = handle; }
|
void setCallerHandle(CallerHandle *handle) { QMutexLocker locker(&m_mutex); m_callerHandle = handle; }
|
||||||
|
|
||||||
|
|||||||
@@ -60,12 +60,6 @@ MimeType mimeTypeForFile(const QString &fileName, MimeMatchMode mode)
|
|||||||
return mdb.mimeTypeForFile(fileName, MimeDatabase::MatchMode(mode));
|
return mdb.mimeTypeForFile(fileName, MimeDatabase::MatchMode(mode));
|
||||||
}
|
}
|
||||||
|
|
||||||
MimeType mimeTypeForFile(const QFileInfo &fileInfo, MimeMatchMode mode)
|
|
||||||
{
|
|
||||||
MimeDatabase mdb;
|
|
||||||
return mdb.mimeTypeForFile(fileInfo, MimeDatabase::MatchMode(mode));
|
|
||||||
}
|
|
||||||
|
|
||||||
MimeType mimeTypeForFile(const FilePath &filePath, MimeMatchMode mode)
|
MimeType mimeTypeForFile(const FilePath &filePath, MimeMatchMode mode)
|
||||||
{
|
{
|
||||||
MimeDatabase mdb;
|
MimeDatabase mdb;
|
||||||
|
|||||||
@@ -44,10 +44,6 @@
|
|||||||
#include <mimemagicrule_p.h>
|
#include <mimemagicrule_p.h>
|
||||||
#include <mimetype.h>
|
#include <mimetype.h>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
|
||||||
class QFileInfo;
|
|
||||||
QT_END_NAMESPACE
|
|
||||||
|
|
||||||
namespace Utils {
|
namespace Utils {
|
||||||
|
|
||||||
class FilePath;
|
class FilePath;
|
||||||
@@ -59,8 +55,6 @@ enum class MimeMatchMode { MatchDefault = 0x0, MatchExtension = 0x1, MatchConten
|
|||||||
|
|
||||||
QTCREATOR_UTILS_EXPORT MimeType mimeTypeForFile(const QString &fileName,
|
QTCREATOR_UTILS_EXPORT MimeType mimeTypeForFile(const QString &fileName,
|
||||||
MimeMatchMode mode = MimeMatchMode::MatchDefault);
|
MimeMatchMode mode = MimeMatchMode::MatchDefault);
|
||||||
QTCREATOR_UTILS_EXPORT MimeType mimeTypeForFile(const QFileInfo &fileInfo,
|
|
||||||
MimeMatchMode mode = MimeMatchMode::MatchDefault);
|
|
||||||
QTCREATOR_UTILS_EXPORT MimeType mimeTypeForFile(const FilePath &filePath,
|
QTCREATOR_UTILS_EXPORT MimeType mimeTypeForFile(const FilePath &filePath,
|
||||||
MimeMatchMode mode = MimeMatchMode::MatchDefault);
|
MimeMatchMode mode = MimeMatchMode::MatchDefault);
|
||||||
QTCREATOR_UTILS_EXPORT QList<MimeType> mimeTypesForFileName(const QString &fileName);
|
QTCREATOR_UTILS_EXPORT QList<MimeType> mimeTypesForFileName(const QString &fileName);
|
||||||
|
|||||||
@@ -85,13 +85,22 @@ enum class ProcessSignalType {
|
|||||||
Done
|
Done
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class QTCREATOR_UTILS_EXPORT ProcessBlockingInterface : public QObject
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
// Wait for:
|
||||||
|
// - Started is being called only in Starting state.
|
||||||
|
// - ReadyRead is being called in Starting or Running state.
|
||||||
|
// - Done is being called in Starting or Running state.
|
||||||
|
virtual bool waitForSignal(ProcessSignalType signalType, int msecs) = 0;
|
||||||
|
|
||||||
|
friend class Internal::QtcProcessPrivate;
|
||||||
|
};
|
||||||
|
|
||||||
class QTCREATOR_UTILS_EXPORT ProcessInterface : public QObject
|
class QTCREATOR_UTILS_EXPORT ProcessInterface : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
|
||||||
ProcessInterface(QObject *parent = nullptr) : QObject(parent) {}
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
// This should be emitted when being in Starting state only.
|
// This should be emitted when being in Starting state only.
|
||||||
// After emitting this signal the process enters Running state.
|
// After emitting this signal the process enters Running state.
|
||||||
@@ -121,14 +130,7 @@ private:
|
|||||||
// It's being called in Starting or Running state.
|
// It's being called in Starting or Running state.
|
||||||
virtual void sendControlSignal(ControlSignal controlSignal) = 0;
|
virtual void sendControlSignal(ControlSignal controlSignal) = 0;
|
||||||
|
|
||||||
// It's being called only in Starting state.
|
virtual ProcessBlockingInterface *processBlockingInterface() const { return nullptr; }
|
||||||
virtual bool waitForStarted(int msecs) = 0;
|
|
||||||
|
|
||||||
// It's being called in Starting or Running state.
|
|
||||||
virtual bool waitForReadyRead(int msecs) = 0;
|
|
||||||
|
|
||||||
// It's being called in Starting or Running state.
|
|
||||||
virtual bool waitForFinished(int msecs) = 0;
|
|
||||||
|
|
||||||
friend class QtcProcess;
|
friend class QtcProcess;
|
||||||
friend class Internal::QtcProcessPrivate;
|
friend class Internal::QtcProcessPrivate;
|
||||||
|
|||||||
@@ -322,10 +322,34 @@ bool DefaultImpl::ensureProgramExists(const QString &program)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class QProcessBlockingImpl : public ProcessBlockingInterface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QProcessBlockingImpl(QProcess *process) : m_process(process) {}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool waitForSignal(ProcessSignalType signalType, int msecs) final
|
||||||
|
{
|
||||||
|
switch (signalType) {
|
||||||
|
case ProcessSignalType::Started:
|
||||||
|
return m_process->waitForStarted(msecs);
|
||||||
|
case ProcessSignalType::ReadyRead:
|
||||||
|
return m_process->waitForReadyRead(msecs);
|
||||||
|
case ProcessSignalType::Done:
|
||||||
|
return m_process->waitForFinished(msecs);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QProcess *m_process = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
class QProcessImpl final : public DefaultImpl
|
class QProcessImpl final : public DefaultImpl
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
QProcessImpl() : m_process(new ProcessHelper(this))
|
QProcessImpl()
|
||||||
|
: m_process(new ProcessHelper(this))
|
||||||
|
, m_blockingImpl(new QProcessBlockingImpl(m_process))
|
||||||
{
|
{
|
||||||
connect(m_process, &QProcess::started,
|
connect(m_process, &QProcess::started,
|
||||||
this, &QProcessImpl::handleStarted);
|
this, &QProcessImpl::handleStarted);
|
||||||
@@ -361,9 +385,7 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool waitForStarted(int msecs) final { return m_process->waitForStarted(msecs); }
|
virtual ProcessBlockingInterface *processBlockingInterface() const { return m_blockingImpl; }
|
||||||
bool waitForReadyRead(int msecs) final { return m_process->waitForReadyRead(msecs); }
|
|
||||||
bool waitForFinished(int msecs) final { return m_process->waitForFinished(msecs); }
|
|
||||||
|
|
||||||
void doDefaultStart(const QString &program, const QStringList &arguments) final
|
void doDefaultStart(const QString &program, const QStringList &arguments) final
|
||||||
{
|
{
|
||||||
@@ -411,7 +433,8 @@ private:
|
|||||||
emit done(result);
|
emit done(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
ProcessHelper *m_process;
|
ProcessHelper *m_process = nullptr;
|
||||||
|
QProcessBlockingImpl *m_blockingImpl = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
static uint uniqueToken()
|
static uint uniqueToken()
|
||||||
@@ -420,6 +443,33 @@ static uint uniqueToken()
|
|||||||
return ++globalUniqueToken;
|
return ++globalUniqueToken;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class ProcessLauncherBlockingImpl : public ProcessBlockingInterface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ProcessLauncherBlockingImpl(CallerHandle *caller) : m_caller(caller) {}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool waitForSignal(ProcessSignalType signalType, int msecs) final
|
||||||
|
{
|
||||||
|
// TODO: Remove CallerHandle::SignalType
|
||||||
|
const CallerHandle::SignalType type = [signalType] {
|
||||||
|
switch (signalType) {
|
||||||
|
case ProcessSignalType::Started:
|
||||||
|
return CallerHandle::SignalType::Started;
|
||||||
|
case ProcessSignalType::ReadyRead:
|
||||||
|
return CallerHandle::SignalType::ReadyRead;
|
||||||
|
case ProcessSignalType::Done:
|
||||||
|
return CallerHandle::SignalType::Done;
|
||||||
|
}
|
||||||
|
QTC_CHECK(false);
|
||||||
|
return CallerHandle::SignalType::NoSignal;
|
||||||
|
}();
|
||||||
|
return m_caller->waitForSignal(type, msecs);
|
||||||
|
}
|
||||||
|
|
||||||
|
CallerHandle *m_caller = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
class ProcessLauncherImpl final : public DefaultImpl
|
class ProcessLauncherImpl final : public DefaultImpl
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@@ -434,6 +484,7 @@ public:
|
|||||||
this, &ProcessInterface::readyRead);
|
this, &ProcessInterface::readyRead);
|
||||||
connect(m_handle, &CallerHandle::done,
|
connect(m_handle, &CallerHandle::done,
|
||||||
this, &ProcessInterface::done);
|
this, &ProcessInterface::done);
|
||||||
|
m_blockingImpl = new ProcessLauncherBlockingImpl(m_handle);
|
||||||
}
|
}
|
||||||
~ProcessLauncherImpl() final
|
~ProcessLauncherImpl() final
|
||||||
{
|
{
|
||||||
@@ -462,9 +513,7 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool waitForStarted(int msecs) final { return m_handle->waitForStarted(msecs); }
|
virtual ProcessBlockingInterface *processBlockingInterface() const { return m_blockingImpl; }
|
||||||
bool waitForReadyRead(int msecs) final { return m_handle->waitForReadyRead(msecs); }
|
|
||||||
bool waitForFinished(int msecs) final { return m_handle->waitForFinished(msecs); }
|
|
||||||
|
|
||||||
void doDefaultStart(const QString &program, const QStringList &arguments) final
|
void doDefaultStart(const QString &program, const QStringList &arguments) final
|
||||||
{
|
{
|
||||||
@@ -476,6 +525,7 @@ private:
|
|||||||
const uint m_token = 0;
|
const uint m_token = 0;
|
||||||
// Lives in caller's thread.
|
// Lives in caller's thread.
|
||||||
CallerHandle *m_handle = nullptr;
|
CallerHandle *m_handle = nullptr;
|
||||||
|
ProcessLauncherBlockingImpl *m_blockingImpl = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
static ProcessImpl defaultProcessImpl()
|
static ProcessImpl defaultProcessImpl()
|
||||||
@@ -535,13 +585,15 @@ private:
|
|||||||
const ProcessResultData m_resultData;
|
const ProcessResultData m_resultData;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class GeneralProcessBlockingImpl;
|
||||||
|
|
||||||
class ProcessInterfaceHandler : public QObject
|
class ProcessInterfaceHandler : public QObject
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ProcessInterfaceHandler(QtcProcessPrivate *caller, ProcessInterface *process);
|
ProcessInterfaceHandler(GeneralProcessBlockingImpl *caller, ProcessInterface *process);
|
||||||
|
|
||||||
// Called from caller's thread exclusively.
|
// Called from caller's thread exclusively.
|
||||||
bool waitForSignal(int msecs, ProcessSignalType newSignal);
|
bool waitForSignal(ProcessSignalType newSignal, int msecs);
|
||||||
void moveToCallerThread();
|
void moveToCallerThread();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -555,11 +607,44 @@ private:
|
|||||||
void handleDone(const ProcessResultData &data);
|
void handleDone(const ProcessResultData &data);
|
||||||
void appendSignal(ProcessInterfaceSignal *newSignal);
|
void appendSignal(ProcessInterfaceSignal *newSignal);
|
||||||
|
|
||||||
QtcProcessPrivate *m_caller = nullptr;
|
GeneralProcessBlockingImpl *m_caller = nullptr;
|
||||||
QMutex m_mutex;
|
QMutex m_mutex;
|
||||||
QWaitCondition m_waitCondition;
|
QWaitCondition m_waitCondition;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class GeneralProcessBlockingImpl : public ProcessBlockingInterface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
GeneralProcessBlockingImpl(QtcProcessPrivate *parent);
|
||||||
|
|
||||||
|
void flush() { flushSignals(takeAllSignals()); }
|
||||||
|
bool flushFor(ProcessSignalType signalType) {
|
||||||
|
return flushSignals(takeSignalsFor(signalType), &signalType);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool shouldFlush() const { QMutexLocker locker(&m_mutex); return !m_signals.isEmpty(); }
|
||||||
|
// Called from ProcessInterfaceHandler thread exclusively.
|
||||||
|
void appendSignal(ProcessInterfaceSignal *launcherSignal);
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Called from caller's thread exclusively
|
||||||
|
bool waitForSignal(ProcessSignalType newSignal, int msecs) final;
|
||||||
|
|
||||||
|
QList<ProcessInterfaceSignal *> takeAllSignals();
|
||||||
|
QList<ProcessInterfaceSignal *> takeSignalsFor(ProcessSignalType signalType);
|
||||||
|
bool flushSignals(const QList<ProcessInterfaceSignal *> &signalList,
|
||||||
|
ProcessSignalType *signalType = nullptr);
|
||||||
|
|
||||||
|
void handleStartedSignal(const StartedSignal *launcherSignal);
|
||||||
|
void handleReadyReadSignal(const ReadyReadSignal *launcherSignal);
|
||||||
|
void handleDoneSignal(const DoneSignal *launcherSignal);
|
||||||
|
|
||||||
|
QtcProcessPrivate *m_caller = nullptr;
|
||||||
|
std::unique_ptr<ProcessInterfaceHandler> m_processHandler;
|
||||||
|
mutable QMutex m_mutex;
|
||||||
|
QList<ProcessInterfaceSignal *> m_signals;
|
||||||
|
};
|
||||||
|
|
||||||
class QtcProcessPrivate : public QObject
|
class QtcProcessPrivate : public QObject
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -591,11 +676,18 @@ public:
|
|||||||
void setProcessInterface(ProcessInterface *process)
|
void setProcessInterface(ProcessInterface *process)
|
||||||
{
|
{
|
||||||
m_process.reset(process);
|
m_process.reset(process);
|
||||||
m_processHandler.reset(new ProcessInterfaceHandler(this, process));
|
m_process->setParent(this);
|
||||||
|
connect(m_process.get(), &ProcessInterface::started,
|
||||||
|
this, &QtcProcessPrivate::handleStarted);
|
||||||
|
connect(m_process.get(), &ProcessInterface::readyRead,
|
||||||
|
this, &QtcProcessPrivate::handleReadyRead);
|
||||||
|
connect(m_process.get(), &ProcessInterface::done,
|
||||||
|
this, &QtcProcessPrivate::handleDone);
|
||||||
|
|
||||||
// In order to move the process into another thread together with handle
|
m_blockingInterface.reset(process->processBlockingInterface());
|
||||||
m_process->setParent(m_processHandler.get());
|
if (!m_blockingInterface)
|
||||||
m_processHandler->setParent(this);
|
m_blockingInterface.reset(new GeneralProcessBlockingImpl(this));
|
||||||
|
m_blockingInterface->setParent(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
CommandLine fullCommandLine() const
|
CommandLine fullCommandLine() const
|
||||||
@@ -624,14 +716,11 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
QtcProcess *q;
|
QtcProcess *q;
|
||||||
std::unique_ptr<ProcessInterfaceHandler> m_processHandler;
|
std::unique_ptr<ProcessBlockingInterface> m_blockingInterface;
|
||||||
std::unique_ptr<ProcessInterface> m_process;
|
std::unique_ptr<ProcessInterface> m_process;
|
||||||
ProcessSetupData m_setup;
|
ProcessSetupData m_setup;
|
||||||
|
|
||||||
void slotTimeout();
|
void slotTimeout();
|
||||||
void handleStartedSignal(const StartedSignal *launcherSignal);
|
|
||||||
void handleReadyReadSignal(const ReadyReadSignal *launcherSignal);
|
|
||||||
void handleDoneSignal(const DoneSignal *launcherSignal);
|
|
||||||
void handleStarted(qint64 processId, qint64 applicationMainThreadId);
|
void handleStarted(qint64 processId, qint64 applicationMainThreadId);
|
||||||
void handleReadyRead(const QByteArray &outputData, const QByteArray &errorData);
|
void handleReadyRead(const QByteArray &outputData, const QByteArray &errorData);
|
||||||
void handleDone(const ProcessResultData &data);
|
void handleDone(const ProcessResultData &data);
|
||||||
@@ -647,31 +736,11 @@ public:
|
|||||||
|
|
||||||
ProcessResult interpretExitCode(int exitCode);
|
ProcessResult interpretExitCode(int exitCode);
|
||||||
|
|
||||||
// === ProcessInterfaceHandler related ===
|
bool waitForSignal(ProcessSignalType signalType, int msecs);
|
||||||
// Called from caller's thread exclusively
|
|
||||||
bool waitForSignal(int msecs, ProcessSignalType newSignal);
|
|
||||||
void flush() { flushSignals(takeAllSignals()); }
|
|
||||||
bool flushFor(ProcessSignalType signalType) {
|
|
||||||
return flushSignals(takeSignalsFor(signalType), &signalType);
|
|
||||||
}
|
|
||||||
|
|
||||||
QList<ProcessInterfaceSignal *> takeAllSignals();
|
|
||||||
QList<ProcessInterfaceSignal *> takeSignalsFor(ProcessSignalType signalType);
|
|
||||||
bool flushSignals(const QList<ProcessInterfaceSignal *> &signalList,
|
|
||||||
ProcessSignalType *signalType = nullptr);
|
|
||||||
|
|
||||||
bool shouldFlush() const { QMutexLocker locker(&m_mutex); return !m_signals.isEmpty(); }
|
|
||||||
Qt::ConnectionType connectionType() const;
|
Qt::ConnectionType connectionType() const;
|
||||||
void sendControlSignal(ControlSignal controlSignal);
|
void sendControlSignal(ControlSignal controlSignal);
|
||||||
// Called from ProcessInterfaceHandler thread exclusively.
|
|
||||||
void appendSignal(ProcessInterfaceSignal *launcherSignal);
|
|
||||||
|
|
||||||
mutable QMutex m_mutex;
|
|
||||||
QList<ProcessInterfaceSignal *> m_signals;
|
|
||||||
QTimer m_killTimer;
|
QTimer m_killTimer;
|
||||||
|
|
||||||
// =======================================
|
|
||||||
|
|
||||||
QProcess::ProcessState m_state = QProcess::NotRunning;
|
QProcess::ProcessState m_state = QProcess::NotRunning;
|
||||||
qint64 m_processId = 0;
|
qint64 m_processId = 0;
|
||||||
qint64 m_applicationMainThreadId = 0;
|
qint64 m_applicationMainThreadId = 0;
|
||||||
@@ -692,10 +761,11 @@ public:
|
|||||||
Guard m_guard;
|
Guard m_guard;
|
||||||
};
|
};
|
||||||
|
|
||||||
ProcessInterfaceHandler::ProcessInterfaceHandler(QtcProcessPrivate *caller,
|
ProcessInterfaceHandler::ProcessInterfaceHandler(GeneralProcessBlockingImpl *caller,
|
||||||
ProcessInterface *process)
|
ProcessInterface *process)
|
||||||
: m_caller(caller)
|
: m_caller(caller)
|
||||||
{
|
{
|
||||||
|
process->disconnect();
|
||||||
connect(process, &ProcessInterface::started,
|
connect(process, &ProcessInterface::started,
|
||||||
this, &ProcessInterfaceHandler::handleStarted);
|
this, &ProcessInterfaceHandler::handleStarted);
|
||||||
connect(process, &ProcessInterface::readyRead,
|
connect(process, &ProcessInterface::readyRead,
|
||||||
@@ -705,7 +775,7 @@ ProcessInterfaceHandler::ProcessInterfaceHandler(QtcProcessPrivate *caller,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Called from caller's thread exclusively.
|
// Called from caller's thread exclusively.
|
||||||
bool ProcessInterfaceHandler::waitForSignal(int msecs, ProcessSignalType newSignal)
|
bool ProcessInterfaceHandler::waitForSignal(ProcessSignalType newSignal, int msecs)
|
||||||
{
|
{
|
||||||
QDeadlineTimer deadline(msecs);
|
QDeadlineTimer deadline(msecs);
|
||||||
while (true) {
|
while (true) {
|
||||||
@@ -769,17 +839,20 @@ void ProcessInterfaceHandler::appendSignal(ProcessInterfaceSignal *newSignal)
|
|||||||
}
|
}
|
||||||
m_waitCondition.wakeOne();
|
m_waitCondition.wakeOne();
|
||||||
// call in callers thread
|
// call in callers thread
|
||||||
QMetaObject::invokeMethod(m_caller, &QtcProcessPrivate::flush);
|
QMetaObject::invokeMethod(m_caller, &GeneralProcessBlockingImpl::flush);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called from caller's thread exclusively
|
GeneralProcessBlockingImpl::GeneralProcessBlockingImpl(QtcProcessPrivate *parent)
|
||||||
bool QtcProcessPrivate::waitForSignal(int msecs, ProcessSignalType newSignal)
|
: m_caller(parent)
|
||||||
|
, m_processHandler(new ProcessInterfaceHandler(this, parent->m_process.get()))
|
||||||
{
|
{
|
||||||
const QDeadlineTimer timeout(msecs);
|
// In order to move the process interface into another thread together with handle
|
||||||
const QDeadlineTimer currentKillTimeout(m_killTimer.remainingTime());
|
parent->m_process.get()->setParent(m_processHandler.get());
|
||||||
const bool needsSplit = m_killTimer.isActive() ? timeout > currentKillTimeout : false;
|
m_processHandler->setParent(this);
|
||||||
const QDeadlineTimer mainTimeout = needsSplit ? currentKillTimeout : timeout;
|
}
|
||||||
|
|
||||||
|
bool GeneralProcessBlockingImpl::waitForSignal(ProcessSignalType newSignal, int msecs)
|
||||||
|
{
|
||||||
m_processHandler->setParent(nullptr);
|
m_processHandler->setParent(nullptr);
|
||||||
|
|
||||||
QThread thread;
|
QThread thread;
|
||||||
@@ -789,12 +862,7 @@ bool QtcProcessPrivate::waitForSignal(int msecs, ProcessSignalType newSignal)
|
|||||||
// the caller here is blocked, so all signals should be buffered and we are going
|
// the caller here is blocked, so all signals should be buffered and we are going
|
||||||
// to flush them from inside waitForSignal().
|
// to flush them from inside waitForSignal().
|
||||||
m_processHandler->moveToThread(&thread);
|
m_processHandler->moveToThread(&thread);
|
||||||
bool result = m_processHandler->waitForSignal(mainTimeout.remainingTime(), newSignal);
|
const bool result = m_processHandler->waitForSignal(newSignal, msecs);
|
||||||
if (!result && needsSplit) {
|
|
||||||
m_killTimer.stop();
|
|
||||||
sendControlSignal(ControlSignal::Kill);
|
|
||||||
result = m_processHandler->waitForSignal(timeout.remainingTime(), newSignal);
|
|
||||||
}
|
|
||||||
m_processHandler->moveToCallerThread();
|
m_processHandler->moveToCallerThread();
|
||||||
m_processHandler->setParent(this);
|
m_processHandler->setParent(this);
|
||||||
thread.quit();
|
thread.quit();
|
||||||
@@ -803,14 +871,14 @@ bool QtcProcessPrivate::waitForSignal(int msecs, ProcessSignalType newSignal)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Called from caller's thread exclusively
|
// Called from caller's thread exclusively
|
||||||
QList<ProcessInterfaceSignal *> QtcProcessPrivate::takeAllSignals()
|
QList<ProcessInterfaceSignal *> GeneralProcessBlockingImpl::takeAllSignals()
|
||||||
{
|
{
|
||||||
QMutexLocker locker(&m_mutex);
|
QMutexLocker locker(&m_mutex);
|
||||||
return std::exchange(m_signals, {});
|
return std::exchange(m_signals, {});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called from caller's thread exclusively
|
// Called from caller's thread exclusively
|
||||||
QList<ProcessInterfaceSignal *> QtcProcessPrivate::takeSignalsFor(ProcessSignalType signalType)
|
QList<ProcessInterfaceSignal *> GeneralProcessBlockingImpl::takeSignalsFor(ProcessSignalType signalType)
|
||||||
{
|
{
|
||||||
// If we are flushing for ReadyRead or Done - flush all.
|
// If we are flushing for ReadyRead or Done - flush all.
|
||||||
if (signalType != ProcessSignalType::Started)
|
if (signalType != ProcessSignalType::Started)
|
||||||
@@ -840,7 +908,7 @@ QList<ProcessInterfaceSignal *> QtcProcessPrivate::takeSignalsFor(ProcessSignalT
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Called from caller's thread exclusively
|
// Called from caller's thread exclusively
|
||||||
bool QtcProcessPrivate::flushSignals(const QList<ProcessInterfaceSignal *> &signalList,
|
bool GeneralProcessBlockingImpl::flushSignals(const QList<ProcessInterfaceSignal *> &signalList,
|
||||||
ProcessSignalType *signalType)
|
ProcessSignalType *signalType)
|
||||||
{
|
{
|
||||||
bool signalMatched = false;
|
bool signalMatched = false;
|
||||||
@@ -866,14 +934,50 @@ bool QtcProcessPrivate::flushSignals(const QList<ProcessInterfaceSignal *> &sign
|
|||||||
return signalMatched;
|
return signalMatched;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called from caller's thread exclusively
|
void GeneralProcessBlockingImpl::handleStartedSignal(const StartedSignal *aSignal)
|
||||||
|
{
|
||||||
|
m_caller->handleStarted(aSignal->processId(), aSignal->applicationMainThreadId());
|
||||||
|
}
|
||||||
|
|
||||||
|
void GeneralProcessBlockingImpl::handleReadyReadSignal(const ReadyReadSignal *aSignal)
|
||||||
|
{
|
||||||
|
m_caller->handleReadyRead(aSignal->stdOut(), aSignal->stdErr());
|
||||||
|
}
|
||||||
|
|
||||||
|
void GeneralProcessBlockingImpl::handleDoneSignal(const DoneSignal *aSignal)
|
||||||
|
{
|
||||||
|
m_caller->handleDone(aSignal->resultData());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called from ProcessInterfaceHandler thread exclusively.
|
||||||
|
void GeneralProcessBlockingImpl::appendSignal(ProcessInterfaceSignal *newSignal)
|
||||||
|
{
|
||||||
|
QMutexLocker locker(&m_mutex);
|
||||||
|
m_signals.append(newSignal);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QtcProcessPrivate::waitForSignal(ProcessSignalType newSignal, int msecs)
|
||||||
|
{
|
||||||
|
const QDeadlineTimer timeout(msecs);
|
||||||
|
const QDeadlineTimer currentKillTimeout(m_killTimer.remainingTime());
|
||||||
|
const bool needsSplit = m_killTimer.isActive() ? timeout > currentKillTimeout : false;
|
||||||
|
const QDeadlineTimer mainTimeout = needsSplit ? currentKillTimeout : timeout;
|
||||||
|
|
||||||
|
bool result = m_blockingInterface->waitForSignal(newSignal, mainTimeout.remainingTime());
|
||||||
|
if (!result && needsSplit) {
|
||||||
|
m_killTimer.stop();
|
||||||
|
sendControlSignal(ControlSignal::Kill);
|
||||||
|
result = m_blockingInterface->waitForSignal(newSignal, timeout.remainingTime());
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
Qt::ConnectionType QtcProcessPrivate::connectionType() const
|
Qt::ConnectionType QtcProcessPrivate::connectionType() const
|
||||||
{
|
{
|
||||||
return (m_process->thread() == thread()) ? Qt::DirectConnection
|
return (m_process->thread() == thread()) ? Qt::DirectConnection
|
||||||
: Qt::BlockingQueuedConnection;
|
: Qt::BlockingQueuedConnection;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called from caller's thread exclusively
|
|
||||||
void QtcProcessPrivate::sendControlSignal(ControlSignal controlSignal)
|
void QtcProcessPrivate::sendControlSignal(ControlSignal controlSignal)
|
||||||
{
|
{
|
||||||
QTC_ASSERT(QThread::currentThread() == thread(), return);
|
QTC_ASSERT(QThread::currentThread() == thread(), return);
|
||||||
@@ -885,13 +989,6 @@ void QtcProcessPrivate::sendControlSignal(ControlSignal controlSignal)
|
|||||||
}, connectionType());
|
}, connectionType());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called from ProcessInterfaceHandler thread exclusively.
|
|
||||||
void QtcProcessPrivate::appendSignal(ProcessInterfaceSignal *newSignal)
|
|
||||||
{
|
|
||||||
QMutexLocker locker(&m_mutex);
|
|
||||||
m_signals.append(newSignal);
|
|
||||||
}
|
|
||||||
|
|
||||||
void QtcProcessPrivate::clearForRun()
|
void QtcProcessPrivate::clearForRun()
|
||||||
{
|
{
|
||||||
m_hangTimerCount = 0;
|
m_hangTimerCount = 0;
|
||||||
@@ -1188,17 +1285,6 @@ void QtcProcess::setRemoteProcessHooks(const DeviceProcessHooks &hooks)
|
|||||||
s_deviceHooks = hooks;
|
s_deviceHooks = hooks;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QtcProcess::stopProcess()
|
|
||||||
{
|
|
||||||
if (state() == QProcess::NotRunning)
|
|
||||||
return;
|
|
||||||
terminate();
|
|
||||||
if (waitForFinished(300))
|
|
||||||
return;
|
|
||||||
kill();
|
|
||||||
waitForFinished(300);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool askToKill(const QString &command)
|
static bool askToKill(const QString &command)
|
||||||
{
|
{
|
||||||
#ifdef QT_GUI_LIB
|
#ifdef QT_GUI_LIB
|
||||||
@@ -1275,7 +1361,7 @@ bool QtcProcess::readDataFromProcess(int timeoutS,
|
|||||||
QString QtcProcess::normalizeNewlines(const QString &text)
|
QString QtcProcess::normalizeNewlines(const QString &text)
|
||||||
{
|
{
|
||||||
QString res = text;
|
QString res = text;
|
||||||
const auto newEnd = std::unique(res.begin(), res.end(), [](const QChar &c1, const QChar &c2) {
|
const auto newEnd = std::unique(res.begin(), res.end(), [](const QChar c1, const QChar c2) {
|
||||||
return c1 == '\r' && c2 == '\r'; // QTCREATORBUG-24556
|
return c1 == '\r' && c2 == '\r'; // QTCREATORBUG-24556
|
||||||
});
|
});
|
||||||
res.chop(std::distance(newEnd, res.end()));
|
res.chop(std::distance(newEnd, res.end()));
|
||||||
@@ -1444,8 +1530,8 @@ bool QtcProcess::waitForStarted(int msecs)
|
|||||||
return true;
|
return true;
|
||||||
if (d->m_state == QProcess::NotRunning)
|
if (d->m_state == QProcess::NotRunning)
|
||||||
return false;
|
return false;
|
||||||
return s_waitForStarted.measureAndRun(&QtcProcessPrivate::waitForSignal, d, msecs,
|
return s_waitForStarted.measureAndRun(&QtcProcessPrivate::waitForSignal, d,
|
||||||
ProcessSignalType::Started);
|
ProcessSignalType::Started, msecs);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QtcProcess::waitForReadyRead(int msecs)
|
bool QtcProcess::waitForReadyRead(int msecs)
|
||||||
@@ -1453,7 +1539,7 @@ bool QtcProcess::waitForReadyRead(int msecs)
|
|||||||
QTC_ASSERT(d->m_process, return false);
|
QTC_ASSERT(d->m_process, return false);
|
||||||
if (d->m_state == QProcess::NotRunning)
|
if (d->m_state == QProcess::NotRunning)
|
||||||
return false;
|
return false;
|
||||||
return d->waitForSignal(msecs, ProcessSignalType::ReadyRead);
|
return d->waitForSignal(ProcessSignalType::ReadyRead, msecs);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QtcProcess::waitForFinished(int msecs)
|
bool QtcProcess::waitForFinished(int msecs)
|
||||||
@@ -1461,7 +1547,7 @@ bool QtcProcess::waitForFinished(int msecs)
|
|||||||
QTC_ASSERT(d->m_process, return false);
|
QTC_ASSERT(d->m_process, return false);
|
||||||
if (d->m_state == QProcess::NotRunning)
|
if (d->m_state == QProcess::NotRunning)
|
||||||
return false;
|
return false;
|
||||||
return d->waitForSignal(msecs, ProcessSignalType::Done);
|
return d->waitForSignal(ProcessSignalType::Done, msecs);
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray QtcProcess::readAllStandardOutput()
|
QByteArray QtcProcess::readAllStandardOutput()
|
||||||
@@ -1511,9 +1597,9 @@ void QtcProcess::close()
|
|||||||
d->m_process->disconnect();
|
d->m_process->disconnect();
|
||||||
d->m_process.release()->deleteLater();
|
d->m_process.release()->deleteLater();
|
||||||
}
|
}
|
||||||
if (d->m_processHandler) {
|
if (d->m_blockingInterface) {
|
||||||
d->m_processHandler->disconnect();
|
d->m_blockingInterface->disconnect();
|
||||||
d->m_processHandler.release()->deleteLater();
|
d->m_blockingInterface.release()->deleteLater();
|
||||||
}
|
}
|
||||||
d->clearForRun();
|
d->clearForRun();
|
||||||
}
|
}
|
||||||
@@ -1618,10 +1704,16 @@ QString QtcProcess::allOutput() const
|
|||||||
return !out.isEmpty() ? out : err;
|
return !out.isEmpty() ? out : err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QByteArray QtcProcess::rawStdOut() const
|
||||||
|
{
|
||||||
|
QTC_CHECK(d->m_stdOut.keepRawData);
|
||||||
|
return d->m_stdOut.rawData;
|
||||||
|
}
|
||||||
|
|
||||||
QString QtcProcess::stdOut() const
|
QString QtcProcess::stdOut() const
|
||||||
{
|
{
|
||||||
QTC_CHECK(d->m_stdOut.keepRawData);
|
QTC_CHECK(d->m_stdOut.keepRawData);
|
||||||
return normalizeNewlines(d->m_codec->toUnicode(d->m_stdOut.rawData));
|
return d->m_codec->toUnicode(d->m_stdOut.rawData);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString QtcProcess::stdErr() const
|
QString QtcProcess::stdErr() const
|
||||||
@@ -1631,13 +1723,37 @@ QString QtcProcess::stdErr() const
|
|||||||
// is not trivial. So weaken it a bit for now.
|
// is not trivial. So weaken it a bit for now.
|
||||||
//QTC_CHECK(d->m_stdErr.keepRawData);
|
//QTC_CHECK(d->m_stdErr.keepRawData);
|
||||||
QTC_CHECK(d->m_stdErr.keepRawData || d->m_stdErr.rawData.isEmpty());
|
QTC_CHECK(d->m_stdErr.keepRawData || d->m_stdErr.rawData.isEmpty());
|
||||||
return normalizeNewlines(d->m_codec->toUnicode(d->m_stdErr.rawData));
|
return d->m_codec->toUnicode(d->m_stdErr.rawData);
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray QtcProcess::rawStdOut() const
|
QString QtcProcess::cleanedStdOut() const
|
||||||
{
|
{
|
||||||
QTC_CHECK(d->m_stdOut.keepRawData);
|
return normalizeNewlines(stdOut());
|
||||||
return d->m_stdOut.rawData;
|
}
|
||||||
|
|
||||||
|
QString QtcProcess::cleanedStdErr() const
|
||||||
|
{
|
||||||
|
return normalizeNewlines(stdErr());
|
||||||
|
}
|
||||||
|
|
||||||
|
static QStringList splitLines(const QString &text)
|
||||||
|
{
|
||||||
|
QStringList result = text.split('\n');
|
||||||
|
for (QString &line : result) {
|
||||||
|
if (line.endsWith('\r'))
|
||||||
|
line.chop(1);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QStringList QtcProcess::stdOutLines() const
|
||||||
|
{
|
||||||
|
return splitLines(stdOut());
|
||||||
|
}
|
||||||
|
|
||||||
|
const QStringList QtcProcess::stdErrLines() const
|
||||||
|
{
|
||||||
|
return splitLines(stdErr());
|
||||||
}
|
}
|
||||||
|
|
||||||
QTCREATOR_UTILS_EXPORT QDebug operator<<(QDebug str, const QtcProcess &r)
|
QTCREATOR_UTILS_EXPORT QDebug operator<<(QDebug str, const QtcProcess &r)
|
||||||
@@ -1843,7 +1959,8 @@ void QtcProcessPrivate::slotTimeout()
|
|||||||
|| askToKill(m_setup.m_commandLine.executable().toString());
|
|| askToKill(m_setup.m_commandLine.executable().toString());
|
||||||
m_waitingForUser = false;
|
m_waitingForUser = false;
|
||||||
if (terminate) {
|
if (terminate) {
|
||||||
q->stopProcess();
|
q->stop();
|
||||||
|
q->waitForFinished();
|
||||||
m_result = ProcessResult::Hang;
|
m_result = ProcessResult::Hang;
|
||||||
} else {
|
} else {
|
||||||
m_hangTimerCount = 0;
|
m_hangTimerCount = 0;
|
||||||
@@ -1854,22 +1971,6 @@ void QtcProcessPrivate::slotTimeout()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QtcProcessPrivate::handleStartedSignal(const StartedSignal *aSignal)
|
|
||||||
{
|
|
||||||
handleStarted(aSignal->processId(), aSignal->applicationMainThreadId());
|
|
||||||
}
|
|
||||||
|
|
||||||
void QtcProcessPrivate::handleReadyReadSignal(const ReadyReadSignal *aSignal)
|
|
||||||
{
|
|
||||||
handleReadyRead(aSignal->stdOut(), aSignal->stdErr());
|
|
||||||
}
|
|
||||||
|
|
||||||
void QtcProcessPrivate::handleDoneSignal(const DoneSignal *aSignal)
|
|
||||||
{
|
|
||||||
m_killTimer.stop();
|
|
||||||
handleDone(aSignal->resultData());
|
|
||||||
}
|
|
||||||
|
|
||||||
void QtcProcessPrivate::handleStarted(qint64 processId, qint64 applicationMainThreadId)
|
void QtcProcessPrivate::handleStarted(qint64 processId, qint64 applicationMainThreadId)
|
||||||
{
|
{
|
||||||
QTC_CHECK(m_state == QProcess::Starting);
|
QTC_CHECK(m_state == QProcess::Starting);
|
||||||
@@ -1908,6 +2009,7 @@ void QtcProcessPrivate::handleReadyRead(const QByteArray &outputData, const QByt
|
|||||||
|
|
||||||
void QtcProcessPrivate::handleDone(const ProcessResultData &data)
|
void QtcProcessPrivate::handleDone(const ProcessResultData &data)
|
||||||
{
|
{
|
||||||
|
m_killTimer.stop();
|
||||||
m_resultData = data;
|
m_resultData = data;
|
||||||
|
|
||||||
switch (m_state) {
|
switch (m_state) {
|
||||||
|
|||||||
@@ -175,7 +175,6 @@ public:
|
|||||||
void setStdErrCallback(const std::function<void(const QString &)> &callback);
|
void setStdErrCallback(const std::function<void(const QString &)> &callback);
|
||||||
void setStdErrLineCallback(const std::function<void(const QString &)> &callback);
|
void setStdErrLineCallback(const std::function<void(const QString &)> &callback);
|
||||||
|
|
||||||
void stopProcess();
|
|
||||||
bool readDataFromProcess(int timeoutS, QByteArray *stdOut, QByteArray *stdErr,
|
bool readDataFromProcess(int timeoutS, QByteArray *stdOut, QByteArray *stdErr,
|
||||||
bool showTimeOutMessageBox);
|
bool showTimeOutMessageBox);
|
||||||
|
|
||||||
@@ -185,11 +184,17 @@ public:
|
|||||||
QByteArray allRawOutput() const;
|
QByteArray allRawOutput() const;
|
||||||
QString allOutput() const;
|
QString allOutput() const;
|
||||||
|
|
||||||
QString stdOut() const;
|
|
||||||
QString stdErr() const;
|
|
||||||
|
|
||||||
QByteArray rawStdOut() const;
|
QByteArray rawStdOut() const;
|
||||||
|
|
||||||
|
QString stdOut() const; // possibly with CR
|
||||||
|
QString stdErr() const; // possibly with CR
|
||||||
|
|
||||||
|
QString cleanedStdOut() const; // with CR removed
|
||||||
|
QString cleanedStdErr() const; // with CR removed
|
||||||
|
|
||||||
|
const QStringList stdOutLines() const; // split, CR removed
|
||||||
|
const QStringList stdErrLines() const; // split, CR removed
|
||||||
|
|
||||||
QString exitMessage() const;
|
QString exitMessage() const;
|
||||||
|
|
||||||
QString toStandaloneCommandLine() const;
|
QString toStandaloneCommandLine() const;
|
||||||
|
|||||||
@@ -368,7 +368,10 @@ void ShellCommand::runFullySynchronous(QtcProcess &process, const FilePath &work
|
|||||||
|
|
||||||
void ShellCommand::runSynchronous(QtcProcess &process, const FilePath &workingDirectory)
|
void ShellCommand::runSynchronous(QtcProcess &process, const FilePath &workingDirectory)
|
||||||
{
|
{
|
||||||
connect(this, &ShellCommand::terminate, &process, &QtcProcess::stopProcess);
|
connect(this, &ShellCommand::terminate, &process, [&process] {
|
||||||
|
process.stop();
|
||||||
|
process.waitForFinished();
|
||||||
|
});
|
||||||
process.setEnvironment(processEnvironment());
|
process.setEnvironment(processEnvironment());
|
||||||
if (d->m_codec)
|
if (d->m_codec)
|
||||||
process.setCodec(d->m_codec);
|
process.setCodec(d->m_codec);
|
||||||
|
|||||||
@@ -50,12 +50,6 @@ private:
|
|||||||
qint64 write(const QByteArray &) final { QTC_CHECK(false); return -1; }
|
qint64 write(const QByteArray &) final { QTC_CHECK(false); return -1; }
|
||||||
void sendControlSignal(ControlSignal controlSignal) final;
|
void sendControlSignal(ControlSignal controlSignal) final;
|
||||||
|
|
||||||
// intentionally no-op without an assert
|
|
||||||
bool waitForStarted(int) final { return false; }
|
|
||||||
bool waitForReadyRead(int) final { QTC_CHECK(false); return false; }
|
|
||||||
// intentionally no-op without an assert
|
|
||||||
bool waitForFinished(int) final { return false; }
|
|
||||||
|
|
||||||
// OK, however, impl looks a bit different (!= NotRunning vs == Running).
|
// OK, however, impl looks a bit different (!= NotRunning vs == Running).
|
||||||
// Most probably changing it into (== Running) should be OK.
|
// Most probably changing it into (== Running) should be OK.
|
||||||
bool isRunning() const;
|
bool isRunning() const;
|
||||||
|
|||||||
@@ -127,7 +127,7 @@ bool AndroidQmlPreviewWorker::isPreviewRunning(int lastKnownPid) const
|
|||||||
|
|
||||||
void AndroidQmlPreviewWorker::startPidWatcher()
|
void AndroidQmlPreviewWorker::startPidWatcher()
|
||||||
{
|
{
|
||||||
m_pidFutureWatcher.setFuture(Utils::runAsync([this]() {
|
m_pidFutureWatcher.setFuture(runAsync([this]() {
|
||||||
// wait for started
|
// wait for started
|
||||||
const int sleepTimeMs = 2000;
|
const int sleepTimeMs = 2000;
|
||||||
QDeadlineTimer deadline(20000);
|
QDeadlineTimer deadline(20000);
|
||||||
@@ -157,7 +157,7 @@ void AndroidQmlPreviewWorker::startLogcat()
|
|||||||
QString args = QString("logcat --pid=%1").arg(m_viewerPid);
|
QString args = QString("logcat --pid=%1").arg(m_viewerPid);
|
||||||
if (!m_logcatStartTimeStamp.isEmpty())
|
if (!m_logcatStartTimeStamp.isEmpty())
|
||||||
args += QString(" -T '%1'").arg(m_logcatStartTimeStamp);
|
args += QString(" -T '%1'").arg(m_logcatStartTimeStamp);
|
||||||
Utils::CommandLine cmd(AndroidConfigurations::currentConfig().adbToolPath());
|
CommandLine cmd(AndroidConfigurations::currentConfig().adbToolPath());
|
||||||
cmd.setArguments(args);
|
cmd.setArguments(args);
|
||||||
m_logcatProcess.setCommand(cmd);
|
m_logcatProcess.setCommand(cmd);
|
||||||
m_logcatProcess.setUseCtrlCStub(true);
|
m_logcatProcess.setUseCtrlCStub(true);
|
||||||
@@ -190,7 +190,7 @@ AndroidQmlPreviewWorker::AndroidQmlPreviewWorker(ProjectExplorer::RunControl *ru
|
|||||||
connect(this, &AndroidQmlPreviewWorker::previewPidChanged,
|
connect(this, &AndroidQmlPreviewWorker::previewPidChanged,
|
||||||
this, &AndroidQmlPreviewWorker::startLogcat);
|
this, &AndroidQmlPreviewWorker::startLogcat);
|
||||||
|
|
||||||
connect(this, &RunWorker::stopped, &m_logcatProcess, &Utils::QtcProcess::stopProcess);
|
connect(this, &RunWorker::stopped, &m_logcatProcess, &QtcProcess::stop);
|
||||||
m_logcatProcess.setStdOutCallback([this](const QString &stdOut) {
|
m_logcatProcess.setStdOutCallback([this](const QString &stdOut) {
|
||||||
filterLogcatAndAppendMessage(stdOut);
|
filterLogcatAndAppendMessage(stdOut);
|
||||||
});
|
});
|
||||||
@@ -314,7 +314,7 @@ bool AndroidQmlPreviewWorker::preparePreviewArtefacts()
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const FilePaths allFiles = m_rc->project()->files(m_rc->project()->SourceFiles);
|
const FilePaths allFiles = m_rc->project()->files(m_rc->project()->SourceFiles);
|
||||||
const FilePaths filesToExport = Utils::filtered(allFiles,[](const FilePath &path) {
|
const FilePaths filesToExport = filtered(allFiles, [](const FilePath &path) {
|
||||||
return path.suffix() == "qmlproject";
|
return path.suffix() == "qmlproject";
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -363,7 +363,8 @@ FilePath AndroidQmlPreviewWorker::createQmlrcFile(const FilePath &workFolder,
|
|||||||
QByteArray stdOut;
|
QByteArray stdOut;
|
||||||
QByteArray stdErr;
|
QByteArray stdErr;
|
||||||
if (!rccProcess.readDataFromProcess(30, &stdOut, &stdErr, true)) {
|
if (!rccProcess.readDataFromProcess(30, &stdOut, &stdErr, true)) {
|
||||||
rccProcess.stopProcess();
|
rccProcess.stop();
|
||||||
|
rccProcess.waitForFinished();
|
||||||
appendMessage(tr("A timeout occurred running \"%1\"").
|
appendMessage(tr("A timeout occurred running \"%1\"").
|
||||||
arg(rccProcess.commandLine().toUserOutput()), StdErrFormat);
|
arg(rccProcess.commandLine().toUserOutput()), StdErrFormat);
|
||||||
qrcPath.removeFile();
|
qrcPath.removeFile();
|
||||||
|
|||||||
@@ -166,8 +166,10 @@ static void sdkManagerCommand(const AndroidConfig &config, const QStringList &ar
|
|||||||
proc.setTimeoutS(timeout);
|
proc.setTimeoutS(timeout);
|
||||||
proc.setStdOutCallback([offset, progressQuota, &proc, &assertionFound, &fi](const QString &out) {
|
proc.setStdOutCallback([offset, progressQuota, &proc, &assertionFound, &fi](const QString &out) {
|
||||||
int progressPercent = parseProgress(out, assertionFound);
|
int progressPercent = parseProgress(out, assertionFound);
|
||||||
if (assertionFound)
|
if (assertionFound) {
|
||||||
proc.stopProcess();
|
proc.stop();
|
||||||
|
proc.waitForFinished();
|
||||||
|
}
|
||||||
if (progressPercent != -1)
|
if (progressPercent != -1)
|
||||||
fi.setProgressValue(offset + qRound((progressPercent / 100.0) * progressQuota));
|
fi.setProgressValue(offset + qRound((progressPercent / 100.0) * progressQuota));
|
||||||
});
|
});
|
||||||
@@ -175,8 +177,10 @@ static void sdkManagerCommand(const AndroidConfig &config, const QStringList &ar
|
|||||||
output.stdError = err;
|
output.stdError = err;
|
||||||
});
|
});
|
||||||
if (interruptible) {
|
if (interruptible) {
|
||||||
QObject::connect(&sdkManager, &AndroidSdkManager::cancelActiveOperations,
|
QObject::connect(&sdkManager, &AndroidSdkManager::cancelActiveOperations, &proc, [&proc] {
|
||||||
&proc, &QtcProcess::stopProcess);
|
proc.stop();
|
||||||
|
proc.waitForFinished();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
proc.setCommand({config.sdkManagerToolPath(), newArgs});
|
proc.setCommand({config.sdkManagerToolPath(), newArgs});
|
||||||
proc.runBlocking(EventLoopMode::On);
|
proc.runBlocking(EventLoopMode::On);
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ namespace Autotest {
|
|||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
TestOutputReader *BoostTestConfiguration::outputReader(const QFutureInterface<TestResultPtr> &fi,
|
TestOutputReader *BoostTestConfiguration::outputReader(const QFutureInterface<TestResultPtr> &fi,
|
||||||
QProcess *app) const
|
Utils::QtcProcess *app) const
|
||||||
{
|
{
|
||||||
auto settings = static_cast<BoostTestSettings *>(framework()->testSettings());
|
auto settings = static_cast<BoostTestSettings *>(framework()->testSettings());
|
||||||
return new BoostTestOutputReader(fi, app, buildDirectory(), projectFile(),
|
return new BoostTestOutputReader(fi, app, buildDirectory(), projectFile(),
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ public:
|
|||||||
explicit BoostTestConfiguration(ITestFramework *framework)
|
explicit BoostTestConfiguration(ITestFramework *framework)
|
||||||
: DebuggableTestConfiguration(framework) {}
|
: DebuggableTestConfiguration(framework) {}
|
||||||
TestOutputReader *outputReader(const QFutureInterface<TestResultPtr> &fi,
|
TestOutputReader *outputReader(const QFutureInterface<TestResultPtr> &fi,
|
||||||
QProcess *app) const override;
|
Utils::QtcProcess *app) const override;
|
||||||
QStringList argumentsForTestRunner(QStringList *omitted = nullptr) const override;
|
QStringList argumentsForTestRunner(QStringList *omitted = nullptr) const override;
|
||||||
Utils::Environment filteredEnvironment(const Utils::Environment &original) const override;
|
Utils::Environment filteredEnvironment(const Utils::Environment &original) const override;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -29,6 +29,7 @@
|
|||||||
#include "boosttesttreeitem.h"
|
#include "boosttesttreeitem.h"
|
||||||
|
|
||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
|
#include <utils/qtcprocess.h>
|
||||||
|
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
@@ -41,7 +42,7 @@ namespace Internal {
|
|||||||
static Q_LOGGING_CATEGORY(orLog, "qtc.autotest.boost.outputreader", QtWarningMsg)
|
static Q_LOGGING_CATEGORY(orLog, "qtc.autotest.boost.outputreader", QtWarningMsg)
|
||||||
|
|
||||||
BoostTestOutputReader::BoostTestOutputReader(const QFutureInterface<TestResultPtr> &futureInterface,
|
BoostTestOutputReader::BoostTestOutputReader(const QFutureInterface<TestResultPtr> &futureInterface,
|
||||||
QProcess *testApplication,
|
Utils::QtcProcess *testApplication,
|
||||||
const Utils::FilePath &buildDirectory,
|
const Utils::FilePath &buildDirectory,
|
||||||
const Utils::FilePath &projectFile,
|
const Utils::FilePath &projectFile,
|
||||||
LogLevel log, ReportLevel report)
|
LogLevel log, ReportLevel report)
|
||||||
@@ -51,7 +52,7 @@ BoostTestOutputReader::BoostTestOutputReader(const QFutureInterface<TestResultPt
|
|||||||
, m_reportLevel(report)
|
, m_reportLevel(report)
|
||||||
{
|
{
|
||||||
if (m_testApplication) {
|
if (m_testApplication) {
|
||||||
connect(m_testApplication, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
|
connect(m_testApplication, &Utils::QtcProcess::finished,
|
||||||
this, &BoostTestOutputReader::onFinished);
|
this, &BoostTestOutputReader::onFinished);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -405,7 +406,8 @@ TestResultPtr BoostTestOutputReader::createDefaultResult() const
|
|||||||
return TestResultPtr(result);
|
return TestResultPtr(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BoostTestOutputReader::onFinished(int exitCode, QProcess::ExitStatus /*exitState*/) {
|
void BoostTestOutputReader::onFinished() {
|
||||||
|
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];
|
||||||
m_summary.insert(ResultType::Pass, m_testCaseCount - reportedFailsAndSkips);
|
m_summary.insert(ResultType::Pass, m_testCaseCount - reportedFailsAndSkips);
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ class BoostTestOutputReader : public TestOutputReader
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
BoostTestOutputReader(const QFutureInterface<TestResultPtr> &futureInterface,
|
BoostTestOutputReader(const QFutureInterface<TestResultPtr> &futureInterface,
|
||||||
QProcess *testApplication, const Utils::FilePath &buildDirectory,
|
Utils::QtcProcess *testApplication, const Utils::FilePath &buildDirectory,
|
||||||
const Utils::FilePath &projectFile, LogLevel log, ReportLevel report);
|
const Utils::FilePath &projectFile, LogLevel log, ReportLevel report);
|
||||||
protected:
|
protected:
|
||||||
void processOutputLine(const QByteArray &outputLine) override;
|
void processOutputLine(const QByteArray &outputLine) override;
|
||||||
@@ -47,7 +47,7 @@ protected:
|
|||||||
TestResultPtr createDefaultResult() const override;
|
TestResultPtr createDefaultResult() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void onFinished(int exitCode, QProcess::ExitStatus /*exitState*/);
|
void onFinished();
|
||||||
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);
|
||||||
|
|||||||
@@ -90,22 +90,24 @@ void CatchCodeParser::handleIdentifier()
|
|||||||
QTC_ASSERT(m_currentIndex < m_tokens.size(), return);
|
QTC_ASSERT(m_currentIndex < m_tokens.size(), return);
|
||||||
const Token &token = m_tokens.at(m_currentIndex);
|
const Token &token = m_tokens.at(m_currentIndex);
|
||||||
const QByteArray &identifier = m_source.mid(int(token.bytesBegin()), int(token.bytes()));
|
const QByteArray &identifier = m_source.mid(int(token.bytesBegin()), int(token.bytes()));
|
||||||
if (identifier == "TEST_CASE") {
|
const QByteArray unprefixed = identifier.startsWith("CATCH_") ? identifier.mid(6) : identifier;
|
||||||
|
|
||||||
|
if (unprefixed == "TEST_CASE") {
|
||||||
handleTestCase(false);
|
handleTestCase(false);
|
||||||
} else if (identifier == "SCENARIO") {
|
} else if (unprefixed == "SCENARIO") {
|
||||||
handleTestCase(true);
|
handleTestCase(true);
|
||||||
} else if (identifier == "TEMPLATE_TEST_CASE" || identifier == "TEMPLATE_PRODUCT_TEST_CASE"
|
} else if (unprefixed == "TEMPLATE_TEST_CASE" || unprefixed == "TEMPLATE_PRODUCT_TEST_CASE"
|
||||||
|| identifier == "TEMPLATE_LIST_TEST_CASE" || identifier == "TEMPLATE_TEST_CASE_SIG"
|
|| unprefixed == "TEMPLATE_LIST_TEST_CASE" || unprefixed == "TEMPLATE_TEST_CASE_SIG"
|
||||||
|| identifier == "TEMPLATE_PRODUCT_TEST_CASE_SIG") {
|
|| unprefixed == "TEMPLATE_PRODUCT_TEST_CASE_SIG") {
|
||||||
handleParameterizedTestCase(false);
|
handleParameterizedTestCase(false);
|
||||||
} else if (identifier == "TEST_CASE_METHOD") {
|
} else if (unprefixed == "TEST_CASE_METHOD") {
|
||||||
handleFixtureOrRegisteredTestCase(true);
|
handleFixtureOrRegisteredTestCase(true);
|
||||||
} else if (identifier == "TEMPLATE_TEST_CASE_METHOD_SIG"
|
} else if (unprefixed == "TEMPLATE_TEST_CASE_METHOD_SIG"
|
||||||
|| identifier == "TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG"
|
|| unprefixed == "TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG"
|
||||||
|| identifier == "TEMPLATE_TEST_CASE_METHOD"
|
|| unprefixed == "TEMPLATE_TEST_CASE_METHOD"
|
||||||
|| identifier == "TEMPLATE_LIST_TEST_CASE_METHOD") {
|
|| unprefixed == "TEMPLATE_LIST_TEST_CASE_METHOD") {
|
||||||
handleParameterizedTestCase(true);
|
handleParameterizedTestCase(true);
|
||||||
} else if (identifier == "METHOD_AS_TEST_CASE" || identifier == "REGISTER_TEST_CASE") {
|
} else if (unprefixed == "METHOD_AS_TEST_CASE" || unprefixed == "REGISTER_TEST_CASE") {
|
||||||
handleFixtureOrRegisteredTestCase(false);
|
handleFixtureOrRegisteredTestCase(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,7 +35,8 @@
|
|||||||
namespace Autotest {
|
namespace Autotest {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
TestOutputReader *CatchConfiguration::outputReader(const QFutureInterface<TestResultPtr> &fi, QProcess *app) const
|
TestOutputReader *CatchConfiguration::outputReader(const QFutureInterface<TestResultPtr> &fi,
|
||||||
|
Utils::QtcProcess *app) const
|
||||||
{
|
{
|
||||||
return new CatchOutputReader(fi, app, buildDirectory(), projectFile());
|
return new CatchOutputReader(fi, app, buildDirectory(), projectFile());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ class CatchConfiguration : public DebuggableTestConfiguration
|
|||||||
public:
|
public:
|
||||||
CatchConfiguration(ITestFramework *framework) : DebuggableTestConfiguration(framework) {}
|
CatchConfiguration(ITestFramework *framework) : DebuggableTestConfiguration(framework) {}
|
||||||
TestOutputReader *outputReader(const QFutureInterface<TestResultPtr> &fi,
|
TestOutputReader *outputReader(const QFutureInterface<TestResultPtr> &fi,
|
||||||
QProcess *app) const override;
|
Utils::QtcProcess *app) const override;
|
||||||
QStringList argumentsForTestRunner(QStringList *omitted = nullptr) const override;
|
QStringList argumentsForTestRunner(QStringList *omitted = nullptr) const override;
|
||||||
Utils::Environment filteredEnvironment(const Utils::Environment &original) const override;
|
Utils::Environment filteredEnvironment(const Utils::Environment &original) const override;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -49,7 +49,8 @@ namespace CatchXml {
|
|||||||
}
|
}
|
||||||
|
|
||||||
CatchOutputReader::CatchOutputReader(const QFutureInterface<TestResultPtr> &futureInterface,
|
CatchOutputReader::CatchOutputReader(const QFutureInterface<TestResultPtr> &futureInterface,
|
||||||
QProcess *testApplication, const Utils::FilePath &buildDirectory,
|
Utils::QtcProcess *testApplication,
|
||||||
|
const Utils::FilePath &buildDirectory,
|
||||||
const Utils::FilePath &projectFile)
|
const Utils::FilePath &projectFile)
|
||||||
: TestOutputReader (futureInterface, testApplication, buildDirectory)
|
: TestOutputReader (futureInterface, testApplication, buildDirectory)
|
||||||
, m_projectFile(projectFile)
|
, m_projectFile(projectFile)
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ class CatchOutputReader : public TestOutputReader
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
CatchOutputReader(const QFutureInterface<TestResultPtr> &futureInterface,
|
CatchOutputReader(const QFutureInterface<TestResultPtr> &futureInterface,
|
||||||
QProcess *testApplication, const Utils::FilePath &buildDirectory,
|
Utils::QtcProcess *testApplication, const Utils::FilePath &buildDirectory,
|
||||||
const Utils::FilePath &projectFile);
|
const Utils::FilePath &projectFile);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|||||||
@@ -57,10 +57,11 @@ static bool isCatchTestCaseMacro(const QString ¯oName)
|
|||||||
|
|
||||||
static bool isCatchMacro(const QString ¯oName)
|
static bool isCatchMacro(const QString ¯oName)
|
||||||
{
|
{
|
||||||
|
QString unprefixed = macroName.startsWith("CATCH_") ? macroName.mid(6) : macroName;
|
||||||
const QStringList validSectionMacros = {
|
const QStringList validSectionMacros = {
|
||||||
QStringLiteral("SECTION"), QStringLiteral("WHEN")
|
QStringLiteral("SECTION"), QStringLiteral("WHEN")
|
||||||
};
|
};
|
||||||
return isCatchTestCaseMacro(macroName) || validSectionMacros.contains(macroName);
|
return isCatchTestCaseMacro(unprefixed) || validSectionMacros.contains(unprefixed);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool includesCatchHeader(const CPlusPlus::Document::Ptr &doc,
|
static bool includesCatchHeader(const CPlusPlus::Document::Ptr &doc,
|
||||||
@@ -123,7 +124,8 @@ bool CatchTestParser::processDocument(QFutureInterface<TestParseResultPtr> &futu
|
|||||||
const QByteArray &fileContent = getFileContent(fileName);
|
const QByteArray &fileContent = getFileContent(fileName);
|
||||||
|
|
||||||
if (!hasCatchNames(doc)) {
|
if (!hasCatchNames(doc)) {
|
||||||
const QRegularExpression regex("\\b(SCENARIO|(TEMPLATE_(PRODUCT_)?)?TEST_CASE(_METHOD)?|"
|
const QRegularExpression regex("\\b(CATCH_)?"
|
||||||
|
"(SCENARIO|(TEMPLATE_(PRODUCT_)?)?TEST_CASE(_METHOD)?|"
|
||||||
"TEMPLATE_TEST_CASE(_METHOD)?_SIG|"
|
"TEMPLATE_TEST_CASE(_METHOD)?_SIG|"
|
||||||
"TEMPLATE_PRODUCT_TEST_CASE(_METHOD)?_SIG|"
|
"TEMPLATE_PRODUCT_TEST_CASE(_METHOD)?_SIG|"
|
||||||
"TEMPLATE_LIST_TEST_CASE_METHOD|METHOD_AS_TEST_CASE|"
|
"TEMPLATE_LIST_TEST_CASE_METHOD|METHOD_AS_TEST_CASE|"
|
||||||
|
|||||||
@@ -37,7 +37,9 @@ namespace Internal {
|
|||||||
|
|
||||||
QString CatchTreeItem::testCasesString() const
|
QString CatchTreeItem::testCasesString() const
|
||||||
{
|
{
|
||||||
return m_state & CatchTreeItem::Parameterized ? QString(name() + " -*") : name();
|
QString testcase = m_state & CatchTreeItem::Parameterized ? QString(name() + " -*") : name();
|
||||||
|
// mask comma if it is part of the test case name
|
||||||
|
return testcase.replace(',', "\\,");
|
||||||
}
|
}
|
||||||
|
|
||||||
static QString nonRootDisplayName(const CatchTreeItem *it)
|
static QString nonRootDisplayName(const CatchTreeItem *it)
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ CTestConfiguration::CTestConfiguration(ITestBase *testBase)
|
|||||||
}
|
}
|
||||||
|
|
||||||
TestOutputReader *CTestConfiguration::outputReader(const QFutureInterface<TestResultPtr> &fi,
|
TestOutputReader *CTestConfiguration::outputReader(const QFutureInterface<TestResultPtr> &fi,
|
||||||
QProcess *app) const
|
Utils::QtcProcess *app) const
|
||||||
{
|
{
|
||||||
return new CTestOutputReader(fi, app, workingDirectory());
|
return new CTestOutputReader(fi, app, workingDirectory());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ public:
|
|||||||
explicit CTestConfiguration(ITestBase *testBase);
|
explicit CTestConfiguration(ITestBase *testBase);
|
||||||
|
|
||||||
TestOutputReader *outputReader(const QFutureInterface<TestResultPtr> &fi,
|
TestOutputReader *outputReader(const QFutureInterface<TestResultPtr> &fi,
|
||||||
QProcess *app) const final;
|
Utils::QtcProcess *app) const final;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
CTestOutputReader::CTestOutputReader(const QFutureInterface<TestResultPtr> &futureInterface,
|
CTestOutputReader::CTestOutputReader(const QFutureInterface<TestResultPtr> &futureInterface,
|
||||||
QProcess *testApplication,
|
Utils::QtcProcess *testApplication,
|
||||||
const Utils::FilePath &buildDirectory)
|
const Utils::FilePath &buildDirectory)
|
||||||
: TestOutputReader(futureInterface, testApplication, buildDirectory)
|
: TestOutputReader(futureInterface, testApplication, buildDirectory)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -28,6 +28,8 @@
|
|||||||
|
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
|
|
||||||
|
namespace Utils { class QtcProcess; }
|
||||||
|
|
||||||
namespace Autotest {
|
namespace Autotest {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
@@ -36,7 +38,7 @@ class CTestOutputReader final : public Autotest::TestOutputReader
|
|||||||
Q_DECLARE_TR_FUNCTIONS(Autotest::Internal::CTestOutputReader)
|
Q_DECLARE_TR_FUNCTIONS(Autotest::Internal::CTestOutputReader)
|
||||||
public:
|
public:
|
||||||
CTestOutputReader(const QFutureInterface<TestResultPtr> &futureInterface,
|
CTestOutputReader(const QFutureInterface<TestResultPtr> &futureInterface,
|
||||||
QProcess *testApplication, const Utils::FilePath &buildDirectory);
|
Utils::QtcProcess *testApplication, const Utils::FilePath &buildDirectory);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void processOutputLine(const QByteArray &outputLineWithNewLine) final;
|
void processOutputLine(const QByteArray &outputLineWithNewLine) final;
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ namespace Autotest {
|
|||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
TestOutputReader *GTestConfiguration::outputReader(const QFutureInterface<TestResultPtr> &fi,
|
TestOutputReader *GTestConfiguration::outputReader(const QFutureInterface<TestResultPtr> &fi,
|
||||||
QProcess *app) const
|
Utils::QtcProcess *app) const
|
||||||
{
|
{
|
||||||
return new GTestOutputReader(fi, app, buildDirectory(), projectFile());
|
return new GTestOutputReader(fi, app, buildDirectory(), projectFile());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ public:
|
|||||||
: DebuggableTestConfiguration(framework) {}
|
: DebuggableTestConfiguration(framework) {}
|
||||||
|
|
||||||
TestOutputReader *outputReader(const QFutureInterface<TestResultPtr> &fi,
|
TestOutputReader *outputReader(const QFutureInterface<TestResultPtr> &fi,
|
||||||
QProcess *app) const override;
|
Utils::QtcProcess *app) const override;
|
||||||
QStringList argumentsForTestRunner(QStringList *omitted = nullptr) const override;
|
QStringList argumentsForTestRunner(QStringList *omitted = nullptr) const override;
|
||||||
Utils::Environment filteredEnvironment(const Utils::Environment &original) const override;
|
Utils::Environment filteredEnvironment(const Utils::Environment &original) const override;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -28,6 +28,7 @@
|
|||||||
#include "../testtreemodel.h"
|
#include "../testtreemodel.h"
|
||||||
#include "../testtreeitem.h"
|
#include "../testtreeitem.h"
|
||||||
#include <utils/hostosinfo.h>
|
#include <utils/hostosinfo.h>
|
||||||
|
#include <utils/qtcprocess.h>
|
||||||
|
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
@@ -37,15 +38,16 @@ namespace Autotest {
|
|||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
GTestOutputReader::GTestOutputReader(const QFutureInterface<TestResultPtr> &futureInterface,
|
GTestOutputReader::GTestOutputReader(const QFutureInterface<TestResultPtr> &futureInterface,
|
||||||
QProcess *testApplication,
|
Utils::QtcProcess *testApplication,
|
||||||
const Utils::FilePath &buildDirectory,
|
const Utils::FilePath &buildDirectory,
|
||||||
const Utils::FilePath &projectFile)
|
const Utils::FilePath &projectFile)
|
||||||
: TestOutputReader(futureInterface, testApplication, buildDirectory)
|
: TestOutputReader(futureInterface, testApplication, buildDirectory)
|
||||||
, m_projectFile(projectFile)
|
, m_projectFile(projectFile)
|
||||||
{
|
{
|
||||||
if (m_testApplication) {
|
if (m_testApplication) {
|
||||||
connect(m_testApplication, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
|
connect(m_testApplication, &Utils::QtcProcess::finished,
|
||||||
this, [this] (int exitCode, QProcess::ExitStatus /*exitStatus*/) {
|
this, [this]() {
|
||||||
|
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);
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ class GTestOutputReader : public TestOutputReader
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
GTestOutputReader(const QFutureInterface<TestResultPtr> &futureInterface,
|
GTestOutputReader(const QFutureInterface<TestResultPtr> &futureInterface,
|
||||||
QProcess *testApplication, const Utils::FilePath &buildDirectory,
|
Utils::QtcProcess *testApplication, const Utils::FilePath &buildDirectory,
|
||||||
const Utils::FilePath &projectFile);
|
const Utils::FilePath &projectFile);
|
||||||
protected:
|
protected:
|
||||||
void processOutputLine(const QByteArray &outputLine) override;
|
void processOutputLine(const QByteArray &outputLine) override;
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ namespace Autotest {
|
|||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
TestOutputReader *QtTestConfiguration::outputReader(const QFutureInterface<TestResultPtr> &fi,
|
TestOutputReader *QtTestConfiguration::outputReader(const QFutureInterface<TestResultPtr> &fi,
|
||||||
QProcess *app) const
|
Utils::QtcProcess *app) const
|
||||||
{
|
{
|
||||||
auto qtSettings = static_cast<QtTestSettings *>(framework()->testSettings());
|
auto qtSettings = static_cast<QtTestSettings *>(framework()->testSettings());
|
||||||
const QtTestOutputReader::OutputMode mode = qtSettings && qtSettings->useXMLOutput.value()
|
const QtTestOutputReader::OutputMode mode = qtSettings && qtSettings->useXMLOutput.value()
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ public:
|
|||||||
explicit QtTestConfiguration(ITestFramework *framework)
|
explicit QtTestConfiguration(ITestFramework *framework)
|
||||||
: DebuggableTestConfiguration(framework) {}
|
: DebuggableTestConfiguration(framework) {}
|
||||||
TestOutputReader *outputReader(const QFutureInterface<TestResultPtr> &fi,
|
TestOutputReader *outputReader(const QFutureInterface<TestResultPtr> &fi,
|
||||||
QProcess *app) const override;
|
Utils::QtcProcess *app) const override;
|
||||||
QStringList argumentsForTestRunner(QStringList *omitted = nullptr) const override;
|
QStringList argumentsForTestRunner(QStringList *omitted = nullptr) const override;
|
||||||
Utils::Environment filteredEnvironment(const Utils::Environment &original) const override;
|
Utils::Environment filteredEnvironment(const Utils::Environment &original) const override;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -126,7 +126,7 @@ static QString constructBenchmarkInformation(const QString &metric, double value
|
|||||||
}
|
}
|
||||||
|
|
||||||
QtTestOutputReader::QtTestOutputReader(const QFutureInterface<TestResultPtr> &futureInterface,
|
QtTestOutputReader::QtTestOutputReader(const QFutureInterface<TestResultPtr> &futureInterface,
|
||||||
QProcess *testApplication,
|
Utils::QtcProcess *testApplication,
|
||||||
const Utils::FilePath &buildDirectory,
|
const Utils::FilePath &buildDirectory,
|
||||||
const Utils::FilePath &projectFile,
|
const Utils::FilePath &projectFile,
|
||||||
OutputMode mode, TestType type)
|
OutputMode mode, TestType type)
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
QtTestOutputReader(const QFutureInterface<TestResultPtr> &futureInterface,
|
QtTestOutputReader(const QFutureInterface<TestResultPtr> &futureInterface,
|
||||||
QProcess *testApplication, const Utils::FilePath &buildDirectory,
|
Utils::QtcProcess *testApplication, const Utils::FilePath &buildDirectory,
|
||||||
const Utils::FilePath &projectFile, OutputMode mode, TestType type);
|
const Utils::FilePath &projectFile, OutputMode mode, TestType type);
|
||||||
protected:
|
protected:
|
||||||
void processOutputLine(const QByteArray &outputLine) override;
|
void processOutputLine(const QByteArray &outputLine) override;
|
||||||
|
|||||||
@@ -52,7 +52,9 @@ const QString QtTestResult::outputString(bool selected) const
|
|||||||
case ResultType::UnexpectedPass:
|
case ResultType::UnexpectedPass:
|
||||||
case ResultType::BlacklistedFail:
|
case ResultType::BlacklistedFail:
|
||||||
case ResultType::BlacklistedPass:
|
case ResultType::BlacklistedPass:
|
||||||
output = className + "::" + m_function;
|
output = className;
|
||||||
|
if (!m_function.isEmpty())
|
||||||
|
output.append("::" + m_function);
|
||||||
if (!m_dataTag.isEmpty())
|
if (!m_dataTag.isEmpty())
|
||||||
output.append(QString(" (%1)").arg(m_dataTag));
|
output.append(QString(" (%1)").arg(m_dataTag));
|
||||||
if (selected && !desc.isEmpty()) {
|
if (selected && !desc.isEmpty()) {
|
||||||
@@ -60,7 +62,9 @@ const QString QtTestResult::outputString(bool selected) const
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ResultType::Benchmark:
|
case ResultType::Benchmark:
|
||||||
output = className + "::" + m_function;
|
output = className;
|
||||||
|
if (!m_function.isEmpty())
|
||||||
|
output.append("::" + m_function);
|
||||||
if (!m_dataTag.isEmpty())
|
if (!m_dataTag.isEmpty())
|
||||||
output.append(QString(" (%1)").arg(m_dataTag));
|
output.append(QString(" (%1)").arg(m_dataTag));
|
||||||
if (!desc.isEmpty()) {
|
if (!desc.isEmpty()) {
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ QuickTestConfiguration::QuickTestConfiguration(ITestFramework *framework)
|
|||||||
}
|
}
|
||||||
|
|
||||||
TestOutputReader *QuickTestConfiguration::outputReader(const QFutureInterface<TestResultPtr> &fi,
|
TestOutputReader *QuickTestConfiguration::outputReader(const QFutureInterface<TestResultPtr> &fi,
|
||||||
QProcess *app) const
|
Utils::QtcProcess *app) const
|
||||||
{
|
{
|
||||||
auto qtSettings = static_cast<QtTestSettings *>(framework()->testSettings());
|
auto qtSettings = static_cast<QtTestSettings *>(framework()->testSettings());
|
||||||
const QtTestOutputReader::OutputMode mode = qtSettings && qtSettings->useXMLOutput.value()
|
const QtTestOutputReader::OutputMode mode = qtSettings && qtSettings->useXMLOutput.value()
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ class QuickTestConfiguration : public DebuggableTestConfiguration
|
|||||||
public:
|
public:
|
||||||
explicit QuickTestConfiguration(ITestFramework *framework);
|
explicit QuickTestConfiguration(ITestFramework *framework);
|
||||||
TestOutputReader *outputReader(const QFutureInterface<TestResultPtr> &fi,
|
TestOutputReader *outputReader(const QFutureInterface<TestResultPtr> &fi,
|
||||||
QProcess *app) const override;
|
Utils::QtcProcess *app) const override;
|
||||||
QStringList argumentsForTestRunner(QStringList *omitted = nullptr) const override;
|
QStringList argumentsForTestRunner(QStringList *omitted = nullptr) const override;
|
||||||
Utils::Environment filteredEnvironment(const Utils::Environment &original) const override;
|
Utils::Environment filteredEnvironment(const Utils::Environment &original) const override;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -35,9 +35,7 @@
|
|||||||
#include <QPointer>
|
#include <QPointer>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
namespace Utils { class QtcProcess; }
|
||||||
class QProcess;
|
|
||||||
QT_END_NAMESPACE
|
|
||||||
|
|
||||||
namespace Autotest {
|
namespace Autotest {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
@@ -66,7 +64,7 @@ public:
|
|||||||
Utils::FilePath executableFilePath() const;
|
Utils::FilePath executableFilePath() const;
|
||||||
|
|
||||||
virtual TestOutputReader *outputReader(const QFutureInterface<TestResultPtr> &fi,
|
virtual TestOutputReader *outputReader(const QFutureInterface<TestResultPtr> &fi,
|
||||||
QProcess *app) const = 0;
|
Utils::QtcProcess *app) const = 0;
|
||||||
virtual Utils::Environment filteredEnvironment(const Utils::Environment &original) const;
|
virtual Utils::Environment filteredEnvironment(const Utils::Environment &original) const;
|
||||||
|
|
||||||
ITestBase *testBase() const { return m_testBase; }
|
ITestBase *testBase() const { return m_testBase; }
|
||||||
|
|||||||
@@ -30,6 +30,7 @@
|
|||||||
#include "testtreeitem.h"
|
#include "testtreeitem.h"
|
||||||
|
|
||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
|
#include <utils/qtcprocess.h>
|
||||||
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
@@ -46,11 +47,12 @@ Utils::FilePath TestOutputReader::constructSourceFilePath(const Utils::FilePath
|
|||||||
}
|
}
|
||||||
|
|
||||||
TestOutputReader::TestOutputReader(const QFutureInterface<TestResultPtr> &futureInterface,
|
TestOutputReader::TestOutputReader(const QFutureInterface<TestResultPtr> &futureInterface,
|
||||||
QProcess *testApplication, const Utils::FilePath &buildDirectory)
|
Utils::QtcProcess *testApplication,
|
||||||
|
const Utils::FilePath &buildDirectory)
|
||||||
: m_futureInterface(futureInterface)
|
: m_futureInterface(futureInterface)
|
||||||
, m_testApplication(testApplication)
|
, m_testApplication(testApplication)
|
||||||
, m_buildDir(buildDirectory)
|
, m_buildDir(buildDirectory)
|
||||||
, m_id(testApplication ? testApplication->program() : QString())
|
, m_id(testApplication ? testApplication->commandLine().executable().toUserOutput() : QString())
|
||||||
{
|
{
|
||||||
auto chopLineBreak = [](QByteArray line) {
|
auto chopLineBreak = [](QByteArray line) {
|
||||||
if (line.endsWith('\n'))
|
if (line.endsWith('\n'))
|
||||||
@@ -61,17 +63,11 @@ TestOutputReader::TestOutputReader(const QFutureInterface<TestResultPtr> &future
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (m_testApplication) {
|
if (m_testApplication) {
|
||||||
connect(m_testApplication, &QProcess::readyReadStandardOutput,
|
m_testApplication->setStdOutLineCallback([this, &chopLineBreak](const QString &line) {
|
||||||
this, [chopLineBreak, this] () {
|
processStdOutput(chopLineBreak(line.toUtf8()));
|
||||||
m_testApplication->setReadChannel(QProcess::StandardOutput);
|
|
||||||
while (m_testApplication->canReadLine())
|
|
||||||
processStdOutput(chopLineBreak(m_testApplication->readLine()));
|
|
||||||
});
|
});
|
||||||
connect(m_testApplication, &QProcess::readyReadStandardError,
|
m_testApplication->setStdErrLineCallback([this, &chopLineBreak](const QString &line) {
|
||||||
this, [chopLineBreak, this] () {
|
processStdError(chopLineBreak(line.toUtf8()));
|
||||||
m_testApplication->setReadChannel(QProcess::StandardError);
|
|
||||||
while (m_testApplication->canReadLine())
|
|
||||||
processStdError(chopLineBreak(m_testApplication->readLine()));
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,9 +29,10 @@
|
|||||||
|
|
||||||
#include <QFutureInterface>
|
#include <QFutureInterface>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QProcess>
|
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
|
||||||
|
namespace Utils { class QtcProcess; }
|
||||||
|
|
||||||
namespace Autotest {
|
namespace Autotest {
|
||||||
|
|
||||||
class TestOutputReader : public QObject
|
class TestOutputReader : public QObject
|
||||||
@@ -39,7 +40,7 @@ class TestOutputReader : public QObject
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
TestOutputReader(const QFutureInterface<TestResultPtr> &futureInterface,
|
TestOutputReader(const QFutureInterface<TestResultPtr> &futureInterface,
|
||||||
QProcess *testApplication, const Utils::FilePath &buildDirectory);
|
Utils::QtcProcess *testApplication, const Utils::FilePath &buildDirectory);
|
||||||
virtual ~TestOutputReader();
|
virtual ~TestOutputReader();
|
||||||
void processStdOutput(const QByteArray &outputLine);
|
void processStdOutput(const QByteArray &outputLine);
|
||||||
virtual void processStdError(const QByteArray &outputLine);
|
virtual void processStdError(const QByteArray &outputLine);
|
||||||
@@ -67,7 +68,7 @@ protected:
|
|||||||
|
|
||||||
void reportResult(const TestResultPtr &result);
|
void reportResult(const TestResultPtr &result);
|
||||||
QFutureInterface<TestResultPtr> m_futureInterface;
|
QFutureInterface<TestResultPtr> m_futureInterface;
|
||||||
QProcess *m_testApplication; // not owned
|
Utils::QtcProcess *m_testApplication; // not owned
|
||||||
Utils::FilePath m_buildDir;
|
Utils::FilePath m_buildDir;
|
||||||
QString m_id;
|
QString m_id;
|
||||||
QHash<ResultType, int> m_summary;
|
QHash<ResultType, int> m_summary;
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ public:
|
|||||||
ProjectExplorer::Runnable r;
|
ProjectExplorer::Runnable r;
|
||||||
QTC_ASSERT(m_testConfig, return r);
|
QTC_ASSERT(m_testConfig, return r);
|
||||||
r.command.setExecutable(m_testConfig->executableFilePath());
|
r.command.setExecutable(m_testConfig->executableFilePath());
|
||||||
r.command.setArguments(m_testConfig->argumentsForTestRunner().join(' '));
|
r.command.addArgs(m_testConfig->argumentsForTestRunner().join(' '), Utils::CommandLine::Raw);
|
||||||
r.workingDirectory = m_testConfig->workingDirectory();
|
r.workingDirectory = m_testConfig->workingDirectory();
|
||||||
r.environment = m_testConfig->environment();
|
r.environment = m_testConfig->environment();
|
||||||
return r;
|
return r;
|
||||||
|
|||||||
@@ -90,6 +90,8 @@ TestRunner::TestRunner()
|
|||||||
{
|
{
|
||||||
s_instance = this;
|
s_instance = this;
|
||||||
|
|
||||||
|
m_cancelTimer.setSingleShot(true);
|
||||||
|
connect(&m_cancelTimer, &QTimer::timeout, this, [this]() { cancelCurrent(Timeout); });
|
||||||
connect(&m_futureWatcher, &QFutureWatcher<TestResultPtr>::resultReadyAt,
|
connect(&m_futureWatcher, &QFutureWatcher<TestResultPtr>::resultReadyAt,
|
||||||
this, [this](int index) { emit testResultReady(m_futureWatcher.resultAt(index)); });
|
this, [this](int index) { emit testResultReady(m_futureWatcher.resultAt(index)); });
|
||||||
connect(&m_futureWatcher, &QFutureWatcher<TestResultPtr>::finished,
|
connect(&m_futureWatcher, &QFutureWatcher<TestResultPtr>::finished,
|
||||||
@@ -131,16 +133,17 @@ void TestRunner::runTest(TestRunMode mode, const ITestTreeItem *item)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static QString processInformation(const QProcess *proc)
|
static QString processInformation(const QtcProcess *proc)
|
||||||
{
|
{
|
||||||
QTC_ASSERT(proc, return QString());
|
QTC_ASSERT(proc, return QString());
|
||||||
QString information("\nCommand line: " + proc->program() + ' ' + proc->arguments().join(' '));
|
const Utils::CommandLine command = proc->commandLine();
|
||||||
|
QString information("\nCommand line: " + command.executable().toUserOutput() + ' ' + command.arguments());
|
||||||
QStringList important = { "PATH" };
|
QStringList important = { "PATH" };
|
||||||
if (Utils::HostOsInfo::isLinuxHost())
|
if (Utils::HostOsInfo::isLinuxHost())
|
||||||
important.append("LD_LIBRARY_PATH");
|
important.append("LD_LIBRARY_PATH");
|
||||||
else if (Utils::HostOsInfo::isMacHost())
|
else if (Utils::HostOsInfo::isMacHost())
|
||||||
important.append({ "DYLD_LIBRARY_PATH", "DYLD_FRAMEWORK_PATH" });
|
important.append({ "DYLD_LIBRARY_PATH", "DYLD_FRAMEWORK_PATH" });
|
||||||
const QProcessEnvironment &environment = proc->processEnvironment();
|
const Utils::Environment &environment = proc->environment();
|
||||||
for (const QString &var : important)
|
for (const QString &var : important)
|
||||||
information.append('\n' + var + ": " + environment.value(var));
|
information.append('\n' + var + ": " + environment.value(var));
|
||||||
return information;
|
return information;
|
||||||
@@ -204,34 +207,35 @@ bool TestRunner::currentConfigValid()
|
|||||||
void TestRunner::setUpProcess()
|
void TestRunner::setUpProcess()
|
||||||
{
|
{
|
||||||
QTC_ASSERT(m_currentConfig, return);
|
QTC_ASSERT(m_currentConfig, return);
|
||||||
m_currentProcess = new QProcess;
|
m_currentProcess = new QtcProcess;
|
||||||
m_currentProcess->setReadChannel(QProcess::StandardOutput);
|
|
||||||
if (m_currentConfig->testBase()->type() == ITestBase::Framework) {
|
if (m_currentConfig->testBase()->type() == ITestBase::Framework) {
|
||||||
TestConfiguration *current = static_cast<TestConfiguration *>(m_currentConfig);
|
TestConfiguration *current = static_cast<TestConfiguration *>(m_currentConfig);
|
||||||
m_currentProcess->setProgram(current->executableFilePath().toString());
|
m_currentProcess->setCommand({current->executableFilePath(), {}});
|
||||||
} else {
|
} else {
|
||||||
TestToolConfiguration *current = static_cast<TestToolConfiguration *>(m_currentConfig);
|
TestToolConfiguration *current = static_cast<TestToolConfiguration *>(m_currentConfig);
|
||||||
m_currentProcess->setProgram(current->commandLine().executable().toString());
|
m_currentProcess->setCommand({current->commandLine().executable(), {}});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestRunner::setUpProcessEnv()
|
void TestRunner::setUpProcessEnv()
|
||||||
{
|
{
|
||||||
|
Utils::CommandLine command = m_currentProcess->commandLine();
|
||||||
if (m_currentConfig->testBase()->type() == ITestBase::Framework) {
|
if (m_currentConfig->testBase()->type() == ITestBase::Framework) {
|
||||||
TestConfiguration *current = static_cast<TestConfiguration *>(m_currentConfig);
|
TestConfiguration *current = static_cast<TestConfiguration *>(m_currentConfig);
|
||||||
|
|
||||||
QStringList omitted;
|
QStringList omitted;
|
||||||
m_currentProcess->setArguments(current->argumentsForTestRunner(&omitted));
|
command.addArgs(current->argumentsForTestRunner(&omitted).join(' '), Utils::CommandLine::Raw);
|
||||||
if (!omitted.isEmpty()) {
|
if (!omitted.isEmpty()) {
|
||||||
const QString &details = constructOmittedDetailsString(omitted);
|
const QString &details = constructOmittedDetailsString(omitted);
|
||||||
reportResult(ResultType::MessageWarn, details.arg(current->displayName()));
|
reportResult(ResultType::MessageWarn, details.arg(current->displayName()));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
TestToolConfiguration *current = static_cast<TestToolConfiguration *>(m_currentConfig);
|
TestToolConfiguration *current = static_cast<TestToolConfiguration *>(m_currentConfig);
|
||||||
m_currentProcess->setArguments(current->commandLine().splitArguments());
|
command.setArguments(current->commandLine().arguments());
|
||||||
}
|
}
|
||||||
|
m_currentProcess->setCommand(command);
|
||||||
|
|
||||||
m_currentProcess->setWorkingDirectory(m_currentConfig->workingDirectory().toString());
|
m_currentProcess->setWorkingDirectory(m_currentConfig->workingDirectory());
|
||||||
const Utils::Environment &original = m_currentConfig->environment();
|
const Utils::Environment &original = m_currentConfig->environment();
|
||||||
Utils::Environment environment = m_currentConfig->filteredEnvironment(original);
|
Utils::Environment environment = m_currentConfig->filteredEnvironment(original);
|
||||||
const Utils::EnvironmentItems removedVariables = Utils::filtered(
|
const Utils::EnvironmentItems removedVariables = Utils::filtered(
|
||||||
@@ -243,7 +247,7 @@ void TestRunner::setUpProcessEnv()
|
|||||||
.arg(m_currentConfig->displayName());
|
.arg(m_currentConfig->displayName());
|
||||||
reportResult(ResultType::MessageWarn, details);
|
reportResult(ResultType::MessageWarn, details);
|
||||||
}
|
}
|
||||||
m_currentProcess->setProcessEnvironment(environment.toProcessEnvironment());
|
m_currentProcess->setEnvironment(environment);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestRunner::scheduleNext()
|
void TestRunner::scheduleNext()
|
||||||
@@ -272,15 +276,16 @@ void TestRunner::scheduleNext()
|
|||||||
|
|
||||||
setUpProcessEnv();
|
setUpProcessEnv();
|
||||||
|
|
||||||
connect(m_currentProcess, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
|
connect(m_currentProcess, &Utils::QtcProcess::finished,
|
||||||
this, &TestRunner::onProcessFinished);
|
this, &TestRunner::onProcessFinished);
|
||||||
const int timeout = AutotestPlugin::settings()->timeout;
|
const int timeout = AutotestPlugin::settings()->timeout;
|
||||||
QTimer::singleShot(timeout, m_currentProcess, [this]() { cancelCurrent(Timeout); });
|
m_cancelTimer.setInterval(timeout);
|
||||||
|
m_cancelTimer.start();
|
||||||
|
|
||||||
qCInfo(runnerLog) << "Command:" << m_currentProcess->program();
|
qCInfo(runnerLog) << "Command:" << m_currentProcess->commandLine().executable();
|
||||||
qCInfo(runnerLog) << "Arguments:" << m_currentProcess->arguments();
|
qCInfo(runnerLog) << "Arguments:" << m_currentProcess->commandLine().arguments();
|
||||||
qCInfo(runnerLog) << "Working directory:" << m_currentProcess->workingDirectory();
|
qCInfo(runnerLog) << "Working directory:" << m_currentProcess->workingDirectory();
|
||||||
qCDebug(runnerLog) << "Environment:" << m_currentProcess->environment();
|
qCDebug(runnerLog) << "Environment:" << m_currentProcess->environment().toStringList();
|
||||||
|
|
||||||
m_currentProcess->start();
|
m_currentProcess->start();
|
||||||
if (!m_currentProcess->waitForStarted()) {
|
if (!m_currentProcess->waitForStarted()) {
|
||||||
@@ -355,7 +360,8 @@ void TestRunner::onProcessFinished()
|
|||||||
void TestRunner::resetInternalPointers()
|
void TestRunner::resetInternalPointers()
|
||||||
{
|
{
|
||||||
delete m_currentOutputReader;
|
delete m_currentOutputReader;
|
||||||
delete m_currentProcess;
|
if (m_currentProcess)
|
||||||
|
m_currentProcess->deleteLater();
|
||||||
delete m_currentConfig;
|
delete m_currentConfig;
|
||||||
m_currentOutputReader = nullptr;
|
m_currentOutputReader = nullptr;
|
||||||
m_currentProcess = nullptr;
|
m_currentProcess = nullptr;
|
||||||
@@ -812,6 +818,7 @@ void TestRunner::onBuildQueueFinished(bool success)
|
|||||||
|
|
||||||
void TestRunner::onFinished()
|
void TestRunner::onFinished()
|
||||||
{
|
{
|
||||||
|
m_cancelTimer.stop();
|
||||||
// if we've been canceled and we still have test configurations queued just throw them away
|
// if we've been canceled and we still have test configurations queued just throw them away
|
||||||
qDeleteAll(m_selectedTests);
|
qDeleteAll(m_selectedTests);
|
||||||
m_selectedTests.clear();
|
m_selectedTests.clear();
|
||||||
|
|||||||
@@ -32,16 +32,17 @@
|
|||||||
#include <QFutureWatcher>
|
#include <QFutureWatcher>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QQueue>
|
#include <QQueue>
|
||||||
|
#include <QTimer>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
class QCheckBox;
|
class QCheckBox;
|
||||||
class QComboBox;
|
class QComboBox;
|
||||||
class QDialogButtonBox;
|
class QDialogButtonBox;
|
||||||
class QLabel;
|
class QLabel;
|
||||||
class QProcess;
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
namespace ProjectExplorer { class Project; }
|
namespace ProjectExplorer { class Project; }
|
||||||
|
namespace Utils { class QtcProcess; }
|
||||||
|
|
||||||
namespace Autotest {
|
namespace Autotest {
|
||||||
|
|
||||||
@@ -105,7 +106,7 @@ private:
|
|||||||
bool m_executingTests = false;
|
bool m_executingTests = false;
|
||||||
bool m_canceled = false;
|
bool m_canceled = false;
|
||||||
ITestConfiguration *m_currentConfig = nullptr;
|
ITestConfiguration *m_currentConfig = nullptr;
|
||||||
QProcess *m_currentProcess = nullptr;
|
Utils::QtcProcess *m_currentProcess = nullptr;
|
||||||
TestOutputReader *m_currentOutputReader = nullptr;
|
TestOutputReader *m_currentOutputReader = nullptr;
|
||||||
TestRunMode m_runMode = TestRunMode::None;
|
TestRunMode m_runMode = TestRunMode::None;
|
||||||
|
|
||||||
@@ -116,6 +117,7 @@ private:
|
|||||||
QMetaObject::Connection m_finishDebugConnect;
|
QMetaObject::Connection m_finishDebugConnect;
|
||||||
// temporarily used for handling of switching the current target
|
// temporarily used for handling of switching the current target
|
||||||
QMetaObject::Connection m_targetConnect;
|
QMetaObject::Connection m_targetConnect;
|
||||||
|
QTimer m_cancelTimer;
|
||||||
bool m_skipTargetsCheck = false;
|
bool m_skipTargetsCheck = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -52,7 +52,6 @@ QdbDeployConfigurationFactory::QdbDeployConfigurationFactory()
|
|||||||
return prj->deploymentKnowledge() == DeploymentKnowledge::Bad
|
return prj->deploymentKnowledge() == DeploymentKnowledge::Bad
|
||||||
&& prj->hasMakeInstallEquivalent();
|
&& prj->hasMakeInstallEquivalent();
|
||||||
});
|
});
|
||||||
addInitialStep(RemoteLinux::Constants::CheckForFreeDiskSpaceId);
|
|
||||||
addInitialStep(Qdb::Constants::QdbStopApplicationStepId);
|
addInitialStep(Qdb::Constants::QdbStopApplicationStepId);
|
||||||
addInitialStep(RemoteLinux::Constants::DirectUploadStepId);
|
addInitialStep(RemoteLinux::Constants::DirectUploadStepId);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,7 +45,6 @@
|
|||||||
|
|
||||||
#include <qtsupport/qtversionfactory.h>
|
#include <qtsupport/qtversionfactory.h>
|
||||||
|
|
||||||
#include <remotelinux/checkforfreediskspacestep.h>
|
|
||||||
#include <remotelinux/genericdirectuploadstep.h>
|
#include <remotelinux/genericdirectuploadstep.h>
|
||||||
#include <remotelinux/makeinstallstep.h>
|
#include <remotelinux/makeinstallstep.h>
|
||||||
#include <remotelinux/remotelinux_constants.h>
|
#include <remotelinux/remotelinux_constants.h>
|
||||||
@@ -177,8 +176,6 @@ public:
|
|||||||
QdbStopApplicationStepFactory m_stopApplicationStepFactory;
|
QdbStopApplicationStepFactory m_stopApplicationStepFactory;
|
||||||
QdbMakeDefaultAppStepFactory m_makeDefaultAppStepFactory;
|
QdbMakeDefaultAppStepFactory m_makeDefaultAppStepFactory;
|
||||||
|
|
||||||
QdbDeployStepFactory<RemoteLinux::CheckForFreeDiskSpaceStep>
|
|
||||||
m_checkForFreeDiskSpaceStepFactory{RemoteLinux::Constants::CheckForFreeDiskSpaceId};
|
|
||||||
QdbDeployStepFactory<RemoteLinux::GenericDirectUploadStep>
|
QdbDeployStepFactory<RemoteLinux::GenericDirectUploadStep>
|
||||||
m_directUploadStepFactory{RemoteLinux::Constants::DirectUploadStepId};
|
m_directUploadStepFactory{RemoteLinux::Constants::DirectUploadStepId};
|
||||||
QdbDeployStepFactory<RemoteLinux::MakeInstallStep>
|
QdbDeployStepFactory<RemoteLinux::MakeInstallStep>
|
||||||
|
|||||||
@@ -34,8 +34,6 @@
|
|||||||
# include "test/clangfixittest.h"
|
# include "test/clangfixittest.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <utils/runextensions.h>
|
|
||||||
|
|
||||||
#include <coreplugin/actionmanager/actioncontainer.h>
|
#include <coreplugin/actionmanager/actioncontainer.h>
|
||||||
#include <coreplugin/actionmanager/actionmanager.h>
|
#include <coreplugin/actionmanager/actionmanager.h>
|
||||||
#include <coreplugin/messagemanager.h>
|
#include <coreplugin/messagemanager.h>
|
||||||
@@ -45,6 +43,7 @@
|
|||||||
#include <cppeditor/cppmodelmanager.h>
|
#include <cppeditor/cppmodelmanager.h>
|
||||||
|
|
||||||
#include <projectexplorer/buildconfiguration.h>
|
#include <projectexplorer/buildconfiguration.h>
|
||||||
|
#include <projectexplorer/project.h>
|
||||||
#include <projectexplorer/projectpanelfactory.h>
|
#include <projectexplorer/projectpanelfactory.h>
|
||||||
#include <projectexplorer/projectexplorer.h>
|
#include <projectexplorer/projectexplorer.h>
|
||||||
#include <projectexplorer/session.h>
|
#include <projectexplorer/session.h>
|
||||||
@@ -53,6 +52,9 @@
|
|||||||
|
|
||||||
#include <texteditor/textmark.h>
|
#include <texteditor/textmark.h>
|
||||||
|
|
||||||
|
#include <utils/temporarydirectory.h>
|
||||||
|
#include <utils/runextensions.h>
|
||||||
|
|
||||||
using namespace Utils;
|
using namespace Utils;
|
||||||
|
|
||||||
namespace ClangCodeModel {
|
namespace ClangCodeModel {
|
||||||
@@ -69,10 +71,13 @@ void ClangCodeModelPlugin::generateCompilationDB()
|
|||||||
const auto projectInfo = CppModelManager::instance()->projectInfo(target->project());
|
const auto projectInfo = CppModelManager::instance()->projectInfo(target->project());
|
||||||
if (!projectInfo)
|
if (!projectInfo)
|
||||||
return;
|
return;
|
||||||
|
FilePath baseDir = projectInfo->buildRoot();
|
||||||
|
if (baseDir == target->project()->projectDirectory())
|
||||||
|
baseDir = TemporaryDirectory::masterDirectoryFilePath();
|
||||||
|
|
||||||
QFuture<GenerateCompilationDbResult> task
|
QFuture<GenerateCompilationDbResult> task
|
||||||
= Utils::runAsync(&Internal::generateCompilationDB, projectInfo,
|
= Utils::runAsync(&Internal::generateCompilationDB, projectInfo,
|
||||||
projectInfo->buildRoot(), CompilationDbPurpose::Project,
|
baseDir, CompilationDbPurpose::Project,
|
||||||
warningsConfigForProject(target->project()),
|
warningsConfigForProject(target->project()),
|
||||||
globalClangOptions(),
|
globalClangOptions(),
|
||||||
FilePath());
|
FilePath());
|
||||||
|
|||||||
@@ -185,11 +185,6 @@ CppEditor::CppCompletionAssistProvider *ClangModelManagerSupport::completionAssi
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
CppEditor::CppCompletionAssistProvider *ClangModelManagerSupport::functionHintAssistProvider()
|
|
||||||
{
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClangModelManagerSupport::followSymbol(const CppEditor::CursorInEditor &data,
|
void ClangModelManagerSupport::followSymbol(const CppEditor::CursorInEditor &data,
|
||||||
const Utils::LinkHandler &processLinkCallback, bool resolveTarget,
|
const Utils::LinkHandler &processLinkCallback, bool resolveTarget,
|
||||||
bool inNextSplit)
|
bool inNextSplit)
|
||||||
|
|||||||
@@ -63,7 +63,6 @@ public:
|
|||||||
~ClangModelManagerSupport() override;
|
~ClangModelManagerSupport() override;
|
||||||
|
|
||||||
CppEditor::CppCompletionAssistProvider *completionAssistProvider() override;
|
CppEditor::CppCompletionAssistProvider *completionAssistProvider() override;
|
||||||
CppEditor::CppCompletionAssistProvider *functionHintAssistProvider() override;
|
|
||||||
TextEditor::BaseHoverHandler *createHoverHandler() override { return nullptr; }
|
TextEditor::BaseHoverHandler *createHoverHandler() override { return nullptr; }
|
||||||
CppEditor::BaseEditorDocumentProcessor *createEditorDocumentProcessor(
|
CppEditor::BaseEditorDocumentProcessor *createEditorDocumentProcessor(
|
||||||
TextEditor::TextDocument *baseTextDocument) override;
|
TextEditor::TextDocument *baseTextDocument) override;
|
||||||
|
|||||||
@@ -25,8 +25,6 @@
|
|||||||
|
|
||||||
#include "clangtoolrunner.h"
|
#include "clangtoolrunner.h"
|
||||||
|
|
||||||
#include "clangtoolsconstants.h"
|
|
||||||
|
|
||||||
#include <utils/environment.h>
|
#include <utils/environment.h>
|
||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
#include <utils/qtcprocess.h>
|
#include <utils/qtcprocess.h>
|
||||||
@@ -60,32 +58,17 @@ static QString finishedWithBadExitCode(const QString &name, int exitCode)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ClangToolRunner::ClangToolRunner(QObject *parent)
|
ClangToolRunner::ClangToolRunner(QObject *parent)
|
||||||
: QObject(parent), m_process(new QtcProcess)
|
: QObject(parent)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
ClangToolRunner::~ClangToolRunner()
|
|
||||||
{
|
|
||||||
if (m_process->state() != QProcess::NotRunning) {
|
|
||||||
// asking politly to terminate costs ~300 ms on windows so skip the courtasy and direct kill the process
|
|
||||||
if (HostOsInfo::isWindowsHost()) {
|
|
||||||
m_process->kill();
|
|
||||||
m_process->waitForFinished(100);
|
|
||||||
} else {
|
|
||||||
m_process->stopProcess();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m_process->deleteLater();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClangToolRunner::init(const FilePath &outputDirPath, const Environment &environment)
|
void ClangToolRunner::init(const FilePath &outputDirPath, const Environment &environment)
|
||||||
{
|
{
|
||||||
m_outputDirPath = outputDirPath;
|
m_outputDirPath = outputDirPath;
|
||||||
QTC_CHECK(!m_outputDirPath.isEmpty());
|
QTC_CHECK(!m_outputDirPath.isEmpty());
|
||||||
|
|
||||||
m_process->setEnvironment(environment);
|
m_process.setEnvironment(environment);
|
||||||
m_process->setWorkingDirectory(m_outputDirPath); // Current clang-cl puts log file into working dir.
|
m_process.setWorkingDirectory(m_outputDirPath); // Current clang-cl puts log file into working dir.
|
||||||
connect(m_process, &QtcProcess::done, this, &ClangToolRunner::onProcessDone);
|
connect(&m_process, &QtcProcess::done, this, &ClangToolRunner::onProcessDone);
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList ClangToolRunner::mainToolArguments() const
|
QStringList ClangToolRunner::mainToolArguments() const
|
||||||
@@ -139,20 +122,20 @@ bool ClangToolRunner::run(const QString &fileToAnalyze, const QStringList &compi
|
|||||||
m_commandLine = {m_executable, m_argsCreator(compilerOptions)};
|
m_commandLine = {m_executable, m_argsCreator(compilerOptions)};
|
||||||
|
|
||||||
qCDebug(LOG).noquote() << "Starting" << m_commandLine.toUserOutput();
|
qCDebug(LOG).noquote() << "Starting" << m_commandLine.toUserOutput();
|
||||||
m_process->setCommand(m_commandLine);
|
m_process.setCommand(m_commandLine);
|
||||||
m_process->start();
|
m_process.start();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClangToolRunner::onProcessDone()
|
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.stdOut();
|
||||||
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()),
|
||||||
commandlineAndOutput());
|
commandlineAndOutput());
|
||||||
} else { // == QProcess::CrashExit
|
} else { // == QProcess::CrashExit
|
||||||
emit finishedWithFailure(finishedDueToCrash(m_name), commandlineAndOutput());
|
emit finishedWithFailure(finishedDueToCrash(m_name), commandlineAndOutput());
|
||||||
@@ -165,8 +148,8 @@ QString ClangToolRunner::commandlineAndOutput() const
|
|||||||
"Process Error: %2\n"
|
"Process Error: %2\n"
|
||||||
"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.stdOut());
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
|
|||||||
@@ -28,13 +28,10 @@
|
|||||||
#include "clangtoolslogfilereader.h"
|
#include "clangtoolslogfilereader.h"
|
||||||
|
|
||||||
#include <utils/commandline.h>
|
#include <utils/commandline.h>
|
||||||
|
#include <utils/qtcprocess.h>
|
||||||
#include <QProcess>
|
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
namespace Utils { class QtcProcess; }
|
|
||||||
|
|
||||||
namespace ClangTools {
|
namespace ClangTools {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
@@ -46,7 +43,6 @@ class ClangToolRunner : public QObject
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
ClangToolRunner(QObject *parent = nullptr);
|
ClangToolRunner(QObject *parent = nullptr);
|
||||||
~ClangToolRunner() override;
|
|
||||||
|
|
||||||
void init(const Utils::FilePath &outputDirPath, const Utils::Environment &environment);
|
void init(const Utils::FilePath &outputDirPath, const Utils::Environment &environment);
|
||||||
void setName(const QString &name) { m_name = name; }
|
void setName(const QString &name) { m_name = name; }
|
||||||
@@ -83,7 +79,7 @@ private:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
Utils::FilePath m_outputDirPath;
|
Utils::FilePath m_outputDirPath;
|
||||||
Utils::QtcProcess *m_process = nullptr;
|
Utils::QtcProcess m_process;
|
||||||
|
|
||||||
QString m_name;
|
QString m_name;
|
||||||
Utils::FilePath m_executable;
|
Utils::FilePath m_executable;
|
||||||
|
|||||||
@@ -28,7 +28,6 @@
|
|||||||
#include "cmakebuildconfiguration.h"
|
#include "cmakebuildconfiguration.h"
|
||||||
#include "cmakebuildsystem.h"
|
#include "cmakebuildsystem.h"
|
||||||
#include "cmakekitinformation.h"
|
#include "cmakekitinformation.h"
|
||||||
#include "cmakeprojectconstants.h"
|
|
||||||
#include "cmakeprojectplugin.h"
|
#include "cmakeprojectplugin.h"
|
||||||
#include "cmakespecificsettings.h"
|
#include "cmakespecificsettings.h"
|
||||||
#include "cmaketoolmanager.h"
|
#include "cmaketoolmanager.h"
|
||||||
@@ -90,12 +89,6 @@ BuildDirParameters::BuildDirParameters(CMakeBuildSystem *buildSystem)
|
|||||||
if (Utils::HostOsInfo::isAnyUnixHost())
|
if (Utils::HostOsInfo::isAnyUnixHost())
|
||||||
environment.set("ICECC", "no");
|
environment.set("ICECC", "no");
|
||||||
|
|
||||||
CMakeSpecificSettings *settings = CMakeProjectPlugin::projectTypeSpecificSettings();
|
|
||||||
if (!settings->ninjaPath.filePath().isEmpty()) {
|
|
||||||
const Utils::FilePath ninja = settings->ninjaPath.filePath();
|
|
||||||
environment.appendOrSetPath(ninja.isFile() ? ninja.parentDir() : ninja);
|
|
||||||
}
|
|
||||||
|
|
||||||
cmakeToolId = CMakeKitAspect::cmakeToolId(k);
|
cmakeToolId = CMakeKitAspect::cmakeToolId(k);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -109,8 +102,5 @@ CMakeTool *BuildDirParameters::cmakeTool() const
|
|||||||
return CMakeToolManager::findById(cmakeToolId);
|
return CMakeToolManager::findById(cmakeToolId);
|
||||||
}
|
}
|
||||||
|
|
||||||
BuildDirParameters::BuildDirParameters(const BuildDirParameters &) = default;
|
|
||||||
BuildDirParameters &BuildDirParameters::operator=(const BuildDirParameters &) = default;
|
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
} // namespace CMakeProjectManager
|
} // namespace CMakeProjectManager
|
||||||
|
|||||||
@@ -25,14 +25,10 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "cmakeconfigitem.h"
|
|
||||||
#include "cmaketool.h"
|
#include "cmaketool.h"
|
||||||
|
|
||||||
#include <utils/environment.h>
|
#include <utils/environment.h>
|
||||||
#include <utils/fileutils.h>
|
#include <utils/filepath.h>
|
||||||
#include <utils/macroexpander.h>
|
|
||||||
|
|
||||||
#include <QString>
|
|
||||||
|
|
||||||
namespace CMakeProjectManager {
|
namespace CMakeProjectManager {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
@@ -44,8 +40,6 @@ class BuildDirParameters
|
|||||||
public:
|
public:
|
||||||
BuildDirParameters();
|
BuildDirParameters();
|
||||||
explicit BuildDirParameters(CMakeBuildSystem *buildSystem);
|
explicit BuildDirParameters(CMakeBuildSystem *buildSystem);
|
||||||
BuildDirParameters(const BuildDirParameters &other);
|
|
||||||
BuildDirParameters &operator=(const BuildDirParameters &other);
|
|
||||||
|
|
||||||
bool isValid() const;
|
bool isValid() const;
|
||||||
CMakeTool *cmakeTool() const;
|
CMakeTool *cmakeTool() const;
|
||||||
|
|||||||
@@ -379,7 +379,16 @@ CMakeBuildSettingsWidget::CMakeBuildSettingsWidget(CMakeBuildSystem *bs) :
|
|||||||
}
|
}
|
||||||
|
|
||||||
connect(m_buildSystem, &BuildSystem::parsingFinished, this, [this] {
|
connect(m_buildSystem, &BuildSystem::parsingFinished, this, [this] {
|
||||||
m_configModel->setConfiguration(m_buildSystem->configurationFromCMake());
|
const CMakeConfig config = m_buildSystem->configurationFromCMake();
|
||||||
|
auto qmlDebugAspect = m_buildSystem->buildConfiguration()
|
||||||
|
->aspect<QtSupport::QmlDebuggingAspect>();
|
||||||
|
const TriState qmlDebugSetting = qmlDebugAspect->value();
|
||||||
|
bool qmlDebugConfig = CMakeBuildConfiguration::hasQmlDebugging(config);
|
||||||
|
if ((qmlDebugSetting == TriState::Enabled && !qmlDebugConfig)
|
||||||
|
|| (qmlDebugSetting == TriState::Disabled && qmlDebugConfig)) {
|
||||||
|
qmlDebugAspect->setValue(TriState::Default);
|
||||||
|
}
|
||||||
|
m_configModel->setConfiguration(config);
|
||||||
m_configModel->setInitialParametersConfiguration(
|
m_configModel->setInitialParametersConfiguration(
|
||||||
m_buildSystem->initialCMakeConfiguration());
|
m_buildSystem->initialCMakeConfiguration());
|
||||||
m_buildSystem->filterConfigArgumentsFromAdditionalCMakeArguments();
|
m_buildSystem->filterConfigArgumentsFromAdditionalCMakeArguments();
|
||||||
@@ -738,7 +747,8 @@ void CMakeBuildSettingsWidget::updateButtonState()
|
|||||||
} else {
|
} else {
|
||||||
m_reconfigureButton->setText(tr("Run CMake"));
|
m_reconfigureButton->setText(tr("Run CMake"));
|
||||||
}
|
}
|
||||||
reconfigureButtonFont.setBold(m_configModel->hasChanges(isInitial));
|
reconfigureButtonFont.setBold(isInitial ? m_configModel->hasChanges(isInitial)
|
||||||
|
: !configChanges.isEmpty());
|
||||||
}
|
}
|
||||||
m_reconfigureButton->setFont(reconfigureButtonFont);
|
m_reconfigureButton->setFont(reconfigureButtonFont);
|
||||||
|
|
||||||
@@ -1388,6 +1398,16 @@ bool CMakeBuildConfiguration::isIos(const Kit *k)
|
|||||||
|| deviceType == Ios::Constants::IOS_SIMULATOR_TYPE;
|
|| deviceType == Ios::Constants::IOS_SIMULATOR_TYPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CMakeBuildConfiguration::hasQmlDebugging(const CMakeConfig &config)
|
||||||
|
{
|
||||||
|
// Determine QML debugging flags. This must match what we do in
|
||||||
|
// CMakeBuildSettingsWidget::getQmlDebugCxxFlags()
|
||||||
|
// such that in doubt we leave the QML Debugging setting at "Leave at default"
|
||||||
|
const QString cxxFlagsInit = config.stringValueOf("CMAKE_CXX_FLAGS_INIT");
|
||||||
|
const QString cxxFlags = config.stringValueOf("CMAKE_CXX_FLAGS");
|
||||||
|
return cxxFlagsInit.contains("-DQT_QML_DEBUG") && cxxFlags.contains("-DQT_QML_DEBUG");
|
||||||
|
}
|
||||||
|
|
||||||
void CMakeBuildConfiguration::buildTarget(const QString &buildTarget)
|
void CMakeBuildConfiguration::buildTarget(const QString &buildTarget)
|
||||||
{
|
{
|
||||||
auto cmBs = qobject_cast<CMakeBuildStep *>(findOrDefault(
|
auto cmBs = qobject_cast<CMakeBuildStep *>(findOrDefault(
|
||||||
@@ -1694,6 +1714,15 @@ FilePath CMakeBuildConfiguration::sourceDirectory() const
|
|||||||
return aspect<SourceDirectoryAspect>()->filePath();
|
return aspect<SourceDirectoryAspect>()->filePath();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CMakeBuildConfiguration::addToEnvironment(Utils::Environment &env) const
|
||||||
|
{
|
||||||
|
CMakeSpecificSettings *settings = CMakeProjectPlugin::projectTypeSpecificSettings();
|
||||||
|
if (!settings->ninjaPath.filePath().isEmpty()) {
|
||||||
|
const Utils::FilePath ninja = settings->ninjaPath.filePath();
|
||||||
|
env.appendOrSetPath(ninja.isFile() ? ninja.parentDir() : ninja);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
QString CMakeBuildSystem::cmakeBuildType() const
|
QString CMakeBuildSystem::cmakeBuildType() const
|
||||||
{
|
{
|
||||||
auto setBuildTypeFromConfig = [this](const CMakeConfig &config) {
|
auto setBuildTypeFromConfig = [this](const CMakeConfig &config) {
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ public:
|
|||||||
shadowBuildDirectory(const Utils::FilePath &projectFilePath, const ProjectExplorer::Kit *k,
|
shadowBuildDirectory(const Utils::FilePath &projectFilePath, const ProjectExplorer::Kit *k,
|
||||||
const QString &bcName, BuildConfiguration::BuildType buildType);
|
const QString &bcName, BuildConfiguration::BuildType buildType);
|
||||||
static bool isIos(const ProjectExplorer::Kit *k);
|
static bool isIos(const ProjectExplorer::Kit *k);
|
||||||
|
static bool hasQmlDebugging(const CMakeConfig &config);
|
||||||
|
|
||||||
// Context menu action:
|
// Context menu action:
|
||||||
void buildTarget(const QString &buildTarget);
|
void buildTarget(const QString &buildTarget);
|
||||||
@@ -63,6 +64,8 @@ public:
|
|||||||
void setSourceDirectory(const Utils::FilePath& path);
|
void setSourceDirectory(const Utils::FilePath& path);
|
||||||
Utils::FilePath sourceDirectory() const;
|
Utils::FilePath sourceDirectory() const;
|
||||||
|
|
||||||
|
void addToEnvironment(Utils::Environment &env) const override;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void signingFlagsChanged();
|
void signingFlagsChanged();
|
||||||
|
|
||||||
|
|||||||
@@ -36,26 +36,31 @@
|
|||||||
#include "cmakeprojectplugin.h"
|
#include "cmakeprojectplugin.h"
|
||||||
#include "cmakespecificsettings.h"
|
#include "cmakespecificsettings.h"
|
||||||
#include "projecttreehelper.h"
|
#include "projecttreehelper.h"
|
||||||
#include "utils/algorithm.h"
|
|
||||||
|
|
||||||
#include <android/androidconstants.h>
|
#include <android/androidconstants.h>
|
||||||
|
|
||||||
#include <coreplugin/icore.h>
|
#include <coreplugin/icore.h>
|
||||||
#include <coreplugin/progressmanager/progressmanager.h>
|
#include <coreplugin/progressmanager/progressmanager.h>
|
||||||
|
|
||||||
#include <cppeditor/cppeditorconstants.h>
|
#include <cppeditor/cppeditorconstants.h>
|
||||||
#include <cppeditor/cppprojectupdater.h>
|
#include <cppeditor/cppprojectupdater.h>
|
||||||
#include <cppeditor/generatedcodemodelsupport.h>
|
#include <cppeditor/generatedcodemodelsupport.h>
|
||||||
|
|
||||||
|
#include <projectexplorer/buildsteplist.h>
|
||||||
#include <projectexplorer/kitinformation.h>
|
#include <projectexplorer/kitinformation.h>
|
||||||
#include <projectexplorer/projectexplorer.h>
|
#include <projectexplorer/projectexplorer.h>
|
||||||
#include <projectexplorer/projectexplorerconstants.h>
|
#include <projectexplorer/projectexplorerconstants.h>
|
||||||
#include <projectexplorer/session.h>
|
#include <projectexplorer/session.h>
|
||||||
#include <projectexplorer/target.h>
|
#include <projectexplorer/target.h>
|
||||||
#include <projectexplorer/taskhub.h>
|
#include <projectexplorer/taskhub.h>
|
||||||
|
|
||||||
#include <qmljs/qmljsmodelmanagerinterface.h>
|
#include <qmljs/qmljsmodelmanagerinterface.h>
|
||||||
#include <qtsupport/qtcppkitinfo.h>
|
#include <qtsupport/qtcppkitinfo.h>
|
||||||
#include <qtsupport/qtkitinformation.h>
|
#include <qtsupport/qtkitinformation.h>
|
||||||
|
|
||||||
#include <app/app_version.h>
|
#include <app/app_version.h>
|
||||||
|
|
||||||
|
#include <utils/algorithm.h>
|
||||||
#include <utils/checkablemessagebox.h>
|
#include <utils/checkablemessagebox.h>
|
||||||
#include <utils/fileutils.h>
|
#include <utils/fileutils.h>
|
||||||
#include <utils/macroexpander.h>
|
#include <utils/macroexpander.h>
|
||||||
@@ -1314,5 +1319,31 @@ void CMakeBuildSystem::updateInitialCMakeExpandableVars()
|
|||||||
emit configurationChanged(config);
|
emit configurationChanged(config);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MakeInstallCommand CMakeBuildSystem::makeInstallCommand(const FilePath &installRoot) const
|
||||||
|
{
|
||||||
|
MakeInstallCommand cmd;
|
||||||
|
if (CMakeTool *tool = CMakeKitAspect::cmakeTool(target()->kit()))
|
||||||
|
cmd.command.setExecutable(tool->cmakeExecutable());
|
||||||
|
|
||||||
|
QString installTarget = "install";
|
||||||
|
if (usesAllCapsTargets())
|
||||||
|
installTarget = "INSTALL";
|
||||||
|
|
||||||
|
FilePath buildDirectory = ".";
|
||||||
|
if (auto bc = buildConfiguration())
|
||||||
|
buildDirectory = bc->buildDirectory();
|
||||||
|
|
||||||
|
cmd.command.addArg("--build");
|
||||||
|
cmd.command.addArg(buildDirectory.onDevice(cmd.command.executable()).path());
|
||||||
|
cmd.command.addArg("--target");
|
||||||
|
cmd.command.addArg(installTarget);
|
||||||
|
|
||||||
|
if (isMultiConfigReader())
|
||||||
|
cmd.command.addArgs({"--config", cmakeBuildType()});
|
||||||
|
|
||||||
|
cmd.environment.set("DESTDIR", installRoot.nativePath());
|
||||||
|
return cmd;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
} // namespace CMakeProjectManager
|
} // namespace CMakeProjectManager
|
||||||
|
|||||||
@@ -98,6 +98,9 @@ public:
|
|||||||
Utils::CommandLine commandLineForTests(const QList<QString> &tests,
|
Utils::CommandLine commandLineForTests(const QList<QString> &tests,
|
||||||
const QStringList &options) const final;
|
const QStringList &options) const final;
|
||||||
|
|
||||||
|
ProjectExplorer::MakeInstallCommand makeInstallCommand(
|
||||||
|
const Utils::FilePath &installRoot) const final;
|
||||||
|
|
||||||
static bool filteredOutTarget(const CMakeBuildTarget &target);
|
static bool filteredOutTarget(const CMakeBuildTarget &target);
|
||||||
|
|
||||||
bool isMultiConfig() const;
|
bool isMultiConfig() const;
|
||||||
|
|||||||
@@ -64,6 +64,13 @@ void CMakeParser::setSourceDirectory(const QString &sourceDir)
|
|||||||
|
|
||||||
OutputLineParser::Result CMakeParser::handleLine(const QString &line, OutputFormat type)
|
OutputLineParser::Result CMakeParser::handleLine(const QString &line, OutputFormat type)
|
||||||
{
|
{
|
||||||
|
if (line.startsWith("ninja: build stopped")) {
|
||||||
|
m_lastTask = BuildSystemTask(Task::Error, line);
|
||||||
|
m_lines = 1;
|
||||||
|
flush();
|
||||||
|
return Status::Done;
|
||||||
|
}
|
||||||
|
|
||||||
if (type != StdErrFormat)
|
if (type != StdErrFormat)
|
||||||
return Status::NotHandled;
|
return Status::NotHandled;
|
||||||
|
|
||||||
|
|||||||
@@ -116,40 +116,4 @@ ProjectExplorer::DeploymentKnowledge CMakeProject::deploymentKnowledge() const
|
|||||||
: DeploymentKnowledge::Bad;
|
: DeploymentKnowledge::Bad;
|
||||||
}
|
}
|
||||||
|
|
||||||
MakeInstallCommand CMakeProject::makeInstallCommand(const Target *target,
|
|
||||||
const FilePath &installRoot)
|
|
||||||
{
|
|
||||||
MakeInstallCommand cmd;
|
|
||||||
if (const BuildConfiguration * const bc = target->activeBuildConfiguration()) {
|
|
||||||
if (const auto cmakeStep = bc->buildSteps()->firstOfType<CMakeBuildStep>()) {
|
|
||||||
if (CMakeTool *tool = CMakeKitAspect::cmakeTool(target->kit()))
|
|
||||||
cmd.command.setExecutable(tool->cmakeExecutable());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QString installTarget = "install";
|
|
||||||
QStringList config;
|
|
||||||
|
|
||||||
auto bs = qobject_cast<CMakeBuildSystem*>(target->buildSystem());
|
|
||||||
QTC_ASSERT(bs, return {});
|
|
||||||
|
|
||||||
if (bs->usesAllCapsTargets())
|
|
||||||
installTarget = "INSTALL";
|
|
||||||
if (bs->isMultiConfigReader())
|
|
||||||
config << "--config" << bs->cmakeBuildType();
|
|
||||||
|
|
||||||
FilePath buildDirectory = ".";
|
|
||||||
if (auto bc = bs->buildConfiguration())
|
|
||||||
buildDirectory = bc->buildDirectory();
|
|
||||||
|
|
||||||
cmd.command.addArg("--build");
|
|
||||||
cmd.command.addArg(buildDirectory.onDevice(cmd.command.executable()).path());
|
|
||||||
cmd.command.addArg("--target");
|
|
||||||
cmd.command.addArg(installTarget);
|
|
||||||
cmd.command.addArgs(config);
|
|
||||||
|
|
||||||
cmd.environment.set("DESTDIR", installRoot.nativePath());
|
|
||||||
return cmd;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace CMakeProjectManager
|
} // namespace CMakeProjectManager
|
||||||
|
|||||||
@@ -54,8 +54,6 @@ protected:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
ProjectExplorer::DeploymentKnowledge deploymentKnowledge() const override;
|
ProjectExplorer::DeploymentKnowledge deploymentKnowledge() const override;
|
||||||
ProjectExplorer::MakeInstallCommand makeInstallCommand(const ProjectExplorer::Target *target,
|
|
||||||
const Utils::FilePath &installRoot) final;
|
|
||||||
|
|
||||||
mutable Internal::CMakeProjectImporter *m_projectImporter = nullptr;
|
mutable Internal::CMakeProjectImporter *m_projectImporter = nullptr;
|
||||||
|
|
||||||
|
|||||||
@@ -337,13 +337,7 @@ QList<void *> CMakeProjectImporter::examineDirectory(const FilePath &importPath,
|
|||||||
canonicalProjectDirectory.toUserOutput());
|
canonicalProjectDirectory.toUserOutput());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determine QML debugging flags. This must match what we do in
|
data->hasQmlDebugging = CMakeBuildConfiguration::hasQmlDebugging(config);
|
||||||
// CMakeBuildSettingsWidget::getQmlDebugCxxFlags()
|
|
||||||
// such that in doubt we leave the QML Debugging setting at "Leave at default"
|
|
||||||
const QString cxxFlagsInit = config.stringValueOf("CMAKE_CXX_FLAGS_INIT");
|
|
||||||
const QString cxxFlags = config.stringValueOf("CMAKE_CXX_FLAGS");
|
|
||||||
data->hasQmlDebugging = cxxFlagsInit.contains("-DQT_QML_DEBUG")
|
|
||||||
&& cxxFlags.contains("-DQT_QML_DEBUG");
|
|
||||||
|
|
||||||
data->buildDirectory = importPath;
|
data->buildDirectory = importPath;
|
||||||
data->cmakeBuildType = buildType;
|
data->cmakeBuildType = buildType;
|
||||||
@@ -394,10 +388,7 @@ bool CMakeProjectImporter::matchKit(void *directoryData, const Kit *k) const
|
|||||||
if (!Utils::contains(allLanguages, [&tcd](const Id& language) {return language == tcd.language;}))
|
if (!Utils::contains(allLanguages, [&tcd](const Id& language) {return language == tcd.language;}))
|
||||||
continue;
|
continue;
|
||||||
ToolChain *tc = ToolChainKitAspect::toolChain(k, tcd.language);
|
ToolChain *tc = ToolChainKitAspect::toolChain(k, tcd.language);
|
||||||
if (!tc
|
if (!tc || !tc->matchesCompilerCommand(tcd.compilerPath)) {
|
||||||
|| !Utils::Environment::systemEnvironment()
|
|
||||||
.isSameExecutable(tc->compilerCommand().toString(),
|
|
||||||
tcd.compilerPath.toString())) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -154,15 +154,11 @@ class CocoTextMark : public TextEditor::TextMark
|
|||||||
public:
|
public:
|
||||||
CocoTextMark(const FilePath &fileName, const CocoDiagnostic &diag, const Id &clientId)
|
CocoTextMark(const FilePath &fileName, const CocoDiagnostic &diag, const Id &clientId)
|
||||||
: TextEditor::TextMark(fileName, diag.range().start().line() + 1, clientId)
|
: TextEditor::TextMark(fileName, diag.range().start().line() + 1, clientId)
|
||||||
|
, m_severity(diag.cocoSeverity())
|
||||||
{
|
{
|
||||||
setLineAnnotation(diag.message());
|
setLineAnnotation(diag.message());
|
||||||
setToolTip(diag.message());
|
setToolTip(diag.message());
|
||||||
if (optional<CocoDiagnosticSeverity> severity = diag.cocoSeverity()) {
|
updateAnnotationColor();
|
||||||
|
|
||||||
const TextEditor::TextStyle style = styleForSeverity(*severity);
|
|
||||||
m_annotationColor =
|
|
||||||
TextEditor::TextEditorSettings::fontSettings().formatFor(style).foreground();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QColor annotationColor() const override
|
QColor annotationColor() const override
|
||||||
@@ -171,6 +167,16 @@ public:
|
|||||||
: TextEditor::TextMark::annotationColor();
|
: TextEditor::TextMark::annotationColor();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void updateAnnotationColor()
|
||||||
|
{
|
||||||
|
if (m_severity) {
|
||||||
|
const TextEditor::TextStyle style = styleForSeverity(*m_severity);
|
||||||
|
m_annotationColor =
|
||||||
|
TextEditor::TextEditorSettings::fontSettings().formatFor(style).foreground();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
optional<CocoDiagnosticSeverity> m_severity;
|
||||||
QColor m_annotationColor;
|
QColor m_annotationColor;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -180,10 +186,22 @@ public:
|
|||||||
CocoDiagnosticManager(Client *client)
|
CocoDiagnosticManager(Client *client)
|
||||||
: DiagnosticManager(client)
|
: DiagnosticManager(client)
|
||||||
{
|
{
|
||||||
|
connect(TextEditor::TextEditorSettings::instance(),
|
||||||
|
&TextEditor::TextEditorSettings::fontSettingsChanged,
|
||||||
|
this,
|
||||||
|
&CocoDiagnosticManager::fontSettingsChanged);
|
||||||
setExtraSelectionsId("CocoExtraSelections");
|
setExtraSelectionsId("CocoExtraSelections");
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void fontSettingsChanged()
|
||||||
|
{
|
||||||
|
forAllMarks([](TextEditor::TextMark *mark){
|
||||||
|
static_cast<CocoTextMark *>(mark)->updateAnnotationColor();
|
||||||
|
mark->updateMarker();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
TextEditor::TextMark *createTextMark(const FilePath &filePath,
|
TextEditor::TextMark *createTextMark(const FilePath &filePath,
|
||||||
const Diagnostic &diagnostic,
|
const Diagnostic &diagnostic,
|
||||||
bool /*isProjectFile*/) const override
|
bool /*isProjectFile*/) const override
|
||||||
|
|||||||
@@ -188,7 +188,7 @@ const char G_VIEW_PANES[] = "QtCreator.Group.View.Panes";
|
|||||||
|
|
||||||
// Tools menu groups
|
// Tools menu groups
|
||||||
const char G_TOOLS_DEBUG[] = "QtCreator.Group.Tools.Debug";
|
const char G_TOOLS_DEBUG[] = "QtCreator.Group.Tools.Debug";
|
||||||
const char G_TOOLS_OPTIONS[] = "QtCreator.Group.Tools.Options";
|
const char G_EDIT_PREFERENCES[] = "QtCreator.Group.Edit.Preferences";
|
||||||
|
|
||||||
// Window menu groups
|
// Window menu groups
|
||||||
const char G_WINDOW_SIZE[] = "QtCreator.Group.Window.Size";
|
const char G_WINDOW_SIZE[] = "QtCreator.Group.Window.Size";
|
||||||
|
|||||||
@@ -32,8 +32,10 @@
|
|||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
|
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
|
#include <QDirIterator>
|
||||||
#include <QTemporaryFile>
|
#include <QTemporaryFile>
|
||||||
#include <QVariant>
|
#include <QVariant>
|
||||||
|
#include <QVersionNumber>
|
||||||
|
|
||||||
namespace Core {
|
namespace Core {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
@@ -165,5 +167,34 @@ QString UtilsJsExtension::asciify(const QString &input) const
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString UtilsJsExtension::qtQuickVersion(const QString &filePath) const
|
||||||
|
{
|
||||||
|
QDirIterator dirIt(Utils::FilePath::fromString(filePath).parentDir().path(), {"*.qml"},
|
||||||
|
QDir::Files, QDirIterator::Subdirectories);
|
||||||
|
while (dirIt.hasNext()) {
|
||||||
|
Utils::FileReader reader;
|
||||||
|
if (!reader.fetch(Utils::FilePath::fromString(dirIt.next())))
|
||||||
|
continue;
|
||||||
|
const QString data = QString::fromUtf8(reader.data());
|
||||||
|
static const QString importString("import QtQuick");
|
||||||
|
const int importIndex = data.indexOf(importString);
|
||||||
|
if (importIndex == -1)
|
||||||
|
continue;
|
||||||
|
const int versionIndex = importIndex + importString.length();
|
||||||
|
const int newLineIndex = data.indexOf('\n', versionIndex);
|
||||||
|
if (newLineIndex == -1)
|
||||||
|
continue;
|
||||||
|
const QString versionString = data.mid(versionIndex,
|
||||||
|
newLineIndex - versionIndex).simplified();
|
||||||
|
if (versionString.isEmpty())
|
||||||
|
return {};
|
||||||
|
const auto version = QVersionNumber::fromString(versionString);
|
||||||
|
if (version.isNull())
|
||||||
|
return {};
|
||||||
|
return version.toString();
|
||||||
|
}
|
||||||
|
return QLatin1String("2.15");
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
} // namespace Core
|
} // namespace Core
|
||||||
|
|||||||
@@ -76,6 +76,9 @@ public:
|
|||||||
|
|
||||||
// Generate a ascii-only string:
|
// Generate a ascii-only string:
|
||||||
Q_INVOKABLE QString asciify(const QString &input) const;
|
Q_INVOKABLE QString asciify(const QString &input) const;
|
||||||
|
|
||||||
|
// Heuristic to find out which QtQuick import version to use for the given file.
|
||||||
|
Q_INVOKABLE QString qtQuickVersion(const QString &filePath) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
|
|||||||
@@ -152,7 +152,7 @@ void FilePropertiesDialog::refresh()
|
|||||||
m_ui->name->setText(fileInfo.fileName());
|
m_ui->name->setText(fileInfo.fileName());
|
||||||
m_ui->path->setText(QDir::toNativeSeparators(fileInfo.canonicalPath()));
|
m_ui->path->setText(QDir::toNativeSeparators(fileInfo.canonicalPath()));
|
||||||
|
|
||||||
const Utils::MimeType mimeType = Utils::mimeTypeForFile(fileInfo);
|
const Utils::MimeType mimeType = Utils::mimeTypeForFile(m_filePath);
|
||||||
m_ui->mimeType->setText(mimeType.name());
|
m_ui->mimeType->setText(mimeType.name());
|
||||||
|
|
||||||
const EditorTypeList factories = IEditorFactory::preferredEditorTypes(m_filePath);
|
const EditorTypeList factories = IEditorFactory::preferredEditorTypes(m_filePath);
|
||||||
|
|||||||
@@ -2148,8 +2148,8 @@ void EditorManagerPrivate::updateWindowTitleForDocument(IDocument *document, QWi
|
|||||||
if (!documentName.isEmpty())
|
if (!documentName.isEmpty())
|
||||||
windowTitle.append(documentName);
|
windowTitle.append(documentName);
|
||||||
|
|
||||||
const QString filePath = document ? document->filePath().absoluteFilePath().path()
|
const Utils::FilePath filePath = document ? document->filePath().absoluteFilePath()
|
||||||
: QString();
|
: Utils::FilePath();
|
||||||
const QString windowTitleAddition = d->m_titleAdditionHandler
|
const QString windowTitleAddition = d->m_titleAdditionHandler
|
||||||
? d->m_titleAdditionHandler(filePath)
|
? d->m_titleAdditionHandler(filePath)
|
||||||
: QString();
|
: QString();
|
||||||
@@ -2181,7 +2181,7 @@ void EditorManagerPrivate::updateWindowTitleForDocument(IDocument *document, QWi
|
|||||||
windowTitle.append(dashSep);
|
windowTitle.append(dashSep);
|
||||||
windowTitle.append(Core::Constants::IDE_DISPLAY_NAME);
|
windowTitle.append(Core::Constants::IDE_DISPLAY_NAME);
|
||||||
window->window()->setWindowTitle(windowTitle);
|
window->window()->setWindowTitle(windowTitle);
|
||||||
window->window()->setWindowFilePath(filePath);
|
window->window()->setWindowFilePath(filePath.path());
|
||||||
|
|
||||||
if (HostOsInfo::isMacHost()) {
|
if (HostOsInfo::isMacHost()) {
|
||||||
if (document)
|
if (document)
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ class CORE_EXPORT EditorManager : public QObject
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using WindowTitleHandler = std::function<QString (const QString &)>;
|
using WindowTitleHandler = std::function<QString (const Utils::FilePath &)>;
|
||||||
|
|
||||||
static EditorManager *instance();
|
static EditorManager *instance();
|
||||||
|
|
||||||
|
|||||||
@@ -717,14 +717,14 @@ void MainWindow::registerDefaultActions()
|
|||||||
connect(m_loggerAction, &QAction::triggered, this, [] { LoggingViewer::showLoggingView(); });
|
connect(m_loggerAction, &QAction::triggered, this, [] { LoggingViewer::showLoggingView(); });
|
||||||
|
|
||||||
// Options Action
|
// Options Action
|
||||||
mtools->appendGroup(Constants::G_TOOLS_OPTIONS);
|
medit->appendGroup(Constants::G_EDIT_PREFERENCES);
|
||||||
mtools->addSeparator(Constants::G_TOOLS_OPTIONS);
|
medit->addSeparator(Constants::G_EDIT_PREFERENCES);
|
||||||
|
|
||||||
m_optionsAction = new QAction(tr("&Options..."), this);
|
m_optionsAction = new QAction(tr("&Preferences..."), this);
|
||||||
m_optionsAction->setMenuRole(QAction::PreferencesRole);
|
m_optionsAction->setMenuRole(QAction::PreferencesRole);
|
||||||
cmd = ActionManager::registerAction(m_optionsAction, Constants::OPTIONS);
|
cmd = ActionManager::registerAction(m_optionsAction, Constants::OPTIONS);
|
||||||
cmd->setDefaultKeySequence(QKeySequence::Preferences);
|
cmd->setDefaultKeySequence(QKeySequence::Preferences);
|
||||||
mtools->addAction(cmd, Constants::G_TOOLS_OPTIONS);
|
medit->addAction(cmd, Constants::G_EDIT_PREFERENCES);
|
||||||
connect(m_optionsAction, &QAction::triggered, this, [] { ICore::showOptionsDialog(Id()); });
|
connect(m_optionsAction, &QAction::triggered, this, [] { ICore::showOptionsDialog(Id()); });
|
||||||
|
|
||||||
mwindow->addSeparator(Constants::G_WINDOW_LIST);
|
mwindow->addSeparator(Constants::G_WINDOW_LIST);
|
||||||
|
|||||||
@@ -112,7 +112,8 @@ static bool runPatchHelper(const QByteArray &input, const FilePath &workingDirec
|
|||||||
QByteArray stdOut;
|
QByteArray stdOut;
|
||||||
QByteArray stdErr;
|
QByteArray stdErr;
|
||||||
if (!patchProcess.readDataFromProcess(30, &stdOut, &stdErr, true)) {
|
if (!patchProcess.readDataFromProcess(30, &stdOut, &stdErr, true)) {
|
||||||
patchProcess.stopProcess();
|
patchProcess.stop();
|
||||||
|
patchProcess.waitForFinished();
|
||||||
MessageManager::writeFlashing(
|
MessageManager::writeFlashing(
|
||||||
QApplication::translate("Core::PatchTool", "A timeout occurred running \"%1\"")
|
QApplication::translate("Core::PatchTool", "A timeout occurred running \"%1\"")
|
||||||
.arg(patch.toUserOutput()));
|
.arg(patch.toUserOutput()));
|
||||||
|
|||||||
@@ -124,11 +124,6 @@ CppCompletionAssistProvider *BuiltinModelManagerSupport::completionAssistProvide
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
CppCompletionAssistProvider *BuiltinModelManagerSupport::functionHintAssistProvider()
|
|
||||||
{
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
TextEditor::BaseHoverHandler *BuiltinModelManagerSupport::createHoverHandler()
|
TextEditor::BaseHoverHandler *BuiltinModelManagerSupport::createHoverHandler()
|
||||||
{
|
{
|
||||||
return new CppHoverHandler;
|
return new CppHoverHandler;
|
||||||
|
|||||||
@@ -42,7 +42,6 @@ public:
|
|||||||
~BuiltinModelManagerSupport() override;
|
~BuiltinModelManagerSupport() override;
|
||||||
|
|
||||||
CppCompletionAssistProvider *completionAssistProvider() final;
|
CppCompletionAssistProvider *completionAssistProvider() final;
|
||||||
CppCompletionAssistProvider *functionHintAssistProvider() override;
|
|
||||||
TextEditor::BaseHoverHandler *createHoverHandler() final;
|
TextEditor::BaseHoverHandler *createHoverHandler() final;
|
||||||
BaseEditorDocumentProcessor *createEditorDocumentProcessor(
|
BaseEditorDocumentProcessor *createEditorDocumentProcessor(
|
||||||
TextEditor::TextDocument *baseTextDocument) final;
|
TextEditor::TextDocument *baseTextDocument) final;
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ static FilePath fallbackClangdFilePath()
|
|||||||
{
|
{
|
||||||
if (g_defaultClangdFilePath.exists())
|
if (g_defaultClangdFilePath.exists())
|
||||||
return g_defaultClangdFilePath;
|
return g_defaultClangdFilePath;
|
||||||
return "clangd";
|
return Environment::systemEnvironment().searchInPath("clangd");
|
||||||
}
|
}
|
||||||
|
|
||||||
void CppCodeModelSettings::fromSettings(QSettings *s)
|
void CppCodeModelSettings::fromSettings(QSettings *s)
|
||||||
|
|||||||
@@ -26,16 +26,13 @@
|
|||||||
#include "cppeditordocument.h"
|
#include "cppeditordocument.h"
|
||||||
|
|
||||||
#include "baseeditordocumentparser.h"
|
#include "baseeditordocumentparser.h"
|
||||||
#include "builtineditordocumentprocessor.h"
|
|
||||||
#include "cppcodeformatter.h"
|
#include "cppcodeformatter.h"
|
||||||
#include "cppcodemodelsettings.h"
|
|
||||||
#include "cppeditorconstants.h"
|
#include "cppeditorconstants.h"
|
||||||
#include "cppeditorplugin.h"
|
#include "cppeditorplugin.h"
|
||||||
#include "cppmodelmanager.h"
|
#include "cppmodelmanager.h"
|
||||||
#include "cppeditorconstants.h"
|
#include "cppeditorconstants.h"
|
||||||
#include "cppeditorplugin.h"
|
#include "cppeditorplugin.h"
|
||||||
#include "cpphighlighter.h"
|
#include "cpphighlighter.h"
|
||||||
#include "cppqtstyleindenter.h"
|
|
||||||
#include "cppquickfixassistant.h"
|
#include "cppquickfixassistant.h"
|
||||||
|
|
||||||
#include <coreplugin/editormanager/editormanager.h>
|
#include <coreplugin/editormanager/editormanager.h>
|
||||||
@@ -58,20 +55,17 @@
|
|||||||
|
|
||||||
const char NO_PROJECT_CONFIGURATION[] = "NoProject";
|
const char NO_PROJECT_CONFIGURATION[] = "NoProject";
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
CppEditor::CppModelManager *mm()
|
|
||||||
{
|
|
||||||
return CppEditor::CppModelManager::instance();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // anonymous namespace
|
|
||||||
|
|
||||||
using namespace TextEditor;
|
using namespace TextEditor;
|
||||||
|
using namespace Utils;
|
||||||
|
|
||||||
namespace CppEditor {
|
namespace CppEditor {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
|
static CppEditor::CppModelManager *mm()
|
||||||
|
{
|
||||||
|
return CppEditor::CppModelManager::instance();
|
||||||
|
}
|
||||||
|
|
||||||
enum { processDocumentIntervalInMs = 150 };
|
enum { processDocumentIntervalInMs = 150 };
|
||||||
|
|
||||||
class CppEditorDocumentHandleImpl : public CppEditorDocumentHandle
|
class CppEditorDocumentHandleImpl : public CppEditorDocumentHandle
|
||||||
@@ -150,24 +144,12 @@ void CppEditorDocument::setCompletionAssistProvider(TextEditor::CompletionAssist
|
|||||||
m_completionAssistProvider = nullptr;
|
m_completionAssistProvider = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CppEditorDocument::setFunctionHintAssistProvider(TextEditor::CompletionAssistProvider *provider)
|
|
||||||
{
|
|
||||||
TextDocument::setFunctionHintAssistProvider(provider);
|
|
||||||
m_functionHintAssistProvider = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
CompletionAssistProvider *CppEditorDocument::completionAssistProvider() const
|
CompletionAssistProvider *CppEditorDocument::completionAssistProvider() const
|
||||||
{
|
{
|
||||||
return m_completionAssistProvider
|
return m_completionAssistProvider
|
||||||
? m_completionAssistProvider : TextDocument::completionAssistProvider();
|
? m_completionAssistProvider : TextDocument::completionAssistProvider();
|
||||||
}
|
}
|
||||||
|
|
||||||
CompletionAssistProvider *CppEditorDocument::functionHintAssistProvider() const
|
|
||||||
{
|
|
||||||
return m_functionHintAssistProvider
|
|
||||||
? m_functionHintAssistProvider : TextDocument::functionHintAssistProvider();
|
|
||||||
}
|
|
||||||
|
|
||||||
TextEditor::IAssistProvider *CppEditorDocument::quickFixAssistProvider() const
|
TextEditor::IAssistProvider *CppEditorDocument::quickFixAssistProvider() const
|
||||||
{
|
{
|
||||||
if (const auto baseProvider = TextDocument::quickFixAssistProvider())
|
if (const auto baseProvider = TextDocument::quickFixAssistProvider())
|
||||||
@@ -223,7 +205,6 @@ void CppEditorDocument::onMimeTypeChanged()
|
|||||||
m_isObjCEnabled = (mt == QLatin1String(Constants::OBJECTIVE_C_SOURCE_MIMETYPE)
|
m_isObjCEnabled = (mt == QLatin1String(Constants::OBJECTIVE_C_SOURCE_MIMETYPE)
|
||||||
|| mt == QLatin1String(Constants::OBJECTIVE_CPP_SOURCE_MIMETYPE));
|
|| mt == QLatin1String(Constants::OBJECTIVE_CPP_SOURCE_MIMETYPE));
|
||||||
m_completionAssistProvider = mm()->completionAssistProvider();
|
m_completionAssistProvider = mm()->completionAssistProvider();
|
||||||
m_functionHintAssistProvider = mm()->functionHintAssistProvider();
|
|
||||||
|
|
||||||
initializeTimer();
|
initializeTimer();
|
||||||
}
|
}
|
||||||
@@ -258,14 +239,13 @@ void CppEditorDocument::reparseWithPreferredParseContext(const QString &parseCon
|
|||||||
scheduleProcessDocument();
|
scheduleProcessDocument();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CppEditorDocument::onFilePathChanged(const Utils::FilePath &oldPath,
|
void CppEditorDocument::onFilePathChanged(const FilePath &oldPath, const FilePath &newPath)
|
||||||
const Utils::FilePath &newPath)
|
|
||||||
{
|
{
|
||||||
Q_UNUSED(oldPath)
|
Q_UNUSED(oldPath)
|
||||||
|
|
||||||
if (!newPath.isEmpty()) {
|
if (!newPath.isEmpty()) {
|
||||||
indenter()->setFileName(newPath);
|
indenter()->setFileName(newPath);
|
||||||
setMimeType(Utils::mimeTypeForFile(newPath.toFileInfo()).name());
|
setMimeType(mimeTypeForFile(newPath).name());
|
||||||
|
|
||||||
connect(this, &Core::IDocument::contentsChanged,
|
connect(this, &Core::IDocument::contentsChanged,
|
||||||
this, &CppEditorDocument::scheduleProcessDocument,
|
this, &CppEditorDocument::scheduleProcessDocument,
|
||||||
@@ -376,13 +356,13 @@ void CppEditorDocument::releaseResources()
|
|||||||
|
|
||||||
void CppEditorDocument::showHideInfoBarAboutMultipleParseContexts(bool show)
|
void CppEditorDocument::showHideInfoBarAboutMultipleParseContexts(bool show)
|
||||||
{
|
{
|
||||||
const Utils::Id id = Constants::MULTIPLE_PARSE_CONTEXTS_AVAILABLE;
|
const Id id = Constants::MULTIPLE_PARSE_CONTEXTS_AVAILABLE;
|
||||||
|
|
||||||
if (show) {
|
if (show) {
|
||||||
Utils::InfoBarEntry info(id,
|
InfoBarEntry info(id,
|
||||||
tr("Note: Multiple parse contexts are available for this file. "
|
tr("Note: Multiple parse contexts are available for this file. "
|
||||||
"Choose the preferred one from the editor toolbar."),
|
"Choose the preferred one from the editor toolbar."),
|
||||||
Utils::InfoBarEntry::GlobalSuppression::Enabled);
|
InfoBarEntry::GlobalSuppression::Enabled);
|
||||||
info.removeCancelButton();
|
info.removeCancelButton();
|
||||||
if (infoBar()->canInfoBeAdded(id))
|
if (infoBar()->canInfoBeAdded(id))
|
||||||
infoBar()->addInfo(info);
|
infoBar()->addInfo(info);
|
||||||
@@ -457,9 +437,9 @@ TextEditor::TabSettings CppEditorDocument::tabSettings() const
|
|||||||
return indenter()->tabSettings().value_or(TextEditor::TextDocument::tabSettings());
|
return indenter()->tabSettings().value_or(TextEditor::TextDocument::tabSettings());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CppEditorDocument::save(QString *errorString, const Utils::FilePath &filePath, bool autoSave)
|
bool CppEditorDocument::save(QString *errorString, const FilePath &filePath, bool autoSave)
|
||||||
{
|
{
|
||||||
Utils::ExecuteOnDestruction resetSettingsOnScopeExit;
|
ExecuteOnDestruction resetSettingsOnScopeExit;
|
||||||
|
|
||||||
if (indenter()->formatOnSave() && !autoSave) {
|
if (indenter()->formatOnSave() && !autoSave) {
|
||||||
auto *layout = qobject_cast<TextEditor::TextDocumentLayout *>(document()->documentLayout());
|
auto *layout = qobject_cast<TextEditor::TextDocumentLayout *>(document()->documentLayout());
|
||||||
|
|||||||
@@ -51,9 +51,7 @@ public:
|
|||||||
|
|
||||||
bool isObjCEnabled() const;
|
bool isObjCEnabled() const;
|
||||||
void setCompletionAssistProvider(TextEditor::CompletionAssistProvider *provider) override;
|
void setCompletionAssistProvider(TextEditor::CompletionAssistProvider *provider) override;
|
||||||
void setFunctionHintAssistProvider(TextEditor::CompletionAssistProvider *provider) override;
|
|
||||||
TextEditor::CompletionAssistProvider *completionAssistProvider() const override;
|
TextEditor::CompletionAssistProvider *completionAssistProvider() const override;
|
||||||
TextEditor::CompletionAssistProvider *functionHintAssistProvider() const override;
|
|
||||||
TextEditor::IAssistProvider *quickFixAssistProvider() const override;
|
TextEditor::IAssistProvider *quickFixAssistProvider() const override;
|
||||||
|
|
||||||
void recalculateSemanticInfoDetached();
|
void recalculateSemanticInfoDetached();
|
||||||
@@ -128,7 +126,6 @@ private:
|
|||||||
QScopedPointer<BaseEditorDocumentProcessor> m_processor;
|
QScopedPointer<BaseEditorDocumentProcessor> m_processor;
|
||||||
|
|
||||||
CppCompletionAssistProvider *m_completionAssistProvider = nullptr;
|
CppCompletionAssistProvider *m_completionAssistProvider = nullptr;
|
||||||
CppCompletionAssistProvider *m_functionHintAssistProvider = nullptr;
|
|
||||||
|
|
||||||
// (Un)Registration in CppModelManager
|
// (Un)Registration in CppModelManager
|
||||||
QScopedPointer<CppEditorDocumentHandle> m_editorDocumentHandle;
|
QScopedPointer<CppEditorDocumentHandle> m_editorDocumentHandle;
|
||||||
|
|||||||
@@ -632,25 +632,6 @@ CPlusPlus::Symbol *CppFindReferences::findSymbol(const CppFindReferencesParamete
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
Utils::optional<QString> getContainingFunctionName(const Utils::FilePath &fileName,
|
|
||||||
int line,
|
|
||||||
int column)
|
|
||||||
{
|
|
||||||
const CPlusPlus::Snapshot snapshot = CppModelManager::instance()->snapshot();
|
|
||||||
auto document = snapshot.document(fileName);
|
|
||||||
|
|
||||||
// context properties need lookup inside function scope, and thus require a full check
|
|
||||||
CPlusPlus::Document::Ptr localDoc = document;
|
|
||||||
if (document->checkMode() != CPlusPlus::Document::FullCheck) {
|
|
||||||
localDoc = snapshot.documentFromSource(document->utf8Source(), document->fileName());
|
|
||||||
localDoc->check();
|
|
||||||
}
|
|
||||||
|
|
||||||
auto funcName = localDoc->functionAt(line, column);
|
|
||||||
|
|
||||||
return funcName.size() ? Utils::make_optional(funcName) : Utils::nullopt;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void displayResults(SearchResult *search,
|
static void displayResults(SearchResult *search,
|
||||||
QFutureWatcher<CPlusPlus::Usage> *watcher,
|
QFutureWatcher<CPlusPlus::Usage> *watcher,
|
||||||
int first,
|
int first,
|
||||||
@@ -665,24 +646,11 @@ static void displayResults(SearchResult *search,
|
|||||||
item.setMainRange(result.line, result.col, result.len);
|
item.setMainRange(result.line, result.col, result.len);
|
||||||
item.setLineText(result.lineText);
|
item.setLineText(result.lineText);
|
||||||
item.setUserData(int(result.type));
|
item.setUserData(int(result.type));
|
||||||
|
item.setContainingFunctionName(result.containingFunction);
|
||||||
item.setStyle(colorStyleForUsageType(result.type));
|
item.setStyle(colorStyleForUsageType(result.type));
|
||||||
item.setUseTextEditorFont(true);
|
item.setUseTextEditorFont(true);
|
||||||
if (search->supportsReplace())
|
if (search->supportsReplace())
|
||||||
item.setSelectForReplacement(SessionManager::projectForFile(result.path));
|
item.setSelectForReplacement(SessionManager::projectForFile(result.path));
|
||||||
|
|
||||||
// In case we're looking for a function, we need to look at the symbol near the end. This
|
|
||||||
// is needed to avoid following corner-cases:
|
|
||||||
// 1) if we're looking at the beginning of the function declaration, we can get the
|
|
||||||
// declaration of the previous function
|
|
||||||
// 2) if we're looking somewhere at the middle of the function declaration, we can still
|
|
||||||
// get the declaration of the previous function if the cursor is located at the
|
|
||||||
// namespace declaration, i.e. CppReference>|<s::findUsages
|
|
||||||
|
|
||||||
const auto containingFunctionName = getContainingFunctionName(result.path,
|
|
||||||
result.line,
|
|
||||||
(result.col + result.len) - 1);
|
|
||||||
|
|
||||||
item.setContainingFunctionName(containingFunctionName);
|
|
||||||
search->addResult(item);
|
search->addResult(item);
|
||||||
|
|
||||||
if (parameters.prettySymbolName.isEmpty())
|
if (parameters.prettySymbolName.isEmpty())
|
||||||
@@ -777,7 +745,7 @@ restart_search:
|
|||||||
if (macro.name() == useMacro.name()) {
|
if (macro.name() == useMacro.name()) {
|
||||||
unsigned column;
|
unsigned column;
|
||||||
const QString &lineSource = matchingLine(use.bytesBegin(), source, &column);
|
const QString &lineSource = matchingLine(use.bytesBegin(), source, &column);
|
||||||
usages.append(CPlusPlus::Usage(fileName, lineSource,
|
usages.append(CPlusPlus::Usage(fileName, lineSource, {},
|
||||||
CPlusPlus::Usage::Type::Other, use.beginLine(),
|
CPlusPlus::Usage::Type::Other, use.beginLine(),
|
||||||
column, useMacro.nameToQString().size()));
|
column, useMacro.nameToQString().size()));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1620,11 +1620,6 @@ CppCompletionAssistProvider *CppModelManager::completionAssistProvider() const
|
|||||||
return d->m_builtinModelManagerSupport->completionAssistProvider();
|
return d->m_builtinModelManagerSupport->completionAssistProvider();
|
||||||
}
|
}
|
||||||
|
|
||||||
CppCompletionAssistProvider *CppModelManager::functionHintAssistProvider() const
|
|
||||||
{
|
|
||||||
return d->m_builtinModelManagerSupport->functionHintAssistProvider();
|
|
||||||
}
|
|
||||||
|
|
||||||
TextEditor::BaseHoverHandler *CppModelManager::createHoverHandler() const
|
TextEditor::BaseHoverHandler *CppModelManager::createHoverHandler() const
|
||||||
{
|
{
|
||||||
return d->m_builtinModelManagerSupport->createHoverHandler();
|
return d->m_builtinModelManagerSupport->createHoverHandler();
|
||||||
|
|||||||
@@ -162,7 +162,6 @@ public:
|
|||||||
|
|
||||||
void activateClangCodeModel(ModelManagerSupportProvider *modelManagerSupportProvider);
|
void activateClangCodeModel(ModelManagerSupportProvider *modelManagerSupportProvider);
|
||||||
CppCompletionAssistProvider *completionAssistProvider() const;
|
CppCompletionAssistProvider *completionAssistProvider() const;
|
||||||
CppCompletionAssistProvider *functionHintAssistProvider() const;
|
|
||||||
BaseEditorDocumentProcessor *createEditorDocumentProcessor(
|
BaseEditorDocumentProcessor *createEditorDocumentProcessor(
|
||||||
TextEditor::TextDocument *baseTextDocument) const;
|
TextEditor::TextDocument *baseTextDocument) const;
|
||||||
TextEditor::BaseHoverHandler *createHoverHandler() const;
|
TextEditor::BaseHoverHandler *createHoverHandler() const;
|
||||||
|
|||||||
@@ -57,7 +57,6 @@ public:
|
|||||||
virtual ~ModelManagerSupport() = 0;
|
virtual ~ModelManagerSupport() = 0;
|
||||||
|
|
||||||
virtual CppCompletionAssistProvider *completionAssistProvider() = 0;
|
virtual CppCompletionAssistProvider *completionAssistProvider() = 0;
|
||||||
virtual CppCompletionAssistProvider *functionHintAssistProvider() = 0;
|
|
||||||
virtual TextEditor::BaseHoverHandler *createHoverHandler() = 0;
|
virtual TextEditor::BaseHoverHandler *createHoverHandler() = 0;
|
||||||
virtual BaseEditorDocumentProcessor *createEditorDocumentProcessor(
|
virtual BaseEditorDocumentProcessor *createEditorDocumentProcessor(
|
||||||
TextEditor::TextDocument *baseTextDocument) = 0;
|
TextEditor::TextDocument *baseTextDocument) = 0;
|
||||||
|
|||||||
@@ -1745,6 +1745,16 @@ void QuickfixTest::testGeneric_data()
|
|||||||
<< CppQuickFixFactoryPtr(new EscapeStringLiteral)
|
<< CppQuickFixFactoryPtr(new EscapeStringLiteral)
|
||||||
<< _(R"(const char *str = @"\xc3\xa0""f23\xd0\xb1g\xd0\xb1""1";)")
|
<< _(R"(const char *str = @"\xc3\xa0""f23\xd0\xb1g\xd0\xb1""1";)")
|
||||||
<< _(R"(const char *str = "àf23бgб1";)");
|
<< _(R"(const char *str = "àf23бgб1";)");
|
||||||
|
QTest::newRow("AddLocalDeclaration_QTCREATORBUG-26004")
|
||||||
|
<< CppQuickFixFactoryPtr(new AddLocalDeclaration)
|
||||||
|
<< _("void func() {\n"
|
||||||
|
" QStringList list;\n"
|
||||||
|
" @it = list.cbegin();\n"
|
||||||
|
"}\n")
|
||||||
|
<< _("void func() {\n"
|
||||||
|
" QStringList list;\n"
|
||||||
|
" auto it = list.cbegin();\n"
|
||||||
|
"}\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void QuickfixTest::testGeneric()
|
void QuickfixTest::testGeneric()
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user